{"id":11112,"date":"2025-10-10T09:54:22","date_gmt":"2025-10-10T08:54:22","guid":{"rendered":"https:\/\/dronesonen.usn.no\/?p=11112"},"modified":"2025-10-10T09:54:22","modified_gmt":"2025-10-10T08:54:22","slug":"week-6-7","status":"publish","type":"post","link":"https:\/\/dronesonen.usn.no\/?p=11112","title":{"rendered":"Week 6 &amp; 7"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Wang<\/h2>\n\n\n\n<p>This week there hasn\u2019t been much focus on the project due to account exams. The code logic to get the car to start driving is well underway together with the distance sensor. The car hasn\u2019t been able to drive yet using Zephyr, but it does run with Ada code and the distance sensor used in the other project that has the same car.<\/p>\n\n\n\n<p>This week and next, I will have little time to work much on the project because of the account tests.<\/p>\n\n\n\n<p><a href=\"https:\/\/docs.nordicsemi.com\/bundle\/nrf-connect-vscode\/page\/guides\/work_with_devicetree_editor.html\">How to work with Devicetree Visual Editor<\/a><\/p>\n\n\n\n<p><a href=\"https:\/\/docs.google.com\/document\/d\/11IXEAOeEb7_dCMOqLLH4vVTUHFcYyUNieQWqt3716vs\/edit?tab=t.0\">https:\/\/docs.google.com\/document\/d\/11IXEAOeEb7_dCMOqLLH4vVTUHFcYyUNieQWqt3716vs\/edit?tab=t.0<\/a><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Get the car to move<\/h2>\n\n\n\n<p>To get the car to drive, the plan is to use the Zephyr environment. The car uses DC motors that are connected to a driver expansion board (V2.0) DFR0548.<\/p>\n\n\n\n<p>To get in contact with the motors, we need to use pins 20 and 19.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Zephyr setup on VS Code<\/h3>\n\n\n\n<p>To set up the Zephyr environment, we followed the Google Docs document &#8220;CS4120-1 24V&#8221; that we received from Lecturer &#8220;Steaven Bos&#8221;.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Step 1 The first thing we had to do was download the nRF Connect SDK and VS Code. So we followed the instructions from this page: <a href=\"https:\/\/academy.nordicsemi.com\/courses\/nrf-connect-sdk-fundamentals\/lessons\/lesson-1-nrf-connect-sdk-introduction\/topic\/exercise-1-1\/\">Exercise 1 &#8211; Installing nRF Connect SDK and VS Code &#8211; Nordic Developer Academy<\/a> First, you need to download SEGGER J-Link and VS-code if you don&#8217;t already have it. Then inside VS-code you need to add &#8220;nRF Connect for VS Code Extension pack&#8221;<\/li>\n\n\n\n<li>Step 2 If you have followed everything correctly up to this point, you can go to nRF Connect Create a new application. Then you will be taken to the search field where you can type &#8220;nRF LED matrix sample&#8221; which will give you an example where the LEDs on the micro:bit should start to light up and show some different patterns. But before it runs, you must first go down to &#8220;Applications&#8221; then down to build and then you need to specify that you are using micro:bit. Search for &#8220;bbc&#8221; and it will come up. Then you can open the terminal in VS Code by right-clicking on build and you will get a window with info, then select &#8220;start new Terminal Here&#8221;. Then to start the program you type &#8220;west build&#8221; then &#8220;west flash&#8221; or you can just type &#8220;west flash&#8221; If you want to see the activity, you can download &#8220;Serial monitor&#8221; for VS Code.<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">How to code<\/h3>\n\n\n\n<p>So now that everything should be set up, it should be time to code this.<\/p>\n\n\n\n<p>When you set up an empty project in Zephyr, it creates some folders and files for you automatically. Your main code should be located in src as a main.c file. At the same level as you find the src folder, you will also see the prj.conf file and CMakeList.txt<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>prj.conf This file is the project&#8217;s main configuration file. Since Zephyr is a very large library of drivers, protocols, and core functions. So for it to be as efficient and small as possible, it will only include what you specifically ask for.<\/li>\n\n\n\n<li>CMakeList.txt This is the build instructions for the project. prj.conf is the one that tells which parts CMakeList.txt needs.<\/li>\n\n\n\n<li>GPIO (General Purpose Input\/Output)<\/li>\n\n\n\n<li>PWM (Pulse Width Modulation)\n<ul class=\"wp-block-list\">\n<li>It tells the strength of current it sends out.<\/li>\n<\/ul>\n<\/li>\n\n\n\n<li>I2C (Inter-integrated Circuit)<\/li>\n\n\n\n<li>SPI (Serial Peripheral Interface)<\/li>\n<\/ul>\n\n\n\n<p>The communication between the DFR0548 board and micro:bit v2 is via the I2C protocol. So by using Zephyr&#8217;s I2C API, you can establish communication with the DC motors.<\/p>\n\n\n\n<p>Micro:bit driver expansion board (V2.0) uses the PCA9685PW chip.<\/p>\n\n\n\n<p><a href=\"https:\/\/docs.rs-online.com\/8054\/0900766b80f65101.pdf\">https:\/\/docs.rs-online.com\/8054\/0900766b80f65101.pdf<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"390\" height=\"478\" src=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-2.png\" alt=\"\" class=\"wp-image-11113\" srcset=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-2.png 390w, https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-2-245x300.png 245w\" sizes=\"auto, (max-width: 390px) 100vw, 390px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">Code<\/h3>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/bbc_microbit_v2.overlay\n\n&amp;i2c0 {\n    status = \"okay\";\n    \n    pca9685: pca9685@40 {\n        compatible = \"nxp,pca9685-pwm\";\n        reg = &lt;0x40&gt;; \n        #pwm-cells = &lt;2&gt;;\n        status = \"okay\";\n        label = \"PCA9685\";\n    };\n};\n\n\/ {\n    aliases {\n        pwm-driver = &amp;pca9685;\n    };\n};\n<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/prj.conf\n\n# I2C st\u00f8tte (n\u00f8dvendig for PCA9685)\nCONFIG_I2C=y\n\n# PWM st\u00f8tte\nCONFIG_PWM=y\n\n# PCA9685 PWM driver\nCONFIG_PWM_PCA9685=y\n\n# Logging og debugging\nCONFIG_PRINTK=y\nCONFIG_LOG=y\n\n# \u00d8k stack st\u00f8rrelse hvis n\u00f8dvendig\nCONFIG_MAIN_STACK_SIZE=2048\n\n# GPIO st\u00f8tte (for eventuell knappekontroll)\nCONFIG_GPIO=y\n<\/code><\/pre>\n\n\n\n<p>Test main.c from Gemini AI to see if it gets any contact with the DC motors.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;zephyr\/kernel.h&gt;\n#include &lt;zephyr\/device.h&gt;\n#include &lt;zephyr\/drivers\/i2c.h&gt;\n#include &lt;zephyr\/drivers\/pwm.h&gt;\n#include &lt;zephyr\/sys\/printk.h&gt;\n\n\/\/ PCA9685 I2C address (standard er 0x40 for DFR0548)\n#define PCA9685_I2C_ADDR 0x40\n\n\/\/ Motor kanaler p\u00e5 PCA9685 - basert p\u00e5 DFR0548 skjema\n\/\/ Motor 1 (U2\/HR8833): LED0-LED3\n#define M1_IN1_CHANNEL 0   \/\/ LED0 -&gt; AIN1\n#define M1_IN2_CHANNEL 1   \/\/ LED1 -&gt; AIN2  \n#define M1_PWM_CHANNEL 2   \/\/ LED2 -&gt; Enable (nSLEEP h\u00f8y for \u00e5 aktivere)\n\n\/\/ Motor 2 (U3\/HR8833): LED4-LED6\n#define M2_IN1_CHANNEL 4   \/\/ LED4 -&gt; AIN1\n#define M2_IN2_CHANNEL 5   \/\/ LED5 -&gt; AIN2\n#define M2_PWM_CHANNEL 6   \/\/ LED6 -&gt; Enable (nSLEEP h\u00f8y for \u00e5 aktivere)\n\n\/\/ PWM verdier (0-4095 for 12-bit PCA9685)\n#define PWM_MAX 4095\n#define PWM_OFF 0\n\n\/\/ Motor hastigheter\n#define SPEED_SLOW 2048    \/\/ 50% hastighet\n#define SPEED_MEDIUM 3072  \/\/ 75% hastighet\n#define SPEED_FAST 4095    \/\/ 100% hastighet\n\n\/\/ Hent PWM device\nstatic const struct device *pwm_dev;\n\n\/\/ Funksjon for \u00e5 sette PWM p\u00e5 en kanal\nint set_channel_pwm(uint8_t channel, uint16_t value) {\n    uint32_t pulse_us;\n    int ret;\n    \n    \/\/ Konverter 0-4095 verdi til mikrosekunder (20ms periode for PCA9685)\n    \/\/ PCA9685 har 20ms periode (50Hz), s\u00e5 full PWM = 20000us\n    pulse_us = (value * 20000) \/ 4096;\n    \n    ret = pwm_set(pwm_dev, channel, PWM_USEC(20000), PWM_USEC(pulse_us), 0);\n    if (ret &lt; 0) {\n        printk(\"Feil ved setting av PWM p\u00e5 kanal %d: %d\\\\n\", channel, ret);\n        return ret;\n    }\n    \n    return 0;\n}\n\n\/\/ Funksjon for \u00e5 kontrollere motor 1\nvoid motor1_control(bool forward, uint16_t speed) {\n    \/\/ F\u00f8rst aktiver motor med nSLEEP h\u00f8y\n    set_channel_pwm(M1_PWM_CHANNEL, PWM_MAX);\n    \n    if (forward) {\n        \/\/ Fremover: IN1=HIGH, IN2=LOW\n        set_channel_pwm(M1_IN1_CHANNEL, speed);\n        set_channel_pwm(M1_IN2_CHANNEL, PWM_OFF);\n    } else {\n        \/\/ Bakover: IN1=LOW, IN2=HIGH\n        set_channel_pwm(M1_IN1_CHANNEL, PWM_OFF);\n        set_channel_pwm(M1_IN2_CHANNEL, speed);\n    }\n}\n\n\/\/ Funksjon for \u00e5 kontrollere motor 2\nvoid motor2_control(bool forward, uint16_t speed) {\n    \/\/ F\u00f8rst aktiver motor med nSLEEP h\u00f8y\n    set_channel_pwm(M2_PWM_CHANNEL, PWM_MAX);\n    \n    if (forward) {\n        \/\/ Fremover: IN1=HIGH, IN2=LOW\n        set_channel_pwm(M2_IN1_CHANNEL, speed);\n        set_channel_pwm(M2_IN2_CHANNEL, PWM_OFF);\n    } else {\n        \/\/ Bakover: IN1=LOW, IN2=HIGH\n        set_channel_pwm(M2_IN1_CHANNEL, PWM_OFF);\n        set_channel_pwm(M2_IN2_CHANNEL, speed);\n    }\n}\n\n\/\/ Bevegelse funksjoner\nvoid drive_forward(uint16_t speed) {\n    printk(\"Kj\u00f8rer fremover\\\\n\");\n    motor1_control(true, speed);\n    motor2_control(true, speed);\n}\n\nvoid drive_backward(uint16_t speed) {\n    printk(\"Kj\u00f8rer bakover\\\\n\");\n    motor1_control(false, speed);\n    motor2_control(false, speed);\n}\n\nvoid turn_left(uint16_t speed) {\n    printk(\"Svinger til venstre\\\\n\");\n    motor1_control(false, speed);  \/\/ Venstre motor bakover\n    motor2_control(true, speed);    \/\/ H\u00f8yre motor fremover\n}\n\nvoid turn_right(uint16_t speed) {\n    printk(\"Svinger til h\u00f8yre\\\\n\");\n    motor1_control(true, speed);    \/\/ Venstre motor fremover\n    motor2_control(false, speed);   \/\/ H\u00f8yre motor bakover\n}\n\nvoid stop_motors(void) {\n    printk(\"Stopper motorer\\\\n\");\n    \/\/ Sett alle kanaler til OFF\n    set_channel_pwm(M1_IN1_CHANNEL, PWM_OFF);\n    set_channel_pwm(M1_IN2_CHANNEL, PWM_OFF);\n    set_channel_pwm(M1_PWM_CHANNEL, PWM_OFF);\n    set_channel_pwm(M2_IN1_CHANNEL, PWM_OFF);\n    set_channel_pwm(M2_IN2_CHANNEL, PWM_OFF);\n    set_channel_pwm(M2_PWM_CHANNEL, PWM_OFF);\n}\n\nint main(void)\n{\n    int ret;\n    \n    printk(\"\\\\n========================================\\\\n\");\n    printk(\"Starter micro:bit bil med DFR0548\\\\n\");\n    printk(\"Motor driver board V2.0\\\\n\");\n    printk(\"========================================\\\\n\\\\n\");\n    \n    \/\/ Vent litt for \u00e5 la systemet stabilisere seg\n    k_msleep(1000);\n    \n    \/\/ Hent PWM device (PCA9685)\n    pwm_dev = device_get_binding(\"PCA9685\");\n    if (!pwm_dev) {\n        printk(\"FEIL: Kunne ikke finne PCA9685 PWM device!\\\\n\");\n        printk(\"Sjekk at I2C er aktivert og devicetree overlay er riktig.\\\\n\");\n        return -1;\n    }\n    \n    printk(\"PCA9685 PWM driver funnet og klar!\\\\n\");\n    \n    \/\/ Test at vi kan sette PWM p\u00e5 alle kanaler\n    printk(\"Tester PWM kanaler...\\\\n\");\n    for (int i = 0; i &lt; 7; i++) {\n        ret = set_channel_pwm(i, PWM_OFF);\n        if (ret &lt; 0) {\n            printk(\"Kunne ikke initialisere kanal %d\\\\n\", i);\n        } else {\n            printk(\"Kanal %d OK\\\\n\", i);\n        }\n    }\n    \n    printk(\"\\\\nStarter motor test sekvens om 2 sekunder...\\\\n\");\n    k_msleep(2000);\n    \n    \/\/ Test sekvens\n    while (1) {\n        printk(\"\\\\n--- Kj\u00f8rer fremover ---\\\\n\");\n        drive_forward(SPEED_SLOW);\n        k_msleep(3000);\n        \n        printk(\"\\\\n--- Stopper ---\\\\n\");\n        stop_motors();\n        k_msleep(1000);\n        \n        printk(\"\\\\n--- Kj\u00f8rer bakover ---\\\\n\");\n        drive_backward(SPEED_SLOW);\n        k_msleep(3000);\n        \n        printk(\"\\\\n--- Stopper ---\\\\n\");\n        stop_motors();\n        k_msleep(1000);\n        \n        printk(\"\\\\n--- Svinger venstre ---\\\\n\");\n        turn_left(SPEED_SLOW);\n        k_msleep(2000);\n        \n        printk(\"\\\\n--- Stopper ---\\\\n\");\n        stop_motors();\n        k_msleep(1000);\n        \n        printk(\"\\\\n--- Svinger h\u00f8yre ---\\\\n\");\n        turn_right(SPEED_SLOW);\n        k_msleep(2000);\n        \n        printk(\"\\\\n--- Stopper ---\\\\n\");\n        stop_motors();\n        k_msleep(3000);\n        \n        printk(\"\\\\n=== Test sekvens ferdig, starter p\u00e5 nytt ===\\\\n\");\n    }\n    \n    return 0;\n}\n<\/code><\/pre>\n\n\n\n<p>After a lot of troubleshooting, I have found out that the PCA9685 was not at address 0x40 but at 0x70. I have now also managed to get contact with the serial monitor in VS Code. The car is still not running.<\/p>\n\n\n\n<p>The new prj.conf<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\n# prj.conf - Enkel konfigurasjon med direkte I2C\n\n# Serial\nCONFIG_SERIAL=y\nCONFIG_CONSOLE=y\nCONFIG_UART_CONSOLE=y\nCONFIG_PRINTK=y\n\n# I2C \nCONFIG_I2C=y\n\n# GPIO\nCONFIG_GPIO=y\n\n# Stack\nCONFIG_MAIN_STACK_SIZE=2048\n<\/code><\/pre>\n\n\n\n<p>The new bbc_microbit_v2<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ bbc_microbit_v2.overlay\n\n&amp;i2c0 {\n    status = \"okay\";\n    \n    \/\/ PCA9685 PWM controller p\u00e5 adresse 0x70\n    pca9685: pca9685@70 {\n        compatible = \"nxp,pca9685-pwm\";\n        reg = &lt;0x70&gt;;  \n        #pwm-cells = &lt;2&gt;;\n        status = \"okay\";\n        label = \"PCA9685\";\n    };\n};\n<\/code><\/pre>\n\n\n\n<p>New main.c from AI to just quickly see if it now has any contact.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ main.c - Direkte I2C kontroll av PCA9685 p\u00e5 adresse 0x70\n#include &lt;zephyr\/kernel.h&gt;\n#include &lt;zephyr\/device.h&gt;\n#include &lt;zephyr\/drivers\/i2c.h&gt;\n#include &lt;zephyr\/sys\/printk.h&gt;\n\n\/\/ PCA9685 registre\n#define PCA9685_MODE1 0x00\n#define PCA9685_MODE2 0x01\n#define PCA9685_PRESCALE 0xFE\n#define PCA9685_LED0_ON_L 0x06\n#define PCA9685_LED0_ON_H 0x07\n#define PCA9685_LED0_OFF_L 0x08\n#define PCA9685_LED0_OFF_H 0x09\n\n\/\/ I2C adresse (funnet av scanner)\n#define PCA9685_ADDR 0x70\n\n\/\/ Motor kanaler\n#define M1_IN1 0   \/\/ LED0\n#define M1_IN2 1   \/\/ LED1  \n#define M1_EN  2   \/\/ LED2\n#define M2_IN1 4   \/\/ LED4\n#define M2_IN2 5   \/\/ LED5\n#define M2_EN  6   \/\/ LED6\n\nstatic const struct device *i2c_dev;\n\n\/\/ Skriv til PCA9685 register\nint pca9685_write_reg(uint8_t reg, uint8_t value) {\n    uint8_t buf&#091;2] = {reg, value};\n    return i2c_write(i2c_dev, buf, 2, PCA9685_ADDR);\n}\n\n\/\/ Les fra PCA9685 register\nint pca9685_read_reg(uint8_t reg, uint8_t *value) {\n    return i2c_write_read(i2c_dev, PCA9685_ADDR, &amp;reg, 1, value, 1);\n}\n\n\/\/ Sett PWM p\u00e5 en kanal (0-4095)\nvoid set_pwm(uint8_t channel, uint16_t on, uint16_t off) {\n    uint8_t reg_base = PCA9685_LED0_ON_L + 4 * channel;\n    \n    i2c_reg_write_byte(i2c_dev, PCA9685_ADDR, reg_base, on &amp; 0xFF);\n    i2c_reg_write_byte(i2c_dev, PCA9685_ADDR, reg_base + 1, on &gt;&gt; 8);\n    i2c_reg_write_byte(i2c_dev, PCA9685_ADDR, reg_base + 2, off &amp; 0xFF);\n    i2c_reg_write_byte(i2c_dev, PCA9685_ADDR, reg_base + 3, off &gt;&gt; 8);\n}\n\n\/\/ Initialiser PCA9685\nint init_pca9685(void) {\n    uint8_t mode1;\n    int ret;\n    \n    printk(\"Initialiserer PCA9685 p\u00e5 adresse 0x%02X\\\\n\", PCA9685_ADDR);\n    \n    \/\/ Les MODE1 register\n    ret = pca9685_read_reg(PCA9685_MODE1, &amp;mode1);\n    if (ret &lt; 0) {\n        printk(\"Kunne ikke lese fra PCA9685: %d\\\\n\", ret);\n        return ret;\n    }\n    printk(\"MODE1 register: 0x%02X\\\\n\", mode1);\n    \n    \/\/ Reset (sleep mode)\n    pca9685_write_reg(PCA9685_MODE1, 0x00);\n    k_msleep(10);\n    \n    \/\/ Sett prescale for 50Hz (for motorer)\n    pca9685_write_reg(PCA9685_MODE1, 0x10); \/\/ Sleep\n    pca9685_write_reg(PCA9685_PRESCALE, 121); \/\/ ~50Hz\n    pca9685_write_reg(PCA9685_MODE1, 0x00); \/\/ Wake up\n    k_msleep(10);\n    pca9685_write_reg(PCA9685_MODE1, 0x20); \/\/ Auto increment\n    \n    printk(\"PCA9685 initialisert!\\\\n\");\n    return 0;\n}\n\n\/\/ Motor kontroll\nvoid motor1(bool forward, uint16_t speed) {\n    printk(\"Motor 1: %s, hastighet: %d\\\\n\", forward ? \"FREM\" : \"BAK\", speed);\n    \n    \/\/ Enable motor\n    set_pwm(M1_EN, 0, 4095);\n    \n    if (forward) {\n        set_pwm(M1_IN1, 0, speed);\n        set_pwm(M1_IN2, 0, 0);\n    } else {\n        set_pwm(M1_IN1, 0, 0);\n        set_pwm(M1_IN2, 0, speed);\n    }\n}\n\nvoid motor2(bool forward, uint16_t speed) {\n    printk(\"Motor 2: %s, hastighet: %d\\\\n\", forward ? \"FREM\" : \"BAK\", speed);\n    \n    \/\/ Enable motor\n    set_pwm(M2_EN, 0, 4095);\n    \n    if (forward) {\n        set_pwm(M2_IN1, 0, speed);\n        set_pwm(M2_IN2, 0, 0);\n    } else {\n        set_pwm(M2_IN1, 0, 0);\n        set_pwm(M2_IN2, 0, speed);\n    }\n}\n\nvoid stop_all(void) {\n    printk(\"Stopper alle motorer\\\\n\");\n    for(int i = 0; i &lt; 16; i++) {\n        set_pwm(i, 0, 0);\n    }\n}\n\nint main(void)\n{\n    int ret;\n    \n    k_msleep(2000);\n    \n    printk(\"\\\\n\\\\n****************************************\\\\n\");\n    printk(\"* DIREKTE I2C KONTROLL AV PCA9685     *\\\\n\");\n    printk(\"****************************************\\\\n\\\\n\");\n    \n    \/\/ Hent I2C device\n    i2c_dev = DEVICE_DT_GET(DT_NODELABEL(i2c0));\n    if (!device_is_ready(i2c_dev)) {\n        printk(\"I2C device ikke klar!\\\\n\");\n        return -1;\n    }\n    printk(\"I2C device klar\\\\n\");\n    \n    \/\/ Test om PCA9685 er der\n    uint8_t test;\n    ret = pca9685_read_reg(PCA9685_MODE1, &amp;test);\n    if (ret &lt; 0) {\n        printk(\"Fant ikke PCA9685 p\u00e5 0x%02X!\\\\n\", PCA9685_ADDR);\n        printk(\"Feilkode: %d\\\\n\", ret);\n        return -1;\n    }\n    printk(\"\u2713 PCA9685 funnet p\u00e5 0x%02X!\\\\n\", PCA9685_ADDR);\n    \n    \/\/ Initialiser PCA9685\n    ret = init_pca9685();\n    if (ret &lt; 0) {\n        printk(\"Initialisering feilet!\\\\n\");\n        return -1;\n    }\n    \n    \/\/ Nullstill alle kanaler\n    stop_all();\n    \n    printk(\"\\\\nStarter motortest om 3 sekunder...\\\\n\");\n    printk(\"Sjekk at motorene er koblet til M1 og M2!\\\\n\");\n    k_msleep(3000);\n    \n    uint16_t speed = 2048; \/\/ 50% hastighet\n    \n    while (1) {\n        printk(\"\\\\n=== TEST RUNDE ===\\\\n\");\n        \n        \/\/ Test motor 1\n        printk(\"\\\\nMotor 1 fremover...\\\\n\");\n        motor1(true, speed);\n        k_msleep(2000);\n        \n        printk(\"Motor 1 bakover...\\\\n\");\n        motor1(false, speed);\n        k_msleep(2000);\n        \n        stop_all();\n        k_msleep(500);\n        \n        \/\/ Test motor 2\n        printk(\"\\\\nMotor 2 fremover...\\\\n\");\n        motor2(true, speed);\n        k_msleep(2000);\n        \n        printk(\"Motor 2 bakover...\\\\n\");\n        motor2(false, speed);\n        k_msleep(2000);\n        \n        stop_all();\n        k_msleep(500);\n        \n        \/\/ Begge sammen\n        printk(\"\\\\nBegge fremover...\\\\n\");\n        motor1(true, speed);\n        motor2(true, speed);\n        k_msleep(3000);\n        \n        printk(\"\\\\nStopper...\\\\n\");\n        stop_all();\n        k_msleep(2000);\n    }\n    \n    return 0;\n}\n<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">\u00d8ivind<\/h2>\n\n\n\n<p class=\"has-text-align-center\"><strong>(Almost) Complete Robot Car Parts List<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>6\u00d7 XTAR 18650 2600mAh 30A Li-ion cells<\/strong> \u2013 Battery cells, main energy source :ETA 8\/10<\/li>\n\n\n\n<li><strong>6-slot 18650 holder with brass contacts<\/strong> \u2013 Temporary battery holder for prototyping :Wang<\/li>\n\n\n\n<li><strong>Nickel strips (pure nickel 0.15\u20130.2mm)<\/strong> \u2013 For spot-welding cells into a permanent pack ETA 12-18\/10<\/li>\n\n\n\n<li><strong>Spot welder (mini portable welder)<\/strong> \u2013 For welding nickel strips to battery terminals ETA 12-18\/10<\/li>\n\n\n\n<li><strong>3S 30\u201340A BMS with balancing<\/strong> \u2013 Protects batteries from overcharge, overdischarge, short circuit, balances cells ETA 12-18\/10<\/li>\n\n\n\n<li><strong>Balance leads + JST-XH 4-pin connector<\/strong> \u2013 Wires to connect cell taps to the BMS for balancing ETA 12-18\/10<\/li>\n\n\n\n<li><strong>20A automotive blade fuse + holder<\/strong> \u2013 Main fuse for safety, prevents fire from short circuits: Henning<\/li>\n\n\n\n<li><strong>DC rocker switch \/ XT60 loop-key<\/strong> \u2013 Main disconnect switch for battery: Borrowed of Steven<\/li>\n\n\n\n<li><strong>Heat shrink tubing + Kapton tape<\/strong> \u2013 For insulation and safe battery pack assembly<\/li>\n<\/ul>\n\n\n\n<p>ETA 12-18\/10<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DC-DC Buck Converter (LM2596 \/ MP1584)<\/strong> \u2013 Steps down battery voltage (12.6V) to 5V for Raspberry Pi &amp; sensors :In stock<\/li>\n\n\n\n<li><strong>Pololu 5V 3A Step-Down Regulator<\/strong> \u2013 Stable 5V power for Raspberry Pi ETA 12-18\/10<\/li>\n\n\n\n<li><strong>3.3V LDO regulator<\/strong> \u2013 For sensors\/microcontrollers requiring 3.3V ETA 12-18\/10<\/li>\n\n\n\n<li><strong>L298N Dual H-Bridge Boards (x2)<\/strong> \u2013 Motor drivers for 4 DC motors 1 in stock, the rest ETA 12-18\/10<\/li>\n\n\n\n<li><strong>Alternative: BTS7960 motor drivers (x2)<\/strong> \u2013 More efficient option for motor driving ETA 12-18\/10 Ordered as option<\/li>\n\n\n\n<li><strong>4\u00d7 6\u201312V gear motors with wheels<\/strong> \u2013 Drives the wheels of the robot ETA 12-18\/10<\/li>\n\n\n\n<li><strong>Pololu Magnetic Encoder Kit or Alps Encoder<\/strong> \u2013 Wheel speed feedback (motion sensing)<\/li>\n\n\n\n<li><strong>1000\u00b5F electrolytic capacitor (per motor driver)<\/strong> \u2013 Smooths motor supply voltage, reduces noise: Henning<\/li>\n\n\n\n<li><strong>TVS diode (12V)<\/strong> \u2013 Transient protection against motor spikes: Henning<\/li>\n\n\n\n<li><strong>Raspberry Pi 4 or Zero 2 W<\/strong> \u2013 Main controller for navigation &amp; AI :In stock<\/li>\n\n\n\n<li><strong>BBC micro:bit or Arduino Nano<\/strong> \u2013 Optional microcontroller for motor\/sensor tasks In stock<\/li>\n\n\n\n<li><strong>4\u20136\u00d7 HC-SR04 Ultrasonic sensors<\/strong> \u2013 Obstacle detection around the car In stock, more coming<\/li>\n\n\n\n<li><strong>ADS1115 ADC Modules (x2)<\/strong> \u2013 High-precision analog input converters for sensors ETA 12-18\/10<\/li>\n\n\n\n<li><strong>MPU6050 \/ MPU9250 IMU<\/strong> \u2013 Gyroscope + accelerometer for orientation ETA 12-18\/10<\/li>\n\n\n\n<li><strong>Optional: Pi Camera Module 3<\/strong> \u2013 Vision system for advanced navigation In stock<\/li>\n\n\n\n<li><strong>0.1\u00b5F ceramic capacitors<\/strong> \u2013 Decoupling for sensors and microcontroller :Henning<\/li>\n\n\n\n<li><strong>Chassis (kit or custom 3D print)<\/strong> \u2013 Physical base of the robot: We have two!<\/li>\n\n\n\n<li><strong>Caster wheel (1\u20132)<\/strong> \u2013 Balance and smooth turning: Not going to use<\/li>\n\n\n\n<li><strong>M3 standoffs, screws, cable ties, tape<\/strong> \u2013 Assembly hardware: Ongoing<\/li>\n\n\n\n<li><strong>14\u201316 AWG silicone wire<\/strong> \u2013 High-current wiring for motors and power: Henning<\/li>\n\n\n\n<li><strong>22\u201324 AWG wire<\/strong> \u2013 Signal wiring for sensors and logic: Henning<\/li>\n\n\n\n<li><strong>XT30\/XT60 connectors<\/strong> \u2013 Battery and motor driver connections ETA 12-18\/10<\/li>\n\n\n\n<li><strong>JST-XH connectors (4-pin)<\/strong> \u2013 Balance leads for BMS ETA 12-18\/10<\/li>\n\n\n\n<li><strong>Dupont wires \/ header pins<\/strong> \u2013 Connections between controllers and sensors: Ongoing<\/li>\n\n\n\n<li><strong>Screw terminal blocks<\/strong> \u2013 For secure modular connections: Ongoing<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading has-text-align-center\">Simple Robot Car Wiring Schematic<\/h2>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"510\" height=\"399\" src=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-41.png\" alt=\"\" class=\"wp-image-11245\" srcset=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-41.png 510w, https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-41-300x235.png 300w\" sizes=\"auto, (max-width: 510px) 100vw, 510px\" \/><\/figure>\n\n\n\n<p>What happened to my understanding of what Steven said the first day of this course, when he said: \u201cExecution is King!\u201d?<\/p>\n\n\n\n<p>At least the process has moved forward, nonetheless is this going to be both fun and challenging as the parts arrive, since I know we are going to face obstacles while implementing them and test software with sensors, actuators and motors. I have created a temporary BOM (Bill of materials) for many of the parts I know we are going to use, with comments on what we have acquired, what we have in order and what I will ask Henning for. I will send it to our blogmaster with this post and he will decide how to share the document in the blog.<\/p>\n\n\n\n<div class=\"wp-block-media-text has-media-on-the-right is-stacked-on-mobile\"><div class=\"wp-block-media-text__content\">\n<p>I still have not found these speed encoder wheels for sale other than included in expensive packages, so I will investigate if they are crucial parts we need.<\/p>\n<\/div><figure class=\"wp-block-media-text__media\"><img loading=\"lazy\" decoding=\"async\" width=\"125\" height=\"129\" src=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-42.png\" alt=\"\" class=\"wp-image-11247 size-full\" \/><\/figure><\/div>\n\n\n\n<p>In the part list I included a really simple diagram, without the Arduino and specific sensors we will use, since there will be changes shortly when we switch from micro:bit to Arduino.<\/p>\n\n\n\n<p>One C-prioritized option we are working on is a robotic arm, with DC motor powered drillbit and laser rangefinder on the same disc, with 180 degrees rotation by servo. But before we get deeper into the core functionality of the car, this is slightly on hold. But I can say that the idea is, if we can find a way to map underground either via <strong>GPR (Ground penetrating Radar)<\/strong> or <strong>Electrical resistivity tomography<\/strong>&nbsp;(<strong>ERT<\/strong>) or&nbsp;<strong>electrical resistivity imaging<\/strong>&nbsp;(<strong>ERI<\/strong>).I\u2019m unsure about seismoacoustic mapping underground, need more research from my side. I read early in this course an article that used seismoacoustic mapping, and found somewhere a picture that visualize a method to test this in practice. I\u2019m afraid I do not follow practice right now, since I cannot site the article, and \u201csteal\u201d a drawing without creditating the person that made it. Anyway, this is a picture of a model that can be used put the car on and check for cavities.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"192\" height=\"164\" src=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image.gif\" alt=\"\" class=\"wp-image-11246\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Henning<\/h2>\n\n\n\n<p>These last weeks i have been struggling with the same issues as the past! As i have been working with the end side of the project and a new programming language. It has really been a wall to climb. So from my past weeks i have had issues with figuring out how to access OpenAI API keys. In the meantime i have constructed more windows and labels for the data which our sensors will show. <\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"677\" height=\"487\" src=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-44.png\" alt=\"\" class=\"wp-image-11249\" srcset=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-44.png 677w, https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-44-300x216.png 300w\" sizes=\"auto, (max-width: 677px) 100vw, 677px\" \/><\/figure>\n\n\n\n<p>Now for the AI which im trying to make work with the GUI! I have figured out how to access the AI through <a href=\"https:\/\/platform.openai.com\/chat\">https:\/\/platform.openai.com\/chat<\/a>. All i needed to do was to make an account and create a project through OpenAI. My next goal will be to figure out how to extract the API key and connect it to my code. If i get this up, i will reach a solid end to our project as i can start training the AI to function with our goal.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"402\" src=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-45-1024x402.png\" alt=\"\" class=\"wp-image-11250\" srcset=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-45-1024x402.png 1024w, https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-45-300x118.png 300w, https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-45-768x301.png 768w, https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-45-1536x603.png 1536w, https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-45.png 1893w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The picture above shows the website of the project i have created so far and the AI itself. This is all through the website and not through the GUI which i`m trying to solve. I am hoping for a result in the next weeks to come.<\/p>\n\n\n\n<p>Unfortunately because of the issues with the code that i currently have, i cannot build the GUI and i can`t show any result of the sensors button yet. Once everything is up and running, i will be able to provide more videos and pictures.  <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Oskaras<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>The Week Before Last<\/strong><\/h3>\n\n\n\n<p>This week, we installed Zephyr and managed to communicate with the micro:bit. Then I tried to communicate with the extension board on the car. Here is the code:<\/p>\n\n\n\n<p><strong>C Code (<code>main.c<\/code>):<\/strong><\/p>\n\n\n\n<p>C<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#include &lt;zephyr\/kernel.h&gt;\n#include &lt;zephyr\/device.h&gt;\n#include &lt;zephyr\/drivers\/pwm.h&gt;\n\nstatic const struct pwm_dt_spec motor1 = PWM_DT_SPEC_GET(DT_ALIAS(motor-m1));\n\n#define PERIOD_USEC (20 * 1000) \n#define DUTY_CYCLE_MAX PERIOD_USEC\n\nvoid main(void)\n{\n    if (!pwm_is_ready_dt(&amp;motor1)) {\n        printk(\"Error: PWM device %s is not ready\\\\n\", motor1.dev-&gt;name);\n        return;\n    }\n\n    printk(\"I2C Motor control starting...\\\\n\");\n\n    \/* Run motor forward at 75% speed for 3 seconds *\/\n    printk(\"Spinning M1 forward at 75%%...\\\\n\");\n\n    uint32_t pulse_width = (DUTY_CYCLE_MAX * 75) \/ 100;\n    pwm_set_pulse_dt(&amp;motor1, pulse_width);\n\n    k_sleep(K_SECONDS(3));\n\n    \/* Stop the motor *\/\n    printk(\"Stopping M1.\\\\n\");\n    pwm_set_pulse_dt(&amp;motor1, 0);\n}\n<\/code><\/pre>\n\n\n\n<p><strong>Project Configuration (<code>prj.conf<\/code>):<\/strong><\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CONFIG_PRINTK=y\nCONFIG_I2C=y\nCONFIG_PWM=y\nCONFIG_PWM_PCA9685=y\n<\/code><\/pre>\n\n\n\n<p><strong>Device Tree Overlay (<code>app.overlay<\/code>):<\/strong><\/p>\n\n\n\n<p>Kodebit<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/ {\n    \/* Create aliases for our two motors *\/\n    aliases {\n        motor-m1 = &amp;motor_m1;\n        motor-m2 = &amp;motor_m2;\n    };\n\n    \/* Define the motors. They are connected to the PCA9685, not the micro:bit directly. *\/\n    motor_m1: motor_m1 {\n        compatible = \"pwm-motor\";\n        pwms = &lt;&amp;pca9685 0 0&gt;, \/* Motor M1 uses channel 0 (AIN1) and 1 (AIN2) of the PCA9685 *\/\n               &lt;&amp;pca9685 1 0&gt;;\n        label = \"MOTOR_M1\";\n    };\n    motor_m2: motor_m2 {\n        compatible = \"pwm-motor\";\n        pwms = &lt;&amp;pca9685 2 0&gt;, \/* Motor M2 uses channel 2 (BIN1) and 3 (BIN2) of the PCA9685 *\/\n               &lt;&amp;pca9685 3 0&gt;;\n        label = \"MOTOR_M2\";\n    };\n};\n\n&amp;i2c0 {\n    status = \"okay\";\n\n    pca9685: pwm-controller@40 {\n        compatible = \"nxp,pca9685-pwm\";\n        reg = &lt;0x70&gt;; \n        label = \"PCA9685\";\n    };\n};\n<\/code><\/pre>\n\n\n\n<p>After a lot of troubleshooting, Zephyr would not cooperate properly, so I hit a wall there that I couldn&#8217;t get past. Furthermore, this was the week of the Network and Security exam, so unfortunately, I had to dedicate a good deal of time to that as well.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Last Week:<\/strong><\/h3>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"418\" src=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-46-1024x418.png\" alt=\"\" class=\"wp-image-11252\" srcset=\"https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-46-1024x418.png 1024w, https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-46-300x122.png 300w, https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-46-768x313.png 768w, https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-46-1536x627.png 1536w, https:\/\/dronesonen.usn.no\/wp-content\/uploads\/2025\/10\/image-46.png 1865w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>I mostly worked on the layout for the presentation and reworked some of the tables to make them more presentable. I also started on an &#8220;ABC form&#8221; for the project, because I felt it might work quite well to represent the goals:<\/p>\n\n\n\n<p><strong>A:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Identify motor controls<\/li>\n\n\n\n<li>Get the car to move forward, backward, and to the sides<\/li>\n\n\n\n<li>Get the sensors to work<\/li>\n\n\n\n<li>Capture an image and make it available for the micro:bit<\/li>\n<\/ul>\n\n\n\n<p><strong>B:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Make it so that the car responds to obstacles and stops or performs a predetermined action<\/li>\n\n\n\n<li>Adjust the behavior of the car based on the image from the camera<\/li>\n<\/ul>\n\n\n\n<p><strong>C:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Implement AI to map out an optimal route<\/li>\n<\/ul>\n\n\n\n<p>As we saw from the presentation, I got more inspiration and thought that what the others had done was very well-structured and easy to follow, so I am going to work on elaborating on this a bit more, while at the same time continuing with the Scrum methodology I have already started.<\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Wang This week there hasn\u2019t been much focus on the project due to account exams. The code logic to get the car to start driving is well underway together with the distance sensor. The car hasn\u2019t been able to drive yet using Zephyr, but it does run with Ada code and the distance sensor used [&hellip;]<\/p>\n","protected":false},"author":117,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-11112","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/dronesonen.usn.no\/index.php?rest_route=\/wp\/v2\/posts\/11112","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/dronesonen.usn.no\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/dronesonen.usn.no\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/dronesonen.usn.no\/index.php?rest_route=\/wp\/v2\/users\/117"}],"replies":[{"embeddable":true,"href":"https:\/\/dronesonen.usn.no\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=11112"}],"version-history":[{"count":5,"href":"https:\/\/dronesonen.usn.no\/index.php?rest_route=\/wp\/v2\/posts\/11112\/revisions"}],"predecessor-version":[{"id":11254,"href":"https:\/\/dronesonen.usn.no\/index.php?rest_route=\/wp\/v2\/posts\/11112\/revisions\/11254"}],"wp:attachment":[{"href":"https:\/\/dronesonen.usn.no\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=11112"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/dronesonen.usn.no\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=11112"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/dronesonen.usn.no\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=11112"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}