This commit is contained in:
Your Name
2026-05-27 20:02:30 +03:00
commit 0056c84c4c
58 changed files with 65602 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
build
tmp
.vscode
+3
View File
@@ -0,0 +1,3 @@
[submodule "Firmware/main_app"]
path = Firmware/main_app
url = https://git.aintmina.org/aintgit/chill.git
+26
View File
@@ -0,0 +1,26 @@
# nRF52840 Dongle NRF52840 board configuration
# Copyright (c) 2018-2023 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
if BOARD_NRF52840_QALMARI
config BOARD_ENABLE_DCDC
bool "DCDC mode"
select SOC_DCDC_NRF52X
default n
config BOARD_ENABLE_DCDC_HV
bool "High Voltage DCDC converter"
select SOC_DCDC_NRF52X_HV
default n
config BOARD_HAS_NRF5_BOOTLOADER
bool "Board has nRF5 bootloader"
default n
help
If selected, applications are linked so that they can be loaded by Nordic
nRF5 bootloader.
endif # BOARD_NRF52840_QALMARI
+16
View File
@@ -0,0 +1,16 @@
# nRF52840 Dongle NRF52840 board configuration
#
# Copyright (c) 2018-2023 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: Apache-2.0
if BOARD_NRF52840_QALMARI
config BOARD
default "nrf52840_qalmari"
config FLASH_LOAD_OFFSET
default 0x12000
depends on BOARD_HAS_NRF5_BOOTLOADER && (MCUBOOT || !USE_DT_CODE_PARTITION)
endif # BOARD_NRF52840_QALMARI
@@ -0,0 +1,7 @@
# nRF52840 Dongle NRF52840 board configuration
# Copyright (c) 2018 Nordic Semiconductor ASA
# SPDX-License-Identifier: Apache-2.0
config BOARD_NRF52840_QALMARI
select SOC_NRF52840_QIAA
+9
View File
@@ -0,0 +1,9 @@
# SPDX-License-Identifier: Apache-2.0
board_runner_args(jlink "--device=nRF52840_xxAA" "--speed=4000")
board_runner_args(pyocd "--target=nrf52840" "--frequency=4000000")
include(${ZEPHYR_BASE}/boards/common/nrfjprog.board.cmake)
include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake)
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)
include(${ZEPHYR_BASE}/boards/common/openocd-nrf5.board.cmake)
+6
View File
@@ -0,0 +1,6 @@
board:
name: nrf52840_qalmari
full_name: nRF52840 Qalmari
vendor: qalmari
socs:
- name: nrf52840
+34
View File
@@ -0,0 +1,34 @@
/*
* Copyright (c) 2019 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/* Flash partition table without support for Nordic nRF5 bootloader */
&flash0 {
partitions {
compatible = "fixed-partitions";
#address-cells = <1>;
#size-cells = <1>;
boot_partition: partition@0 {
label = "mcuboot";
reg = <0x00000000 0x00014000>;
};
slot0_partition: partition@14000 {
label = "image-0";
reg = <0x00014000 0x00074000>;
};
slot1_partition: partition@88000 {
label = "image-1";
reg = <0x00088000 0x00074000>;
};
storage_partition: partition@fc000 {
label = "storage";
reg = <0x000fc000 0x00004000>;
};
};
};
@@ -0,0 +1,153 @@
/*
* Copyright (c) 2022 Nordic Semiconductor
* SPDX-License-Identifier: Apache-2.0
*/
&pinctrl {
uart0_default: uart0_default {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 17)>;
};
group2 {
psels = <NRF_PSEL(UART_RX, 0, 15)>;
bias-pull-up;
};
};
uart0_sleep: uart0_sleep {
group1 {
psels = <NRF_PSEL(UART_TX, 0, 16)>,
<NRF_PSEL(UART_RX, 0, 24)>,
<NRF_PSEL(UART_RTS, 0, 14)>,
<NRF_PSEL(UART_CTS, 0, 22)>;
low-power-enable;
};
};
i2c0_default: i2c0_default {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 0, 21)>, <NRF_PSEL(TWIM_SCL, 0, 19)>;
};
};
i2c0_sleep: i2c0_sleep {
group1 {
psels = <NRF_PSEL(TWIM_SDA, 0, 21)>, <NRF_PSEL(TWIM_SCL, 0, 19)>;
low-power-enable;
};
};
i2c1_default: i2c1_default {
group1 {
psels = <NRF_PSEL(TWIM_SCL, 0, 19)>, <NRF_PSEL(TWIM_SDA, 0, 21)>;
};
};
i2c1_sleep: i2c1_sleep {
group1 {
psels = <NRF_PSEL(TWIM_SCL, 0, 19)>, <NRF_PSEL(TWIM_SDA, 0, 21)>;
low-power-enable;
};
};
i2s0_default: i2s0_default {
group1 {
psels = <NRF_PSEL(I2S_SCK_M, 1, 11)>,
<NRF_PSEL(I2S_LRCK_M, 1, 12)>,
<NRF_PSEL(I2S_SDOUT, 0, 25)>,
<NRF_PSEL(I2S_SDIN, 1, 14)>;
};
};
pwm0_default: pwm0_default {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 0, 13)>,
<NRF_PSEL(PWM_OUT1, 0, 6)>;
};
};
pwm0_sleep: pwm0_sleep {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 0, 13)>,
<NRF_PSEL(PWM_OUT1, 0, 6)>;
low-power-enable;
};
};
pwm1_leds_default: pwm1_leds_default {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 0, 30)>,
<NRF_PSEL(PWM_OUT1, 0, 8)>,
<NRF_PSEL(PWM_OUT2, 0, 20)>,
<NRF_PSEL(PWM_OUT3, 1, 15)>;
nordic,invert;
};
};
pwm1_leds_sleep: pwm1_leds_sleep {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 0, 30)>,
<NRF_PSEL(PWM_OUT1, 0, 8)>,
<NRF_PSEL(PWM_OUT2, 0, 20)>,
<NRF_PSEL(PWM_OUT3, 1, 15)>;
nordic,invert;
low-power-enable;
};
};
pwm2_leds_default: pwm2_leds_default {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 1, 13)>,
<NRF_PSEL(PWM_OUT1, 1, 10)>,
<NRF_PSEL(PWM_OUT2, 0, 29)>,
<NRF_PSEL(PWM_OUT3, 0, 31)>;
nordic,invert;
};
};
pwm2_leds_sleep: pwm2_leds_sleep {
group1 {
psels = <NRF_PSEL(PWM_OUT0, 1, 13)>,
<NRF_PSEL(PWM_OUT1, 1, 10)>,
<NRF_PSEL(PWM_OUT2, 0, 29)>,
<NRF_PSEL(PWM_OUT3, 0, 31)>;
nordic,invert;
low-power-enable;
};
};
spi0_default: spi0_default {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 0, 27)>,
<NRF_PSEL(SPIM_MOSI, 0, 25)>,
<NRF_PSEL(SPIM_MISO, 1, 10)>;
};
};
spi0_sleep: spi0_sleep {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 0, 27)>,
<NRF_PSEL(SPIM_MOSI, 0, 25)>,
<NRF_PSEL(SPIM_MISO, 1, 10)>;
low-power-enable;
};
};
spi1_default: spi1_default {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 0, 31)>,
<NRF_PSEL(SPIM_MOSI, 0, 30)>,
<NRF_PSEL(SPIM_MISO, 1, 13)>;
};
};
spi1_sleep: spi1_sleep {
group1 {
psels = <NRF_PSEL(SPIM_SCK, 0, 31)>,
<NRF_PSEL(SPIM_MOSI, 0, 30)>,
<NRF_PSEL(SPIM_MISO, 1, 13)>;
low-power-enable;
};
};
};
@@ -0,0 +1,357 @@
/*
* Copyright (c) 2018-2023 Nordic Semiconductor ASA
* Copyright (c) 2017 Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
/dts-v1/;
#include <nordic/nrf52840_qiaa.dtsi>
#include "nrf52840_qalmari-pinctrl.dtsi"
#include <zephyr/dt-bindings/input/input-event-codes.h>
#include <zephyr/dt-bindings/led/led.h>
#include "fstab.dtsi"
/ {
model = "Nordic NRF52840 QALMARI";
compatible = "nordic,nrf52840-qalmari";
chosen {
zephyr,console = &cdc_acm_uart;
zephyr,shell-uart = &cdc_acm_uart;
zephyr,uart-mcumgr = &cdc_acm_uart;
zephyr,bt-mon-uart = &cdc_acm_uart;
zephyr,bt-c2h-uart = &cdc_acm_uart;
zephyr,sram = &sram0;
zephyr,flash = &flash0;
zephyr,code-partition = &slot0_partition;
zephyr,ieee802154 = &ieee802154;
};
leds {
compatible = "gpio-leds";
led1: led_1 {
gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
label = "LED 1";
status = "okay";
};
led2: led_2 {
gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
label = "LED 2";
status = "okay";
};
led3: led_3 {
gpios = <&gpio0 20 GPIO_ACTIVE_LOW>;
label = "LED 3";
status = "okay";
};
led4: led_4 {
gpios = <&gpio1 15 GPIO_ACTIVE_LOW>;
label = "LED 4";
status = "okay";
};
led5: led_5 {
gpios = <&gpio1 13 GPIO_ACTIVE_LOW>;
label = "LED 5";
status = "okay";
};
led6: led_6 {
gpios = <&gpio1 10 GPIO_ACTIVE_LOW>;
label = "LED 6";
status = "okay";
};
led7: led_7 {
gpios = <&gpio0 29 GPIO_ACTIVE_LOW>;
label = "LED 7";
status = "okay";
};
led8: led_8 {
gpios = <&gpio0 31 GPIO_ACTIVE_LOW>;
label = "LED 8";
status = "okay";
};
};
pwmleds {
compatible = "pwm-leds";
pwm_led1: pwm_led_1 {
pwms = <&pwm1 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
label = "PWM LED 1";
};
pwm_led2: pwm_led_2 {
pwms = <&pwm1 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
label = "PWM LED 2";
};
pwm_led3: pwm_led_3 {
pwms = <&pwm1 2 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
label = "PWM LED 3";
};
pwm_led4: pwm_led_4 {
pwms = <&pwm1 3 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
label = "PWM LED 4";
};
pwm_led5: pwm_led_5 {
pwms = <&pwm2 0 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
label = "PWM LED 5";
};
pwm_led6: pwm_led_6 {
pwms = <&pwm2 1 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
label = "PWM LED 6";
};
pwm_led7: pwm_led_7 {
pwms = <&pwm2 2 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
label = "PWM LED 7";
};
pwm_led8: pwm_led_8 {
pwms = <&pwm2 3 PWM_MSEC(20) PWM_POLARITY_INVERTED>;
label = "PWM LED 8";
};
};
pwm {
compatible = "pwm-leds";
pwm_vibration: pwm_vibration {
pwms = <&pwm0 0 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
label = "PWM vibration motor";
};
pwm_buzzer: pwm_buzzer {
pwms = <&pwm0 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>;
label = "PWM buzzer";
};
};
buttons {
compatible = "gpio-keys";
debounce-interval-ms = <100>;
button1: button_1 {
gpios = <&gpio0 17 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Push button switch 1";
zephyr,code = <INPUT_KEY_0>;
};
button2: button_2 {
gpios = <&gpio0 15 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
label = "Push button switch 2";
zephyr,code = <INPUT_KEY_1>;
};
};
interrupts {
compatible = "gpio-keys";
interrupt_head: interrupt_head {
gpios = <&gpio0 23 (GPIO_ACTIVE_HIGH)>;
label = "head interrupt pin";
};
};
aliases {
btn1 = &button1;
btn2 = &button2;
int-head = &interrupt_head;
int-btn-1 = &button1;
int-btn-2 = &button2;
led1 = &led1;
led2 = &led2;
led3 = &led3;
led4 = &led4;
led5 = &led5;
led6 = &led6;
led7 = &led7;
led8 = &led8;
pwm-led1 = &pwm_led1;
pwm-led2 = &pwm_led2;
pwm-led3 = &pwm_led3;
pwm-led4 = &pwm_led4;
pwm-led5 = &pwm_led5;
pwm-led6 = &pwm_led6;
pwm-led7 = &pwm_led7;
pwm-led8 = &pwm_led8;
buzzer = &pwm_buzzer;
vibration = &pwm_vibration;
mcuboot-button0 = &button1;
mcuboot-button1 = &button2;
mcuboot-led0 = &led1;
watchdog0 = &wdt0;
pwm0 = &pwm0;
pwm-leds = &pwm1;
led-strip = &led_strip;
i2c-1 = &i2c1;
uart-0 = &uart0;
};
vbatt {
status = "okay";
compatible = "voltage-divider";
io-channels = <&adc 2>;
output-ohms = <100000>;
full-ohms = <(100000 + 100000)>;
//power-gpios = <&gpio0 11 GPIO_PULL_UP>;
};
};
&pwm0 {
status = "okay";
pinctrl-0 = <&pwm0_default>;
pinctrl-1 = <&pwm0_sleep>;
pinctrl-names = "default", "sleep";
};
&pwm1 {
status = "okay";
pinctrl-0 = <&pwm1_leds_default>;
pinctrl-1 = <&pwm1_leds_sleep>;
pinctrl-names = "default", "sleep";
};
&pwm2 {
status = "okay";
pinctrl-0 = <&pwm2_leds_default>;
pinctrl-1 = <&pwm2_leds_sleep>;
pinctrl-names = "default", "sleep";
};
&uart0 {
compatible = "nordic,nrf-uarte";
status = "okay";
current-speed = <115200>;
pinctrl-0 = <&uart0_default>;
pinctrl-names = "default";
};
&spi0 {
compatible = "nordic,nrf-spi";
/* Cannot be used together with i2c0. */
status = "okay";
pinctrl-0 = <&spi0_default>;
pinctrl-1 = <&spi0_sleep>;
pinctrl-names = "default", "sleep";
led_strip: ws2812-spi@0 {
compatible = "worldsemi,ws2812-spi";
reg = <0x0>;
chain-length = <2>;
color-mapping = <LED_COLOR_ID_GREEN
LED_COLOR_ID_RED
LED_COLOR_ID_BLUE>;
spi-one-frame = <0x70>;
spi-zero-frame = <0x40>;
spi-max-frequency = <4000000>;
};
};
&spi1 {
compatible = "nordic,nrf-spi";
//status = "okay";
status = "disabled";
pinctrl-0 = <&spi1_default>;
pinctrl-1 = <&spi1_sleep>;
pinctrl-names = "default", "sleep";
};
&i2c0 {
/* Cannot be used together with spi0. */
status = "disabled";
pinctrl-0 = <&i2c0_default>;
pinctrl-names = "default";
clock-frequency = <I2C_BITRATE_STANDARD>;
};
&i2c1 {
status = "okay";
pinctrl-0 = <&i2c1_default>;
pinctrl-names = "default";
clock-frequency = <I2C_BITRATE_STANDARD>;
};
zephyr_udc0: &usbd {
compatible = "nordic,nrf-usbd";
status = "okay";
cdc_acm_uart: cdc_acm_uart {
compatible = "zephyr,cdc-acm-uart";
};
};
&ieee802154 {
status = "okay";
};
&adc {
status = "okay";
};
&gpiote {
status = "okay";
};
&uicr {
nfct-pins-as-gpios;
gpio-as-nreset;
};
&gpio0 {
status = "okay";
};
&gpio1 {
status = "okay";
};
&systick {
status = "disabled";
};
&nfct {
status = "disabled";
};
&egu0 {
status = "okay";
};
&ccm {
status = "okay";
};
&cryptocell {
status = "okay";
};
&ecb {
status = "okay";
};
&rng {
status = "okay";
};
&ppi {
status = "okay";
};
&clock {
status = "okay";
};
// RTC0 is not okay anymore! v.4.3.99
// &rtc0 {
// status = "okay";
// };
&mwu {
status = "okay";
};
&power {
status = "okay";
};
&acl {
status = "okay";
};
// ITM is used for printf debugging and tracing on the SWO pin
&itm {
status = "okay";
};
@@ -0,0 +1,22 @@
identifier: nrf52840_qalmari
name: NRF52840-QALMARI
type: mcu
arch: arm
ram: 256
flash: 1024
toolchain:
- zephyr
- gnuarmemb
- xtools
supported:
- adc
- usb_device
- usb_cdc
- ble
- pwm
- spi
- watchdog
- counter
- netif:openthread
- gpio
vendor: qalmari
@@ -0,0 +1,22 @@
# SPDX-License-Identifier: Apache-2.0
# CONFIG_SOC_SERIES_NRF52X=y
# CONFIG_SOC_NRF52840_QIAA=y
# CONFIG_BOARD_NRF52840_QALMARI=y
# Disable DCDC converter
CONFIG_BOARD_ENABLE_DCDC=n
CONFIG_BOARD_ENABLE_DCDC_HV=n
# 32K clock
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC=y
CONFIG_CLOCK_CONTROL_NRF_K32SRC_RC_CALIBRATION=y
# Enable MPU
CONFIG_ARM_MPU=y
# enable GPIO
CONFIG_GPIO=y
# Enable Zephyr application to be booted by MCUboot
# CONFIG_BOOTLOADER_MCUBOOT=y
@@ -0,0 +1,7 @@
# Copyright (c) 2022 Nordic Semiconductor
# SPDX-License-Identifier: Apache-2.0
# Suppress "unique_unit_address_if_enabled" to handle the following overlaps:
# - power@40000000 & clock@40000000 & bprot@40000000
# - acl@4001e000 & flash-controller@4001e000
list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled")
+1
Submodule Firmware/main_app added at 26f3e99d8a
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
https://jlcpcb.com/blog/Flex-PCB-Designing-Useful-Tips---JLCPCB
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+12007
View File
File diff suppressed because it is too large Load Diff
+5826
View File
File diff suppressed because it is too large Load Diff
+16167
View File
File diff suppressed because it is too large Load Diff
+159
View File
@@ -0,0 +1,159 @@
# SulaJalmari
nRF 52840 -pohjainen pöytälelu/opetustyökalu.
## Table of Contents
- [Intro](#intro)
- [Ominaisuudet](#ominaisuudet)
- [Vaatimukset](#vaatimukset)
- [Käyttö](#käyttö)
- [Ohjelmointi](#ohjelmointi)
- [Resurssit](#resurssit)
## Intro
### SulaJalmari on nRF52840-pohjainen opetustyökalu ja pöytälelu, joka on suunniteltu tarjoamaan käytännönläheistä oppimiskokemusta sulautetuista järjestelmistä ja IoT-teknologioista.
<img src="pics/Device.jpg" height=600>
## Ominaisuudet
### Hardware:
- 2x RGB LED (silmät)
- 8x sininen LED (jalat)
- Kiihtyvyysanturi
- Tärinämoottori
- Piippari
- Bluetooth
- USB-C
### Software:
- Bootloader
- Valmiita demo-koodeja
- Ohjelmoitavissa USB:n yli
## Vaatimukset
### Demot
Demojen ohjelmoimiseen tarvitset nRF Connect for Desktop -ohjelmointityökalun ja tästä Git-reposta löytyvien demokoodien app_signed.hex-tiedostot. Tämän jälkeen siirry kohtaan: [Ohjelmointi](#ohjelmointi)
### Kehitys
Kehitystä varten tarvitset vähintään nRF Connect SDK:n ja tästä Git-reposta löytyvät "Board"-kansion tiedostot sekä pjr.conf-tiedoston. Suositeltavaa on kuitenkin aloittaa valmiista demokoodista, jossa tulee mukana kaikki tarpeelliset tiedostot ja kyseiseen demoon räätälöity pjr.conf-tiedosto. Parhaiten pääset alkuun asentamalla "nRF Connect for VS Code" -lisäosan Visual Studio Codeen. nRF Connect for VS Code -lisäosasta pääset asentamaan vaatimukset.
![Manage SDK](pics/Manage.png)
<br>
Tarvitset toolchainin sekä SDK:n.
<br>
![Install SDK](pics/Install.png)
<br>
Valitse Install SDK/Toolchain -valikosta, ja valitse sen jälkeen versio, jonka haluat asentaa. Tämän hetkinen versio on rakennettu ja todettu toimivaksi version 2.6.1 kanssa.
<br>
![SDKVER](pics/SDKVER.png)
<br>
## Käyttö
### Aloitus
Toolchainin sekä SDK:n asentamisen jälkeen voit avata valmiin demokoodin nRF Connect for VS Code -lisäosasta.
![Open](pics/OpenExisting.png)
Sovelluksen valinnan jälkeen voit aloittaa ohjelmoinnin src-kansiosta löytyvien tiedostojen avulla.
![Files](pics/ProjectView.png)
### Valmiin sovelluksen ohjelmointi laitteelle
#### Build Configuration
Build configuration vaaditaan sovelluksen build-vaihetta varten. Build configurationin voi luoda nRF Connect -lisäosan "Applications" tai "Build Configuration" -osiosta painamalla "Add Build Configuration". Mikäli "Applications"-osiossa näkyy valmis build configuration, tai projektissa on valmiiksi olemassa "Build"-kansio etkä ole itse niitä lisännyt, poista build configuration ja kansio ennen uuden lisäämistä. Toisella laitteella lisätyt build configurationit eivät välttämättä toimi laitteellasi.
Jos noudatit kehitysvaiheen ohjeita, "Add Build Configuration" -ikkunassa painaessasi "Custom Board" -valintaa, listasta löytyy laitteelle valmiiksi luotu board-tiedosto "nrf52840_qalmari".
![Build](pics/Build.png)
Painamalla "Build Configuration" -painiketta lisäät build configurationin projektiisi. Tämän jälkeen sen tulisi löytyä "Applications" -ikkunasta nRF Connect -lisäosasta.
#### Build
Jos et käyttänyt valmista demokoodia ohjelmoinnin pohjana, varmista pjr.conf-tiedoston sisältö. Laitteen bootloader vaatii ohjelmoidessaan tietyn tunnisteen, jonka Zephyr kirjoittaa app_signed.hex-tiedostoon automaattisesti vain, jos pjr.conf-tiedostosta löytyy rivi:
```
CONFIG_BOOTLOADER_MCUBOOT=y
```
Ilman tätä riviä Zephyr ei luo app_signed.hex-tiedostoa, eikä laitetta voi ohjelmoida USB:n yli.
Varmista myös että projektin sisältä lyötyy "child_image" kansio, mikäli kansiota ei löydy, luo se itse ja lisää sen sisälle "mcuboot.conf" niminen tiedosto, ja kirjoita sen sisälle rivi:
```
CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x12000
```
![Build](pics/child_image.png)
Tämän jälkeen voit käyttää lisäosan "Actions"-osion "Build" -valintaa, jonka jälkeen projektikansion polkuun luodaan tarvittava .hex-tiedosto:
```
main_project/build/zephyr/app_signed.hex
```
### Ohjelmointi
Ohjelmointi tapahtuu nRF Connect for Desktop -sovelluksessa, josta valitaan "Programmer" (Programmer täytyy asentaa erikseen ennen sen käyttämistä painamalla "Install" "Open"-painikkeen tilalla).
![DesktopStart](pics/Connect_start.png)
Programmer aukeaa erilliseen ikkunaan, josta vasemmassa yläkulmassa olevasta painikkeesta "SELECT DEVICE" aukeaa lista käytettävissä olevista USB-laitteista. Näistä valitaan MCUBOOT.
![Select](pics/programmer_not_chosen.png)
Laitteen valinnan jälkeen aukeaa uusi ikkuna, josta löytyy lista vaihtoehtoja. Tämän jälkeen voit navigoida app_signed.hex-tiedostoon painamalla "Add File" -painiketta. Vaihtoehtoisesti tiedoston voi vetää ja pudottaa "File Memory Layout" -kenttään.
![Selected](pics/programmer_chosen.png)
Kun tiedosto on lisätty ohjelmointityökaluun, vihreä alue ilmestyy "File Memory Layout" -kenttään visualisoimaan sovelluksen aloitusosoitetta ja sovelluksen kokoa verrattuna käytettävissä olevaan muistiin.
![Hex](pics/programmer_hex.png)
Tämän jälkeen on mahdollista ohjelmoida laite painamalla "Write" -painiketta.
![Program](pics/programmer_program.png)
Uudessa ikkunassa voit painaa taas "Write".
Jos laite ohjelmoitiin onnistuneesti, oranssin kentän tilalle ilmestyy vihreä kenttä, jossa lukee "Completed successfully in X seconds."
## Resurssit
Tästä osiosta löydät tarvittavat kehittämiseen.
Suositellut nRF lisäosat VS Codeen (nRF Terminal vanhentunut): <br>
![Ext](pics/ext.png)
- nRF Connect for Desktop:
https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop
- nRF Command Line Tools:
https://www.nordicsemi.com/Products/Development-tools/nRF-Command-Line-Tools/Download?lang=en#infotabs
- Kconfig-komennot (pjr.conf):
https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/kconfig/ (Offline 18/6/2024) <br>
https://docs.zephyrproject.org/latest/kconfig.html (Backup)
- Dokumentaatiot:
https://docs.nordicsemi.com/category/nrf52840-category (nRF52840) <br>
https://invensense.tdk.com/wp-content/uploads/2016/10/DS-000176-ICM-20602-v1.0.pdf (ICM-20602 kiihtyvyysanturi) <br>
https://docs.zephyrproject.org/latest/index.html (Zephyr project) <br>
- EasyEDA:
Projektin kytkentäkaaviot sekä linkki projektin EasyEDA sivulle löytyy tämän Git-repon kansiosta Hardware/Prototype2
+159
View File
@@ -0,0 +1,159 @@
# SulaJalmari
nRF 52840 -pohjainen pöytälelu/opetustyökalu.
## Table of Contents
- [Intro](#intro)
- [Ominaisuudet](#ominaisuudet)
- [Vaatimukset](#vaatimukset)
- [Käyttö](#käyttö)
- [Ohjelmointi](#ohjelmointi)
- [Resurssit](#resurssit)
## Intro
### SulaJalmari on nRF52840-pohjainen opetustyökalu ja pöytälelu, joka on suunniteltu tarjoamaan käytännönläheistä oppimiskokemusta sulautetuista järjestelmistä ja IoT-teknologioista.
<img src="pics/Device.jpg" height=600>
## Ominaisuudet
### Hardware:
- 2x RGB LED (silmät)
- 8x sininen LED (jalat)
- Kiihtyvyysanturi
- Tärinämoottori
- Piippari
- Bluetooth
- USB-C
### Software:
- Bootloader
- Valmiita demo-koodeja
- Ohjelmoitavissa USB:n yli
## Vaatimukset
### Demot
Demojen ohjelmoimiseen tarvitset nRF Connect for Desktop -ohjelmointityökalun ja tästä Git-reposta löytyvien demokoodien app_signed.hex-tiedostot. Tämän jälkeen siirry kohtaan: [Ohjelmointi](#ohjelmointi)
### Kehitys
Kehitystä varten tarvitset vähintään nRF Connect SDK:n ja tästä Git-reposta löytyvät "Board"-kansion tiedostot sekä pjr.conf-tiedoston. Suositeltavaa on kuitenkin aloittaa valmiista demokoodista, jossa tulee mukana kaikki tarpeelliset tiedostot ja kyseiseen demoon räätälöity pjr.conf-tiedosto. Parhaiten pääset alkuun asentamalla "nRF Connect for VS Code" -lisäosan Visual Studio Codeen. nRF Connect for VS Code -lisäosasta pääset asentamaan vaatimukset.
![Manage SDK](pics/Manage.png)
<br>
Tarvitset toolchainin sekä SDK:n.
<br>
![Install SDK](pics/Install.png)
<br>
Valitse Install SDK/Toolchain -valikosta, ja valitse sen jälkeen versio, jonka haluat asentaa. Tämän hetkinen versio on rakennettu ja todettu toimivaksi version 2.6.1 kanssa.
<br>
![SDKVER](pics/SDKVER.png)
<br>
## Käyttö
### Aloitus
Toolchainin sekä SDK:n asentamisen jälkeen voit avata valmiin demokoodin nRF Connect for VS Code -lisäosasta.
![Open](pics/OpenExisting.png)
Sovelluksen valinnan jälkeen voit aloittaa ohjelmoinnin src-kansiosta löytyvien tiedostojen avulla.
![Files](pics/ProjectView.png)
### Valmiin sovelluksen ohjelmointi laitteelle
#### Build Configuration
Build configuration vaaditaan sovelluksen build-vaihetta varten. Build configurationin voi luoda nRF Connect -lisäosan "Applications" tai "Build Configuration" -osiosta painamalla "Add Build Configuration". Mikäli "Applications"-osiossa näkyy valmis build configuration, tai projektissa on valmiiksi olemassa "Build"-kansio etkä ole itse niitä lisännyt, poista build configuration ja kansio ennen uuden lisäämistä. Toisella laitteella lisätyt build configurationit eivät välttämättä toimi laitteellasi.
Jos noudatit kehitysvaiheen ohjeita, "Add Build Configuration" -ikkunassa painaessasi "Custom Board" -valintaa, listasta löytyy laitteelle valmiiksi luotu board-tiedosto "nrf52840_qalmari".
![Build](pics/Build.png)
Painamalla "Build Configuration" -painiketta lisäät build configurationin projektiisi. Tämän jälkeen sen tulisi löytyä "Applications" -ikkunasta nRF Connect -lisäosasta.
#### Build
Jos et käyttänyt valmista demokoodia ohjelmoinnin pohjana, varmista pjr.conf-tiedoston sisältö. Laitteen bootloader vaatii ohjelmoidessaan tietyn tunnisteen, jonka Zephyr kirjoittaa app_signed.hex-tiedostoon automaattisesti vain, jos pjr.conf-tiedostosta löytyy rivi:
```
CONFIG_BOOTLOADER_MCUBOOT=y
```
Ilman tätä riviä Zephyr ei luo app_signed.hex-tiedostoa, eikä laitetta voi ohjelmoida USB:n yli.
Varmista myös että projektin sisältä lyötyy "child_image" kansio, mikäli kansiota ei löydy, luo se itse ja lisää sen sisälle "mcuboot.conf" niminen tiedosto, ja kirjoita sen sisälle rivi:
```
CONFIG_PM_PARTITION_SIZE_MCUBOOT=0x12000
```
![Build](pics/child_image.png)
Tämän jälkeen voit käyttää lisäosan "Actions"-osion "Build" -valintaa, jonka jälkeen projektikansion polkuun luodaan tarvittava .hex-tiedosto:
```
main_project/build/zephyr/app_signed.hex
```
### Ohjelmointi
Ohjelmointi tapahtuu nRF Connect for Desktop -sovelluksessa, josta valitaan "Programmer" (Programmer täytyy asentaa erikseen ennen sen käyttämistä painamalla "Install" "Open"-painikkeen tilalla).
![DesktopStart](pics/Connect_start.png)
Programmer aukeaa erilliseen ikkunaan, josta vasemmassa yläkulmassa olevasta painikkeesta "SELECT DEVICE" aukeaa lista käytettävissä olevista USB-laitteista. Näistä valitaan MCUBOOT.
![Select](pics/programmer_not_chosen.png)
Laitteen valinnan jälkeen aukeaa uusi ikkuna, josta löytyy lista vaihtoehtoja. Tämän jälkeen voit navigoida app_signed.hex-tiedostoon painamalla "Add File" -painiketta. Vaihtoehtoisesti tiedoston voi vetää ja pudottaa "File Memory Layout" -kenttään.
![Selected](pics/programmer_chosen.png)
Kun tiedosto on lisätty ohjelmointityökaluun, vihreä alue ilmestyy "File Memory Layout" -kenttään visualisoimaan sovelluksen aloitusosoitetta ja sovelluksen kokoa verrattuna käytettävissä olevaan muistiin.
![Hex](pics/programmer_hex.png)
Tämän jälkeen on mahdollista ohjelmoida laite painamalla "Write" -painiketta.
![Program](pics/programmer_program.png)
Uudessa ikkunassa voit painaa taas "Write".
Jos laite ohjelmoitiin onnistuneesti, oranssin kentän tilalle ilmestyy vihreä kenttä, jossa lukee "Completed successfully in X seconds."
## Resurssit
Tästä osiosta löydät tarvittavat kehittämiseen.
Suositellut nRF lisäosat VS Codeen (nRF Terminal vanhentunut): <br>
![Ext](pics/ext.png)
- nRF Connect for Desktop:
https://www.nordicsemi.com/Products/Development-tools/nRF-Connect-for-Desktop
- nRF Command Line Tools:
https://www.nordicsemi.com/Products/Development-tools/nRF-Command-Line-Tools/Download?lang=en#infotabs
- Kconfig-komennot (pjr.conf):
https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/kconfig/ (Offline 18/6/2024) <br>
https://docs.zephyrproject.org/latest/kconfig.html (Backup)
- Dokumentaatiot:
https://docs.nordicsemi.com/category/nrf52840-category (nRF52840) <br>
https://invensense.tdk.com/wp-content/uploads/2016/10/DS-000176-ICM-20602-v1.0.pdf (ICM-20602 kiihtyvyysanturi) <br>
https://docs.zephyrproject.org/latest/index.html (Zephyr project) <br>
- EasyEDA:
Projektin kytkentäkaaviot sekä linkki projektin EasyEDA sivulle löytyy tämän Git-repon kansiosta Hardware/Prototype2
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 515 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 586 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 699 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 376 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 190 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 497 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Executable
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 MiB

+118
View File
@@ -0,0 +1,118 @@
# Flex pcb octopus
## Third prototype specs
- 2x flex pcb (as octopus head and legs) and 1x FR4 pcb (as base board)
- NRF52 {nRF52840-QIAA} (soldered to the flex pcb. also has a stiffener on the other side)
- IMU {ICM-20602} (shares interrupt with light sensor)
- 8x LEDs 2mA on legs (blue) {LED0603-RD}
- 2x RGB addressable LEDs {WS2812B-2020} (as eyes)
- buzzer (with transistor)
- place for vibration motor (with transistor) (not installed in final version)
- I2C ambient light sensor {XYC-ALS21C-K1} (shares interrupt with IMU)
- battery charger 50mA {TP4054}
- USB-C
- LDO 3V3 {ME6211C22M5G-N}
- LDO 3V6 {XC6206P362MR} (for the addressable LEDs)
- 2x user buttons and 1x reset button (tactile)
- debugger pins (debugging works with ~3€ daplink debugger from aliexpress and pyocd/openocd)
- 5V rail to chain devices together
- bluetooth pcb antenna (no idea about RF, so it was minimal. just a straight track)
- on/off switch
- silkscreen sucktion cups and mouth
## prototyping
- initial idea with paper cutout (do you have any of the papers you used? would be nice to see a picture of it)
- first prototype designed while learning to make whisky sour
- had yellow flex pcb
- major problem: 5V rail connected to gnd
- found the problem by pumping current through and seeing a black line on the flex pcb
- concept worked
- second prototype had working MCU, but missing some features and mechanical problems
- switched to black flex pcb and blue base board for contrast and company colors
- debugger pins were on the flex pcb, didn't work out that well (lost contact and came loose) (moved the pins to the base board)
- Third prototype was fully working
- debugger pins moved to the base board and all the legs got 2 tracks per leg
- vibration motor not installed (too small vibrations)
## Software
- Zephyr
- first personal use of zephyr in school with nrf52840 and hated it
- all the documentation was deprecated and really hard to find info
- no experience with devicetree made it difficult
- wanted to give another chance for nrf and zephyr (hence the MCU choice, but also we wanted bluetooth)
- now liking zephyr
- one framework to rule them all (no need to learn framework for every MCU)
- gained embedded linux and devicetree experience
- custom board files uses nrf52840-dk as template
- Arduino
- modified adafruit nrf52 library to work with arduino
- added some custom examples (like IMU)
- Bootloaders
- zephyr uses MCUboot as bootloader
- arduino uses modified adafruit nrf52 bootloader for arduino
## Story
- Idea came to me when sitting on sofa after watching flex pcb videos on youtube(insert channel here)
- modelled 3 versions for shape with paper cutout and magnets (wanted magnes to pcb, but discarded it quickly because of hard to use)
- messaged friend if he wanted to help me with it and he agreed
- took a bottle of cheap whiskey with me and bought ingredients for whiskey sour(never made before)
- started designing it with easyEDA for easy of use (and this was our first custom MCU pcb project)
- why make things easy when you can challenge yourself, right?
- first prototype ordered and hand soldered by us
- problems:
- nrf52840 has 0.4mm pitch in footprint, so hard to solder (especially on flex pcb)
- 5V rail connected straight to ground via accidental via (drc was full of warning and errors, so we ignored it)
- wanted battery support, buzzer, vibration motor
- ...
- this project was related to the current company we were working for part time
- showed it to the company and they agreed to sponsor the materials and services (the PCBs and assembly was expensive)
- second prototype was complete redesign and cleaning DRC errors and warnings
- ordered assembly from JLC rather than hand soldering it (the 3 pcb boards had to be soldered by hand and was fairly tricky because of the bending of the flex pcbs and keeping them straight on the pads)
- also fixing some mistakes and adding more functionality (got feedback from the companys senior embedded developers)
- after fiddling with it with debugger, we managed to get the LED working. (didn't add a 32k clock, so had troubles configuring it and it kept crashing)
- Third batch was 10pcs (as "ready product")
- this batch worked and was ready for software integration and example codes (zephyr and arduino)
- this became a desk toy for the company, for technical and non-technical co-workers, so had to be easy to use
## Fun things
- all the PCBs assembled take the shape of an octopus, so it wobbles when shaken
- when the device wobbles and the LEDs run PWM, you can actually see with naked eye, the PWM working where the LED turns on and off (id like to see a video of it)
- the IMU is in the top of the head, meaning you can tap the whole device and it can register that as a button press (do some demo of it, or an application that responds to the orientation its tilted towards)
## Flaws
- when stress testing the devices mechanical aspect by slamming the it to the base board, eventually some of the MCU pins got detached. (rip please dont torture electronics) (what else are testers supposed to do?)
- vibration motor was mostly unnoticable
- transporting it is tricky
## point of this project
- everyone wants to know the point, but there is none
- it was made to be a project where art and engineering collide
- and to learn more about pcb design, software, device development, etc.
- so the point was mostly the journey
- and of course it looks cool. who wouldn't want one
## open source resources
- HW
- EasyEDA project
- gerber
- pick and place
- BOM
- schematics
- SW
- MCUBoot
- Arduino bootloader
- Zephyr board files and examples
- Pics
- Paper prototype
- first prototype (yellow)
- Second prototype
- "finished" product
- Eye LED test
- IMU I2C debugging with logic analyzer
- Multiple devices (looks like army)
## Thanks
- massive thanks goes to:
- to my friend, helping me empty the whiskey bottle
- the company for sponsoring my dumb project and supporting us to learn and improve as engineers
- hackaday europe 2026 for being excited about it and asking questions (if you saw me, say hi in the comments)