Compare commits
102 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
0c4a728c17 | |
|
|
d92a1d9533 | |
|
|
9325fa20c8 | |
|
|
08c47f00f8 | |
|
|
1cba00df8c | |
|
|
35bd208cc0 | |
|
|
48cfcd5d4c | |
|
|
d76b897eb2 | |
|
|
0713f8255e | |
|
|
fc089e5a33 | |
|
|
ef966cb078 | |
|
|
6f304efb57 | |
|
|
e1ae96506d | |
|
|
6cb17be451 | |
|
|
54e991294b | |
|
|
0227e54198 | |
|
|
c3c23efc95 | |
|
|
4466b677a6 | |
|
|
dcbd02ad7a | |
|
|
8467b3e347 | |
|
|
fc0add8583 | |
|
|
66cdc3ae27 | |
|
|
32bb77926f | |
|
|
4df0181d7f | |
|
|
d6fb501594 | |
|
|
76d0d0647c | |
|
|
3de42a46c2 | |
|
|
ddaaa8988d | |
|
|
b937c52bcc | |
|
|
3c2235733b | |
|
|
a3e8d5c168 | |
|
|
5fd904de9e | |
|
|
92bb171e85 | |
|
|
bd8a7a766c | |
|
|
8f89713866 | |
|
|
bf29061db6 | |
|
|
c1622bb01c | |
|
|
222ffea568 | |
|
|
a9a0626913 | |
|
|
b11f844415 | |
|
|
2e8a86bc54 | |
|
|
224adccf6b | |
|
|
9b7159d5a4 | |
|
|
bc327acc41 | |
|
|
c9b0f38576 | |
|
|
edf0fb2563 | |
|
|
537d76ef5d | |
|
|
45d011952f | |
|
|
bb25134b6c | |
|
|
9f96384aa5 | |
|
|
b543579393 | |
|
|
69cf7e9511 | |
|
|
8df7aef51b | |
|
|
f6ee0a5122 | |
|
|
6c1ff0c4df | |
|
|
3f0d5a76c6 | |
|
|
10a770de59 | |
|
|
1b0519aadf | |
|
|
e429a0874d | |
|
|
3a05c80b25 | |
|
|
5208f1370d | |
|
|
a59e8518cc | |
|
|
2a2890b675 | |
|
|
38fd3a6aac | |
|
|
c3df6565b7 | |
|
|
140d2baa24 | |
|
|
711341f362 | |
|
|
a5da0a61dd | |
|
|
b54c73edb1 | |
|
|
2418d4e218 | |
|
|
2b4890f052 | |
|
|
85d493f24a | |
|
|
f486d4c4ab | |
|
|
6cfd4b8b4d | |
|
|
0088030d66 | |
|
|
4d828b41f1 | |
|
|
95f435923f | |
|
|
33f2a15cf3 | |
|
|
c4e87a3125 | |
|
|
773027f6b0 | |
|
|
461cce7a48 | |
|
|
23b88ada83 | |
|
|
c2916662e2 | |
|
|
24087f5622 | |
|
|
95fd88e93e | |
|
|
21797d8507 | |
|
|
6dcb11ae0c | |
|
|
38d6dbe95a | |
|
|
b100a8acf7 | |
|
|
269e9e88a1 | |
|
|
8cab3eecc1 | |
|
|
6a9e4773ea | |
|
|
b836f9a2f4 | |
|
|
032ddf2cc0 | |
|
|
1067796df4 | |
|
|
6f81e84541 | |
|
|
0d3696bf93 | |
|
|
b005fd5c11 | |
|
|
6c15b7021f | |
|
|
842b204d36 | |
|
|
5ce96a662d | |
|
|
fbeaa916b9 |
|
|
@ -0,0 +1,7 @@
|
||||||
|
feat(modbus): Implement persistent and improved reconfiguration for Modbus server
|
||||||
|
|
||||||
|
This commit enhances the Modbus server's configuration handling by:
|
||||||
|
|
||||||
|
- Loading saved baudrate and unit ID settings during initialization, ensuring persistence across reboots.
|
||||||
|
- Providing improved feedback during `modbus_reconfigure`, including logging for successful changes and informing the user when a device restart is required for changes to take effect.
|
||||||
|
- Saving new configuration settings even if immediate reinitialization fails, allowing them to be applied on the next boot.
|
||||||
|
|
@ -1 +1,65 @@
|
||||||
**/build
|
**/build
|
||||||
|
|
||||||
|
# Zephyr build directories
|
||||||
|
build/
|
||||||
|
build-*/
|
||||||
|
*/build/
|
||||||
|
**/build/
|
||||||
|
|
||||||
|
# Zephyr out-of-tree build directories
|
||||||
|
out-of-tree-build/
|
||||||
|
|
||||||
|
# Files generated by the build system
|
||||||
|
zephyr.elf
|
||||||
|
zephyr.bin
|
||||||
|
zephyr.hex
|
||||||
|
zephyr.map
|
||||||
|
zephyr.strip
|
||||||
|
zephyr.lst
|
||||||
|
zephyr.asm
|
||||||
|
zephyr.stat
|
||||||
|
zephyr.a
|
||||||
|
zephyr.o
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
*.so.*
|
||||||
|
*.dll
|
||||||
|
*.exe
|
||||||
|
|
||||||
|
# Cmake
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles/
|
||||||
|
cmake_install.cmake
|
||||||
|
CTestTestfile.cmake
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
|
# Kconfig generated files
|
||||||
|
.config
|
||||||
|
.config.old
|
||||||
|
autoconf.h
|
||||||
|
|
||||||
|
# Doxygen
|
||||||
|
doxygen/
|
||||||
|
|
||||||
|
# west
|
||||||
|
.west/
|
||||||
|
west.yml.bak
|
||||||
|
|
||||||
|
# Editor-specific files
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*~
|
||||||
|
*.bak
|
||||||
|
*.orig
|
||||||
|
|
||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
|
|
||||||
|
# Mac OS X
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
Thumbs.db
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "software/modules/zephyr_vnd7050aj_driver"]
|
||||||
|
path = software/modules/zephyr_vnd7050aj_driver
|
||||||
|
url = https://gitea.iten.pro/edi/zephyr_vnd7050aj_driver.git
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"fwu.h": "c"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"type": "shell",
|
||||||
|
"label": "Build Zephyr app",
|
||||||
|
"command": "west build -b weact_stm32g431_core .",
|
||||||
|
"group": "build",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$gcc"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./docs/img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
🇩🇪 Deutsch | [🇬🇧 English](README.md) | [🇫🇷 Français](README.fr.md) | [🇪🇸 Español](README.es.md)
|
🇩🇪 Deutsch | [🇬🇧 English](README.md) | [🇫🇷 Français](README.fr.md) | [🇪🇸 Español](README.es.md)
|
||||||
|
|
||||||
# Modulares Bewässerungssystem
|
# Modulares Bewässerungssystem
|
||||||
|
|
@ -11,6 +13,8 @@ Die detaillierte Dokumentation befindet sich im Verzeichnis [`docs/`](./docs/):
|
||||||
* **[Konzept](./docs/concept.de.md)**: Beschreibt die Systemarchitektur, die verwendeten Komponenten und die grundlegenden Design-Entscheidungen.
|
* **[Konzept](./docs/concept.de.md)**: Beschreibt die Systemarchitektur, die verwendeten Komponenten und die grundlegenden Design-Entscheidungen.
|
||||||
* **[MODBUS Register](./docs/modbus-registers.de.md)**: Definiert die Register-Map für die Kommunikation mit den Slave-Nodes.
|
* **[MODBUS Register](./docs/modbus-registers.de.md)**: Definiert die Register-Map für die Kommunikation mit den Slave-Nodes.
|
||||||
* **[Projektplan](./docs/planning.de.md)**: Enthält den Entwicklungs- und Implementierungsplan.
|
* **[Projektplan](./docs/planning.de.md)**: Enthält den Entwicklungs- und Implementierungsplan.
|
||||||
|
* **[Firmware-Handbuch](./docs/firmware-manual.de.md)**: Beschreibt den Funktionsumfang und die Bedienung der Slave-Node-Firmware.
|
||||||
|
* **[Modbus Test-Tool](./software/tools/modbus_tool/README.de.md)**: Anleitung für das Python-basierte Kommandozeilen-Tool zum Testen der Slaves.
|
||||||
|
|
||||||
## Schnellstart
|
## Schnellstart
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./docs/img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](README.de.md) | [🇬🇧 English](README.md) | [🇫🇷 Français](README.fr.md) | 🇪🇸 Español
|
[🇩🇪 Deutsch](README.de.md) | [🇬🇧 English](README.md) | [🇫🇷 Français](README.fr.md) | 🇪🇸 Español
|
||||||
|
|
||||||
# Sistema de riego modular
|
# Sistema de riego modular
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./docs/img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](README.de.md) | [🇬🇧 English](README.md) | 🇫🇷 Français | [🇪🇸 Español](README.es.md)
|
[🇩🇪 Deutsch](README.de.md) | [🇬🇧 English](README.md) | 🇫🇷 Français | [🇪🇸 Español](README.es.md)
|
||||||
|
|
||||||
# Système d'irrigation modulaire
|
# Système d'irrigation modulaire
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./docs/img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](README.de.md) | 🇬🇧 English | [🇫🇷 Français](README.fr.md) | [🇪🇸 Español](README.es.md)
|
[🇩🇪 Deutsch](README.de.md) | 🇬🇧 English | [🇫🇷 Français](README.fr.md) | [🇪🇸 Español](README.es.md)
|
||||||
|
|
||||||
# Modular Irrigation System
|
# Modular Irrigation System
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
🇩🇪 Deutsch | [🇬🇧 English](concept.en.md) | [🇫🇷 Français](concept.fr.md) | [🇪🇸 Español](concept.es.md)
|
🇩🇪 Deutsch | [🇬🇧 English](concept.en.md) | [🇫🇷 Français](concept.fr.md) | [🇪🇸 Español](concept.es.md)
|
||||||
|
|
||||||
# Konzept: Modulares Bewässerungssystem
|
# Konzept: Modulares Bewässerungssystem
|
||||||
|
|
@ -37,7 +39,7 @@ Die Slave-Nodes sind die Arbeitseinheiten im Feld. Um bei der Fertigung kleiner
|
||||||
|
|
||||||
* **Mikrocontroller:** Ein `STM32G431PB`. Dieser ist zwar leistungsstark, bietet aber alle nötigen Peripherien (mehrere UARTs, ADCs, CAN) und ermöglicht ein einheitliches Hardware- und Software-Design.
|
* **Mikrocontroller:** Ein `STM32G431PB`. Dieser ist zwar leistungsstark, bietet aber alle nötigen Peripherien (mehrere UARTs, ADCs, CAN) und ermöglicht ein einheitliches Hardware- und Software-Design.
|
||||||
* **Peripherie pro Node:**
|
* **Peripherie pro Node:**
|
||||||
* **Zwei High-Side Ausgänge (+12V):** Realisiert über einen `VND7050AJ`. Perfekt zur Ansteuerung der 12V-Motorventile (`Öffnen`/`Schliessen`). Die `Sense`-Leitung des Treibers wird über einen AD-Wandler ausgelesen, um durch Messung des Motorstroms eine Endlagen-Erkennung ohne physische Endschalter zu realisieren (Motorstrom im Stillstand ≈ 0).
|
* **Zwei High-Side Ausgänge (+12V):** Realisiert über einen `VND7050AJ`. Perfekt zur Ansteuerung der 12V-Motorventile (`Öffnen`/`Schliessen`). Die `Sense`-Leitung des Treibers wird über einen AD-Wandler ausgelesen, um durch Messung des Motorstroms eine Endlagen-Erkennung ohne physische Endschalter zu realisieren (Motorstrom im Stillstand ≈ 0). Zusätzlich können die Temperatur und die Versorgungsspannung des Treibers ausgelesen werden.
|
||||||
* **Zwei Low-Side Ausgänge (0V):** Über N-Kanal-MOSFETs geschaltete Ausgänge. Nutzbar zur Ansteuerung von 12V-LEDs in Tastern oder zum Schalten des Halbleiter-Relais für die Pumpe.
|
* **Zwei Low-Side Ausgänge (0V):** Über N-Kanal-MOSFETs geschaltete Ausgänge. Nutzbar zur Ansteuerung von 12V-LEDs in Tastern oder zum Schalten des Halbleiter-Relais für die Pumpe.
|
||||||
* **Zwei digitale Eingänge:** Direkte, geschützte Eingänge am Controller zum Anschluss von Tastern oder den kapazitiven NPN-Sensoren.
|
* **Zwei digitale Eingänge:** Direkte, geschützte Eingänge am Controller zum Anschluss von Tastern oder den kapazitiven NPN-Sensoren.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](concept.de.md) | 🇬🇧 English | [🇫🇷 Français](concept.fr.md) | [🇪🇸 Español](concept.es.md)
|
[🇩🇪 Deutsch](concept.de.md) | 🇬🇧 English | [🇫🇷 Français](concept.fr.md) | [🇪🇸 Español](concept.es.md)
|
||||||
|
|
||||||
# Concept: Modular Irrigation System
|
# Concept: Modular Irrigation System
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](concept.de.md) | [🇬🇧 English](concept.en.md) | [🇫🇷 Français](concept.fr.md) | 🇪🇸 Español
|
[🇩🇪 Deutsch](concept.de.md) | [🇬🇧 English](concept.en.md) | [🇫🇷 Français](concept.fr.md) | 🇪🇸 Español
|
||||||
|
|
||||||
# Concepto: Sistema de riego modular
|
# Concepto: Sistema de riego modular
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](concept.de.md) | [🇬🇧 English](concept.en.md) | 🇫🇷 Français | [🇪🇸 Español](concept.es.md)
|
[🇩🇪 Deutsch](concept.de.md) | [🇬🇧 English](concept.en.md) | 🇫🇷 Français | [🇪🇸 Español](concept.es.md)
|
||||||
|
|
||||||
# Concept : Système d'irrigation modulaire
|
# Concept : Système d'irrigation modulaire
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 272 KiB |
|
|
@ -0,0 +1,16 @@
|
||||||
|
<svg width="100" height="120" viewBox="0 0 100 120" xmlns="http://www.w3.org/2000/svg" aria-labelledby="logoTitle">
|
||||||
|
<title id="logoTitle">Logo: Wassertropfen mit integriertem Chip</title>
|
||||||
|
|
||||||
|
<path
|
||||||
|
d="M50 115 C 85 85, 95 65, 95 45 A 45 45 0 1 0 5 45 C 5 65, 15 85, 50 115 Z"
|
||||||
|
fill="#2563EB"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<g fill="#FFFFFF">
|
||||||
|
<rect x="25" y="35" width="50" height="8" rx="2"/>
|
||||||
|
<rect x="25" y="50" width="35" height="8" rx="2"/>
|
||||||
|
<rect x="70" y="50" width="5" height="8" rx="2"/>
|
||||||
|
<rect x="25" y="65" width="50" height="8" rx="2"/>
|
||||||
|
</g>
|
||||||
|
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 568 B |
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
🇩🇪 Deutsch | [🇬🇧 English](modbus-registers.en.md) | [🇫🇷 Français](modbus-registers.fr.md) | [🇪🇸 Español](modbus-registers.es.md)
|
🇩🇪 Deutsch | [🇬🇧 English](modbus-registers.en.md) | [🇫🇷 Français](modbus-registers.fr.md) | [🇪🇸 Español](modbus-registers.es.md)
|
||||||
|
|
||||||
# MODBUS Register Map Definition v1.0
|
# MODBUS Register Map Definition v1.0
|
||||||
|
|
@ -27,31 +29,38 @@ Alle Register sind in einer einzigen, durchgehenden Liste pro Register-Typ (`Inp
|
||||||
|
|
||||||
| Adresse (hex) | Name | Zugehörigkeit | Beschreibung |
|
| Adresse (hex) | Name | Zugehörigkeit | Beschreibung |
|
||||||
| :------------ | :----------------------------- | :---------------- | :---------------------------------------------------------------------------------------------------------------------------------------- |
|
| :------------ | :----------------------------- | :---------------- | :---------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **0x0000** | `VENTIL_ZUSTAND_BEWEGUNG` | Ventil | Kombiniertes Status-Register. **High-Byte**: Bewegung (`0`=Idle, `1`=Öffnet, `2`=Schliesst, `3`=Fehler). **Low-Byte**: Zustand (`0`=Geschlossen, `1`=Geöffnet). |
|
| **0x0000** | `VALVE_STATE_MOVEMENT` | Ventil | Kombiniertes Status-Register. **High-Byte**: Bewegung (`0`=Idle, `1`=Öffnet, `2`=Schliesst, `3`=Fehler). **Low-Byte**: Zustand (`0`=Geschlossen, `1`=Geöffnet). |
|
||||||
| **0x0001** | `MOTORSTROM_MA` | Ventil | Aktueller Motorstrom in Milliampere (mA). |
|
| **0x0001** | `REG_INPUT_MOTOR_OPEN_CURRENT_MA` | Ventil | Motorstrom beim Öffnen in Milliampere (mA). |
|
||||||
| **0x0020** | `DIGITAL_EINGAENGE_ZUSTAND` | Eingänge | Bitmaske der digitalen Eingänge. Bit 0: Eingang 1, Bit 1: Eingang 2. `1`=Aktiv. |
|
| **0x0002** | `REG_INPUT_MOTOR_CLOSE_CURRENT_MA` | Ventil | Motorstrom beim Schließen in Milliampere (mA). |
|
||||||
| **0x0021** | `TASTER_EVENTS` | Eingänge | Event-Flags für Taster (Clear-on-Read). Bit 0: Taster 1 gedrückt. Bit 1: Taster 2 gedrückt. |
|
| **0x0020** | `REG_INPUT_DIGITAL_INPUTS_STATE` | Eingänge | Bitmaske der digitalen Eingänge. Bit 0: Eingang 1, Bit 1: Eingang 2. `1`=Aktiv. |
|
||||||
| **0x00F0** | `FIRMWARE_VERSION_MAJOR_MINOR` | System | z.B. `0x0102` für v1.2. |
|
| **0x0021** | `REG_INPUT_BUTTON_EVENTS` | Eingänge | Event-Flags für Taster (Clear-on-Read). Bit 0: Taster 1 gedrückt. Bit 1: Taster 2 gedrückt. |
|
||||||
| **0x00F1** | `FIRMWARE_VERSION_PATCH` | System | z.B. `3` für v1.2.3. |
|
| **0x00F0** | `REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR` | System | z.B. `0x0102` für v1.2. |
|
||||||
| **0x00F2** | `DEVICE_STATUS` | System | `0`=OK, `1`=Allgemeiner Fehler. |
|
| **0x00F1** | `REG_INPUT_FIRMWARE_VERSION_PATCH` | System | z.B. `3` für v1.2.3. |
|
||||||
| **0x00F3** | `UPTIME_SECONDS_LOW` | System | Untere 16 Bit der Uptime in Sekunden. |
|
| **0x00F2** | `REG_INPUT_DEVICE_STATUS` | System | `0`=OK, `1`=Allgemeiner Fehler. |
|
||||||
| **0x00F4** | `UPTIME_SECONDS_HIGH` | System | Obere 16 Bit der Uptime. |
|
| **0x00F3** | `REG_INPUT_UPTIME_SECONDS_LOW` | System | Untere 16 Bit der Uptime in Sekunden. |
|
||||||
| **0x0100** | `FWU_LAST_CHUNK_CRC` | Firmware-Update | Enthält den CRC16 des zuletzt im Puffer empfangenen Daten-Chunks. |
|
| **0x00F4** | `REG_INPUT_UPTIME_SECONDS_HIGH` | System | Obere 16 Bit der Uptime. |
|
||||||
|
| **0x00F5** | `REG_INPUT_SUPPLY_VOLTAGE_MV` | System | Aktuelle Versorgungsspannung in Millivolt (mV). |
|
||||||
|
| **0x0100** | `REG_INPUT_FWU_LAST_CHUNK_CRC` | Firmware-Update | Enthält den CRC16 des zuletzt im Puffer empfangenen Daten-Chunks. |
|
||||||
|
|
||||||
## 3. Holding Registers (4xxxx, Read/Write)
|
## 3. Holding Registers (4xxxx, Read/Write)
|
||||||
|
|
||||||
| Adresse (hex) | Name | Zugehörigkeit | Beschreibung |
|
| Adresse (hex) | Name | Zugehörigkeit | Beschreibung |
|
||||||
| :------------ | :---------------------------- | :---------------- | :---------------------------------------------------------------------------------------------------------------------------------------- |
|
| :------------ | :---------------------------- | :---------------- | :---------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **0x0000** | `VENTIL_BEFEHL` | Ventil | `1`=Öffnen, `2`=Schliessen, `0`=Bewegung stoppen. |
|
| **0x0000** | `REG_HOLDING_VALVE_COMMAND` | Ventil | `1`=Öffnen, `2`=Schliessen, `0`=Bewegung stoppen. |
|
||||||
| **0x0001** | `MAX_OEFFNUNGSZEIT_S` | Ventil | Sicherheits-Timeout in Sekunden für den Öffnen-Vorgang. |
|
| **0x0001** | `REG_HOLDING_MAX_OPENING_TIME_S` | Ventil | Sicherheits-Timeout in Sekunden für den Öffnen-Vorgang. |
|
||||||
| **0x0002** | `MAX_SCHLIESSZEIT_S` | Ventil | Sicherheits-Timeout in Sekunden für den Schliessen-Vorgang. |
|
| **0x0002** | `REG_HOLDING_MAX_CLOSING_TIME_S` | Ventil | Sicherheits-Timeout in Sekunden für den Schliessen-Vorgang. |
|
||||||
| **0x0010** | `DIGITAL_AUSGAENGE_ZUSTAND` | Ausgänge | Bitmaske zum Lesen und Schreiben der Ausgänge. Bit 0: Ausgang 1, Bit 1: Ausgang 2. `1`=AN, `0`=AUS. |
|
| **0x0003** | `REG_HOLDING_END_CURRENT_THRESHOLD_OPEN_MA` | Ventil | Minimaler Stromschwellenwert in mA zur Endlagenerkennung beim Öffnen. |
|
||||||
| **0x00F0** | `WATCHDOG_TIMEOUT_S` | System | Timeout des Fail-Safe-Watchdogs in Sekunden. `0`=Deaktiviert. |
|
| **0x0004** | `REG_HOLDING_END_CURRENT_THRESHOLD_CLOSE_MA` | Ventil | Minimaler Stromschwellenwert in mA zur Endlagenerkennung beim Schliessen. |
|
||||||
| **0x0100** | `FWU_COMMAND` | Firmware-Update | `1`: **Verify Chunk**: Der zuletzt übertragene Chunk wurde vom Client als gültig befunden. Der Slave soll ihn nun ins Flash schreiben. `2`: **Finalize Update**: Alle Chunks sind übertragen. Installation abschliessen und neu starten. |
|
| **0x0005** | `REG_HOLDING_OBSTACLE_THRESHOLD_OPEN_MA` | Ventil | Stromschwellenwert in mA für die Hinderniserkennung beim Öffnen. |
|
||||||
| **0x0101** | `FWU_CHUNK_OFFSET_LOW` | Firmware-Update | Untere 16 Bit des 32-Bit-Offsets, an den der nächste Chunk geschrieben werden soll. |
|
| **0x0006** | `REG_HOLDING_OBSTACLE_THRESHOLD_CLOSE_MA` | Ventil | Stromschwellenwert in mA für die Hinderniserkennung beim Schließen. |
|
||||||
| **0x0102** | `FWU_CHUNK_OFFSET_HIGH` | Firmware-Update | Obere 16 Bit des 32-Bit-Offsets. |
|
| **0x0010** | `REG_HOLDING_DIGITAL_OUTPUTS_STATE` | Ausgänge | Bitmaske zum Lesen und Schreiben der Ausgänge. Bit 0: Ausgang 1, Bit 1: Ausgang 2. `1`=AN, `0`=AUS. |
|
||||||
| **0x0103** | `FWU_CHUNK_SIZE` | Firmware-Update | Grösse des nächsten Chunks in Bytes (max. 256). |
|
| **0x00F0** | `REG_HOLDING_WATCHDOG_TIMEOUT_S` | System | Timeout des Fail-Safe-Watchdogs in Sekunden. `0`=Deaktiviert. |
|
||||||
| **0x0180** | `FWU_DATA_BUFFER` | Firmware-Update | **Startadresse** eines 128x16-bit Puffers (256 Bytes). Entspricht den Registern `40384` bis `40511`. |
|
| **0x00F1** | `REG_HOLDING_DEVICE_RESET` | System | Schreibt `1` um das Gerät neu zu starten. |
|
||||||
|
| **0x0100** | `REG_HOLDING_FWU_COMMAND` | Firmware-Update | `1`: **Verify Chunk**: Der zuletzt übertragene Chunk wurde vom Client als gültig befunden. Der Slave soll ihn nun ins Flash schreiben. `2`: **Finalize Update**: Alle Chunks sind übertragen. Installation abschliessen und neu starten. |
|
||||||
|
| **0x0101** | `REG_HOLDING_FWU_CHUNK_OFFSET_LOW` | Firmware-Update | Untere 16 Bit des 32-Bit-Offsets, an den der nächste Chunk geschrieben werden soll. |
|
||||||
|
| **0x0102** | `REG_HOLDING_FWU_CHUNK_OFFSET_HIGH` | Firmware-Update | Obere 16 Bit des 32-Bit-Offsets. |
|
||||||
|
| **0x0103** | `REG_HOLDING_FWU_CHUNK_SIZE` | Firmware-Update | Grösse des nächsten Chunks in Bytes (max. 256). |
|
||||||
|
| **0x0180** | `REG_HOLDING_FWU_DATA_BUFFER` | Firmware-Update | **Startadresse** eines 128x16-bit Puffers (256 Bytes). Entspricht den Registern `40384` bis `40511`. |
|
||||||
|
|
||||||
## 4. Detaillierter Firmware-Update-Prozess
|
## 4. Detaillierter Firmware-Update-Prozess
|
||||||
|
|
||||||
|
|
@ -76,10 +85,10 @@ Diese Register gehören zum externen Füllstandsensor und können auf dem Bus eb
|
||||||
|
|
||||||
| Adresse (hex) | Name | R/W | Beschreibung |
|
| Adresse (hex) | Name | R/W | Beschreibung |
|
||||||
| :------------ | :------------------------- | :-- | :---------------------------------------------------------------------------------------------------------------------------------------- |
|
| :------------ | :------------------------- | :-- | :---------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **0x0000** | `NODE_ADRESSE` | R/W | Geräteadresse des Sensors (1-255). |
|
| **0x0000** | `NODE_ADDRESS` | R/W | Geräteadresse des Sensors (1-255). |
|
||||||
| **0x0001** | `BAUDRATE` | R/W | `0`=1200, `1`=2400, `2`=4800, `3`=9600, `4`=19200, `5`=38400, `6`=57600, `7`=115200. |
|
| **0x0001** | `BAUDRATE` | R/W | `0`=1200, `1`=2400, `2`=4800, `3`=9600, `4`=19200, `5`=38400, `6`=57600, `7`=115200. |
|
||||||
| **0x0002** | `EINHEIT` | R/W | `0`=Keine, `1`=cm, `2`=mm, `3`=MPa, `4`=Pa, `5`=kPa. |
|
| **0x0002** | `UNIT` | R/W | `0`=Keine, `1`=cm, `2`=mm, `3`=MPa, `4`=Pa, `5`=kPa. |
|
||||||
| **0x0003** | `NACHKOMMASTELLEN` | R/W | Anzahl der Dezimalstellen für den Messwert (0-3). |
|
| **0x0003** | `DECIMAL_PLACES` | R/W | Anzahl der Dezimalstellen für den Messwert (0-3). |
|
||||||
| **0x0004** | `MESSWERT_AKTUELL` | R | Der skalierte Messwert als vorzeichenbehafteter 16-Bit-Integer. |
|
| **0x0004** | `CURRENT_MEASUREMENT` | R | Der skalierte Messwert als vorzeichenbehafteter 16-Bit-Integer. |
|
||||||
| **0x0005** | `MESSBEREICH_NULLPUNKT` | R/W | Rohwert für den Nullpunkt der Skala. |
|
| **0x0005** | `MEASUREMENT_RANGE_ZERO_POINT` | R/W | Rohwert für den Nullpunkt der Skala. |
|
||||||
| **0x0006** | `MESSBEREICH_ENDPUNKT` | R/W | Rohwert für den Endpunkt der Skala. |
|
| **0x0006** | `MEASUREMENT_RANGE_END_POINT` | R/W | Rohwert für den Endpunkt der Skala. |
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](modbus-registers.de.md) | 🇬🇧 English | [🇫🇷 Français](modbus-registers.fr.md) | [🇪🇸 Español](modbus-registers.es.md)
|
[🇩🇪 Deutsch](modbus-registers.de.md) | 🇬🇧 English | [🇫🇷 Français](modbus-registers.fr.md) | [🇪🇸 Español](modbus-registers.es.md)
|
||||||
|
|
||||||
# MODBUS Register Map Definition v1.0
|
# MODBUS Register Map Definition v1.0
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](modbus-registers.de.md) | [🇬🇧 English](modbus-registers.en.md) | [🇫🇷 Français](modbus-registers.fr.md) | 🇪🇸 Español
|
[🇩🇪 Deutsch](modbus-registers.de.md) | [🇬🇧 English](modbus-registers.en.md) | [🇫🇷 Français](modbus-registers.fr.md) | 🇪🇸 Español
|
||||||
|
|
||||||
# Definición del mapa de registros MODBUS v1.0
|
# Definición del mapa de registros MODBUS v1.0
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](modbus-registers.de.md) | [🇬🇧 English](modbus-registers.en.md) | 🇫🇷 Français | [🇪🇸 Español](modbus-registers.es.md)
|
[🇩🇪 Deutsch](modbus-registers.de.md) | [🇬🇧 English](modbus-registers.en.md) | 🇫🇷 Français | [🇪🇸 Español](modbus-registers.es.md)
|
||||||
|
|
||||||
# Définition de la carte des registres MODBUS v1.0
|
# Définition de la carte des registres MODBUS v1.0
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
🇩🇪 Deutsch | [🇬🇧 English](planning.en.md) | [🇫🇷 Français](planning.fr.md) | [🇪🇸 Español](planning.es.md)
|
🇩🇪 Deutsch | [🇬🇧 English](planning.en.md) | [🇫🇷 Français](planning.fr.md) | [🇪🇸 Español](planning.es.md)
|
||||||
|
|
||||||
# Projektplan: Modulares Bewässerungssystem
|
# Projektplan: Modulares Bewässerungssystem
|
||||||
|
|
@ -7,11 +9,13 @@
|
||||||
| ✅ | **Phase 0: Planung & Definition** | | |
|
| ✅ | **Phase 0: Planung & Definition** | | |
|
||||||
| ✅ | Konzept erstellen und finalisieren | 30.06.2025 | Architektur, Komponenten und grundlegende Architektur sind festgelegt. |
|
| ✅ | Konzept erstellen und finalisieren | 30.06.2025 | Architektur, Komponenten und grundlegende Architektur sind festgelegt. |
|
||||||
| ✅ | MODBUS Register Map definieren | 30.06.2025 | Die "API" der Slaves ist definiert und bildet die Grundlage für die Software-Entwicklung. |
|
| ✅ | MODBUS Register Map definieren | 30.06.2025 | Die "API" der Slaves ist definiert und bildet die Grundlage für die Software-Entwicklung. |
|
||||||
|
| ✅ | Header- und deutsche Dokumentation aktualisiert | 10.07.2025 | Doxygen-Kommentare in Headern und deutsche .md-Dateien auf den neuesten Stand gebracht und übersetzt. |
|
||||||
| ☐ | **Phase 1: Slave-Node Prototyp (STM32 Eval-Board)** | | **Ziel:** Ein einzelner Slave wird auf dem Eval-Board zum Leben erweckt. |
|
| ☐ | **Phase 1: Slave-Node Prototyp (STM32 Eval-Board)** | | **Ziel:** Ein einzelner Slave wird auf dem Eval-Board zum Leben erweckt. |
|
||||||
| ✅ | 1.1 Entwicklungsumgebung für STM32/Zephyr einrichten | 30.06.2025 | Toolchain, VS Code, Zephyr-SDK, MCUBoot etc. installieren und ein "Hello World" zum Laufen bringen. |
|
| ✅ | 1.1 Entwicklungsumgebung für STM32/Zephyr einrichten | 30.06.2025 | Toolchain, VS Code, Zephyr-SDK, MCUBoot etc. installieren und ein "Hello World" zum Laufen bringen. |
|
||||||
| ☐ | 1.2 Basis-Firmware für Slave-Node erstellen | | Hardware-Abstraktion (GPIOs, ADC, UART für RS485) implementieren. |
|
| ✅ | 1.2 Hardware-Abstraktion (VND7050AJ, RS485) | 10.07.2025 | Implementierung der Treiber für den VND7050AJ und die RS485-Kommunikation. |
|
||||||
| ☐ | 1.3 MODBUS-RTU Stack auf dem Slave implementieren | | Basierend auf der definierten Register-Map. Zuerst nur lesende Funktionen (Status, Version). |
|
| ✅ | 1.3 Basis-Firmware für Slave-Node erstellen | 10.07.2025 | Hardware-Abstraktion (GPIOs) implementiert. |
|
||||||
| ☐ | 1.4 Kernlogik implementieren (z.B. Ventilsteuerung) | | Umsetzung der `VENTIL_ZUSTAND_BEWEGUNG` Logik, Strommessung für Endlagen etc. |
|
| ✅ | 1.3 MODBUS-RTU Stack auf dem Slave implementieren | 10.07.2025 | Basierend auf der definierten Register-Map. Zuerst nur lesende Funktionen (Status, Version). |
|
||||||
|
| ✅ | 1.4 Kernlogik implementieren (z.B. Ventilsteuerung) | 10.07.2025 | Umsetzung der `VALVE_STATE_MOVEMENT` Logik, Strommessung für Endlagen etc. |
|
||||||
| ☐ | **Phase 2: Verifikation der Slave-Firmware** | | **Ziel:** Nachweisen, dass der Slave sich exakt an die MODBUS-Spezifikation hält. |
|
| ☐ | **Phase 2: Verifikation der Slave-Firmware** | | **Ziel:** Nachweisen, dass der Slave sich exakt an die MODBUS-Spezifikation hält. |
|
||||||
| ☐ | 2.1 Slave-Node mit PC via USB-MODBUS-Adapter testen | | **Kritischer Meilenstein.** Mit Tools wie "QModMaster" oder einem Python-Skript die Register lesen & schreiben. Die Slave-Firmware wird so unabhängig vom Gateway validiert. |
|
| ☐ | 2.1 Slave-Node mit PC via USB-MODBUS-Adapter testen | | **Kritischer Meilenstein.** Mit Tools wie "QModMaster" oder einem Python-Skript die Register lesen & schreiben. Die Slave-Firmware wird so unabhängig vom Gateway validiert. |
|
||||||
| ☐ | 2.2 Firmware-Update Mechanismus testen | | Den kompletten Update-Prozess (Chunking, CRC-Check) mit einem Skript vom PC aus testen. Der Slave schreibt die Firmware dabei vorerst nur in einen ungenutzten RAM-Bereich. |
|
| ☐ | 2.2 Firmware-Update Mechanismus testen | | Den kompletten Update-Prozess (Chunking, CRC-Check) mit einem Skript vom PC aus testen. Der Slave schreibt die Firmware dabei vorerst nur in einen ungenutzten RAM-Bereich. |
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](planning.de.md) | 🇬🇧 English | [🇫🇷 Français](planning.fr.md) | [🇪🇸 Español](planning.es.md)
|
[🇩🇪 Deutsch](planning.de.md) | 🇬🇧 English | [🇫🇷 Français](planning.fr.md) | [🇪🇸 Español](planning.es.md)
|
||||||
|
|
||||||
# Project Plan: Modular Irrigation System
|
# Project Plan: Modular Irrigation System
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](planning.de.md) | [🇬🇧 English](planning.en.md) | [🇫🇷 Français](planning.fr.md) | 🇪🇸 Español
|
[🇩🇪 Deutsch](planning.de.md) | [🇬🇧 English](planning.en.md) | [🇫🇷 Français](planning.fr.md) | 🇪🇸 Español
|
||||||
|
|
||||||
# Plan del proyecto: Sistema de riego modular
|
# Plan del proyecto: Sistema de riego modular
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
<img src="./img/logo.png" alt="Logo" width="100"/>
|
||||||
|
|
||||||
[🇩🇪 Deutsch](planning.de.md) | [🇬🇧 English](planning.en.md) | 🇫🇷 Français | [🇪🇸 Español](planning.es.md)
|
[🇩🇪 Deutsch](planning.de.md) | [🇬🇧 English](planning.en.md) | 🇫🇷 Français | [🇪🇸 Español](planning.es.md)
|
||||||
|
|
||||||
# Plan de projet : Système d'irrigation modulaire
|
# Plan de projet : Système d'irrigation modulaire
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# This script sets up a Git pre-commit hook to automatically format C/C++ files
|
||||||
|
# in the 'software/' subdirectory using clang-format.
|
||||||
|
|
||||||
|
# Define the path for the pre-commit hook
|
||||||
|
HOOK_DIR=".git/hooks"
|
||||||
|
HOOK_FILE="$HOOK_DIR/pre-commit"
|
||||||
|
|
||||||
|
# Create the hooks directory if it doesn't exist
|
||||||
|
mkdir -p "$HOOK_DIR"
|
||||||
|
|
||||||
|
# Create the pre-commit hook script using a 'here document'
|
||||||
|
cat > "$HOOK_FILE" << 'EOF'
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# --- Pre-commit hook for clang-format ---
|
||||||
|
#
|
||||||
|
# This hook formats staged C, C++, and Objective-C files in the 'software/'
|
||||||
|
# subdirectory before a commit is made.
|
||||||
|
# It automatically finds the .clang-format file in the software/ directory.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Directory to be formatted
|
||||||
|
TARGET_DIR="software/"
|
||||||
|
|
||||||
|
# Use git diff to find staged files that are Added (A), Copied (C), or Modified (M).
|
||||||
|
# We filter for files only within the TARGET_DIR.
|
||||||
|
# The grep regex matches common C/C++ and Objective-C file extensions.
|
||||||
|
FILES_TO_FORMAT=$(git diff --cached --name-only --diff-filter=ACM "$TARGET_DIR" | grep -E '\.(c|h|cpp|hpp|cxx|hxx|cc|hh|m|mm)$')
|
||||||
|
|
||||||
|
if [ -z "$FILES_TO_FORMAT" ]; then
|
||||||
|
# No relevant files to format, exit successfully.
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "› Running clang-format on staged files in '$TARGET_DIR'..."
|
||||||
|
|
||||||
|
# Run clang-format in-place on the identified files.
|
||||||
|
# clang-format will automatically find the .clang-format file in the software/ directory
|
||||||
|
# or any of its parent directories.
|
||||||
|
echo "$FILES_TO_FORMAT" | xargs clang-format -i
|
||||||
|
|
||||||
|
# Since clang-format may have changed the files, we need to re-stage them.
|
||||||
|
echo "$FILES_TO_FORMAT" | xargs git add
|
||||||
|
|
||||||
|
echo "› Formatting complete."
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Make the hook executable
|
||||||
|
chmod +x "$HOOK_FILE"
|
||||||
|
|
||||||
|
echo "✅ Git pre-commit hook has been set up successfully."
|
||||||
|
echo " It will now automatically format files in the '$PWD/software' directory before each commit."
|
||||||
|
|
@ -0,0 +1,142 @@
|
||||||
|
# Zephyr Project .clang-format configuration
|
||||||
|
# Based on Linux kernel style with Zephyr-specific adaptations
|
||||||
|
|
||||||
|
# Use LLVM as the base style and customize from there
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
|
||||||
|
# Language settings
|
||||||
|
Language: Cpp
|
||||||
|
|
||||||
|
# Indentation settings
|
||||||
|
IndentWidth: 8
|
||||||
|
TabWidth: 8
|
||||||
|
UseTab: ForIndentation
|
||||||
|
|
||||||
|
# Line length
|
||||||
|
ColumnLimit: 100
|
||||||
|
|
||||||
|
# Brace settings
|
||||||
|
BreakBeforeBraces: Linux
|
||||||
|
BraceWrapping:
|
||||||
|
AfterClass: true
|
||||||
|
AfterControlStatement: false
|
||||||
|
AfterEnum: true
|
||||||
|
AfterFunction: true
|
||||||
|
AfterNamespace: true
|
||||||
|
AfterStruct: true
|
||||||
|
AfterUnion: true
|
||||||
|
BeforeCatch: true
|
||||||
|
BeforeElse: false
|
||||||
|
IndentBraces: false
|
||||||
|
SplitEmptyFunction: true
|
||||||
|
SplitEmptyRecord: true
|
||||||
|
SplitEmptyNamespace: true
|
||||||
|
|
||||||
|
# Always add braces for control statements (Zephyr requirement)
|
||||||
|
RemoveBracesLLVM: false
|
||||||
|
|
||||||
|
# Control statement settings
|
||||||
|
SpaceBeforeParens: ControlStatements
|
||||||
|
SpacesInParentheses: false
|
||||||
|
|
||||||
|
# Function settings
|
||||||
|
AllowShortFunctionsOnASingleLine: None
|
||||||
|
AllowShortBlocksOnASingleLine: Empty
|
||||||
|
AllowShortIfStatementsOnASingleLine: Never
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
|
||||||
|
# Pointer and reference alignment
|
||||||
|
PointerAlignment: Right
|
||||||
|
ReferenceAlignment: Right
|
||||||
|
|
||||||
|
# Spacing settings
|
||||||
|
SpaceAfterCStyleCast: false
|
||||||
|
SpaceAfterLogicalNot: false
|
||||||
|
SpaceBeforeAssignmentOperators: true
|
||||||
|
SpaceBeforeCpp11BracedList: false
|
||||||
|
SpaceBeforeCtorInitializerColon: true
|
||||||
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceInEmptyParentheses: false
|
||||||
|
SpacesBeforeTrailingComments: 1
|
||||||
|
SpacesInAngles: false
|
||||||
|
SpacesInCStyleCastParentheses: false
|
||||||
|
SpacesInContainerLiterals: false
|
||||||
|
SpacesInSquareBrackets: false
|
||||||
|
|
||||||
|
# Alignment settings
|
||||||
|
AlignAfterOpenBracket: DontAlign
|
||||||
|
AlignConsecutiveAssignments: false
|
||||||
|
AlignConsecutiveDeclarations: false
|
||||||
|
AlignEscapedNewlines: Right
|
||||||
|
AlignOperands: false
|
||||||
|
AlignTrailingComments: false
|
||||||
|
|
||||||
|
# Breaking settings
|
||||||
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
|
AlwaysBreakAfterReturnType: None
|
||||||
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
|
AlwaysBreakTemplateDeclarations: false
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeTernaryOperators: true
|
||||||
|
BreakConstructorInitializersBeforeComma: false
|
||||||
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakStringLiterals: true
|
||||||
|
|
||||||
|
# Penalties (used for line breaking decisions)
|
||||||
|
PenaltyBreakAssignment: 2
|
||||||
|
PenaltyBreakBeforeFirstCallParameter: 19
|
||||||
|
PenaltyBreakComment: 300
|
||||||
|
PenaltyBreakFirstLessLess: 120
|
||||||
|
PenaltyBreakString: 1000
|
||||||
|
PenaltyExcessCharacter: 1000000
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
|
|
||||||
|
# Comment settings
|
||||||
|
ReflowComments: true
|
||||||
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
|
|
||||||
|
# Sorting settings
|
||||||
|
SortIncludes: true
|
||||||
|
SortUsingDeclarations: true
|
||||||
|
|
||||||
|
# Preprocessor settings
|
||||||
|
IndentPPDirectives: None
|
||||||
|
MacroBlockBegin: ''
|
||||||
|
MacroBlockEnd: ''
|
||||||
|
|
||||||
|
# Misc settings
|
||||||
|
CompactNamespaces: false
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||||
|
ConstructorInitializerIndentWidth: 4
|
||||||
|
ContinuationIndentWidth: 4
|
||||||
|
Cpp11BracedListStyle: true
|
||||||
|
DerivePointerAlignment: false
|
||||||
|
DisableFormat: false
|
||||||
|
ExperimentalAutoDetectBinPacking: false
|
||||||
|
FixNamespaceComments: true
|
||||||
|
ForEachMacros: ['LISTIFY', 'FOR_EACH', 'FOR_EACH_FIXED_ARG', 'FOR_EACH_IDX', 'FOR_EACH_IDX_FIXED_ARG', 'FOR_EACH_NONEMPTY_TERM', 'Z_FOR_EACH', 'Z_FOR_EACH_FIXED_ARG', 'Z_FOR_EACH_IDX', 'Z_FOR_EACH_IDX_FIXED_ARG']
|
||||||
|
IncludeBlocks: Preserve
|
||||||
|
IncludeCategories:
|
||||||
|
- Regex: '^<zephyr/.*\.h>'
|
||||||
|
Priority: 1
|
||||||
|
- Regex: '^<.*\.h>'
|
||||||
|
Priority: 2
|
||||||
|
- Regex: '^<.*'
|
||||||
|
Priority: 3
|
||||||
|
- Regex: '.*'
|
||||||
|
Priority: 4
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentWrappedFunctionNames: false
|
||||||
|
JavaScriptQuotes: Leave
|
||||||
|
JavaScriptWrapImports: true
|
||||||
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
MaxEmptyLinesToKeep: 1
|
||||||
|
NamespaceIndentation: None
|
||||||
|
ObjCBinPackProtocolList: Auto
|
||||||
|
ObjCBlockIndentWidth: 2
|
||||||
|
ObjCSpaceAfterProperty: false
|
||||||
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
{
|
{
|
||||||
// Hush CMake
|
// Hush CMake
|
||||||
"cmake.configureOnOpen": false,
|
"cmake.configureOnOpen": false,
|
||||||
|
|
||||||
// IntelliSense
|
// IntelliSense
|
||||||
"C_Cpp.default.compilerPath": "${userHome}/zephyr-sdk-0.17.1/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc.exe",
|
"C_Cpp.default.compilerPath": "${userHome}/zephyr-sdk-0.17.1/arm-zephyr-eabi/bin/arm-zephyr-eabi-gcc.exe",
|
||||||
"C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json",
|
"C_Cpp.default.compileCommands": "${workspaceFolder}/build/compile_commands.json",
|
||||||
|
|
||||||
// File Associations
|
// File Associations
|
||||||
"files.associations": {
|
"files.associations": {
|
||||||
}
|
"app_version.h": "c"
|
||||||
|
},
|
||||||
|
"C_Cpp.clang_format_style": "file",
|
||||||
|
"nrf-connect.applications": [
|
||||||
|
"${workspaceFolder}/apps/slave_node"
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
@ -2,31 +2,19 @@
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"tasks": [
|
"tasks": [
|
||||||
{
|
{
|
||||||
"label": "West Build",
|
"label": "Format All C/C++ Files",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
|
"command": "find . -name \"*.c\" -o -name \"*.h\" | xargs clang-format -i",
|
||||||
|
"problemMatcher": [],
|
||||||
"group": {
|
"group": {
|
||||||
"kind": "build",
|
"kind": "build",
|
||||||
"isDefault": true
|
"isDefault": true
|
||||||
},
|
},
|
||||||
"linux": {
|
"presentation": {
|
||||||
"command": "${userHome}/zephyrproject/.venv/bin/west"
|
"reveal": "silent",
|
||||||
},
|
"clear": true,
|
||||||
"windows": {
|
"panel": "shared"
|
||||||
"command": "${userHome}/zephyrproject/.venv/Scripts/west.exe"
|
}
|
||||||
},
|
|
||||||
"osx": {
|
|
||||||
"command": "${userHome}/zephyrproject/.venv/bin/west"
|
|
||||||
},
|
|
||||||
"args": [
|
|
||||||
"build",
|
|
||||||
"-p",
|
|
||||||
"auto",
|
|
||||||
"-b",
|
|
||||||
"valve_node"
|
|
||||||
],
|
|
||||||
"problemMatcher": [
|
|
||||||
"$gcc"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"label": "West Configurable Build",
|
"label": "West Configurable Build",
|
||||||
|
|
|
||||||
|
|
@ -1,14 +0,0 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.20.0)
|
|
||||||
|
|
||||||
# This line should ideally be after project() and find_package(Zephyr)
|
|
||||||
# target_include_directories(app PRIVATE ${ZEPHYR_BASE}/include/zephyr/drivers) # <-- WRONG POSITION
|
|
||||||
|
|
||||||
list(APPEND BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
|
|
||||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
|
||||||
project(valve_node)
|
|
||||||
|
|
||||||
target_include_directories(app PRIVATE ${ZEPHYR_BASE}/include/zephyr/drivers)
|
|
||||||
target_sources(app PRIVATE src/main2.c)
|
|
||||||
|
|
@ -1,25 +0,0 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.20.0)
|
|
||||||
|
|
||||||
list(APPEND BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
|
||||||
|
|
||||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
|
||||||
project(valve_node)
|
|
||||||
|
|
||||||
target_sources(app PRIVATE src/main.c)
|
|
||||||
target_sources(app PRIVATE lib/canbus.c)
|
|
||||||
|
|
||||||
# source files for modbus waterlevel sensor
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_HAS_MODBUS_WATERLEVEL_SENSOR
|
|
||||||
lib/waterlevel_sensor.c
|
|
||||||
)
|
|
||||||
|
|
||||||
#source files for valve
|
|
||||||
zephyr_library_sources_ifdef(CONFIG_HAS_VALVE
|
|
||||||
lib/valve.c
|
|
||||||
)
|
|
||||||
|
|
||||||
zephyr_include_directories(
|
|
||||||
lib
|
|
||||||
)
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
rsource "lib/Kconfig"
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
cmake_minimum_required(VERSION 3.20.0)
|
||||||
|
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
project(bl_test)
|
||||||
|
|
||||||
|
# Add application source files
|
||||||
|
target_sources(app PRIVATE src/main.c)
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
VERSION_MAJOR = 0
|
||||||
|
VERSION_MINOR = 0
|
||||||
|
PATCHLEVEL = 1
|
||||||
|
VERSION_TWEAK = 1
|
||||||
|
EXTRAVERSION = devel
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
# Enable Console and printk for logging via UART
|
||||||
|
CONFIG_CONSOLE=y
|
||||||
|
CONFIG_LOG=y
|
||||||
|
CONFIG_UART_CONSOLE=y
|
||||||
|
|
||||||
|
# Enable more detailed MCUMGR logging
|
||||||
|
CONFIG_MCUMGR_LOG_LEVEL_DBG=y
|
||||||
|
CONFIG_IMG_MANAGER_LOG_LEVEL_DBG=y
|
||||||
|
CONFIG_STREAM_FLASH_LOG_LEVEL_DBG=y
|
||||||
|
|
||||||
|
# Enable USB for MCUMGR only
|
||||||
|
CONFIG_USB_DEVICE_STACK=y
|
||||||
|
CONFIG_USB_CDC_ACM=y
|
||||||
|
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=y
|
||||||
|
|
||||||
|
# USB CDC ACM buffer configuration for better MCUMGR performance
|
||||||
|
CONFIG_USB_CDC_ACM_RINGBUF_SIZE=1024
|
||||||
|
|
||||||
|
# Set log level to info for reasonable size
|
||||||
|
CONFIG_LOG_DEFAULT_LEVEL=3
|
||||||
|
|
||||||
|
# Enable MCUMGR info logging (not debug to save space)
|
||||||
|
CONFIG_MCUMGR_LOG_LEVEL_INF=y
|
||||||
|
|
||||||
|
# Enable USB CDC info logging
|
||||||
|
CONFIG_USB_CDC_ACM_LOG_LEVEL_INF=y
|
||||||
|
|
||||||
|
# STEP 5.2 - Enable mcumgr DFU in application
|
||||||
|
# Enable MCUMGR
|
||||||
|
CONFIG_MCUMGR=y # Enable MCUMGR management for both OS and Images
|
||||||
|
CONFIG_MCUMGR_GRP_OS=y
|
||||||
|
CONFIG_MCUMGR_GRP_IMG=y
|
||||||
|
|
||||||
|
# Configure MCUMGR transport to UART (will use USB-CDC via chosen device)
|
||||||
|
CONFIG_MCUMGR_TRANSPORT_UART=y
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
# Configure dependencies for CONFIG_MCUMGR
|
||||||
|
CONFIG_NET_BUF=y
|
||||||
|
CONFIG_ZCBOR=y
|
||||||
|
CONFIG_CRC=y # Configure dependencies for CONFIG_MCUMGR_GRP_IMG
|
||||||
|
CONFIG_FLASH=y
|
||||||
|
CONFIG_IMG_MANAGER=y # Configure dependencies for CONFIG_IMG_MANAGER
|
||||||
|
CONFIG_STREAM_FLASH=y
|
||||||
|
CONFIG_FLASH_MAP=y # Configure dependencies for CONFIG_MCUMGR_TRANSPORT_USB_CDC
|
||||||
|
CONFIG_BASE64=y
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <app_version.h>
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(bl_test_app, LOG_LEVEL_INF);
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
LOG_INF("Hello World from bl_test! This is version %s", APP_VERSION_EXTENDED_STRING);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
SB_CONFIG_BOOTLOADER_MCUBOOT=y
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include "common.dtsi"
|
||||||
|
|
||||||
|
/* Application Configuration - Firmware wird in slot0_partition geschrieben */
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zephyr,code-partition = &slot0_partition;
|
||||||
|
zephyr,uart-mcumgr = &cdc_acm_uart0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* Common Devicetree Configuration für weact_stm32g431_core
|
||||||
|
* - Konfiguriert einen W25Q128 Flash-Speicher auf SPI2
|
||||||
|
* - Konfiguriert USB-CDC für MCUMGR
|
||||||
|
* - Setzt den Chip Select (CS) Pin auf PA5
|
||||||
|
* - Weist das Label "flash1" zu
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Partitions für internes Flash (STM32G431) */
|
||||||
|
&flash0 {
|
||||||
|
/delete-node/ partitions; /* Entferne die Standard-Partitionen */
|
||||||
|
partitions {
|
||||||
|
compatible = "fixed-partitions";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
/* MCUboot bootloader - 48 KB */
|
||||||
|
boot_partition: partition@0 {
|
||||||
|
label = "mcuboot";
|
||||||
|
reg = <0x00000000 0x0000C000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Slot0 partition für primäres Application Image - 80 KB (20 sectors @ 4KB) */
|
||||||
|
slot0_partition: partition@C000 {
|
||||||
|
label = "image-0";
|
||||||
|
reg = <0x0000C000 0x00014000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/* USB-CDC Konfiguration für MCUMGR */
|
||||||
|
&usb {
|
||||||
|
status = "okay";
|
||||||
|
cdc_acm_uart0: cdc_acm_uart0 {
|
||||||
|
compatible = "zephyr,cdc-acm-uart";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zephyr,uart-mcumgr = &cdc_acm_uart0;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&spi2 {
|
||||||
|
/* Definiere die Pins für SCK, MISO, MOSI auf Port B */
|
||||||
|
pinctrl-0 = <&spi2_sck_pb13 &spi2_miso_pb14 &spi2_mosi_pb15>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
/* === Chip Select (CS) auf PA5 gesetzt === */
|
||||||
|
cs-gpios = <&gpioa 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
|
||||||
|
|
||||||
|
/* Definiere den Flash-Chip als SPI NOR Gerät */
|
||||||
|
flash1: flash@0 {
|
||||||
|
compatible = "jedec,spi-nor";
|
||||||
|
reg = <0>;
|
||||||
|
label = "flash1";
|
||||||
|
|
||||||
|
/* JEDEC ID für einen Winbond W25Q128 (16 MBytes) */
|
||||||
|
jedec-id = [ef 40 18];
|
||||||
|
|
||||||
|
/* Speichergröße in Bytes (16 MBytes) */
|
||||||
|
size = <DT_SIZE_M(16)>;
|
||||||
|
|
||||||
|
/* Maximale Taktfrequenz - angepasst an STM32G431 Limits */
|
||||||
|
spi-max-frequency = <1000000>;
|
||||||
|
|
||||||
|
/* Partitions für externes Flash */
|
||||||
|
partitions {
|
||||||
|
compatible = "fixed-partitions";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
/* Slot1 partition für MCUboot (sekundäres Image) - 80 KB (20 sectors @ 4KB) */
|
||||||
|
slot1_partition: partition@0 {
|
||||||
|
label = "image-1";
|
||||||
|
reg = <0x00000000 0x00014000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Scratch partition für MCUboot - 80 KB (20 sectors @ 4KB) */
|
||||||
|
scratch_partition: partition@14000 {
|
||||||
|
label = "scratch";
|
||||||
|
reg = <0x00014000 0x00014000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Speicher partition für LittleFS - ~15.83 MB */
|
||||||
|
storage_partition: partition@28000 {
|
||||||
|
label = "storage";
|
||||||
|
reg = <0x00028000 0x00FD8000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
CONFIG_LOG=y
|
||||||
|
CONFIG_MCUBOOT_LOG_LEVEL_INF=y
|
||||||
|
|
||||||
|
# Enable UART console for MCUboot debug output
|
||||||
|
CONFIG_UART_CONSOLE=y
|
||||||
|
CONFIG_CONSOLE=y
|
||||||
|
CONFIG_MCUBOOT_INDICATION_LED=y
|
||||||
|
|
||||||
|
# Enable external SPI flash support
|
||||||
|
CONFIG_SPI=y
|
||||||
|
CONFIG_SPI_NOR=y
|
||||||
|
CONFIG_SPI_NOR_SFDP_DEVICETREE=n
|
||||||
|
CONFIG_FLASH=y
|
||||||
|
CONFIG_FLASH_MAP=y
|
||||||
|
CONFIG_GPIO=y
|
||||||
|
|
||||||
|
# Add SPI NOR specific configurations - use 4KB page size (required by driver)
|
||||||
|
CONFIG_SPI_NOR_FLASH_LAYOUT_PAGE_SIZE=4096
|
||||||
|
CONFIG_SPI_NOR_INIT_PRIORITY=80
|
||||||
|
|
||||||
|
# Set maximum image sectors manually since auto doesn't work with external flash
|
||||||
|
CONFIG_BOOT_MAX_IMG_SECTORS_AUTO=n
|
||||||
|
CONFIG_BOOT_MAX_IMG_SECTORS=80
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "common.dtsi"
|
||||||
|
|
||||||
|
/* MCUboot Configuration - Bootloader wird in boot_partition geschrieben */
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zephyr,code-partition = &boot_partition;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
|
||||||
|
project(can_node LANGUAGES C)
|
||||||
|
|
||||||
|
zephyr_include_directories(../../include)
|
||||||
|
add_subdirectory(../../lib lib)
|
||||||
|
|
||||||
|
target_sources(app PRIVATE src/main.c)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
rsource "../../lib/Kconfig"
|
||||||
|
source "Kconfig.zephyr"
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
VERSION_MAJOR = 0
|
||||||
|
VERSION_MINOR = 0
|
||||||
|
PATCHLEVEL = 1
|
||||||
|
VERSION_TWEAK = 1
|
||||||
|
EXTRAVERSION = devel
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Disable UART console
|
||||||
|
CONFIG_UART_CONSOLE=n
|
||||||
|
|
||||||
|
# Enable RTT console
|
||||||
|
CONFIG_RTT_CONSOLE=y
|
||||||
|
CONFIG_USE_SEGGER_RTT=y
|
||||||
|
CONFIG_SHELL_BACKEND_RTT=y
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zephyr,console = &rtt;
|
||||||
|
zephyr,shell = &rtt;
|
||||||
|
zephyr,settings-partition = &storage_partition;
|
||||||
|
};
|
||||||
|
|
||||||
|
rtt: rtt {
|
||||||
|
compatible = "segger,rtt-uart";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
label = "RTT";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&flash0 {
|
||||||
|
partitions {
|
||||||
|
compatible = "fixed-partitions";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
/* Application partition starts at the beginning of flash */
|
||||||
|
slot0_partition: partition@0 {
|
||||||
|
label = "image-0";
|
||||||
|
reg = <0x00000000 DT_SIZE_K(120)>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Use the last 8K for settings */
|
||||||
|
storage_partition: partition@1E000 {
|
||||||
|
label = "storage";
|
||||||
|
reg = <0x0001E000 DT_SIZE_K(8)>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&usart1 {
|
||||||
|
modbus0 {
|
||||||
|
compatible = "zephyr,modbus-serial";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
/ {
|
||||||
|
aliases {
|
||||||
|
vnd7050aj = &vnd7050aj;
|
||||||
|
};
|
||||||
|
|
||||||
|
vnd7050aj: vnd7050aj {
|
||||||
|
compatible = "st,vnd7050aj";
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
input0-gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
|
||||||
|
input1-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
|
||||||
|
select0-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
|
||||||
|
select1-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
|
||||||
|
sense-enable-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
|
||||||
|
fault-reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
|
||||||
|
io-channels = <&adc0 0>;
|
||||||
|
r-sense-ohms = <1500>;
|
||||||
|
k-vcc = <4000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
modbus_uart: uart_2 {
|
||||||
|
compatible = "zephyr,native-pty-uart";
|
||||||
|
status = "okay";
|
||||||
|
current-speed = <19200>;
|
||||||
|
|
||||||
|
modbus0: modbus0 {
|
||||||
|
compatible = "zephyr,modbus-serial";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
&adc0 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
ref-internal-mv = <3300>;
|
||||||
|
ref-external1-mv = <5000>;
|
||||||
|
|
||||||
|
channel@0 {
|
||||||
|
reg = <0>;
|
||||||
|
zephyr,gain = "ADC_GAIN_1";
|
||||||
|
zephyr,reference = "ADC_REF_INTERNAL";
|
||||||
|
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
||||||
|
zephyr,resolution = <12>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
/ {
|
||||||
|
aliases {
|
||||||
|
vnd7050aj = &vnd7050aj;
|
||||||
|
};
|
||||||
|
|
||||||
|
vnd7050aj: vnd7050aj {
|
||||||
|
compatible = "st,vnd7050aj";
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
input0-gpios = <&gpiob 3 GPIO_ACTIVE_HIGH>;
|
||||||
|
input1-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>;
|
||||||
|
select0-gpios = <&gpiob 0 GPIO_ACTIVE_HIGH>;
|
||||||
|
select1-gpios = <&gpiob 1 GPIO_ACTIVE_HIGH>;
|
||||||
|
sense-enable-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>;
|
||||||
|
fault-reset-gpios = <&gpiob 5 GPIO_ACTIVE_LOW>;
|
||||||
|
io-channels = <&adc1 1>;
|
||||||
|
r-sense-ohms = <1500>;
|
||||||
|
k-vcc = <4000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&adc1 {
|
||||||
|
status = "okay";
|
||||||
|
pinctrl-0 = <&adc1_in1_pa0>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
st,adc-clock-source = "SYNC";
|
||||||
|
st,adc-prescaler = <4>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
channel@1 {
|
||||||
|
reg = <1>;
|
||||||
|
zephyr,gain = "ADC_GAIN_1";
|
||||||
|
zephyr,reference = "ADC_REF_INTERNAL";
|
||||||
|
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
||||||
|
zephyr,resolution = <12>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&usart1 {
|
||||||
|
modbus0 {
|
||||||
|
compatible = "zephyr,modbus-serial";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
status = "okay";
|
||||||
|
pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>; // PA9=TX, PA10=RX for Modbus communication
|
||||||
|
pinctrl-names = "default";
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <zephyr/dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
&zephyr_udc0 {
|
||||||
|
cdc_acm_uart0: cdc_acm_uart0 {
|
||||||
|
compatible = "zephyr,cdc-acm-uart";
|
||||||
|
|
||||||
|
modbus0 {
|
||||||
|
compatible = "zephyr,modbus-serial";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&usart1 {
|
||||||
|
/delete-node/ modbus0;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
# Copyright (c) 2024, Eduard Iten
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: |
|
||||||
|
STMicroelectronics VND7050AJ dual-channel high-side driver.
|
||||||
|
This is a GPIO and ADC controlled device.
|
||||||
|
|
||||||
|
compatible: "st,vnd7050aj"
|
||||||
|
|
||||||
|
include: base.yaml
|
||||||
|
|
||||||
|
properties:
|
||||||
|
input0-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO to control output channel 0.
|
||||||
|
|
||||||
|
input1-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO to control output channel 1.
|
||||||
|
|
||||||
|
select0-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO for MultiSense selection bit 0.
|
||||||
|
|
||||||
|
select1-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO for MultiSense selection bit 1.
|
||||||
|
|
||||||
|
sense-enable-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO to enable the MultiSense output.
|
||||||
|
|
||||||
|
fault-reset-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO to reset a latched fault (active-low).
|
||||||
|
|
||||||
|
io-channels:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: |
|
||||||
|
ADC channel connected to the MultiSense pin. This should be an
|
||||||
|
io-channels property pointing to the ADC controller and channel number.
|
||||||
|
|
||||||
|
r-sense-ohms:
|
||||||
|
type: int
|
||||||
|
required: true
|
||||||
|
description: |
|
||||||
|
Value of the external sense resistor connected from the MultiSense
|
||||||
|
pin to GND, specified in Ohms. This is critical for correct
|
||||||
|
conversion of the analog readings.
|
||||||
|
|
||||||
|
k-factor:
|
||||||
|
type: int
|
||||||
|
default: 1500
|
||||||
|
description: |
|
||||||
|
Factor between PowerMOS and SenseMOS.
|
||||||
|
|
||||||
|
k-vcc:
|
||||||
|
type: int
|
||||||
|
default: 8000
|
||||||
|
description: |
|
||||||
|
VCC sense ratio multiplied by 1000. Used for supply voltage calculation.
|
||||||
|
|
||||||
|
t-sense-0:
|
||||||
|
type: int
|
||||||
|
default: 25
|
||||||
|
description: |
|
||||||
|
Temperature sense reference temperature in degrees Celsius.
|
||||||
|
|
||||||
|
v-sense-0:
|
||||||
|
type: int
|
||||||
|
default: 2070
|
||||||
|
description: |
|
||||||
|
Temperature sense reference voltage in millivolts.
|
||||||
|
|
||||||
|
k-tchip:
|
||||||
|
type: int
|
||||||
|
default: -5500
|
||||||
|
description: |
|
||||||
|
Temperature sense gain coefficient multiplied by 1000.
|
||||||
|
Used for chip temperature calculation.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
CONFIG_USB_DEVICE_STACK=y
|
||||||
|
CONFIG_USB_DEVICE_PRODUCT="Modbus slave node"
|
||||||
|
CONFIG_UART_LINE_CTRL=y
|
||||||
|
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Enable Console and printk for logging
|
||||||
|
CONFIG_CONSOLE=y
|
||||||
|
CONFIG_LOG=y
|
||||||
|
|
||||||
|
# Enable Shell
|
||||||
|
CONFIG_SHELL=y
|
||||||
|
CONFIG_REBOOT=y
|
||||||
|
CONFIG_SHELL_MODBUS=n
|
||||||
|
CONFIG_SHELL_VALVE=y
|
||||||
|
CONFIG_SHELL_SYSTEM=y
|
||||||
|
|
||||||
|
# Enable Settings Subsystem
|
||||||
|
CONFIG_SETTINGS=y
|
||||||
|
CONFIG_SETTINGS_NVS=y
|
||||||
|
CONFIG_NVS=y
|
||||||
|
CONFIG_FLASH=y
|
||||||
|
CONFIG_FLASH_MAP=y
|
||||||
|
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||||
|
|
||||||
|
# Config modbus
|
||||||
|
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||||
|
CONFIG_MODBUS=y
|
||||||
|
CONFIG_MODBUS_ROLE_SERVER=y
|
||||||
|
CONFIG_MODBUS_LOG_LEVEL_DBG=y
|
||||||
|
|
||||||
|
# enable Valve Driver
|
||||||
|
CONFIG_LIB_VALVE=y
|
||||||
|
CONFIG_LOG_VALVE_LEVEL=4
|
||||||
|
|
||||||
|
# Enable VND7050AJ
|
||||||
|
CONFIG_VND7050AJ=y
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/settings/settings.h>
|
||||||
|
#include <app_version.h>
|
||||||
|
#include <lib/valve.h>
|
||||||
|
#include <lib/vnd7050aj.h>
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
LOG_INF("Starting Irrigation System CAN Node, Version %s", APP_VERSION_EXTENDED_STRING);
|
||||||
|
|
||||||
|
/* Initialize settings subsystem */
|
||||||
|
rc = settings_subsys_init();
|
||||||
|
if (rc != 0) {
|
||||||
|
LOG_ERR("Failed to initialize settings subsystem (%d)", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
LOG_INF("Settings subsystem initialized");
|
||||||
|
|
||||||
|
/* Load settings from storage */
|
||||||
|
rc = settings_load();
|
||||||
|
if (rc == 0) {
|
||||||
|
LOG_INF("Settings loaded successfully");
|
||||||
|
} else {
|
||||||
|
LOG_WRN("Failed to load settings (%d)", rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize valve system */
|
||||||
|
rc = valve_init();
|
||||||
|
if (rc != 0) {
|
||||||
|
LOG_ERR("Failed to initialize valve system (%d)", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
LOG_INF("Valve system initialized");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
SB_CONFIG_BOOTLOADER_MCUBOOT=y
|
||||||
|
SB_CONFIG_MCUBOOT_MODE_SINGLE_APP=y
|
||||||
|
|
||||||
|
CONFIG_LOG=y
|
||||||
|
CONFIG_MCUBOOT_LOG_LEVEL_INF=y
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
cmake_minimum_required(VERSION 3.20.5)
|
||||||
|
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
|
||||||
|
project(gateway)
|
||||||
|
target_sources(app PRIVATE src/main.c)
|
||||||
|
|
||||||
|
target_include_directories(app PRIVATE include)
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
# README for the Hello World Zephyr Application
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This is a minimal Hello World application built using the Zephyr RTOS. The application demonstrates basic logging functionality by printing a message every 5 seconds, including the version number of the application.
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
The project consists of the following files:
|
||||||
|
|
||||||
|
- `src/main.c`: The entry point of the application that initializes logging and sets up a timer.
|
||||||
|
- `include/app_version.h`: Header file that defines the application version.
|
||||||
|
- `VERSION`: A text file containing the version number of the application.
|
||||||
|
- `prj.conf`: Configuration file for the Zephyr project, specifying necessary options.
|
||||||
|
- `CMakeLists.txt`: Build configuration file for CMake.
|
||||||
|
- `README.md`: Documentation for the project.
|
||||||
|
|
||||||
|
## Building the Application
|
||||||
|
|
||||||
|
To build the application, follow these steps:
|
||||||
|
|
||||||
|
1. Ensure you have the Zephyr development environment set up.
|
||||||
|
2. Navigate to the `apps/gateway` directory.
|
||||||
|
3. Run the following command to build the application:
|
||||||
|
|
||||||
|
```
|
||||||
|
west build -b <your_board> .
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `<your_board>` with the appropriate board name.
|
||||||
|
|
||||||
|
## Running the Application
|
||||||
|
|
||||||
|
After building the application, you can flash it to your board using:
|
||||||
|
|
||||||
|
```
|
||||||
|
west flash
|
||||||
|
```
|
||||||
|
|
||||||
|
Once the application is running, you will see log messages printed every 5 seconds, including the version number.
|
||||||
|
|
||||||
|
## Version
|
||||||
|
|
||||||
|
The version of this application can be found in the `VERSION` file and is also included in the log messages.
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
VERSION_MAJOR = 0
|
||||||
|
VERSION_MINOR = 0
|
||||||
|
PATCHLEVEL = 1
|
||||||
|
VERSION_TWEAK = 0
|
||||||
|
EXTRAVERSION = devel
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
&flash0 {
|
||||||
|
reg = <0x0 0x400000>; /* 4MB flash */
|
||||||
|
};
|
||||||
|
|
||||||
|
#include "espressif/partitions_0x0_default_4M.dtsi"
|
||||||
|
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zephyr,shell-uart = &uart0;
|
||||||
|
zephyr,uart-mcumgr = &usb_serial;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&usb_serial {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
#include "common_4MB.dtsi"
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
# -------------------
|
||||||
|
# Logging and Console
|
||||||
|
# -------------------
|
||||||
|
CONFIG_LOG=y
|
||||||
|
CONFIG_UART_CONSOLE=y
|
||||||
|
|
||||||
|
# -------------
|
||||||
|
# Zephyr Shell
|
||||||
|
# -------------
|
||||||
|
CONFIG_SHELL=y
|
||||||
|
CONFIG_KERNEL_SHELL=y
|
||||||
|
CONFIG_REBOOT=y
|
||||||
|
|
||||||
|
# -------------------
|
||||||
|
# MCUmgr OS Management
|
||||||
|
# -------------------
|
||||||
|
CONFIG_MCUMGR=y
|
||||||
|
CONFIG_MCUMGR_GRP_OS=y
|
||||||
|
CONFIG_MCUMGR_TRANSPORT_UART=y
|
||||||
|
|
||||||
|
# -------------------
|
||||||
|
# MCUmgr Filesystem Group
|
||||||
|
# -------------------
|
||||||
|
CONFIG_MCUMGR_GRP_FS=y
|
||||||
|
|
||||||
|
# -------------------
|
||||||
|
# LittleFS and Flash
|
||||||
|
# -------------------
|
||||||
|
CONFIG_FILE_SYSTEM=y
|
||||||
|
CONFIG_FILE_SYSTEM_LITTLEFS=y
|
||||||
|
CONFIG_FLASH=y
|
||||||
|
CONFIG_FLASH_MAP=y
|
||||||
|
|
||||||
|
# -------------------
|
||||||
|
# Settings Subsystem
|
||||||
|
# -------------------
|
||||||
|
CONFIG_SETTINGS=y
|
||||||
|
CONFIG_SETTINGS_FILE=y
|
||||||
|
CONFIG_SETTINGS_FILE_PATH="/lfs/settings.bin"
|
||||||
|
|
||||||
|
# -------------------
|
||||||
|
# Dependencies
|
||||||
|
# -------------------
|
||||||
|
CONFIG_NET_BUF=y
|
||||||
|
CONFIG_ZCBOR=y
|
||||||
|
CONFIG_CRC=y
|
||||||
|
CONFIG_BASE64=y
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
#include <zephyr/fs/fs.h>
|
||||||
|
#include <zephyr/fs/littlefs.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/settings/settings.h>
|
||||||
|
#include <zephyr/shell/shell.h>
|
||||||
|
#include <app_version.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(hello_world);
|
||||||
|
|
||||||
|
/* LittleFS mount configuration for 'storage_partition' partition */
|
||||||
|
FS_LITTLEFS_DECLARE_DEFAULT_CONFIG(storage_partition);
|
||||||
|
static struct fs_mount_t littlefs_mnt = {
|
||||||
|
.type = FS_LITTLEFS,
|
||||||
|
.mnt_point = "/lfs",
|
||||||
|
.fs_data = &storage_partition, // default config macro
|
||||||
|
.storage_dev = (void *)FIXED_PARTITION_ID(storage_partition),
|
||||||
|
};
|
||||||
|
|
||||||
|
static char my_setting[32] = "default";
|
||||||
|
|
||||||
|
static int my_settings_set(const char *name, size_t len, settings_read_cb read_cb, void *cb_arg)
|
||||||
|
{
|
||||||
|
if (strcmp(name, "value") == 0) {
|
||||||
|
if (len > sizeof(my_setting) - 1) {
|
||||||
|
len = sizeof(my_setting) - 1;
|
||||||
|
}
|
||||||
|
if (read_cb(cb_arg, my_setting, len) == len) {
|
||||||
|
my_setting[len] = '\0';
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int my_settings_export(int (*export_func)(const char *, const void *, size_t))
|
||||||
|
{
|
||||||
|
return export_func("my/setting/value", my_setting, strlen(my_setting));
|
||||||
|
}
|
||||||
|
|
||||||
|
SETTINGS_STATIC_HANDLER_DEFINE(my, "my/setting", NULL, my_settings_set, NULL, my_settings_export);
|
||||||
|
|
||||||
|
static int cmd_my_get(const struct shell *shell, size_t argc, char **argv)
|
||||||
|
{
|
||||||
|
shell_print(shell, "my_setting = '%s'", my_setting);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cmd_my_reset(const struct shell *shell, size_t argc, char **argv)
|
||||||
|
{
|
||||||
|
strcpy(my_setting, "default");
|
||||||
|
settings_save();
|
||||||
|
shell_print(shell, "my_setting reset to default");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Improved set command: join all arguments for whitespace support
|
||||||
|
static int cmd_my_set(const struct shell *shell, size_t argc, char **argv)
|
||||||
|
{
|
||||||
|
if (argc < 2) {
|
||||||
|
shell_error(shell, "Usage: my set <value>");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
// Join all argv[1..] with spaces
|
||||||
|
size_t i, pos = 0;
|
||||||
|
my_setting[0] = '\0';
|
||||||
|
for (i = 1; i < argc; ++i) {
|
||||||
|
size_t left = sizeof(my_setting) - 1 - pos;
|
||||||
|
if (left == 0)
|
||||||
|
break;
|
||||||
|
strncat(my_setting, argv[i], left);
|
||||||
|
pos = strlen(my_setting);
|
||||||
|
if (i < argc - 1 && left > 1) {
|
||||||
|
strncat(my_setting, " ", left - 1);
|
||||||
|
pos = strlen(my_setting);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
my_setting[sizeof(my_setting) - 1] = '\0';
|
||||||
|
settings_save();
|
||||||
|
shell_print(shell, "my_setting set to '%s'", my_setting);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SHELL_STATIC_SUBCMD_SET_CREATE(my_subcmds,
|
||||||
|
SHELL_CMD(get, NULL, "Get my_setting", cmd_my_get),
|
||||||
|
SHELL_CMD(set, NULL, "Set my_setting (supports spaces)", cmd_my_set),
|
||||||
|
SHELL_CMD(reset, NULL, "Reset my_setting to default and compact settings file", cmd_my_reset),
|
||||||
|
SHELL_SUBCMD_SET_END);
|
||||||
|
|
||||||
|
SHELL_CMD_REGISTER(my, &my_subcmds, "My settings commands", NULL);
|
||||||
|
|
||||||
|
static void compact_settings_file(void)
|
||||||
|
{
|
||||||
|
struct fs_file_t file;
|
||||||
|
fs_file_t_init(&file);
|
||||||
|
int rc = fs_open(&file, "/lfs/settings.bin", FS_O_WRITE | FS_O_CREATE | FS_O_TRUNC);
|
||||||
|
if (rc == 0) {
|
||||||
|
fs_close(&file);
|
||||||
|
LOG_INF("Settings file compacted (truncated and recreated)");
|
||||||
|
} else if (rc == -ENOENT) {
|
||||||
|
LOG_INF("Settings file did not exist, created new");
|
||||||
|
} else {
|
||||||
|
LOG_ERR("Failed to compact settings file (%d)", rc);
|
||||||
|
}
|
||||||
|
settings_save();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int rc = fs_mount(&littlefs_mnt);
|
||||||
|
if (rc < 0) {
|
||||||
|
LOG_ERR("Error mounting LittleFS [%d]", rc);
|
||||||
|
} else {
|
||||||
|
LOG_INF("LittleFS mounted at /lfs");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize settings subsystem */
|
||||||
|
settings_subsys_init();
|
||||||
|
LOG_INF("Settings subsystem initialized");
|
||||||
|
|
||||||
|
/* Load settings from storage */
|
||||||
|
rc = settings_load();
|
||||||
|
if (rc == 0) {
|
||||||
|
LOG_INF("Settings loaded: my_setting='%s'", my_setting);
|
||||||
|
} else {
|
||||||
|
LOG_ERR("Failed to load settings (%d)", rc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compact settings file on each start */
|
||||||
|
compact_settings_file();
|
||||||
|
|
||||||
|
LOG_INF("Hello World! Version: %s", APP_VERSION_EXTENDED_STRING);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
SB_CONFIG_BOOTLOADER_MCUBOOT=y
|
||||||
|
SB_CONFIG_MCUBOOT_MODE_SINGLE_APP=y
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "../boards/common_4MB.dtsi"
|
||||||
|
|
||||||
|
/* Application Configuration - Firmware goes to slot0_partition (0x20000) */
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zephyr,code-partition = &slot0_partition;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
CONFIG_LOG=y
|
||||||
|
CONFIG_MCUBOOT_LOG_LEVEL_INF=y
|
||||||
|
CONFIG_UART_CONSOLE=n
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "../boards/common_4MB.dtsi"
|
||||||
|
|
||||||
|
/* MCUboot Configuration - Bootloader goes to boot_partition (0x0) */
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zephyr,code-partition = &boot_partition;
|
||||||
|
};
|
||||||
|
aliases {
|
||||||
|
mcuboot-button0 = &user_button1;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit 6e669cfc4e400c3ef6e55c16401788ce0d804577
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"compileCommands": "${workspaceFolder}/build/compile_commands.json",
|
||||||
|
"cStandard": "c99",
|
||||||
|
"cppStandard": "gnu++17",
|
||||||
|
"intelliSenseMode": "linux-gcc-arm"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
cmake_minimum_required(VERSION 3.20)
|
||||||
|
|
||||||
|
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||||
|
|
||||||
|
project(slave_node LANGUAGES C)
|
||||||
|
|
||||||
|
zephyr_include_directories(../../include)
|
||||||
|
add_subdirectory(../../lib lib)
|
||||||
|
|
||||||
|
target_sources(app PRIVATE src/main.c)
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
rsource "../../lib/Kconfig"
|
||||||
|
source "Kconfig.zephyr"
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
VERSION_MAJOR = 0
|
||||||
|
VERSION_MINOR = 0
|
||||||
|
PATCHLEVEL = 1
|
||||||
|
VERSION_TWEAK = 1
|
||||||
|
EXTRAVERSION = devel
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Disable UART console
|
||||||
|
CONFIG_UART_CONSOLE=n
|
||||||
|
|
||||||
|
# Enable RTT console
|
||||||
|
CONFIG_RTT_CONSOLE=y
|
||||||
|
CONFIG_USE_SEGGER_RTT=y
|
||||||
|
CONFIG_SHELL_BACKEND_RTT=y
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
/ {
|
||||||
|
chosen {
|
||||||
|
zephyr,console = &rtt;
|
||||||
|
zephyr,shell = &rtt;
|
||||||
|
zephyr,settings-partition = &storage_partition;
|
||||||
|
};
|
||||||
|
|
||||||
|
rtt: rtt {
|
||||||
|
compatible = "segger,rtt-uart";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
label = "RTT";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&flash0 {
|
||||||
|
partitions {
|
||||||
|
compatible = "fixed-partitions";
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
|
||||||
|
/* Application partition starts at the beginning of flash */
|
||||||
|
slot0_partition: partition@0 {
|
||||||
|
label = "image-0";
|
||||||
|
reg = <0x00000000 DT_SIZE_K(120)>;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Use the last 8K for settings */
|
||||||
|
storage_partition: partition@1E000 {
|
||||||
|
label = "storage";
|
||||||
|
reg = <0x0001E000 DT_SIZE_K(8)>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&usart1 {
|
||||||
|
modbus0 {
|
||||||
|
compatible = "zephyr,modbus-serial";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
/ {
|
||||||
|
aliases {
|
||||||
|
vnd7050aj = &vnd7050aj;
|
||||||
|
};
|
||||||
|
|
||||||
|
vnd7050aj: vnd7050aj {
|
||||||
|
compatible = "st,vnd7050aj";
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
input0-gpios = <&gpio0 1 GPIO_ACTIVE_HIGH>;
|
||||||
|
input1-gpios = <&gpio0 2 GPIO_ACTIVE_HIGH>;
|
||||||
|
select0-gpios = <&gpio0 3 GPIO_ACTIVE_HIGH>;
|
||||||
|
select1-gpios = <&gpio0 4 GPIO_ACTIVE_HIGH>;
|
||||||
|
sense-enable-gpios = <&gpio0 5 GPIO_ACTIVE_HIGH>;
|
||||||
|
fault-reset-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
|
||||||
|
io-channels = <&adc0 0>;
|
||||||
|
r-sense-ohms = <1500>;
|
||||||
|
k-vcc = <4000>;
|
||||||
|
};
|
||||||
|
|
||||||
|
modbus_uart: uart_2 {
|
||||||
|
compatible = "zephyr,native-pty-uart";
|
||||||
|
status = "okay";
|
||||||
|
current-speed = <19200>;
|
||||||
|
|
||||||
|
modbus0: modbus0 {
|
||||||
|
compatible = "zephyr,modbus-serial";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
&adc0 {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
ref-internal-mv = <3300>;
|
||||||
|
ref-external1-mv = <5000>;
|
||||||
|
|
||||||
|
channel@0 {
|
||||||
|
reg = <0>;
|
||||||
|
zephyr,gain = "ADC_GAIN_1";
|
||||||
|
zephyr,reference = "ADC_REF_INTERNAL";
|
||||||
|
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
||||||
|
zephyr,resolution = <12>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
/ {
|
||||||
|
aliases {
|
||||||
|
vnd7050aj = &vnd7050aj;
|
||||||
|
};
|
||||||
|
|
||||||
|
vnd7050aj: vnd7050aj {
|
||||||
|
compatible = "st,vnd7050aj";
|
||||||
|
status = "okay";
|
||||||
|
|
||||||
|
input0-gpios = <&gpiob 3 GPIO_ACTIVE_HIGH>;
|
||||||
|
input1-gpios = <&gpiob 4 GPIO_ACTIVE_HIGH>;
|
||||||
|
select0-gpios = <&gpiob 7 GPIO_ACTIVE_HIGH>;
|
||||||
|
select1-gpios = <&gpiob 9 GPIO_ACTIVE_HIGH>;
|
||||||
|
sense-enable-gpios = <&gpiob 6 GPIO_ACTIVE_HIGH>;
|
||||||
|
fault-reset-gpios = <&gpiob 5 GPIO_ACTIVE_LOW>;
|
||||||
|
io-channels = <&adc1 1>;
|
||||||
|
r-sense-ohms = <1500>;
|
||||||
|
k-vcc = <4000>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&adc1 {
|
||||||
|
status = "okay";
|
||||||
|
pinctrl-0 = <&adc1_in1_pa0>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
st,adc-clock-source = "SYNC";
|
||||||
|
st,adc-prescaler = <4>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
channel@1 {
|
||||||
|
reg = <1>;
|
||||||
|
zephyr,gain = "ADC_GAIN_1";
|
||||||
|
zephyr,reference = "ADC_REF_INTERNAL";
|
||||||
|
zephyr,acquisition-time = <ADC_ACQ_TIME_DEFAULT>;
|
||||||
|
zephyr,resolution = <12>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&usart1 {
|
||||||
|
modbus0 {
|
||||||
|
compatible = "zephyr,modbus-serial";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
status = "okay";
|
||||||
|
pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>; // PA9=TX, PA10=RX for Modbus communication
|
||||||
|
pinctrl-names = "default";
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include <zephyr/dt-bindings/gpio/gpio.h>
|
||||||
|
|
||||||
|
&zephyr_udc0 {
|
||||||
|
cdc_acm_uart0: cdc_acm_uart0 {
|
||||||
|
compatible = "zephyr,cdc-acm-uart";
|
||||||
|
|
||||||
|
modbus0 {
|
||||||
|
compatible = "zephyr,modbus-serial";
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
&usart1 {
|
||||||
|
/delete-node/ modbus0;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
# Copyright (c) 2024, Eduard Iten
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
description: |
|
||||||
|
STMicroelectronics VND7050AJ dual-channel high-side driver.
|
||||||
|
This is a GPIO and ADC controlled device.
|
||||||
|
|
||||||
|
compatible: "st,vnd7050aj"
|
||||||
|
|
||||||
|
include: base.yaml
|
||||||
|
|
||||||
|
properties:
|
||||||
|
input0-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO to control output channel 0.
|
||||||
|
|
||||||
|
input1-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO to control output channel 1.
|
||||||
|
|
||||||
|
select0-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO for MultiSense selection bit 0.
|
||||||
|
|
||||||
|
select1-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO for MultiSense selection bit 1.
|
||||||
|
|
||||||
|
sense-enable-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO to enable the MultiSense output.
|
||||||
|
|
||||||
|
fault-reset-gpios:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: GPIO to reset a latched fault (active-low).
|
||||||
|
|
||||||
|
io-channels:
|
||||||
|
type: phandle-array
|
||||||
|
required: true
|
||||||
|
description: |
|
||||||
|
ADC channel connected to the MultiSense pin. This should be an
|
||||||
|
io-channels property pointing to the ADC controller and channel number.
|
||||||
|
|
||||||
|
r-sense-ohms:
|
||||||
|
type: int
|
||||||
|
required: true
|
||||||
|
description: |
|
||||||
|
Value of the external sense resistor connected from the MultiSense
|
||||||
|
pin to GND, specified in Ohms. This is critical for correct
|
||||||
|
conversion of the analog readings.
|
||||||
|
|
||||||
|
k-factor:
|
||||||
|
type: int
|
||||||
|
default: 1500
|
||||||
|
description: |
|
||||||
|
Factor between PowerMOS and SenseMOS.
|
||||||
|
|
||||||
|
k-vcc:
|
||||||
|
type: int
|
||||||
|
default: 8000
|
||||||
|
description: |
|
||||||
|
VCC sense ratio multiplied by 1000. Used for supply voltage calculation.
|
||||||
|
|
||||||
|
t-sense-0:
|
||||||
|
type: int
|
||||||
|
default: 25
|
||||||
|
description: |
|
||||||
|
Temperature sense reference temperature in degrees Celsius.
|
||||||
|
|
||||||
|
v-sense-0:
|
||||||
|
type: int
|
||||||
|
default: 2070
|
||||||
|
description: |
|
||||||
|
Temperature sense reference voltage in millivolts.
|
||||||
|
|
||||||
|
k-tchip:
|
||||||
|
type: int
|
||||||
|
default: -5500
|
||||||
|
description: |
|
||||||
|
Temperature sense gain coefficient multiplied by 1000.
|
||||||
|
Used for chip temperature calculation.
|
||||||
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
CONFIG_USB_DEVICE_STACK=y
|
||||||
|
CONFIG_USB_DEVICE_PRODUCT="Modbus slave node"
|
||||||
|
CONFIG_UART_LINE_CTRL=y
|
||||||
|
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Enable Console and printk for logging
|
||||||
|
CONFIG_CONSOLE=y
|
||||||
|
CONFIG_LOG=y
|
||||||
|
|
||||||
|
# Enable Shell
|
||||||
|
CONFIG_SHELL=y
|
||||||
|
CONFIG_REBOOT=y
|
||||||
|
CONFIG_SHELL_MODBUS=y
|
||||||
|
CONFIG_SHELL_VALVE=y
|
||||||
|
CONFIG_SHELL_SYSTEM=y
|
||||||
|
|
||||||
|
# Enable Settings Subsystem
|
||||||
|
CONFIG_SETTINGS=y
|
||||||
|
CONFIG_SETTINGS_NVS=y
|
||||||
|
CONFIG_NVS=y
|
||||||
|
CONFIG_FLASH=y
|
||||||
|
CONFIG_FLASH_MAP=y
|
||||||
|
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||||
|
CONFIG_SETTINGS_LOG_LEVEL_DBG=y
|
||||||
|
|
||||||
|
# Config modbus
|
||||||
|
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||||
|
CONFIG_MODBUS=y
|
||||||
|
CONFIG_MODBUS_ROLE_SERVER=y
|
||||||
|
CONFIG_MODBUS_LOG_LEVEL_DBG=y
|
||||||
|
|
||||||
|
# Enable VND7050AJ
|
||||||
|
CONFIG_VND7050AJ=y
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
#include <zephyr/logging/log.h>
|
||||||
|
#include <zephyr/settings/settings.h>
|
||||||
|
#include <lib/fwu.h>
|
||||||
|
#include <lib/modbus_server.h>
|
||||||
|
#include <lib/valve.h>
|
||||||
|
|
||||||
|
LOG_MODULE_REGISTER(main, LOG_LEVEL_INF);
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
LOG_INF("Starting Irrigation System Slave Node");
|
||||||
|
|
||||||
|
if (settings_subsys_init() || settings_load()) {
|
||||||
|
LOG_ERR("Settings initialization or loading failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
valve_init();
|
||||||
|
fwu_init();
|
||||||
|
|
||||||
|
rc = modbus_server_init();
|
||||||
|
if (rc) {
|
||||||
|
LOG_ERR("Modbus server initialization failed: %d", rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INF("Irrigation System Slave Node started successfully");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
SB_CONFIG_BOOTLOADER_MCUBOOT=y
|
||||||
|
SB_CONFIG_MCUBOOT_MODE_SINGLE_APP=y
|
||||||
|
|
||||||
|
CONFIG_LOG=y
|
||||||
|
CONFIG_MCUBOOT_LOG_LEVEL_INF=y
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Copyright (c) 2025 Eduard Iten
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
config BOARD_BLUEPILL_F103RB
|
||||||
|
select SOC_STM32F103XB
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025 Eduard Iten
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/dts-v1/;
|
||||||
|
#include <st/f1/stm32f1.dtsi>
|
||||||
|
#include <st/f1/stm32f103Xb.dtsi>
|
||||||
|
#include <st/f1/stm32f103r(8-b)tx-pinctrl.dtsi>
|
||||||
|
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
model = "Blue-Pill STM32F103RB";
|
||||||
|
compatible = "iten,bluepill-f103rb";
|
||||||
|
|
||||||
|
chosen {
|
||||||
|
zephyr,console = &usart1;
|
||||||
|
zephyr,shell-uart = &usart1;
|
||||||
|
zephyr,sram = &sram0;
|
||||||
|
zephyr,flash = &flash0;
|
||||||
|
};
|
||||||
|
|
||||||
|
leds {
|
||||||
|
compatible = "gpio-leds";
|
||||||
|
led_status: led_status {
|
||||||
|
gpios = <&gpioc 13 GPIO_ACTIVE_LOW>;
|
||||||
|
label = "User LED";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
aliases {
|
||||||
|
led0 = &led_status;
|
||||||
|
watchdog0 = &iwdg;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
&clk_lsi {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&clk_hse {
|
||||||
|
clock-frequency = <DT_FREQ_M(8)>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&pll {
|
||||||
|
mul = <9>;
|
||||||
|
clocks = <&clk_hse>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&rcc {
|
||||||
|
clocks = <&pll>;
|
||||||
|
clock-frequency = <DT_FREQ_M(72)>;
|
||||||
|
ahb-prescaler = <1>;
|
||||||
|
apb1-prescaler = <2>;
|
||||||
|
apb2-prescaler = <1>;
|
||||||
|
adc-prescaler = <6>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
&usart1 {
|
||||||
|
pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>;
|
||||||
|
pinctrl-names = "default";
|
||||||
|
current-speed = <115200>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&iwdg {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
&clk_lsi {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&clk_hse {
|
||||||
|
clock-frequency = <DT_FREQ_M(8)>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&pll {
|
||||||
|
mul = <9>;
|
||||||
|
clocks = <&clk_hse>;
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&rcc {
|
||||||
|
clocks = <&pll>;
|
||||||
|
clock-frequency = <DT_FREQ_M(72)>;
|
||||||
|
ahb-prescaler = <1>;
|
||||||
|
apb1-prescaler = <2>;
|
||||||
|
apb2-prescaler = <1>;
|
||||||
|
adc-prescaler = <6>;
|
||||||
|
};
|
||||||
|
|
||||||
|
&exti {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
||||||
|
&dma1 {
|
||||||
|
status = "okay";
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Copyright (c) 2025 Eduard Iten
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
CONFIG_SERIAL=y
|
||||||
|
CONFIG_GPIO=y
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
|
# Copyright (c) 2025 Eduard Iten
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
# keep first
|
# keep first
|
||||||
board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw")
|
|
||||||
board_runner_args(jlink "--device=STM32F103RB" "--speed=4000")
|
board_runner_args(jlink "--device=STM32F103RB" "--speed=4000")
|
||||||
|
board_runner_args(stm32cubeprogrammer "--port=swd" "--reset-mode=hw")
|
||||||
|
|
||||||
# keep first
|
# keep first
|
||||||
|
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
||||||
include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake)
|
include(${ZEPHYR_BASE}/boards/common/stm32cubeprogrammer.board.cmake)
|
||||||
include(${ZEPHYR_BASE}/boards/common/openocd-stm32.board.cmake)
|
include(${ZEPHYR_BASE}/boards/common/openocd-stm32.board.cmake)
|
||||||
include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
|
|
||||||
include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake)
|
include(${ZEPHYR_BASE}/boards/common/blackmagicprobe.board.cmake)
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
# Copyright (c) 2025 Eduard Iten
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
board:
|
||||||
|
name: bluepill_f103rb
|
||||||
|
vendor: iten
|
||||||
|
socs:
|
||||||
|
- name: stm32f103xb
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
config BOARD_VALVE_NODE
|
|
||||||
select SOC_STM32F103XB
|
|
||||||
|
|
||||||
mainmenu "APP CAN Settings"
|
|
||||||
config LOOPBACK_MODE
|
|
||||||
bool "Loopback LOOPBACK_MODE"
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Set the can controller to loopback mode.
|
|
||||||
This allows testing without a second board.
|
|
||||||
|
|
||||||
mainmenu "APP Logging Settings"
|
|
||||||
config LOG_CAN_LEVEL
|
|
||||||
int "Log level for CAN"
|
|
||||||
default 3
|
|
||||||
range 0 7
|
|
||||||
help
|
|
||||||
Set the log level for CAN messages.
|
|
||||||
0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug, 5 = Trace, 6 = Debug2, 7 = Debug3
|
|
||||||
|
|
||||||
config LOG_SETTINGS_LEVEL
|
|
||||||
int "Log level for settings"
|
|
||||||
default 3
|
|
||||||
range 0 7
|
|
||||||
help
|
|
||||||
Set the log level for CAN messages.
|
|
||||||
0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug, 5 = Trace, 6 = Debug2, 7 = Debug3
|
|
||||||
|
|
||||||
config LOG_WATERLEVELSENSOR_LEVEL
|
|
||||||
int "Log level for waterlevel sensor"
|
|
||||||
default 3
|
|
||||||
range 0 7
|
|
||||||
help
|
|
||||||
Set the log level for CAN messages.
|
|
||||||
0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug, 5 = Trace, 6 = Debug2, 7 = Debug3
|
|
||||||
|
|
||||||
config LOG_VALVE_LEVEL
|
|
||||||
int "Log level for valve control"
|
|
||||||
default 3
|
|
||||||
range 0 7
|
|
||||||
help
|
|
||||||
Set the log level for valve control messages.
|
|
||||||
0 = None, 1 = Error, 2 = Warning, 3 = Info, 4 = Debug, 5 = Trace, 6 = Debug2, 7 = Debug3
|
|
||||||
|
|
||||||
mainmenu "Irrigation controller node configuration"
|
|
||||||
config HAS_MODBUS_WATERLEVEL_SENSOR
|
|
||||||
bool "Has modbus water level sensor"
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Enable modbus water level sensor support.
|
|
||||||
This allows reading the water level from a modbus device.
|
|
||||||
|
|
||||||
config HAS_VALVE
|
|
||||||
bool "Has valve control"
|
|
||||||
default n
|
|
||||||
help
|
|
||||||
Enable valve control support.
|
|
||||||
This allows controlling valves via CAN messages.
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
board:
|
|
||||||
name: valve_node
|
|
||||||
full_name: Irrigation system CANbus valve node
|
|
||||||
socs:
|
|
||||||
- name: stm32f103xb
|
|
||||||
# revision:
|
|
||||||
# format: number
|
|
||||||
# default: "1"
|
|
||||||
# revisions:
|
|
||||||
# -name: "1"
|
|
||||||
|
|
@ -1,206 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2017 Linaro Limited
|
|
||||||
*
|
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
/dts-v1/;
|
|
||||||
#include <st/f1/stm32f1.dtsi>
|
|
||||||
#include <st/f1/stm32f103Xb.dtsi>
|
|
||||||
#include <st/f1/stm32f103r(8-b)tx-pinctrl.dtsi>
|
|
||||||
#include <zephyr/dt-bindings/input/input-event-codes.h>
|
|
||||||
|
|
||||||
/ {
|
|
||||||
model = "Iten engineering Valve Node";
|
|
||||||
compatible = "st,stm32f103rb";
|
|
||||||
|
|
||||||
can_loopback0: can_loopback0 {
|
|
||||||
status = "disabled";
|
|
||||||
compatible = "zephyr,can-loopback";
|
|
||||||
};
|
|
||||||
|
|
||||||
chosen {
|
|
||||||
zephyr,console = &usart1;
|
|
||||||
zephyr,shell-uart = &usart1;
|
|
||||||
zephyr,sram = &sram0;
|
|
||||||
zephyr,flash = &flash0;
|
|
||||||
zephyr,canbus = &can1;
|
|
||||||
};
|
|
||||||
|
|
||||||
leds: leds {
|
|
||||||
compatible = "gpio-leds";
|
|
||||||
|
|
||||||
green_led_2: led_2 {
|
|
||||||
gpios = <&gpiob 2 GPIO_ACTIVE_HIGH>;
|
|
||||||
label = "User LD2";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
gpio_keys {
|
|
||||||
compatible = "gpio-keys";
|
|
||||||
|
|
||||||
user_button: button {
|
|
||||||
label = "User";
|
|
||||||
gpios = <&gpioc 13 GPIO_ACTIVE_LOW>;
|
|
||||||
zephyr,code = <INPUT_KEY_0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
endstopopen: endstop_open {
|
|
||||||
gpios = <&gpiob 4 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
|
|
||||||
label = "Endstop Open";
|
|
||||||
};
|
|
||||||
|
|
||||||
endstopclose: endstop_closed {
|
|
||||||
gpios = <&gpiob 5 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
|
|
||||||
label = "Endstop Close";
|
|
||||||
};
|
|
||||||
|
|
||||||
statusopen: status_open {
|
|
||||||
gpios = <&gpiob 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
|
|
||||||
label = "Status Open";
|
|
||||||
};
|
|
||||||
|
|
||||||
statusclose: status_close {
|
|
||||||
gpios = <&gpioa 8 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
|
|
||||||
label = "Status Close";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
aliases {
|
|
||||||
led0 = &green_led_2;
|
|
||||||
sw0 = &user_button;
|
|
||||||
watchdog0 = &iwdg;
|
|
||||||
die-temp0 = &die_temp;
|
|
||||||
adc-motor-current = &motor_current_channel;
|
|
||||||
adc-vref = &vref_channel;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
&clk_lsi {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&clk_hse {
|
|
||||||
clock-frequency = <DT_FREQ_M(8)>;
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&pll {
|
|
||||||
mul = <9>;
|
|
||||||
clocks = <&clk_hse>;
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&rcc {
|
|
||||||
clocks = <&pll>;
|
|
||||||
clock-frequency = <DT_FREQ_M(72)>;
|
|
||||||
ahb-prescaler = <1>;
|
|
||||||
apb1-prescaler = <2>;
|
|
||||||
apb2-prescaler = <1>;
|
|
||||||
adc-prescaler = <6>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&usart1 {
|
|
||||||
pinctrl-0 = <&usart1_tx_pa9 &usart1_rx_pa10>;
|
|
||||||
pinctrl-names = "default";
|
|
||||||
status = "okay";
|
|
||||||
current-speed = <115200>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&usart2 {
|
|
||||||
pinctrl-0 = <&usart2_tx_pa2 &usart2_rx_pa3>;
|
|
||||||
current-speed = <9600>;
|
|
||||||
pinctrl-names = "default";
|
|
||||||
status = "okay";
|
|
||||||
modbus0 {
|
|
||||||
compatible = "zephyr,modbus-serial";
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&usart3 {
|
|
||||||
pinctrl-0 = <&usart3_tx_pb10 &usart3_rx_pb11>;
|
|
||||||
current-speed = <115200>;
|
|
||||||
pinctrl-names = "default";
|
|
||||||
};
|
|
||||||
|
|
||||||
&i2c1 {
|
|
||||||
pinctrl-0 = <&i2c1_scl_remap1_pb8 &i2c1_sda_remap1_pb9>;
|
|
||||||
pinctrl-names = "default";
|
|
||||||
status = "okay";
|
|
||||||
clock-frequency = <I2C_BITRATE_FAST>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&iwdg {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&rtc {
|
|
||||||
clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>,
|
|
||||||
<&rcc STM32_SRC_LSI RTC_SEL(2)>;
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&adc1 {
|
|
||||||
pinctrl-0 = <&adc_pb1_pins>;
|
|
||||||
pinctrl-names = "default";
|
|
||||||
status = "okay";
|
|
||||||
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <0>;
|
|
||||||
|
|
||||||
motor_current_channel: channel@9 {
|
|
||||||
reg = <0x9>;
|
|
||||||
zephyr,gain = "ADC_GAIN_1";
|
|
||||||
zephyr,reference = "ADC_REF_VDD_1";
|
|
||||||
zephyr,acquisition-time = <49159>;
|
|
||||||
zephyr,resolution = <12>;
|
|
||||||
};
|
|
||||||
|
|
||||||
vref_channel: channel@11 { /* 17 dezimal = 11 hex */
|
|
||||||
reg = <0x11>;
|
|
||||||
zephyr,gain = "ADC_GAIN_1";
|
|
||||||
zephyr,reference = "ADC_REF_VDD_1";
|
|
||||||
zephyr,acquisition-time = <49159>;
|
|
||||||
zephyr,resolution = <12>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&die_temp {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&dma1 {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&flash0 {
|
|
||||||
partitions {
|
|
||||||
compatible = "fixed-partitions";
|
|
||||||
#address-cells = <1>;
|
|
||||||
#size-cells = <1>;
|
|
||||||
|
|
||||||
storage_partition: partition@1f800 {
|
|
||||||
label = "storage";
|
|
||||||
reg = <0x0001f800 DT_SIZE_K(2)>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
&can1 {
|
|
||||||
pinctrl-0 = <&can_rx_pa11 &can_tx_pa12>;
|
|
||||||
pinctrl-names = "default";
|
|
||||||
status= "okay";
|
|
||||||
bitrate = <125000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
&exti {
|
|
||||||
status = "okay";
|
|
||||||
};
|
|
||||||
|
|
||||||
&pinctrl {
|
|
||||||
adc_pb1_pins: adc_pb1_pins {
|
|
||||||
pinmux = <STM32F1_PINMUX('B', 1, ANALOG, NO_REMAP)>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
|
||||||
|
|
||||||
# enable uart driver
|
|
||||||
CONFIG_SERIAL=y
|
|
||||||
# enable console
|
|
||||||
CONFIG_CONSOLE=y
|
|
||||||
|
|
||||||
# enable GPIO
|
|
||||||
CONFIG_GPIO=y
|
|
||||||
|
|
||||||
# modbus config
|
|
||||||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
|
||||||
CONFIG_UART_LINE_CTRL=n
|
|
||||||
CONFIG_MODBUS=y
|
|
||||||
CONFIG_MODBUS_ROLE_CLIENT=y
|
|
||||||
|
|
||||||
# can config
|
|
||||||
CONFIG_CAN=y
|
|
||||||
CONFIG_CAN_INIT_PRIORITY=80
|
|
||||||
#CONFIG_CAN_MAX_FILTER=5
|
|
||||||
CONFIG_CAN_ACCEPT_RTR=y
|
|
||||||
|
|
||||||
# settings
|
|
||||||
CONFIG_FLASH=y
|
|
||||||
CONFIG_FLASH_MAP=y
|
|
||||||
CONFIG_SETTINGS=y
|
|
||||||
CONFIG_SETTINGS_RUNTIME=y
|
|
||||||
CONFIG_NVS=y
|
|
||||||
CONFIG_SETTINGS_NVS=y
|
|
||||||
CONFIG_HEAP_MEM_POOL_SIZE=256
|
|
||||||
CONFIG_MPU_ALLOW_FLASH_WRITE=y
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
# Gitignore settings for ESPHome
|
||||||
|
# This is an example and may include too much for your use-case.
|
||||||
|
# You can modify this file to suit your needs.
|
||||||
|
/.esphome/
|
||||||
|
/secrets.yaml
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
# ===================================================================
|
||||||
|
# ESPHome Configuration
|
||||||
|
# CAN-Bus Master für ein Bewässerungssystem auf Basis des ESP32-C6
|
||||||
|
#
|
||||||
|
# Version 10: Finale Korrektur der Lambda-Signatur gemäß Dokumentation
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: can-bridge
|
||||||
|
friendly_name: Irrigation can bridge
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32-c6-devkitm-1
|
||||||
|
framework:
|
||||||
|
type: esp-idf # Erforderlich für den ESP32-C6
|
||||||
|
|
||||||
|
# --- Netzwerk & Sicherheit ---
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: true
|
||||||
|
|
||||||
|
api:
|
||||||
|
encryption:
|
||||||
|
key: !secret api_key
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
password: !secret ota_password
|
||||||
|
|
||||||
|
logger:
|
||||||
|
|
||||||
|
web_server:
|
||||||
|
|
||||||
|
# --- Globale Variablen ---
|
||||||
|
globals:
|
||||||
|
- id: ventil_2_can_state
|
||||||
|
type: int
|
||||||
|
initial_value: '0' # Startet als "geschlossen"
|
||||||
|
|
||||||
|
# --- CAN-Bus Konfiguration ---
|
||||||
|
canbus:
|
||||||
|
- platform: esp32_can
|
||||||
|
id: my_can_bus
|
||||||
|
tx_pin: GPIO5
|
||||||
|
rx_pin: GPIO4
|
||||||
|
bit_rate: 125kbps
|
||||||
|
can_id: 0x000 # Erforderlich, um Parser-Fehler zu beheben.
|
||||||
|
on_frame:
|
||||||
|
# Horcht nur auf die Statusmeldung von Knoten 2 (ID 0x422)
|
||||||
|
- can_id: 0x422
|
||||||
|
then:
|
||||||
|
- lambda: |-
|
||||||
|
if (x.size() < 1) {
|
||||||
|
ESP_LOGW("on_can_frame", "Received empty Frame for ID 0x422");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int received_state = x[0];
|
||||||
|
id(ventil_2_can_state) = received_state;
|
||||||
|
ESP_LOGD("on_can_frame", "Received state from Valve 2: %i", received_state);
|
||||||
|
- valve.template.publish:
|
||||||
|
id: ventil_2
|
||||||
|
current_operation: !lambda |-
|
||||||
|
int state = id(ventil_2_can_state);
|
||||||
|
if (state == 2) {
|
||||||
|
return VALVE_OPERATION_OPENING;
|
||||||
|
} else if (state == 3) {
|
||||||
|
return VALVE_OPERATION_CLOSING;
|
||||||
|
} else {
|
||||||
|
return VALVE_OPERATION_IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
# --- Home Assistant Entitäten ---
|
||||||
|
valve:
|
||||||
|
- platform: template
|
||||||
|
name: "Ventil 2"
|
||||||
|
id: ventil_2
|
||||||
|
|
||||||
|
# Diese Lambda meldet nur den binären End-Zustand (offen/geschlossen)
|
||||||
|
lambda: |-
|
||||||
|
if (id(ventil_2_can_state) == 0) {
|
||||||
|
return VALVE_CLOSED;
|
||||||
|
} else if (id(ventil_2_can_state) == 1) {
|
||||||
|
return VALVE_OPEN;
|
||||||
|
} else {
|
||||||
|
return NAN;
|
||||||
|
}
|
||||||
|
|
||||||
|
# Aktionen zum Steuern des Ventils
|
||||||
|
open_action:
|
||||||
|
- canbus.send:
|
||||||
|
canbus_id: my_can_bus
|
||||||
|
can_id: 0x210
|
||||||
|
data: [0x02, 0x01]
|
||||||
|
|
||||||
|
close_action:
|
||||||
|
- canbus.send:
|
||||||
|
canbus_id: my_can_bus
|
||||||
|
can_id: 0x210
|
||||||
|
data: [0x02, 0x00]
|
||||||
|
|
||||||
|
stop_action:
|
||||||
|
- canbus.send:
|
||||||
|
canbus_id: my_can_bus
|
||||||
|
can_id: 0x210
|
||||||
|
data: [0x02, 0x03]
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import secrets
|
||||||
|
import string
|
||||||
|
import os
|
||||||
|
import base64
|
||||||
|
from ruamel.yaml import YAML
|
||||||
|
|
||||||
|
def generate_password(length=32):
|
||||||
|
"""Generate a random password."""
|
||||||
|
alphabet = string.ascii_letters + string.digits
|
||||||
|
return ''.join(secrets.choice(alphabet) for i in range(length))
|
||||||
|
|
||||||
|
def generate_api_key():
|
||||||
|
"""Generate a random 32-byte key and base64 encode it."""
|
||||||
|
return base64.b64encode(secrets.token_bytes(32)).decode('utf-8')
|
||||||
|
|
||||||
|
SECRETS_FILE = 'secrets.yaml'
|
||||||
|
# In a real ESPHome project, secrets are often included from a central location
|
||||||
|
# but for this script, we'll assume it's in the current directory.
|
||||||
|
# You might need to adjust this path.
|
||||||
|
secrets_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), SECRETS_FILE)
|
||||||
|
|
||||||
|
yaml = YAML()
|
||||||
|
yaml.preserve_quotes = True
|
||||||
|
# To prevent line wrapping
|
||||||
|
yaml.width = 4096
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(secrets_path, 'r') as f:
|
||||||
|
secrets_data = yaml.load(f)
|
||||||
|
if secrets_data is None:
|
||||||
|
secrets_data = {}
|
||||||
|
except FileNotFoundError:
|
||||||
|
print(f"Info: '{SECRETS_FILE}' not found. A new file will be created.")
|
||||||
|
secrets_data = {}
|
||||||
|
|
||||||
|
# Generate new random passwords
|
||||||
|
new_api_key = generate_api_key()
|
||||||
|
new_ota_password = generate_password()
|
||||||
|
|
||||||
|
# Update the dictionary with the new passwords
|
||||||
|
if 'api_password' in secrets_data:
|
||||||
|
del secrets_data['api_password']
|
||||||
|
secrets_data['api_key'] = new_api_key
|
||||||
|
secrets_data['ota_password'] = new_ota_password
|
||||||
|
|
||||||
|
# Write the updated dictionary back to the YAML file
|
||||||
|
with open(secrets_path, 'w') as f:
|
||||||
|
yaml.dump(secrets_data, f)
|
||||||
|
|
||||||
|
print(f"Successfully updated '{SECRETS_FILE}'.")
|
||||||
|
print("New values:")
|
||||||
|
print(f" api_key: {new_api_key}")
|
||||||
|
print(f" ota_password: {new_ota_password}")
|
||||||
|
|
@ -0,0 +1,166 @@
|
||||||
|
# ===================================================================
|
||||||
|
# ESPHome Configuration - Final Version
|
||||||
|
#
|
||||||
|
# This version corrects the C++ function call inside the valve actions
|
||||||
|
# to use the correct `send` method from the ModbusDevice base class,
|
||||||
|
# which is compatible with the esp-idf framework.
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
esphome:
|
||||||
|
name: irrigation-system
|
||||||
|
friendly_name: Bewässerung
|
||||||
|
|
||||||
|
esp32:
|
||||||
|
board: esp32-c6-devkitm-1
|
||||||
|
framework:
|
||||||
|
type: esp-idf # Set to esp-idf as required by the ESP32-C6 board
|
||||||
|
|
||||||
|
wifi:
|
||||||
|
ssid: !secret wifi_ssid
|
||||||
|
password: !secret wifi_password
|
||||||
|
fast_connect: true
|
||||||
|
|
||||||
|
api:
|
||||||
|
encryption:
|
||||||
|
key: !secret api_key
|
||||||
|
|
||||||
|
ota:
|
||||||
|
platform: esphome
|
||||||
|
password: !secret ota_password
|
||||||
|
|
||||||
|
logger:
|
||||||
|
|
||||||
|
web_server:
|
||||||
|
|
||||||
|
# ===================================================================
|
||||||
|
# HARDWARE SETUP - COMPLETE
|
||||||
|
# ===================================================================
|
||||||
|
|
||||||
|
# --- UART for RS485 Communication ---
|
||||||
|
uart:
|
||||||
|
id: uart_bus
|
||||||
|
tx_pin: GPIO1
|
||||||
|
rx_pin: GPIO2
|
||||||
|
baud_rate: 9600
|
||||||
|
data_bits: 8
|
||||||
|
stop_bits: 1
|
||||||
|
parity: NONE
|
||||||
|
|
||||||
|
# --- Base Modbus component for the bus ---
|
||||||
|
modbus:
|
||||||
|
- id: modbus_hub
|
||||||
|
uart_id: uart_bus
|
||||||
|
|
||||||
|
# --- Modbus Controller for the specific valve device ---
|
||||||
|
modbus_controller:
|
||||||
|
- id: valve_controller
|
||||||
|
modbus_id: modbus_hub
|
||||||
|
address: 0 # The Modbus address of your valve. Change if not 0.
|
||||||
|
# update_interval: 1s
|
||||||
|
|
||||||
|
# ===================================================================
|
||||||
|
# SENSORS - COMPLETE
|
||||||
|
# ===================================================================
|
||||||
|
sensor:
|
||||||
|
# This sensor reads the raw 16-bit value from the valve's input register.
|
||||||
|
- platform: modbus_controller
|
||||||
|
modbus_controller_id: valve_controller
|
||||||
|
name: "Valve Raw Status"
|
||||||
|
id: valve_raw_status
|
||||||
|
internal: true # Hide from Home Assistant UI
|
||||||
|
register_type: read # 'read' is the valid type for input registers
|
||||||
|
address: 0x0000 # The address of the register to read
|
||||||
|
value_type: U_WORD # Read the full 16-bit unsigned word
|
||||||
|
- platform: modbus_controller
|
||||||
|
modbus_controller_id: valve_controller
|
||||||
|
name: "VDD"
|
||||||
|
id: valve_vdd
|
||||||
|
register_type: read # 'read' is the valid type for input registers
|
||||||
|
address: 0x00FC # The address of the register to read
|
||||||
|
value_type: U_WORD # Read the full 16-bit unsigned word
|
||||||
|
entity_category: diagnostic # Mark as diagnostic
|
||||||
|
unit_of_measurement: "V"
|
||||||
|
accuracy_decimals: 2 # Show two decimal places
|
||||||
|
# Apply filters to convert the raw value to volts and update periodically
|
||||||
|
filters:
|
||||||
|
- lambda: |-
|
||||||
|
// Convert the raw VDD value to volts
|
||||||
|
return x / 1000.0; // Assuming the value is in millivolts
|
||||||
|
- heartbeat: 60s # Update every 60 seconds
|
||||||
|
- delta: 200 # Only update if the value changes by more than 200 mV
|
||||||
|
|
||||||
|
# ===================================================================
|
||||||
|
# TEXT SENSORS FOR HUMAN-READABLE STATUS
|
||||||
|
# ===================================================================
|
||||||
|
text_sensor:
|
||||||
|
# 1. This text sensor extracts the HIGH BYTE for the operation status.
|
||||||
|
- platform: template
|
||||||
|
name: "Valve Operation"
|
||||||
|
id: valve_operation_status
|
||||||
|
icon: "mdi:state-machine"
|
||||||
|
lambda: |-
|
||||||
|
// Extract the high byte from the raw status sensor
|
||||||
|
// using a bitwise right shift.
|
||||||
|
int operation_code = (int)id(valve_raw_status).state >> 8;
|
||||||
|
switch (operation_code) {
|
||||||
|
case 0: return {"Idle"};
|
||||||
|
case 1: return {"Opening"};
|
||||||
|
case 2: return {"Closing"};
|
||||||
|
case 3: return {"Obstacle Detected"};
|
||||||
|
case 4: return {"End Position Not Reached"};
|
||||||
|
default: return {"Unknown Operation"};
|
||||||
|
}
|
||||||
|
|
||||||
|
# 2. This text sensor extracts the LOW BYTE for the current valve state.
|
||||||
|
- platform: template
|
||||||
|
name: "Valve Position"
|
||||||
|
id: valve_position_status
|
||||||
|
icon: "mdi:valve"
|
||||||
|
lambda: |-
|
||||||
|
// Extract the low byte from the raw status sensor
|
||||||
|
// using a bitwise AND mask.
|
||||||
|
int state_code = (int)id(valve_raw_status).state & 0xFF;
|
||||||
|
switch (state_code) {
|
||||||
|
case 0: return {"Closed"};
|
||||||
|
case 1: return {"Open"};
|
||||||
|
default: return {"Unknown"};
|
||||||
|
}
|
||||||
|
|
||||||
|
# ===================================================================
|
||||||
|
# THE MAIN VALVE COMPONENT
|
||||||
|
# ===================================================================
|
||||||
|
valve:
|
||||||
|
- platform: template
|
||||||
|
name: "Modbus Controlled Valve"
|
||||||
|
id: modbus_valve
|
||||||
|
optimistic: false
|
||||||
|
# The lambda determines the current state (open or closed) of the valve.
|
||||||
|
lambda: |-
|
||||||
|
int state_code = (int)id(valve_raw_status).state & 0xFF;
|
||||||
|
if (state_code == 1) {
|
||||||
|
return true; // Open
|
||||||
|
} else if (state_code == 0) {
|
||||||
|
return false; // Closed
|
||||||
|
} else {
|
||||||
|
return {}; // Unknown
|
||||||
|
}
|
||||||
|
# Action to execute when the "OPEN" button is pressed.
|
||||||
|
open_action:
|
||||||
|
- lambda: |-
|
||||||
|
// Use the send() command inherited from ModbusDevice
|
||||||
|
// Function 0x06: Write Single Register
|
||||||
|
// Payload for value 1 is {0x00, 0x01}
|
||||||
|
const uint8_t data[] = {0x00, 0x01};
|
||||||
|
id(valve_controller).send(0x06, 0x0000, 1, 2, data);
|
||||||
|
# Action to execute when the "CLOSE" button is pressed.
|
||||||
|
close_action:
|
||||||
|
- lambda: |-
|
||||||
|
// Payload for value 2 is {0x00, 0x02}
|
||||||
|
const uint8_t data[] = {0x00, 0x02};
|
||||||
|
id(valve_controller).send(0x06, 0x0000, 1, 2, data);
|
||||||
|
# Action to execute when the "STOP" button is pressed.
|
||||||
|
stop_action:
|
||||||
|
- lambda: |-
|
||||||
|
// Payload for value 3 is {0x00, 0x03}
|
||||||
|
const uint8_t data[] = {0x00, 0x03};
|
||||||
|
id(valve_controller).send(0x06, 0x0000, 1, 2, data);
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
ruamel.yaml
|
||||||
|
esphome
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
wifi_ssid: 'PUT YOUR WIFI SSID HERE'
|
||||||
|
wifi_password: 'PUT YOUR WIFI PASSWORD HERE'
|
||||||
|
api_key: 'PUT YOUR KEY HERE OR USE create_secrets.py'
|
||||||
|
ota_password: 'PUT YOUR KEY HERE OR USE create_secrets.py'
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifndef CAN_IDS_H
|
||||||
|
#define CAN_IDS_H
|
||||||
|
|
||||||
|
/*
|
||||||
|
CAN ID structure for the irrigation system.
|
||||||
|
PPP FFFF NNNN
|
||||||
|
|
||||||
|
PPP: Priority
|
||||||
|
000: Network segment
|
||||||
|
001: Critical error
|
||||||
|
010: Commands
|
||||||
|
100: Status messages
|
||||||
|
110: measurements
|
||||||
|
111: Info messages
|
||||||
|
|
||||||
|
FFFF: Function
|
||||||
|
0001: Valve Commands
|
||||||
|
0010: Valve States
|
||||||
|
0011: IO Commands
|
||||||
|
0100: IO States
|
||||||
|
0101: Measurements
|
||||||
|
0111: Sysem Functions (e.g. reset, firmware update)
|
||||||
|
|
||||||
|
NNNN: Node ID
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CAN_ID_PRIORITY_NETWORK 0x000
|
||||||
|
#define CAN_ID_PRIORITY_CRITICAL_ERROR 0x100
|
||||||
|
#define CAN_ID_PRIORITY_COMMANDS 0x200
|
||||||
|
#define CAN_ID_PRIORITY_STATUS 0x400
|
||||||
|
#define CAN_ID_PRIORITY_MEASUREMENTS 0x600
|
||||||
|
#define CAN_ID_PRIORITY_INFO 0x700
|
||||||
|
|
||||||
|
#define CAN_ID_FUNCTION_VALVE_COMMANDS 0x010
|
||||||
|
#define CAN_ID_FUNCTION_VALVE_STATES 0x020
|
||||||
|
#define CAN_ID_FUNCTION_IO_COMMANDS 0x030
|
||||||
|
#define CAN_ID_FUNCTION_IO_STATES 0x040
|
||||||
|
#define CAN_ID_FUNCTION_MEASUREMENTS 0x050
|
||||||
|
#define CAN_ID_FUNCTION_SYSTEM_FUNCTIONS 0x070
|
||||||
|
|
||||||
|
#endif // CAN_IDS_H
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef FWU_H
|
||||||
|
#define FWU_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file fwu.h
|
||||||
|
* @brief API for the Firmware Update (FWU) library.
|
||||||
|
*
|
||||||
|
* This library provides the core logic for handling the over-the-air firmware
|
||||||
|
* update process via Modbus. It manages the data buffer, processes commands,
|
||||||
|
* and calculates CRC checksums for data verification.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the firmware update module.
|
||||||
|
*
|
||||||
|
* This function currently does nothing but is a placeholder for future
|
||||||
|
* initialization logic.
|
||||||
|
*/
|
||||||
|
void fwu_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handles incoming Modbus register writes related to firmware updates.
|
||||||
|
*
|
||||||
|
* This function is the main entry point for the FWU process. It parses the
|
||||||
|
* address and value from a Modbus write operation and takes appropriate action,
|
||||||
|
* such as storing metadata (offset, size) or data chunks, and processing
|
||||||
|
* commands (verify, finalize).
|
||||||
|
*
|
||||||
|
* @param addr The Modbus register address being written to.
|
||||||
|
* @param reg The 16-bit value being written to the register.
|
||||||
|
*/
|
||||||
|
void fwu_handler(uint16_t addr, uint16_t reg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the CRC16-CCITT of the last received firmware chunk.
|
||||||
|
*
|
||||||
|
* After a data chunk is fully received into the buffer, this function can be
|
||||||
|
* called to retrieve the calculated CRC checksum. The master can then compare
|
||||||
|
* this with its own calculated CRC to verify data integrity.
|
||||||
|
*
|
||||||
|
* @return The 16-bit CRC of the last chunk.
|
||||||
|
*/
|
||||||
|
uint16_t fwu_get_last_chunk_crc(void);
|
||||||
|
|
||||||
|
#endif // FWU_H
|
||||||
|
|
@ -0,0 +1,185 @@
|
||||||
|
#ifndef MODBUS_SERVER_H
|
||||||
|
#define MODBUS_SERVER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file modbus_server.h
|
||||||
|
* @brief API for the Modbus server implementation.
|
||||||
|
*
|
||||||
|
* This file defines the Modbus register map and provides functions to
|
||||||
|
* initialize and manage the Modbus server.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Modbus Input Register Addresses (Read-Only).
|
||||||
|
* @see docs/modbus-registers.de.md
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
/**
|
||||||
|
* @brief Combined status register for the valve.
|
||||||
|
* High-Byte: Movement (0=Idle, 1=Opening, 2=Closing, 3=Error).
|
||||||
|
* Low-Byte: State (0=Closed, 1=Open).
|
||||||
|
*/
|
||||||
|
REG_INPUT_VALVE_STATE_MOVEMENT = 0x0000,
|
||||||
|
/**
|
||||||
|
* @brief Motor current during opening in milliamperes (mA).
|
||||||
|
*/
|
||||||
|
REG_INPUT_MOTOR_OPEN_CURRENT_MA = 0x0001,
|
||||||
|
/**
|
||||||
|
* @brief Motor current during closing in milliamperes (mA).
|
||||||
|
*/
|
||||||
|
REG_INPUT_MOTOR_CLOSE_CURRENT_MA = 0x0002,
|
||||||
|
/**
|
||||||
|
* @brief Bitmask of digital inputs. Bit 0: Input 1, Bit 1: Input 2.
|
||||||
|
* 1=Active.
|
||||||
|
*/
|
||||||
|
REG_INPUT_DIGITAL_INPUTS_STATE = 0x0020,
|
||||||
|
/**
|
||||||
|
* @brief Event flags for buttons (Clear-on-Read). Bit 0: Button 1 pressed.
|
||||||
|
* Bit 1: Button 2 pressed.
|
||||||
|
*/
|
||||||
|
REG_INPUT_BUTTON_EVENTS = 0x0021,
|
||||||
|
/**
|
||||||
|
* @brief Firmware version, e.g., 0x0102 for v1.2.
|
||||||
|
*/
|
||||||
|
REG_INPUT_FIRMWARE_VERSION_MAJOR_MINOR = 0x00F0,
|
||||||
|
/**
|
||||||
|
* @brief Firmware version patch level, e.g., 3 for v1.2.3.
|
||||||
|
*/
|
||||||
|
REG_INPUT_FIRMWARE_VERSION_PATCH = 0x00F1,
|
||||||
|
/**
|
||||||
|
* @brief Device status (0=OK, 1=General Error).
|
||||||
|
*/
|
||||||
|
REG_INPUT_DEVICE_STATUS = 0x00F2,
|
||||||
|
/**
|
||||||
|
* @brief Lower 16 bits of uptime in seconds.
|
||||||
|
*/
|
||||||
|
REG_INPUT_UPTIME_SECONDS_LOW = 0x00F3,
|
||||||
|
/**
|
||||||
|
* @brief Upper 16 bits of uptime in seconds.
|
||||||
|
*/
|
||||||
|
REG_INPUT_UPTIME_SECONDS_HIGH = 0x00F4,
|
||||||
|
/**
|
||||||
|
* @brief Current supply voltage in millivolts (mV).
|
||||||
|
*/
|
||||||
|
REG_INPUT_SUPPLY_VOLTAGE_MV = 0x00F5,
|
||||||
|
/**
|
||||||
|
* @brief CRC16 of the last received data chunk in the buffer for firmware
|
||||||
|
* update.
|
||||||
|
*/
|
||||||
|
REG_INPUT_FWU_LAST_CHUNK_CRC = 0x0100
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Modbus Holding Register Addresses (Read/Write).
|
||||||
|
* @see docs/modbus-registers.de.md
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
/**
|
||||||
|
* @brief Valve control command (1=Open, 2=Close, 0=Stop movement).
|
||||||
|
*/
|
||||||
|
REG_HOLDING_VALVE_COMMAND = 0x0000,
|
||||||
|
/**
|
||||||
|
* @brief Safety timeout in seconds for the opening process.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_MAX_OPENING_TIME_S = 0x0001,
|
||||||
|
/**
|
||||||
|
* @brief Safety timeout in seconds for the closing process.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_MAX_CLOSING_TIME_S = 0x0002,
|
||||||
|
/**
|
||||||
|
* @brief Minimum current threshold in mA for end-position detection.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_END_CURRENT_THRESHOLD_OPEN_MA = 0x0003,
|
||||||
|
/**
|
||||||
|
* @brief Minimum current threshold in mA for end-position detection during
|
||||||
|
* closing.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_END_CURRENT_THRESHOLD_CLOSE_MA = 0x0004,
|
||||||
|
/**
|
||||||
|
* @brief Current threshold in mA for obstacle detection during opening.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_OBSTACLE_THRESHOLD_OPEN_MA = 0x0005,
|
||||||
|
/**
|
||||||
|
* @brief Current threshold in mA for obstacle detection during closing.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_OBSTACLE_THRESHOLD_CLOSE_MA = 0x0006,
|
||||||
|
/**
|
||||||
|
* @brief Bitmask for reading and writing digital outputs. Bit 0: Output 1,
|
||||||
|
* Bit 1: Output 2. 1=ON, 0=OFF.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_DIGITAL_OUTPUTS_STATE = 0x0010,
|
||||||
|
/**
|
||||||
|
* @brief Fail-safe watchdog timeout in seconds. 0=Disabled.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_WATCHDOG_TIMEOUT_S = 0x00F0,
|
||||||
|
/**
|
||||||
|
* @brief Writing 1 restarts the device.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_DEVICE_RESET = 0x00F1,
|
||||||
|
/**
|
||||||
|
* @brief Command for firmware update.
|
||||||
|
* 1: Verify Chunk - Slave writes the last chunk to flash.
|
||||||
|
* 2: Finalize Update - Complete installation and restart.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_FWU_COMMAND = 0x0100,
|
||||||
|
/**
|
||||||
|
* @brief Lower 16 bits of the 32-bit offset for the next firmware update
|
||||||
|
* chunk.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_FWU_CHUNK_OFFSET_LOW = 0x0101,
|
||||||
|
/**
|
||||||
|
* @brief Upper 16 bits of the 32-bit offset for the next firmware update
|
||||||
|
* chunk.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_FWU_CHUNK_OFFSET_HIGH = 0x0102,
|
||||||
|
/**
|
||||||
|
* @brief Size of the next firmware update chunk in bytes (max. 256).
|
||||||
|
*/
|
||||||
|
REG_HOLDING_FWU_CHUNK_SIZE = 0x0103,
|
||||||
|
/**
|
||||||
|
* @brief Start address of the 256-byte buffer for firmware update data.
|
||||||
|
*/
|
||||||
|
REG_HOLDING_FWU_DATA_BUFFER = 0x0180,
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the Modbus server.
|
||||||
|
*
|
||||||
|
* This function sets up the Modbus RTU server interface, loads saved settings
|
||||||
|
* (baudrate, unit ID), and starts listening for requests.
|
||||||
|
*
|
||||||
|
* @return 0 on success, or a negative error code on failure.
|
||||||
|
*/
|
||||||
|
int modbus_server_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reconfigures the Modbus server at runtime.
|
||||||
|
*
|
||||||
|
* Updates the baudrate and unit ID of the server. If the reconfiguration
|
||||||
|
* fails, the settings are saved and will be applied after a device reset.
|
||||||
|
*
|
||||||
|
* @param baudrate The new baudrate to set.
|
||||||
|
* @param unit_id The new Modbus unit ID (slave address).
|
||||||
|
* @return 0 on success, or a negative error code if immediate reconfiguration
|
||||||
|
* fails. Returns 0 even on failure if settings could be saved for the next
|
||||||
|
* boot.
|
||||||
|
*/
|
||||||
|
int modbus_reconfigure(uint32_t baudrate, uint8_t unit_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current baudrate of the Modbus server.
|
||||||
|
*
|
||||||
|
* @return The current baudrate.
|
||||||
|
*/
|
||||||
|
uint32_t modbus_get_baudrate(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current unit ID of the Modbus server.
|
||||||
|
*
|
||||||
|
* @return The current unit ID.
|
||||||
|
*/
|
||||||
|
uint8_t modbus_get_unit_id(void);
|
||||||
|
|
||||||
|
#endif // MODBUS_SERVER_H
|
||||||
|
|
@ -0,0 +1,214 @@
|
||||||
|
#ifndef VALVE_H
|
||||||
|
#define VALVE_H
|
||||||
|
|
||||||
|
#include <zephyr/drivers/gpio.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file valve.h
|
||||||
|
* @brief API for controlling the motorized valve.
|
||||||
|
*
|
||||||
|
* This library provides functions to initialize, open, close, and stop the
|
||||||
|
* valve. It also allows getting the valve's state and movement status, and
|
||||||
|
* configuring the maximum opening and closing times.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define VALVE_CHANNEL_OPEN 0
|
||||||
|
#define VALVE_CHANNEL_CLOSE 1
|
||||||
|
#define VALVE_CURRENT_CHECK_INTERVAL K_MSEC(CONFIG_VALVE_INTERVALL_CURRENT_CHECK_MS)
|
||||||
|
#define VALVE_INITIAL_CURRENT_CHECK_INTERVAL K_MSEC(CONFIG_VALVE_INITIAL_INTERVALL_CURRENT_CHECK_MS)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Represents the static state of the valve (open or closed).
|
||||||
|
*/
|
||||||
|
enum valve_state {
|
||||||
|
VALVE_STATE_CLOSED, /**< The valve is fully closed. */
|
||||||
|
VALVE_STATE_OPEN, /**< The valve is fully open. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Represents the dynamic movement status of the valve.
|
||||||
|
*/
|
||||||
|
enum valve_movement {
|
||||||
|
VALVE_MOVEMENT_IDLE, /**< The valve is not moving. */
|
||||||
|
VALVE_MOVEMENT_OPENING, /**< The valve is currently opening. */
|
||||||
|
VALVE_MOVEMENT_CLOSING, /**< The valve is currently closing. */
|
||||||
|
VALVE_MOVEMENT_ERROR /**< An error occurred during movement. */
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the valve control system.
|
||||||
|
*
|
||||||
|
* Configures the GPIOs and loads saved settings for timeouts.
|
||||||
|
* This function must be called before any other valve functions.
|
||||||
|
*
|
||||||
|
* @return 0 on success, or a negative error code on failure.
|
||||||
|
*/
|
||||||
|
int valve_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts opening the valve.
|
||||||
|
*
|
||||||
|
* The valve will open for the configured maximum opening time.
|
||||||
|
*/
|
||||||
|
void valve_open(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Starts closing the valve.
|
||||||
|
*
|
||||||
|
* The valve will close for the configured maximum closing time.
|
||||||
|
*/
|
||||||
|
void valve_close(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stops any ongoing valve movement immediately.
|
||||||
|
*/
|
||||||
|
void valve_stop(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current static state of the valve.
|
||||||
|
*
|
||||||
|
* @return The current valve state (VALVE_STATE_CLOSED or VALVE_STATE_OPEN).
|
||||||
|
*/
|
||||||
|
enum valve_state valve_get_state(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current movement status of the valve.
|
||||||
|
*
|
||||||
|
* @return The current movement status.
|
||||||
|
*/
|
||||||
|
enum valve_movement valve_get_movement(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the maximum time for the valve to open.
|
||||||
|
*
|
||||||
|
* @param seconds The timeout in seconds.
|
||||||
|
*/
|
||||||
|
void valve_set_max_open_time(uint16_t seconds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the maximum time for the valve to close.
|
||||||
|
*
|
||||||
|
* @param seconds The timeout in seconds.
|
||||||
|
*/
|
||||||
|
void valve_set_max_close_time(uint16_t seconds);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the current threshold for end-position detection during opening.
|
||||||
|
*
|
||||||
|
* @param current_ma The current threshold in milliamps.
|
||||||
|
*/
|
||||||
|
void valve_set_end_current_threshold_open(uint16_t current_ma);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the current threshold for end-position detection during closing.
|
||||||
|
*
|
||||||
|
* @param current_ma The current threshold in milliamps.
|
||||||
|
*/
|
||||||
|
void valve_set_end_current_threshold_close(uint16_t current_ma);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current threshold for end-position detection during opening.
|
||||||
|
*
|
||||||
|
* @return The current threshold in milliamps.
|
||||||
|
*/
|
||||||
|
uint16_t valve_get_end_current_threshold_open(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current threshold for end-position detection during closing.
|
||||||
|
*
|
||||||
|
* @return The current threshold in milliamps.
|
||||||
|
*/
|
||||||
|
uint16_t valve_get_end_current_threshold_close(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the configured maximum opening time.
|
||||||
|
*
|
||||||
|
* @return The timeout in seconds.
|
||||||
|
*/
|
||||||
|
uint16_t valve_get_max_open_time(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the configured maximum closing time.
|
||||||
|
*
|
||||||
|
* @return The timeout in seconds.
|
||||||
|
*/
|
||||||
|
uint16_t valve_get_max_close_time(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current drawn by the valve motor during opening.
|
||||||
|
*
|
||||||
|
* @return The motor current in milliamps.
|
||||||
|
*/
|
||||||
|
int32_t valve_get_opening_current(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current drawn by the valve motor during closing.
|
||||||
|
*
|
||||||
|
* @return The motor current in milliamps.
|
||||||
|
*/
|
||||||
|
int32_t valve_get_closing_current(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the temperature of the valve motor driver.
|
||||||
|
*
|
||||||
|
* @return The temperature in degrees Celsius.
|
||||||
|
*/
|
||||||
|
int32_t valve_get_vnd_temp(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the voltage supplied to the valve motor driver.
|
||||||
|
*
|
||||||
|
* @return The voltage in millivolts.
|
||||||
|
*/
|
||||||
|
int32_t valve_get_vnd_voltage(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the current threshold for obstacle detection during opening.
|
||||||
|
*
|
||||||
|
* @param current_ma The current threshold in milliamps.
|
||||||
|
*/
|
||||||
|
void valve_set_obstacle_threshold_open(uint16_t current_ma);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the current threshold for obstacle detection during closing.
|
||||||
|
*
|
||||||
|
* @param current_ma The current threshold in milliamps.
|
||||||
|
*/
|
||||||
|
void valve_set_obstacle_threshold_close(uint16_t current_ma);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current threshold for obstacle detection during opening.
|
||||||
|
*
|
||||||
|
* @return The current threshold in milliamps.
|
||||||
|
*/
|
||||||
|
uint16_t valve_get_obstacle_threshold_open(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets the current threshold for obstacle detection during closing.
|
||||||
|
*
|
||||||
|
* @return The current threshold in milliamps.
|
||||||
|
*/
|
||||||
|
uint16_t valve_get_obstacle_threshold_close(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function called during valve opening with current readings.
|
||||||
|
*
|
||||||
|
* This is a weak function that can be overridden to provide custom handling
|
||||||
|
* of current readings during valve opening operations.
|
||||||
|
*
|
||||||
|
* @param current_ma The current reading in milliamps.
|
||||||
|
*/
|
||||||
|
void valve_current_open_callback(int current_ma);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback function called during valve closing with current readings.
|
||||||
|
*
|
||||||
|
* This is a weak function that can be overridden to provide custom handling
|
||||||
|
* of current readings during valve closing operations.
|
||||||
|
*
|
||||||
|
* @param current_ma The current reading in milliamps.
|
||||||
|
*/
|
||||||
|
void valve_current_close_callback(int current_ma);
|
||||||
|
|
||||||
|
#endif // VALVE_H
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2025, Eduard Iten
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ZEPHYR_INCLUDE_DRIVERS_MISC_VND7050AJ_H_
|
||||||
|
#define ZEPHYR_INCLUDE_DRIVERS_MISC_VND7050AJ_H_
|
||||||
|
|
||||||
|
#include <zephyr/device.h>
|
||||||
|
#include <zephyr/kernel.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Channel identifiers for the VND7050AJ.
|
||||||
|
*/
|
||||||
|
#define VND7050AJ_CHANNEL_0 0
|
||||||
|
#define VND7050AJ_CHANNEL_1 1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets the state of a specific output channel.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param channel The channel to control (VND7050AJ_CHANNEL_0 or VND7050AJ_CHANNEL_1).
|
||||||
|
* @param state The desired state (true for ON, false for OFF).
|
||||||
|
* @return 0 on success, negative error code on failure.
|
||||||
|
*/
|
||||||
|
int vnd7050aj_set_output_state(const struct device *dev, uint8_t channel, bool state);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads the load current for a specific channel.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param channel The channel to measure (VND7050AJ_CHANNEL_0 or VND7050AJ_CHANNEL_1).
|
||||||
|
* @param[out] current_ma Pointer to store the measured current in milliamperes (mA).
|
||||||
|
* @return 0 on success, negative error code on failure.
|
||||||
|
*/
|
||||||
|
int vnd7050aj_read_load_current(const struct device *dev, uint8_t channel, int32_t *current_ma);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads the VCC supply voltage.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param[out] voltage_mv Pointer to store the measured voltage in millivolts (mV).
|
||||||
|
* @return 0 on success, negative error code on failure.
|
||||||
|
*/
|
||||||
|
int vnd7050aj_read_supply_voltage(const struct device *dev, int32_t *voltage_mv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads the internal chip temperature.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @param[out] temp_c Pointer to store the measured temperature in degrees Celsius (°C).
|
||||||
|
* @return 0 on success, negative error code on failure.
|
||||||
|
*/
|
||||||
|
int vnd7050aj_read_chip_temp(const struct device *dev, int32_t *temp_c);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Resets a latched fault condition.
|
||||||
|
*
|
||||||
|
* This function sends a low pulse to the FaultRST pin.
|
||||||
|
*
|
||||||
|
* @param dev Pointer to the device structure for the driver instance.
|
||||||
|
* @return 0 on success, negative error code on failure.
|
||||||
|
*/
|
||||||
|
int vnd7050aj_reset_fault(const struct device *dev);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* ZEPHYR_INCLUDE_DRIVERS_MISC_VND7050AJ_H_ */
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue