From 5089268ef0100c84c5b080cf0e8b493f31290898 Mon Sep 17 00:00:00 2001 From: "Bence T." <3326575+tbb98@users.noreply.github.com> Date: Sat, 8 Mar 2025 00:04:43 +0100 Subject: [PATCH 01/27] Create packet_structure.md As mentioned by @mofosyne at issue #72 --- docs/packet_structure.md | 50 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 docs/packet_structure.md diff --git a/docs/packet_structure.md b/docs/packet_structure.md new file mode 100644 index 00000000..a38c43ce --- /dev/null +++ b/docs/packet_structure.md @@ -0,0 +1,50 @@ +# Packet Structure + +| Field | Size (bytes) | Description | +|--------------|------------------------|-------------| +| `header` | 1 | Contains routing type, payload type, and payload version. | +| `payload_len` | 2 | Length of the payload in bytes. | +| `path_len` | 2 | Length of the path field in bytes. | +| `path` | `MAX_PATH_SIZE` | Stores the routing path if applicable. | +| `payload` | `MAX_PACKET_PAYLOAD` | The actual data being transmitted. | + +## Header Breakdown + +| Bits | Mask | Field | Description | +|-------|---------------|----------------|-------------| +| 0-1 | `0x03` | Route Type | Specifies the routing type (Flood, Direct, Reserved). | +| 2-5 | `0x0F` | Payload Type | Specifies the type of payload (Request, Response, Text, ACK, etc.). | +| 6-7 | `0x03` | Payload Version | Versioning of the payload format. | + +## Route Type Values + +| Value | Name | Description | +|--------|-------------------------|-------------| +| `0x00` | `ROUTE_TYPE_RESERVED1` | Reserved for future use. | +| `0x01` | `ROUTE_TYPE_FLOOD` | Flood routing mode (builds up path). | +| `0x02` | `ROUTE_TYPE_DIRECT` | Direct route (path is supplied). | +| `0x03` | `ROUTE_TYPE_RESERVED2` | Reserved for future use. | + +## Payload Type Values + +| Value | Name | Description | +|--------|-------------------------|-------------| +| `0x00` | `PAYLOAD_TYPE_REQ` | Request (destination/source hashes + MAC). | +| `0x01` | `PAYLOAD_TYPE_RESPONSE` | Response to REQ or ANON_REQ. | +| `0x02` | `PAYLOAD_TYPE_TXT_MSG` | Plain text message. | +| `0x03` | `PAYLOAD_TYPE_ACK` | Acknowledgment. | +| `0x04` | `PAYLOAD_TYPE_ADVERT` | Node advertisement. | +| `0x05` | `PAYLOAD_TYPE_GRP_TXT` | Group text message (unverified). | +| `0x06` | `PAYLOAD_TYPE_GRP_DATA` | Group datagram (unverified). | +| `0x07` | `PAYLOAD_TYPE_ANON_REQ` | Anonymous request. | +| `0x08` | `PAYLOAD_TYPE_PATH` | Returned path. | +| `0x0F` | `PAYLOAD_TYPE_RAW_CUSTOM` | Custom packet (raw bytes, custom encryption). | + +## Payload Version Values + +| Value | Name | Description | +|--------|---------------|-------------| +| `0x00` | `PAYLOAD_VER_1` | 1-byte src/dest hashes, 2-byte MAC. | +| `0x01` | `PAYLOAD_VER_2` | Future version (e.g., 2-byte hashes, 4-byte MAC). | +| `0x02` | `PAYLOAD_VER_3` | Future version. | +| `0x03` | `PAYLOAD_VER_4` | Future version. | From 9d53fc2679feb621682e3cb2411218730c5bcbde Mon Sep 17 00:00:00 2001 From: Matthew Sainsbury Date: Thu, 5 Jun 2025 20:16:18 -0700 Subject: [PATCH 02/27] corrections and style --- docs/packet_structure.md | 69 ++++++++++++++++++++-------------------- 1 file changed, 35 insertions(+), 34 deletions(-) diff --git a/docs/packet_structure.md b/docs/packet_structure.md index a38c43ce..b02c3c33 100644 --- a/docs/packet_structure.md +++ b/docs/packet_structure.md @@ -1,50 +1,51 @@ # Packet Structure -| Field | Size (bytes) | Description | -|--------------|------------------------|-------------| -| `header` | 1 | Contains routing type, payload type, and payload version. | -| `payload_len` | 2 | Length of the payload in bytes. | -| `path_len` | 2 | Length of the path field in bytes. | -| `path` | `MAX_PATH_SIZE` | Stores the routing path if applicable. | -| `payload` | `MAX_PACKET_PAYLOAD` | The actual data being transmitted. | +| Field | Size (bytes) | Description | +|----------|----------------------------------|-----------------------------------------------------------| +| header | 1 | Contains routing type, payload type, and payload version. | +| path_len | 1 | Length of the path field in bytes. | +| path | up to 64 (`MAX_PATH_SIZE`) | Stores the routing path if applicable. | +| payload | up to 184 (`MAX_PACKET_PAYLOAD`) | The actual data being transmitted. | + +Note: see the [payloads doc](./payloads.md) for more information about the content of payload. ## Header Breakdown -| Bits | Mask | Field | Description | -|-------|---------------|----------------|-------------| -| 0-1 | `0x03` | Route Type | Specifies the routing type (Flood, Direct, Reserved). | -| 2-5 | `0x0F` | Payload Type | Specifies the type of payload (Request, Response, Text, ACK, etc.). | -| 6-7 | `0x03` | Payload Version | Versioning of the payload format. | +| Bits | Mask | Field | Description | +|-------|--------|-----------------|-----------------------------------------------| +| 0-1 | `0x03` | Route Type | Flood, Direct, Reserved - see below. | +| 2-5 | `0x0F` | Payload Type | Request, Response, ACK, etc. - see below. | +| 6-7 | `0x03` | Payload Version | Versioning of the payload format - see below. | ## Route Type Values -| Value | Name | Description | -|--------|-------------------------|-------------| -| `0x00` | `ROUTE_TYPE_RESERVED1` | Reserved for future use. | +| Value | Name | Description | +|--------|------------------------|--------------------------------------| +| `0x00` | `ROUTE_TYPE_RESERVED1` | Reserved for future use. | | `0x01` | `ROUTE_TYPE_FLOOD` | Flood routing mode (builds up path). | -| `0x02` | `ROUTE_TYPE_DIRECT` | Direct route (path is supplied). | -| `0x03` | `ROUTE_TYPE_RESERVED2` | Reserved for future use. | +| `0x02` | `ROUTE_TYPE_DIRECT` | Direct route (path is supplied). | +| `0x03` | `ROUTE_TYPE_RESERVED2` | Reserved for future use. | ## Payload Type Values -| Value | Name | Description | -|--------|-------------------------|-------------| -| `0x00` | `PAYLOAD_TYPE_REQ` | Request (destination/source hashes + MAC). | -| `0x01` | `PAYLOAD_TYPE_RESPONSE` | Response to REQ or ANON_REQ. | -| `0x02` | `PAYLOAD_TYPE_TXT_MSG` | Plain text message. | -| `0x03` | `PAYLOAD_TYPE_ACK` | Acknowledgment. | -| `0x04` | `PAYLOAD_TYPE_ADVERT` | Node advertisement. | -| `0x05` | `PAYLOAD_TYPE_GRP_TXT` | Group text message (unverified). | -| `0x06` | `PAYLOAD_TYPE_GRP_DATA` | Group datagram (unverified). | -| `0x07` | `PAYLOAD_TYPE_ANON_REQ` | Anonymous request. | -| `0x08` | `PAYLOAD_TYPE_PATH` | Returned path. | +| Value | Name | Description | +|--------|---------------------------|-----------------------------------------------| +| `0x00` | `PAYLOAD_TYPE_REQ` | Request (destination/source hashes + MAC). | +| `0x01` | `PAYLOAD_TYPE_RESPONSE` | Response to REQ or ANON_REQ. | +| `0x02` | `PAYLOAD_TYPE_TXT_MSG` | Plain text message. | +| `0x03` | `PAYLOAD_TYPE_ACK` | Acknowledgment. | +| `0x04` | `PAYLOAD_TYPE_ADVERT` | Node advertisement. | +| `0x05` | `PAYLOAD_TYPE_GRP_TXT` | Group text message (unverified). | +| `0x06` | `PAYLOAD_TYPE_GRP_DATA` | Group datagram (unverified). | +| `0x07` | `PAYLOAD_TYPE_ANON_REQ` | Anonymous request. | +| `0x08` | `PAYLOAD_TYPE_PATH` | Returned path. | | `0x0F` | `PAYLOAD_TYPE_RAW_CUSTOM` | Custom packet (raw bytes, custom encryption). | ## Payload Version Values -| Value | Name | Description | -|--------|---------------|-------------| -| `0x00` | `PAYLOAD_VER_1` | 1-byte src/dest hashes, 2-byte MAC. | -| `0x01` | `PAYLOAD_VER_2` | Future version (e.g., 2-byte hashes, 4-byte MAC). | -| `0x02` | `PAYLOAD_VER_3` | Future version. | -| `0x03` | `PAYLOAD_VER_4` | Future version. | +| Value | Version | Description | +|--------|---------|---------------------------------------------------| +| `0x00` | 1 | 1-byte src/dest hashes, 2-byte MAC. | +| `0x01` | 2 | Future version (e.g., 2-byte hashes, 4-byte MAC). | +| `0x02` | 3 | Future version. | +| `0x03` | 4 | Future version. | From 7fffe7755acdab83b779e133051ad3ec3d25e699 Mon Sep 17 00:00:00 2001 From: uncle lit <43320854+LitBomb@users.noreply.github.com> Date: Fri, 13 Jun 2025 13:36:00 -0700 Subject: [PATCH 03/27] Update faq.md add full erase instructions using flasher.meshcore.co.uk add nRF fault tolerant bootloader by discord@che aporeps --- docs/faq.md | 48 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 6 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index c61c8d2b..7a5e28ac 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -64,9 +64,11 @@ author: https://github.com/LitBomb - [6.3. Q: How to connect to a repeater via BLE (Bluetooth)?](#63-q-how-to-connect-to-a-repeater-via-ble-bluetooth) - [6.4. Q: I can't connect via Bluetooth, what is the Bluetooth pairing code?](#64-q-i-cant-connect-via-bluetooth-what-is-the-bluetooth-pairing-code) - [6.5. Q: My Heltec V3 keeps disconnecting from my smartphone. It can't hold a solid Bluetooth connection.](#65-q-my-heltec-v3-keeps-disconnecting-from-my-smartphone--it-cant-hold-a-solid-bluetooth-connection) + - [6.6. Q: My RAK/T1000-E/xiao\_nRF52 device seems to be corrupted, how do I wipe it clean to start fresh?](#66-q-my-rakt1000-exiao_nrf52-device-seems-to-be-corrupted-how-do-i-wipe-it-clean-to-start-fresh) - [7. Other Questions:](#7-other-questions) - [7.2 Q: How to update ESP32-based devices over the air?](#72-q-how-to-update-esp32-based-devices-over-the-air) - [7.1 Q: How to update nRF (RAK, T114, Seed XIAO) repeater and room server firmware over the air using the new simpler DFU app?](#71-q-how-to-update-nrf-rak-t114-seed-xiao-repeater-and-room-server-firmware-over-the-air-using-the-new-simpler-dfu-app) + - [7.2 Q: Is there a way to lower the chance of a failed OTA device firmware update (DFU)?](#72-q-is-there-a-way-to-lower-the-chance-of-a-failed-ota-device-firmware-update-dfu) ## 1. Introduction @@ -533,6 +535,27 @@ You can get the epoch time on and use it to se **A:** Heltec V3 has a very small coil antenna on its PCB for Wi-Fi and Bluetooth connectivity. It has a very short range, only a few feet. It is possible to remove the coil antenna and replace it with a 31mm wire. The BT range is much improved with the modification. +### 6.6. Q: My RAK/T1000-E/xiao_nRF52 device seems to be corrupted, how do I wipe it clean to start fresh? + +**A:** +1. Connect USB-C cable to your device, per your device's instruction, get it to flash mode: + - For RAK, double click its reset button + - For T1000-e, quickly disconnect and reconnect the magnetic side of the cable from the device TWICE + - For Heltec T114, click the reset button once (the bottom button) + - For Xiao nRF52, click the reset button once. If that doesn't work, quickly double click the reset button twice. If that doesn't work, disconnection the board from your PC and reconnect again ([seeed studio wiki](https://wiki.seeedstudio.com/XIAO_BLE/#access-the-swd-pins-for-debugging-and-reflashing-bootloader)) +5. A new folder will appear on your computer's desktop +6. Download the `flash_erase*.uf2` file for your device on flasher.meshcore.co.uk + - RAK WisBlock and Heltec T114: `Flash_erase-nRF32_softdevice_v6.uf2` + - Seeed Studio Xiao nRF52 WIO: `Flash_erase-nRF52_softdevice_v7.uf2` +8. drag and drop the uf2 file for your device to the root of the new folder +9. Wait for the copy to complete. You might get an error dialog, you can ignore it +10. Go to https://flasher.meshcore.co.uk/, click `Console` and select the serial port for your connected device +11. In the console, press enter. Your flash should now be erased +12. You may now flash the latest MeshCore firmware onto your device + +Separately, starting in firmware version 1.7.0, there is a CLI Rescue mode. If your device has a user button (e.g. some RAK, T114), you can activate the rescue mode by hold down the user button of the device within 8 seconds of boot. Then you can use the 'Console' on flasher.meshcore.co.uk + + --- ## 7. Other Questions: @@ -558,12 +581,25 @@ You can get the epoch time on and use it to se 4. Go to the Command Line tab, type `start ota` and hit enter. 5. you should see `OK` to confirm the repeater device is now in OTA mode 6. Run the DFU app,tab `Settings` on the top right corner -7. Enable `Packets receipt notifications` and change `Number of Packets` to 10 for RAK, 8 for T114. 8 also works for RAK. -8. Select the firmware zip file you downloaded -9. Select the device you want to update. If the device you want to updat is not on the list, try enabling`OTA` on the device again -10. Tab the `Upload` to begin OTA update -11. If it fails, try turning off and on Bluetooth on your phone. If that doesn't work, try rebooting your phone. -12. Wait for the update to complete. It can take a few minutes. +7. Enable `Packets receipt notifications`, and change `Number of Packets` to 10 for RAK, 8 for T114. 8 also works for RAK. +9. Select the firmware zip file you downloaded +10. Select the device you want to update. If the device you want to updat is not on the list, try enabling`OTA` on the device again +11. If the device is not found, enable `Force Scanning` in the DFU app +12. Tab the `Upload` to begin OTA update +13. If it fails, try turning off and on Bluetooth on your phone. If that doesn't work, try rebooting your phone. +14. Wait for the update to complete. It can take a few minutes. + +### 7.2 Q: Is there a way to lower the chance of a failed OTA device firmware update (DFU)? + +**A:** Yes, developer `che aporeps` has an enhanced OTA DFU bootloader for nRF52 based devices. With this bootloader, if it detects that the application firmware is invalid, it falls back to OTA DFU mode so you can attempt to flash again to recover. This bootloader has other changes to make the OTA DFU process more fault tolerant. + +Refer to https://github.com/oltaco/Adafruit_nRF52_Bootloader_OTAFIX for the latest information. + +Currently, the following boards are supported: +- Nologo ProMicro +- Seeed Studio XIAO nRF52840 BLE +- Seeed Studio XIAO nRF52840 BLE SENSE +- RAK 4631 --- From 0d78df1b8a2f45048e3398a752b860426fb3787b Mon Sep 17 00:00:00 2001 From: Matthew Sainsbury Date: Fri, 20 Jun 2025 17:59:55 -0700 Subject: [PATCH 04/27] minor changes and fixes to docs --- docs/packet_structure.md | 19 ++++++++++-------- docs/payloads.md | 42 ++++++++++++++++++++++++---------------- 2 files changed, 36 insertions(+), 25 deletions(-) diff --git a/docs/packet_structure.md b/docs/packet_structure.md index b02c3c33..4a28526f 100644 --- a/docs/packet_structure.md +++ b/docs/packet_structure.md @@ -11,20 +11,22 @@ Note: see the [payloads doc](./payloads.md) for more information about the conte ## Header Breakdown +bit 0 means the lowest bit (1s place) + | Bits | Mask | Field | Description | |-------|--------|-----------------|-----------------------------------------------| | 0-1 | `0x03` | Route Type | Flood, Direct, Reserved - see below. | -| 2-5 | `0x0F` | Payload Type | Request, Response, ACK, etc. - see below. | -| 6-7 | `0x03` | Payload Version | Versioning of the payload format - see below. | +| 2-5 | `0x3C` | Payload Type | Request, Response, ACK, etc. - see below. | +| 6-7 | `0xC0` | Payload Version | Versioning of the payload format - see below. | ## Route Type Values -| Value | Name | Description | -|--------|------------------------|--------------------------------------| -| `0x00` | `ROUTE_TYPE_RESERVED1` | Reserved for future use. | -| `0x01` | `ROUTE_TYPE_FLOOD` | Flood routing mode (builds up path). | -| `0x02` | `ROUTE_TYPE_DIRECT` | Direct route (path is supplied). | -| `0x03` | `ROUTE_TYPE_RESERVED2` | Reserved for future use. | +| Value | Name | Description | +|--------|-------------------------------|--------------------------------------| +| `0x00` | `ROUTE_TYPE_TRANSPORT_FLOOD` | Flood routing mode + transport codes | +| `0x01` | `ROUTE_TYPE_FLOOD` | Flood routing mode (builds up path). | +| `0x02` | `ROUTE_TYPE_DIRECT` | Direct route (path is supplied). | +| `0x03` | `ROUTE_TYPE_TRANSPORT_DIRECT` | direct route + transport codes | ## Payload Type Values @@ -39,6 +41,7 @@ Note: see the [payloads doc](./payloads.md) for more information about the conte | `0x06` | `PAYLOAD_TYPE_GRP_DATA` | Group datagram (unverified). | | `0x07` | `PAYLOAD_TYPE_ANON_REQ` | Anonymous request. | | `0x08` | `PAYLOAD_TYPE_PATH` | Returned path. | +| `0x09` | `PAYLOAD_TYPE_TRACE` | trace a path, collecting SNI for each hop. | | `0x0F` | `PAYLOAD_TYPE_RAW_CUSTOM` | Custom packet (raw bytes, custom encryption). | ## Payload Version Values diff --git a/docs/payloads.md b/docs/payloads.md index 2c402102..72ce0a89 100644 --- a/docs/payloads.md +++ b/docs/payloads.md @@ -1,25 +1,29 @@ # Meshcore payloads Inside of each [meshcore packet](./packet_structure.md) is a payload, identified by the payload type in the packet header. The types of payloads are: +* Node advertisement. +* Acknowledgment. +* Returned path. * Request (destination/source hashes + MAC). * Response to REQ or ANON_REQ. * Plain text message. -* Acknowledgment. -* Node advertisement. +* Anonymous request. * Group text message (unverified). * Group datagram (unverified). -* Anonymous request. -* Returned path. * Custom packet (raw bytes, custom encryption). This document defines the structure of each of these payload types +## Important concepts: + +* Node/channel hash: the first byte of the node or channel's public key + # Node advertisement This kind of payload notifies receivers that a node exists, and gives information about the node | Field | Size (bytes) | Description | |---------------|-----------------|----------------------------------------------------------| -| public key | 32 | Ed25519 public key | +| public key | 32 | Ed25519 public key of the node | | timestamp | 4 | unix timestamp of advertisement | | signature | 64 | Ed25519 signature of public key, timestamp, and app data | | appdata | rest of payload | optional, see below | @@ -45,12 +49,18 @@ Appdata Flags | `0x80` | name | appdata contains a node name | # Acknowledgement + +An acknowledgement that a message was received. Note that for returned path messages, an acknowledgement will be sent in the "extra" payload (see [Returned Path](#returned-path)) and not as a discrete ackowledgement. CLI commands do not require an acknowledgement, neither discrete nor extra. + | Field | Size (bytes) | Description | |----------|--------------|------------------------------------------------------------| | checksum | 4 | CRC checksum of message timestamp, text, and sender pubkey | # Returned path, request, response, and plain text message + +Returned path, request, response, and plain text messages are all formatted in the same way. See the subsection for more details about the ciphertext's associated plaintext representation. + | Field | Size (bytes) | Description | |------------------|-----------------|------------------------------------------------------| | destination hash | 1 | first byte of destination node public key | @@ -60,11 +70,13 @@ Appdata Flags ## Returned path +Returned path messages provide a description of the route a packet took from the original author. Receivers will send returned path messages to the author of the original message. + | Field | Size (bytes) | Description | |-------------|--------------|----------------------------------------------------------------------------------------------| | path length | 1 | length of next field | -| path | see above | a list of node hashes (one byte each) describing the route from us to the packet author | -| extra type | 1 | extra, bundled payload type, eg., acknowledgement or response. See packet structure spec | +| path | see above | a list of node hashes (one byte each) | +| extra type | 1 | extra, bundled payload type, eg., acknowledgement or response. Same values as in [packet structure](./packet_structure.md) | | extra | rest of data | extra, bundled payload content, follows same format as main content defined by this document | ## Request @@ -156,18 +168,14 @@ Plaintext message # Group text message / datagram -| Field | Size (bytes) | Description | -|--------------|-----------------|------------------------------------------| -| channel hash | 1 | TODO | -| cipher MAC | 2 | MAC for encrypted data in next field | -| ciphertext | rest of payload | encrypted message, see below for details | +| Field | Size (bytes) | Description | +|--------------|-----------------|--------------------------------------------| +| channel hash | 1 | the first byte of the channel's public key | +| cipher MAC | 2 | MAC for encrypted data in next field | +| ciphertext | rest of payload | encrypted message, see below for details | -Plaintext for text message +The plaintext contained in the ciphertext matches the format described in [plain text message](#plain-text-message). Specifically, it consists of a four byte timestamp, a flags byte, and the message. The flags byte will generally be `0x00` because it is a "plain text message". The message will be of the form `: ` (eg., `user123: I'm on my way`). -| Field | Size (bytes) | Description | -|-----------|-----------------|----------------------------------| -| timestamp | 4 | send time (unix timestamp) | -| content | rest of message | plain group text message content | TODO: describe what datagram looks like From 1de5753a16dd7aba2a3df3510aef961d5df94676 Mon Sep 17 00:00:00 2001 From: Matthew Sainsbury Date: Fri, 20 Jun 2025 19:41:07 -0700 Subject: [PATCH 05/27] add advert detail --- docs/payloads.md | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/payloads.md b/docs/payloads.md index 72ce0a89..b094d9a9 100644 --- a/docs/payloads.md +++ b/docs/payloads.md @@ -41,12 +41,15 @@ Appdata Appdata Flags -| Value | Name | Description | -|--------|-----------|---------------------------------------| -| `0x10` | location | appdata contains lat/long information | -| `0x20` | feature 1 | Reserved for future use. | -| `0x40` | feature 2 | Reserved for future use. | -| `0x80` | name | appdata contains a node name | +| Value | Name | Description | +|--------|----------------|---------------------------------------| +| `0x01` | is chat node | advert is for a chat node | +| `0x02` | is repeater | advert is for a repeater | +| `0x03` | is room server | advert is for a room server | +| `0x10` | has location | appdata contains lat/long information | +| `0x20` | has feature 1 | Reserved for future use. | +| `0x40` | has feature 2 | Reserved for future use. | +| `0x80` | has name | appdata contains a node name | # Acknowledgement From 001b996a24ca1cab1254edade2f9391991dfb521 Mon Sep 17 00:00:00 2001 From: cod3doomy Date: Tue, 24 Jun 2025 17:46:01 -0700 Subject: [PATCH 06/27] RAK4631: BME680 add and GPS cleanup - Added the BME680 environment sensor functionality - Added the GPS Repeater env for those wanting it - Cleaned up the GPS and other RAK4631SensorManager code Verified build and functionality on normal and GPS repeater and companion envs. IAQ readout is still a work in progress, but a placeholder can be seen on Channel 2 of the app telemetry. --- variants/rak4631/platformio.ini | 29 +++- variants/rak4631/target.cpp | 266 ++++++++++++++++++++++++++++---- variants/rak4631/target.h | 32 ++-- 3 files changed, 285 insertions(+), 42 deletions(-) diff --git a/variants/rak4631/platformio.ini b/variants/rak4631/platformio.ini index 3014bc59..9391f99b 100644 --- a/variants/rak4631/platformio.ini +++ b/variants/rak4631/platformio.ini @@ -23,7 +23,6 @@ lib_deps = ${nrf52840_base.lib_deps} adafruit/Adafruit SSD1306 @ ^2.5.13 stevemarple/MicroNMEA @ ^2.0.6 - sparkfun/SparkFun u-blox GNSS Arduino Library @ ^2.2.27 [env:RAK_4631_Repeater] extends = rak4631 @@ -41,6 +40,30 @@ build_src_filter = ${rak4631.build_src_filter} + +<../examples/simple_repeater> +[env:RAK_4631_GPS_Repeater] +extends = rak4631 +build_flags = + ${rak4631.build_flags} + -D DISPLAY_CLASS=SSD1306Display + -D ADVERT_NAME='"RAK4631 GPS Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + -D FORCE_GPS_ALIVE=1 + -D ENV_INCLUDE_GPS=1 + -D ENV_INCLUDE_BME680=1 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +build_src_filter = ${rak4631.build_src_filter} + + + +<../examples/simple_repeater> +lib_deps = + ${rak4631.lib_deps} + sparkfun/SparkFun u-blox GNSS Arduino Library @ ^2.2.27 + https://github.com/boschsensortec/Bosch-BSEC2-Library + https://github.com/boschsensortec/Bosch-BME68x-Library + [env:RAK_4631_room_server] extends = rak4631 build_flags = @@ -104,6 +127,7 @@ build_flags = -D BLE_DEBUG_LOGGING=1 -D OFFLINE_QUEUE_SIZE=256 -D ENV_INCLUDE_GPS=1 + -D ENV_INCLUDE_BME680=1 ; -D MESH_PACKET_LOGGING=1 ; -D MESH_DEBUG=1 build_src_filter = ${rak4631.build_src_filter} @@ -112,6 +136,9 @@ build_src_filter = ${rak4631.build_src_filter} +<../examples/companion_radio> lib_deps = ${rak4631.lib_deps} + sparkfun/SparkFun u-blox GNSS Arduino Library @ ^2.2.27 + https://github.com/boschsensortec/Bosch-BSEC2-Library + https://github.com/boschsensortec/Bosch-BME68x-Library densaugeo/base64 @ ~1.4.0 [env:RAK_4631_terminal_chat] diff --git a/variants/rak4631/target.cpp b/variants/rak4631/target.cpp index ede755e2..b7c74bf4 100644 --- a/variants/rak4631/target.cpp +++ b/variants/rak4631/target.cpp @@ -19,6 +19,21 @@ RAK4631SensorManager sensors = RAK4631SensorManager(nmea); RAK4631SensorManager sensors; #endif +#if ENV_INCLUDE_BME680 +#ifndef TELEM_BME680_ADDRESS +#define TELEM_BME680_ADDRESS 0x76 // BME680 environmental sensor I2C address +#endif +#include +static Bsec2 BME680; +float rawPressure = 0; +float rawTemperature = 0; +float compTemperature = 0; +float rawHumidity = 0; +float compHumidity = 0; +float readIAQ = 0; +float readCO2 = 0; +#endif + #ifdef DISPLAY_CLASS DISPLAY_CLASS display; #endif @@ -43,6 +58,10 @@ void scanDevices(TwoWire *w) Serial.println("\tFound RAK12500 GPS Sensor"); deviceOnline |= RAK12500_ONLINE; break; + case 0x76: + Serial.println("\tFound RAK1906 Environment Sensor"); + deviceOnline |= BME680_ONLINE; + break; default: Serial.print("\tI2C device found at address 0x"); if (addr < 16) { @@ -137,7 +156,7 @@ bool RAK4631SensorManager::gpsIsAwake(uint32_t ioPin){ ublox_GNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT); disStandbyPin = ioPin; gps_active = true; - gps_present = true; + gps_detected = true; return true; } else @@ -147,73 +166,256 @@ bool RAK4631SensorManager::gpsIsAwake(uint32_t ioPin){ } #endif +#if ENV_INCLUDE_BME680 +void checkBMEStatus(Bsec2 bsec) +{ + if (bsec.status < BSEC_OK) + { + MESH_DEBUG_PRINTLN("BSEC error code : %f", String(bsec.status)); + } + else if (bsec.status > BSEC_OK) + { + MESH_DEBUG_PRINTLN("BSEC warning code : %f", String(bsec.status)); + } + + if (bsec.sensor.status < BME68X_OK) + { + MESH_DEBUG_PRINTLN("BME68X error code : %f", String(bsec.sensor.status)); + } + else if (bsec.sensor.status > BME68X_OK) + { + MESH_DEBUG_PRINTLN("BME68X warning code : %f", String(bsec.sensor.status)); + } +} +void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec) +{ + if (!outputs.nOutputs) + { + MESH_DEBUG_PRINTLN("No new data to report out"); + return; + } + + MESH_DEBUG_PRINTLN("BSEC outputs:\n\tTime stamp = %f", String((int) (outputs.output[0].time_stamp / INT64_C(1000000)))); + for (uint8_t i = 0; i < outputs.nOutputs; i++) + { + const bsecData output = outputs.output[i]; + switch (output.sensor_id) + { + case BSEC_OUTPUT_IAQ: + MESH_DEBUG_PRINTLN("\tIAQ = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tIAQ accuracy = %f", String((int) output.accuracy)); + break; + case BSEC_OUTPUT_RAW_TEMPERATURE: + rawTemperature = output.signal; + MESH_DEBUG_PRINTLN("\tTemperature = %f", String(output.signal)); + break; + case BSEC_OUTPUT_RAW_PRESSURE: + rawPressure = output.signal; + MESH_DEBUG_PRINTLN("\tPressure = %f", String(output.signal)); + break; + case BSEC_OUTPUT_RAW_HUMIDITY: + rawHumidity = output.signal; + MESH_DEBUG_PRINTLN("\tHumidity = %f", String(output.signal)); + break; + case BSEC_OUTPUT_RAW_GAS: + MESH_DEBUG_PRINTLN("\tGas resistance = %f", String(output.signal)); + break; + case BSEC_OUTPUT_STABILIZATION_STATUS: + MESH_DEBUG_PRINTLN("\tStabilization status = %f", String(output.signal)); + break; + case BSEC_OUTPUT_RUN_IN_STATUS: + MESH_DEBUG_PRINTLN("\tRun in status = %f", String(output.signal)); + break; + case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE: + compTemperature = output.signal; + MESH_DEBUG_PRINTLN("\tCompensated temperature = %f", String(output.signal)); + break; + case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY: + compHumidity = output.signal; + MESH_DEBUG_PRINTLN("\tCompensated humidity = %f", String(output.signal)); + break; + case BSEC_OUTPUT_STATIC_IAQ: + readIAQ = output.signal; + MESH_DEBUG_PRINTLN("\tStatic IAQ = %f", String(output.signal)); + break; + case BSEC_OUTPUT_CO2_EQUIVALENT: + readCO2 = output.signal; + MESH_DEBUG_PRINTLN("\tCO2 Equivalent = %f", String(output.signal)); + break; + case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT: + MESH_DEBUG_PRINTLN("\tbVOC equivalent = %f", String(output.signal)); + break; + case BSEC_OUTPUT_GAS_PERCENTAGE: + MESH_DEBUG_PRINTLN("\tGas percentage = %f", String(output.signal)); + break; + case BSEC_OUTPUT_COMPENSATED_GAS: + MESH_DEBUG_PRINTLN("\tCompensated gas = %f", String(output.signal)); + break; + default: + break; + } + } +} +#endif + bool RAK4631SensorManager::begin() { #ifdef MESH_DEBUG scanDevices(&Wire); #endif -#if ENV_INCLUDE_GPS - //search for the correct IO standby pin depending on socket used - if(gpsIsAwake(P_GPS_STANDBY_A)){ - MESH_DEBUG_PRINTLN("GPS is on socket A"); - } - else if(gpsIsAwake(P_GPS_STANDBY_C)){ - MESH_DEBUG_PRINTLN("GPS is on socket C"); - } - else if(gpsIsAwake(P_GPS_STANDBY_F)){ - MESH_DEBUG_PRINTLN("GPS is on socket F"); - } - else{ - MESH_DEBUG_PRINTLN("Error: No GPS found on sockets A, C or F"); - gps_active = false; - gps_present = false; - return false; - } + #if ENV_INCLUDE_GPS + //search for the correct IO standby pin depending on socket used + if(gpsIsAwake(P_GPS_STANDBY_A)){ + MESH_DEBUG_PRINTLN("GPS is on socket A"); + } + else if(gpsIsAwake(P_GPS_STANDBY_C)){ + MESH_DEBUG_PRINTLN("GPS is on socket C"); + } + else if(gpsIsAwake(P_GPS_STANDBY_F)){ + MESH_DEBUG_PRINTLN("GPS is on socket F"); + } + else{ + MESH_DEBUG_PRINTLN("Error: No GPS found on sockets A, C or F"); + gps_active = false; + gps_detected = false; + return false; + } - //Now that GPS is found and set up, set to sleep for initial state - stop_gps(); -#endif + #ifndef FORCE_GPS_ALIVE + //Now that GPS is found and set up, set to sleep for initial state + stop_gps(); + #endif + #endif + + #if ENV_INCLUDE_BME680 + + bsecSensor sensorList[4] = { + BSEC_OUTPUT_IAQ, + // BSEC_OUTPUT_RAW_TEMPERATURE, + BSEC_OUTPUT_RAW_PRESSURE, + // BSEC_OUTPUT_RAW_HUMIDITY, + // BSEC_OUTPUT_RAW_GAS, + // BSEC_OUTPUT_STABILIZATION_STATUS, + // BSEC_OUTPUT_RUN_IN_STATUS, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, + BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, + // BSEC_OUTPUT_STATIC_IAQ, + // BSEC_OUTPUT_CO2_EQUIVALENT, + // BSEC_OUTPUT_BREATH_VOC_EQUIVALENT, + // BSEC_OUTPUT_GAS_PERCENTAGE, + // BSEC_OUTPUT_COMPENSATED_GAS + }; + + if(!BME680.begin(TELEM_BME680_ADDRESS, Wire)){ + checkBMEStatus(BME680); + bme680_present = false; + bme680_active = false; + return false; + } + + MESH_DEBUG_PRINTLN("Found BME680 at address: %02X", TELEM_BME680_ADDRESS); + bme680_present = true; + bme680_active = true; + + if (SAMPLING_RATE == BSEC_SAMPLE_RATE_ULP) + { + BME680.setTemperatureOffset(BSEC_SAMPLE_RATE_ULP); + } + else if (SAMPLING_RATE == BSEC_SAMPLE_RATE_LP) + { + BME680.setTemperatureOffset(TEMP_OFFSET_LP); + } + + if (!BME680.updateSubscription(sensorList, ARRAY_LEN(sensorList), SAMPLING_RATE)) + { + checkBMEStatus(BME680); + } + + BME680.attachCallback(newDataCallback); + + #endif } -#if ENV_INCLUDE_GPS bool RAK4631SensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) { + #ifdef ENV_INCLUDE_GPS if (requester_permissions & TELEM_PERM_LOCATION && gps_active) { // does requester have permission? telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude); } + #endif + + if (requester_permissions & TELEM_PERM_ENVIRONMENT) { + + #if ENV_INCLUDE_BME680 + if (bme680_active) { + telemetry.addTemperature(TELEM_CHANNEL_SELF, compTemperature); + telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, compHumidity); + telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, rawPressure); + telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF+1, readIAQ); + } + #endif + } return true; } void RAK4631SensorManager::loop() { static long next_update = 0; + #ifdef ENV_INCLUDE_GPS _nmea->loop(); + #endif - if (millis() > next_update && gps_active) { - node_lat = (double)ublox_GNSS.getLatitude()/10000000.; - node_lon = (double)ublox_GNSS.getLongitude()/10000000.; - node_altitude = (double)ublox_GNSS.getAltitude()/1000.; - MESH_DEBUG_PRINT("lat %f lon %f alt %f\r\n", node_lat, node_lon, node_altitude); + if (millis() > next_update) { + #ifdef ENV_INCLUDE_GPS + if(gps_active){ + node_lat = (double)ublox_GNSS.getLatitude()/10000000.; + node_lon = (double)ublox_GNSS.getLongitude()/10000000.; + node_altitude = (double)ublox_GNSS.getAltitude()/1000.; + MESH_DEBUG_PRINT("lat %f lon %f alt %f\r\n", node_lat, node_lon, node_altitude); + } + #endif + + #ifdef ENV_INCLUDE_BME680 + if(bme680_active){ + if (!BME680.run()){ + checkBMEStatus(BME680); + } + } + #endif next_update = millis() + 1000; } + } -int RAK4631SensorManager::getNumSettings() const { return 1; } // just one supported: "gps" (power switch) +int RAK4631SensorManager::getNumSettings() const { + #if ENV_INCLUDE_GPS + return gps_detected ? 1 : 0; // only show GPS setting if GPS is detected + #else + return 0; + #endif +} const char* RAK4631SensorManager::getSettingName(int i) const { - return i == 0 ? "gps" : NULL; + #if ENV_INCLUDE_GPS + return (gps_detected && i == 0) ? "gps" : NULL; + #else + return NULL; + #endif } const char* RAK4631SensorManager::getSettingValue(int i) const { - if (i == 0) { + #if ENV_INCLUDE_GPS + if (gps_detected && i == 0) { return gps_active ? "1" : "0"; } + #endif return NULL; } bool RAK4631SensorManager::setSettingValue(const char* name, const char* value) { - if (strcmp(name, "gps") == 0) { + #if ENV_INCLUDE_GPS + if (gps_detected && strcmp(name, "gps") == 0) { if (strcmp(value, "0") == 0) { stop_gps(); } else { @@ -221,9 +423,9 @@ bool RAK4631SensorManager::setSettingValue(const char* name, const char* value) } return true; } + #endif return false; // not supported } -#endif mesh::LocalIdentity radio_new_identity() { RadioNoiseListener rng(radio); diff --git a/variants/rak4631/target.h b/variants/rak4631/target.h index 3e6db0aa..0460c9e8 100644 --- a/variants/rak4631/target.h +++ b/variants/rak4631/target.h @@ -11,6 +11,9 @@ #include #include #endif +#if ENV_INCLUDE_BME680 + #include "bsec2.h" +#endif #ifdef DISPLAY_CLASS #include #endif @@ -20,7 +23,7 @@ class RAK4631SensorManager: public SensorManager { #if ENV_INCLUDE_GPS bool gps_active = false; - bool gps_present = false; + bool gps_detected = false; LocationProvider * _nmea; SFE_UBLOX_GNSS ublox_GNSS; uint32_t disStandbyPin = 0; @@ -32,20 +35,26 @@ class RAK4631SensorManager: public SensorManager { bool gpsIsAwake(uint32_t ioPin); #endif + #if ENV_INCLUDE_BME680 + bool bme680_active = false; + bool bme680_present = false; + #define SAMPLING_RATE BSEC_SAMPLE_RATE_ULP + #endif + public: #if ENV_INCLUDE_GPS RAK4631SensorManager(LocationProvider &nmea): _nmea(&nmea) { } - - bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; - void loop() override; - int getNumSettings() const override; - const char* getSettingName(int i) const override; - const char* getSettingValue(int i) const override; - bool setSettingValue(const char* name, const char* value) override; #else RAK4631SensorManager() { } #endif - bool begin() override; + + void loop() override; + bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; + int getNumSettings() const override; + const char* getSettingName(int i) const override; + const char* getSettingValue(int i) const override; + bool setSettingValue(const char* name, const char* value) override; + bool begin() override; }; extern RAK4631Board board; @@ -75,6 +84,11 @@ enum { RAK12500_ONLINE = _BV(14), }; +#if ENV_INCLUDE_BME680 + void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec); + void checkBMEStatus(Bsec2 bsec); +#endif + bool radio_init(); uint32_t radio_get_rng_seed(); void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); From b37c8017d969eb8e95586b807457fbf0500e90da Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 25 Jun 2025 14:04:29 +1000 Subject: [PATCH 07/27] * Fix: /helpers/esp32/TBeamBoard was breaking non-TBeam builds --- src/helpers/esp32/TBeamBoard.cpp | 6 +++++- src/helpers/esp32/TBeamBoard.h | 4 ++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/helpers/esp32/TBeamBoard.cpp b/src/helpers/esp32/TBeamBoard.cpp index 2e3ea040..5f708d71 100644 --- a/src/helpers/esp32/TBeamBoard.cpp +++ b/src/helpers/esp32/TBeamBoard.cpp @@ -1,3 +1,5 @@ +#if defined(TBEAM_SUPREME_SX1262) || defined(TBEAM_SX1262) || defined(TBEAM_SX1276) + #include #include "TBeamBoard.h" //#include @@ -343,4 +345,6 @@ bool TBeamBoard::power_init() // } -#pragma endregion \ No newline at end of file +#pragma endregion + +#endif diff --git a/src/helpers/esp32/TBeamBoard.h b/src/helpers/esp32/TBeamBoard.h index 255a6d22..74baebc3 100644 --- a/src/helpers/esp32/TBeamBoard.h +++ b/src/helpers/esp32/TBeamBoard.h @@ -1,5 +1,7 @@ #pragma once +#if defined(TBEAM_SUPREME_SX1262) || defined(TBEAM_SX1262) || defined(TBEAM_SX1276) + #include #include #include "XPowersLib.h" @@ -162,3 +164,5 @@ public: return "LilyGo T-Beam"; } }; + +#endif From 8191c0901bebd50a25ac6b0ed708235647efab45 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 25 Jun 2025 14:34:27 +1000 Subject: [PATCH 08/27] * new variant board: Tenstar C3 --- variants/tenstar_c3/platformio.ini | 65 ++++++++++++++++++++++++++++++ variants/tenstar_c3/target.cpp | 48 ++++++++++++++++++++++ variants/tenstar_c3/target.h | 21 ++++++++++ 3 files changed, 134 insertions(+) create mode 100644 variants/tenstar_c3/platformio.ini create mode 100644 variants/tenstar_c3/target.cpp create mode 100644 variants/tenstar_c3/target.h diff --git a/variants/tenstar_c3/platformio.ini b/variants/tenstar_c3/platformio.ini new file mode 100644 index 00000000..226f47e4 --- /dev/null +++ b/variants/tenstar_c3/platformio.ini @@ -0,0 +1,65 @@ +[Tenstar_esp32_C3] +extends = esp32_base +board = esp32-c3-devkitm-1 +build_flags = + ${esp32_base.build_flags} + -I variants/tenstar_c3 + -D ESP32_CPU_FREQ=80 + -D LORA_TX_BOOST_PIN=4 +; -D P_LORA_TX_LED=? + -D PIN_VBAT_READ=1 + -D P_LORA_MISO=9 + -D P_LORA_SCLK=8 + -D P_LORA_MOSI=7 + -D P_LORA_DIO_1=2 + -D P_LORA_NSS=6 + -D P_LORA_RESET=RADIOLIB_NC + -D P_LORA_BUSY=3 +; -D PIN_BOARD_SDA=18 +; -D PIN_BOARD_SCL=19 + -D SX126X_DIO2_AS_RF_SWITCH=true + -D SX126X_DIO3_TCXO_VOLTAGE=1.8 + -D SX126X_CURRENT_LIMIT=140 +build_src_filter = ${esp32_base.build_src_filter} + +<../variants/tenstar_c3> + +[env:Tenstar_C3_Repeater_sx1262] +extends = Tenstar_esp32_C3 +build_src_filter = ${Tenstar_esp32_C3.build_src_filter} + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Tenstar_esp32_C3.build_flags} + -D RADIO_CLASS=CustomSX1262 + -D WRAPPER_CLASS=CustomSX1262Wrapper + -D SX126X_RX_BOOSTED_GAIN=1 + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"Tenstar C3 Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 +; -D MESH_PACKET_LOGGING=1 +; -D MESH_DEBUG=1 +lib_deps = + ${Tenstar_esp32_C3.lib_deps} + ${esp32_ota.lib_deps} + +[env:Tenstar_C3_Repeater_sx1268] +extends = Tenstar_esp32_C3 +build_src_filter = ${Tenstar_esp32_C3.build_src_filter} + +<../examples/simple_repeater/main.cpp> +build_flags = + ${Tenstar_esp32_C3.build_flags} + -D RADIO_CLASS=CustomSX1268 + -D WRAPPER_CLASS=CustomSX1268Wrapper + -D LORA_TX_POWER=22 + -D ADVERT_NAME='"Tenstar C3 Repeater"' + -D ADVERT_LAT=0.0 + -D ADVERT_LON=0.0 + -D ADMIN_PASSWORD='"password"' + -D MAX_NEIGHBOURS=8 + ; -D MESH_PACKET_LOGGING=1 + ; -D MESH_DEBUG=1 +lib_deps = + ${Tenstar_esp32_C3.lib_deps} + ${esp32_ota.lib_deps} diff --git a/variants/tenstar_c3/target.cpp b/variants/tenstar_c3/target.cpp new file mode 100644 index 00000000..a29780f0 --- /dev/null +++ b/variants/tenstar_c3/target.cpp @@ -0,0 +1,48 @@ +#include +#include "target.h" + +XiaoC3Board board; + +#if defined(P_LORA_SCLK) + static SPIClass spi; + RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, spi); +#else + RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY); +#endif + +WRAPPER_CLASS radio_driver(radio, board); + +ESP32RTCClock fallback_clock; +AutoDiscoverRTCClock rtc_clock(fallback_clock); +SensorManager sensors; + +bool radio_init() { + fallback_clock.begin(); + rtc_clock.begin(Wire); + +#if defined(P_LORA_SCLK) + return radio.std_init(&spi); +#else + return radio.std_init(); +#endif +} + +uint32_t radio_get_rng_seed() { + return radio.random(0x7FFFFFFF); +} + +void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { + radio.setFrequency(freq); + radio.setSpreadingFactor(sf); + radio.setBandwidth(bw); + radio.setCodingRate(cr); +} + +void radio_set_tx_power(uint8_t dbm) { + radio.setOutputPower(dbm); +} + +mesh::LocalIdentity radio_new_identity() { + RadioNoiseListener rng(radio); + return mesh::LocalIdentity(&rng); // create new random identity +} diff --git a/variants/tenstar_c3/target.h b/variants/tenstar_c3/target.h new file mode 100644 index 00000000..0aea87dd --- /dev/null +++ b/variants/tenstar_c3/target.h @@ -0,0 +1,21 @@ +#pragma once + +#define RADIOLIB_STATIC_ONLY 1 +#include +#include +#include +#include +#include +#include +#include + +extern XiaoC3Board board; +extern WRAPPER_CLASS radio_driver; +extern AutoDiscoverRTCClock rtc_clock; +extern SensorManager sensors; + +bool radio_init(); +uint32_t radio_get_rng_seed(); +void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); +void radio_set_tx_power(uint8_t dbm); +mesh::LocalIdentity radio_new_identity(); From 556051955de08180766e80fdabbaf9fffea8c59a Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 25 Jun 2025 14:54:13 +1000 Subject: [PATCH 09/27] * ESP32Board: added support for Neopixel TX led --- src/helpers/ESP32Board.h | 9 +++++++++ variants/tenstar_c3/platformio.ini | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/helpers/ESP32Board.h b/src/helpers/ESP32Board.h index 4f90296e..e566f929 100644 --- a/src/helpers/ESP32Board.h +++ b/src/helpers/ESP32Board.h @@ -51,6 +51,15 @@ public: void onAfterTransmit() override { digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED off } +#elif defined(P_LORA_TX_NEOPIXEL_LED) + #define NEOPIXEL_BRIGHTNESS 64 // white brightness (max 255) + + void onBeforeTransmit() override { + neopixelWrite(P_LORA_TX_NEOPIXEL_LED, NEOPIXEL_BRIGHTNESS, NEOPIXEL_BRIGHTNESS, NEOPIXEL_BRIGHTNESS); // turn TX neopixel on (White) + } + void onAfterTransmit() override { + neopixelWrite(P_LORA_TX_NEOPIXEL_LED, 0, 0, 0); // turn TX neopixel off + } #endif uint16_t getBattMilliVolts() override { diff --git a/variants/tenstar_c3/platformio.ini b/variants/tenstar_c3/platformio.ini index 226f47e4..4967ec55 100644 --- a/variants/tenstar_c3/platformio.ini +++ b/variants/tenstar_c3/platformio.ini @@ -6,7 +6,7 @@ build_flags = -I variants/tenstar_c3 -D ESP32_CPU_FREQ=80 -D LORA_TX_BOOST_PIN=4 -; -D P_LORA_TX_LED=? + -D P_LORA_TX_NEOPIXEL_LED=10 -D PIN_VBAT_READ=1 -D P_LORA_MISO=9 -D P_LORA_SCLK=8 From 8ccd4f36606a56dbdabdcd849712d4ac02a18497 Mon Sep 17 00:00:00 2001 From: Florent Date: Wed, 25 Jun 2025 11:00:24 +0200 Subject: [PATCH 10/27] stm32: implement halt and reset --- src/helpers/stm32/STM32Board.h | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/helpers/stm32/STM32Board.h b/src/helpers/stm32/STM32Board.h index 65c7414b..06bc768f 100644 --- a/src/helpers/stm32/STM32Board.h +++ b/src/helpers/stm32/STM32Board.h @@ -23,6 +23,13 @@ public: } void reboot() override { + NVIC_SystemReset(); + } + + void powerOff() override { + HAL_PWREx_DisableInternalWakeUpLine(); + __disable_irq(); + HAL_PWREx_EnterSHUTDOWNMode(); } #if defined(P_LORA_TX_LED) From 55ff69bd2504f33675aea5f26bfd19752f1d9cb8 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Wed, 25 Jun 2025 19:02:16 +1000 Subject: [PATCH 11/27] * RAK: 'start ota' returned MAC address was reversed --- src/helpers/nrf52/RAK4631Board.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/nrf52/RAK4631Board.cpp b/src/helpers/nrf52/RAK4631Board.cpp index c75ecf29..97a96602 100644 --- a/src/helpers/nrf52/RAK4631Board.cpp +++ b/src/helpers/nrf52/RAK4631Board.cpp @@ -84,7 +84,7 @@ bool RAK4631Board::startOTAUpdate(const char* id, char reply[]) { memset(mac_addr, 0, sizeof(mac_addr)); Bluefruit.getAddr(mac_addr); sprintf(reply, "OK - mac: %02X:%02X:%02X:%02X:%02X:%02X", - mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + mac_addr[5], mac_addr[4], mac_addr[3], mac_addr[2], mac_addr[1], mac_addr[0]); return true; } From 387579922b539a19e103711f62c28e54b1786e25 Mon Sep 17 00:00:00 2001 From: Florent Date: Wed, 25 Jun 2025 13:55:54 +0200 Subject: [PATCH 12/27] rak3x72: support variations in platformio.ini --- variants/rak3x72/platformio.ini | 4 ++-- variants/rak3x72/target.cpp | 11 ++++++++++- variants/rak3x72/target.h | 8 ++++++-- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/variants/rak3x72/platformio.ini b/variants/rak3x72/platformio.ini index 94e8f595..386866ba 100644 --- a/variants/rak3x72/platformio.ini +++ b/variants/rak3x72/platformio.ini @@ -7,6 +7,8 @@ build_flags = ${stm32_base.build_flags} -D WRAPPER_CLASS=CustomSTM32WLxWrapper -D SPI_INTERFACES_COUNT=0 -D RX_BOOSTED_GAIN=true +; -D STM32WL_TCXO_VOLTAGE=1.6 ; defaults to 0 if undef +; -D LORA_TX_POWER=14 ; Defaults to 22 for HP, 14 is for LP version -I variants/rak3x72 build_src_filter = ${stm32_base.build_src_filter} +<../variants/rak3x72> @@ -14,7 +16,6 @@ build_src_filter = ${stm32_base.build_src_filter} [env:rak3x72-repeater] extends = rak3x72 build_flags = ${rak3x72.build_flags} - -D LORA_TX_POWER=22 -D ADVERT_NAME='"RAK3x72 Repeater"' -D ADMIN_PASSWORD='"password"' build_src_filter = ${rak3x72.build_src_filter} @@ -24,7 +25,6 @@ build_src_filter = ${rak3x72.build_src_filter} extends = rak3x72 build_flags = ${rak3x72.build_flags} ; -D FORMAT_FS=true - -D LORA_TX_POWER=22 -D MAX_CONTACTS=100 -D MAX_GROUP_CHANNELS=8 build_src_filter = ${rak3x72.build_src_filter} diff --git a/variants/rak3x72/target.cpp b/variants/rak3x72/target.cpp index 4cb5929a..d7070eae 100644 --- a/variants/rak3x72/target.cpp +++ b/variants/rak3x72/target.cpp @@ -24,12 +24,21 @@ SensorManager sensors; #define LORA_CR 5 #endif +#ifndef STM32WL_TCXO_VOLTAGE + // TCXO set to 0 for RAK3172 + #define STM32WL_TCXO_VOLTAGE 0 +#endif + +#ifndef LORA_TX_POWER + #define LORA_TX_POWER 22 +#endif + bool radio_init() { // rtc_clock.begin(Wire); radio.setRfSwitchTable(rfswitch_pins, rfswitch_table); - int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, 0, 0); // TCXO set to 0 for RAK3172 + int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, STM32WL_TCXO_VOLTAGE, 0); if (status != RADIOLIB_ERR_NONE) { Serial.print("ERROR: radio init failed: "); diff --git a/variants/rak3x72/target.h b/variants/rak3x72/target.h index c39b69b1..6c86a702 100644 --- a/variants/rak3x72/target.h +++ b/variants/rak3x72/target.h @@ -18,8 +18,12 @@ public: } uint16_t getBattMilliVolts() override { - uint32_t raw = analogRead(PIN_VBAT_READ); - return (ADC_MULTIPLIER * raw) / 1024; + analogReadResolution(12); + uint32_t raw = 0; + for (int i=0; i<8;i++) { + raw += analogRead(PIN_VBAT_READ); + } + return ((double)raw) * ADC_MULTIPLIER / 8 / 4096; } }; From f15f32e1385dad52952d93da87f5df64dae91076 Mon Sep 17 00:00:00 2001 From: recrof Date: Wed, 25 Jun 2025 22:21:22 +0200 Subject: [PATCH 13/27] Station G2 refactor for radio.std_init, set max tx power to 19dBm --- variants/station_g2/platformio.ini | 4 ++-- variants/station_g2/target.cpp | 29 +++-------------------------- 2 files changed, 5 insertions(+), 28 deletions(-) diff --git a/variants/station_g2/platformio.ini b/variants/station_g2/platformio.ini index 8ba368bd..5d9a6823 100644 --- a/variants/station_g2/platformio.ini +++ b/variants/station_g2/platformio.ini @@ -7,7 +7,7 @@ build_flags = -D STATION_G2 -D RADIO_CLASS=CustomSX1262 -D WRAPPER_CLASS=CustomSX1262Wrapper - -D LORA_TX_POWER=7 + -D LORA_TX_POWER=19 ; -D P_LORA_TX_LED=35 -D PIN_BOARD_SDA=5 -D PIN_BOARD_SCL=6 @@ -16,9 +16,9 @@ build_flags = -D SX126X_DIO3_TCXO_VOLTAGE=1.8 -D SX126X_CURRENT_LIMIT=140 ; -D SX126X_RX_BOOSTED_GAIN=1 - DO NOT ENABLE THIS! +; https://wiki.uniteng.com/en/meshtastic/station-g2#impact-of-lora-node-dense-areashigh-noise-environments-on-rf-performance -I src/helpers/ui -D DISPLAY_CLASS=SH1106Display -; https://wiki.uniteng.com/en/meshtastic/station-g2#impact-of-lora-node-dense-areashigh-noise-environments-on-rf-performance build_src_filter = ${esp32_base.build_src_filter} +<../variants/station_g2> + diff --git a/variants/station_g2/target.cpp b/variants/station_g2/target.cpp index dca94f21..2b19f5f0 100644 --- a/variants/station_g2/target.cpp +++ b/variants/station_g2/target.cpp @@ -27,36 +27,13 @@ SensorManager sensors; bool radio_init() { fallback_clock.begin(); rtc_clock.begin(Wire); - -#ifdef SX126X_DIO3_TCXO_VOLTAGE - float tcxo = SX126X_DIO3_TCXO_VOLTAGE; -#else - float tcxo = 1.6f; -#endif #if defined(P_LORA_SCLK) spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); + return radio.std_init(&spi); +#else + return radio.std_init(); #endif - int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); - if (status != RADIOLIB_ERR_NONE) { - Serial.print("ERROR: radio init failed: "); - Serial.println(status); - return false; // fail - } - - radio.setCRC(1); - -#ifdef SX126X_CURRENT_LIMIT - radio.setCurrentLimit(SX126X_CURRENT_LIMIT); -#endif -#ifdef SX126X_DIO2_AS_RF_SWITCH - radio.setDio2AsRfSwitch(SX126X_DIO2_AS_RF_SWITCH); -#endif -#ifdef SX126X_RX_BOOSTED_GAIN - radio.setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); -#endif - - return true; // success } uint32_t radio_get_rng_seed() { From 669ff39cd6b7c37cf5c8a03b81698ec49763349a Mon Sep 17 00:00:00 2001 From: "Ricardo F." <112904881+rfmoz@users.noreply.github.com> Date: Wed, 25 Jun 2025 22:41:14 +0200 Subject: [PATCH 14/27] Update faq.md Order last other questions and add fix to WebFlasher from linux --- docs/faq.md | 43 ++++++++++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 15 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 7a5e28ac..1c67c9c7 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -65,10 +65,12 @@ author: https://github.com/LitBomb - [6.4. Q: I can't connect via Bluetooth, what is the Bluetooth pairing code?](#64-q-i-cant-connect-via-bluetooth-what-is-the-bluetooth-pairing-code) - [6.5. Q: My Heltec V3 keeps disconnecting from my smartphone. It can't hold a solid Bluetooth connection.](#65-q-my-heltec-v3-keeps-disconnecting-from-my-smartphone--it-cant-hold-a-solid-bluetooth-connection) - [6.6. Q: My RAK/T1000-E/xiao\_nRF52 device seems to be corrupted, how do I wipe it clean to start fresh?](#66-q-my-rakt1000-exiao_nrf52-device-seems-to-be-corrupted-how-do-i-wipe-it-clean-to-start-fresh) + - [6.7. Q: WebFlasher fails on Linux with failed to open](#67-q-webflasher-fails-on-Linux-with-failed-to-open) + - [7. Other Questions:](#7-other-questions) - - [7.2 Q: How to update ESP32-based devices over the air?](#72-q-how-to-update-esp32-based-devices-over-the-air) - [7.1 Q: How to update nRF (RAK, T114, Seed XIAO) repeater and room server firmware over the air using the new simpler DFU app?](#71-q-how-to-update-nrf-rak-t114-seed-xiao-repeater-and-room-server-firmware-over-the-air-using-the-new-simpler-dfu-app) - - [7.2 Q: Is there a way to lower the chance of a failed OTA device firmware update (DFU)?](#72-q-is-there-a-way-to-lower-the-chance-of-a-failed-ota-device-firmware-update-dfu) + - [7.2 Q: How to update ESP32-based devices over the air?](#72-q-how-to-update-esp32-based-devices-over-the-air) + - [7.3 Q: Is there a way to lower the chance of a failed OTA device firmware update (DFU)?](#73-q-is-there-a-way-to-lower-the-chance-of-a-failed-ota-device-firmware-update-dfu) ## 1. Introduction @@ -556,21 +558,17 @@ You can get the epoch time on and use it to se Separately, starting in firmware version 1.7.0, there is a CLI Rescue mode. If your device has a user button (e.g. some RAK, T114), you can activate the rescue mode by hold down the user button of the device within 8 seconds of boot. Then you can use the 'Console' on flasher.meshcore.co.uk +### 6.7. Q: WebFlasher fails on Linux with failed to open + +**A:** If the usb port doesn't have the right ownership for this task, the process fails with the following error: +`NetworkError: Failed to execute 'open' on 'SerialPort': Failed to open serial port.` + +Allow the browser user on it: +`# setfacl -m u:YOUR_USER_HERE:rw /dev/ttyUSB0` + --- ## 7. Other Questions: -### 7.2 Q: How to update ESP32-based devices over the air? - -**A:** For ESP32-based devices (e.g. Heltec V3): -1. On flasher.meshcore.co.uk, download the **non-merged** version of the firmware for your ESP32 device (e.g. `Heltec_v3_repeater-v1.6.2-4449fd3.bin`, no `"merged"` in the file name) -2. From the MeshCore app, login remotely to the repeater you want to update with admin priviledge -4. Go to the Command Line tab, type `start ota` and hit enter. -5. you should see `OK` to confirm the repeater device is now in OTA mode -6. The command `start ota` on an ESP32-based device starts a wifi hotspot named `MeshCore OTA` -7. From your phone or computer connect to the 'MeshCore OTA' hotspot -8. From a browser, go to http://192.168.4.1/update and upload the non-merged bin from the flasher - - ### 7.1 Q: How to update nRF (RAK, T114, Seed XIAO) repeater and room server firmware over the air using the new simpler DFU app? **A:** The steps below work on both Android and iOS as nRF has made both apps' user interface the same on both platforms: @@ -589,7 +587,20 @@ Separately, starting in firmware version 1.7.0, there is a CLI Rescue mode. If 13. If it fails, try turning off and on Bluetooth on your phone. If that doesn't work, try rebooting your phone. 14. Wait for the update to complete. It can take a few minutes. -### 7.2 Q: Is there a way to lower the chance of a failed OTA device firmware update (DFU)? + +### 7.2 Q: How to update ESP32-based devices over the air? + +**A:** For ESP32-based devices (e.g. Heltec V3): +1. On flasher.meshcore.co.uk, download the **non-merged** version of the firmware for your ESP32 device (e.g. `Heltec_v3_repeater-v1.6.2-4449fd3.bin`, no `"merged"` in the file name) +2. From the MeshCore app, login remotely to the repeater you want to update with admin priviledge +4. Go to the Command Line tab, type `start ota` and hit enter. +5. you should see `OK` to confirm the repeater device is now in OTA mode +6. The command `start ota` on an ESP32-based device starts a wifi hotspot named `MeshCore OTA` +7. From your phone or computer connect to the 'MeshCore OTA' hotspot +8. From a browser, go to http://192.168.4.1/update and upload the non-merged bin from the flasher + + +### 7.3 Q: Is there a way to lower the chance of a failed OTA device firmware update (DFU)? **A:** Yes, developer `che aporeps` has an enhanced OTA DFU bootloader for nRF52 based devices. With this bootloader, if it detects that the application firmware is invalid, it falls back to OTA DFU mode so you can attempt to flash again to recover. This bootloader has other changes to make the OTA DFU process more fault tolerant. @@ -602,4 +613,6 @@ Currently, the following boards are supported: - RAK 4631 + + --- From 63247667d0b5066771dfa293df1501def1e82ad4 Mon Sep 17 00:00:00 2001 From: cod3doomy Date: Wed, 25 Jun 2025 21:12:36 -0700 Subject: [PATCH 15/27] String removed Removed all string type casting --- variants/rak4631/target.cpp | 51 ++++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/variants/rak4631/target.cpp b/variants/rak4631/target.cpp index b7c74bf4..45d10975 100644 --- a/variants/rak4631/target.cpp +++ b/variants/rak4631/target.cpp @@ -31,6 +31,7 @@ float compTemperature = 0; float rawHumidity = 0; float compHumidity = 0; float readIAQ = 0; +float readStaticIAQ = 0; float readCO2 = 0; #endif @@ -171,20 +172,20 @@ void checkBMEStatus(Bsec2 bsec) { if (bsec.status < BSEC_OK) { - MESH_DEBUG_PRINTLN("BSEC error code : %f", String(bsec.status)); + MESH_DEBUG_PRINTLN("BSEC error code : %f", float(bsec.status)); } else if (bsec.status > BSEC_OK) { - MESH_DEBUG_PRINTLN("BSEC warning code : %f", String(bsec.status)); + MESH_DEBUG_PRINTLN("BSEC warning code : %f", float(bsec.status)); } if (bsec.sensor.status < BME68X_OK) { - MESH_DEBUG_PRINTLN("BME68X error code : %f", String(bsec.sensor.status)); + MESH_DEBUG_PRINTLN("BME68X error code : %f", bsec.sensor.status); } else if (bsec.sensor.status > BME68X_OK) { - MESH_DEBUG_PRINTLN("BME68X warning code : %f", String(bsec.sensor.status)); + MESH_DEBUG_PRINTLN("BME68X warning code : %f", bsec.sensor.status); } } void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec) @@ -195,61 +196,62 @@ void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bse return; } - MESH_DEBUG_PRINTLN("BSEC outputs:\n\tTime stamp = %f", String((int) (outputs.output[0].time_stamp / INT64_C(1000000)))); + MESH_DEBUG_PRINTLN("BSEC outputs:\n\tTime stamp = %f", (int) (outputs.output[0].time_stamp / INT64_C(1000000))); for (uint8_t i = 0; i < outputs.nOutputs; i++) { const bsecData output = outputs.output[i]; switch (output.sensor_id) { case BSEC_OUTPUT_IAQ: - MESH_DEBUG_PRINTLN("\tIAQ = %f", String(output.signal)); - MESH_DEBUG_PRINTLN("\tIAQ accuracy = %f", String((int) output.accuracy)); + readIAQ = output.signal; + MESH_DEBUG_PRINTLN("\tIAQ = %f", output.signal); + MESH_DEBUG_PRINTLN("\tIAQ accuracy = %f", output.accuracy); break; case BSEC_OUTPUT_RAW_TEMPERATURE: rawTemperature = output.signal; - MESH_DEBUG_PRINTLN("\tTemperature = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tTemperature = %f", output.signal); break; case BSEC_OUTPUT_RAW_PRESSURE: rawPressure = output.signal; - MESH_DEBUG_PRINTLN("\tPressure = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tPressure = %f", output.signal); break; case BSEC_OUTPUT_RAW_HUMIDITY: rawHumidity = output.signal; - MESH_DEBUG_PRINTLN("\tHumidity = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tHumidity = %f", output.signal); break; case BSEC_OUTPUT_RAW_GAS: - MESH_DEBUG_PRINTLN("\tGas resistance = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tGas resistance = %f", output.signal); break; case BSEC_OUTPUT_STABILIZATION_STATUS: - MESH_DEBUG_PRINTLN("\tStabilization status = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tStabilization status = %f", output.signal); break; case BSEC_OUTPUT_RUN_IN_STATUS: - MESH_DEBUG_PRINTLN("\tRun in status = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tRun in status = %f", output.signal); break; case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE: compTemperature = output.signal; - MESH_DEBUG_PRINTLN("\tCompensated temperature = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tCompensated temperature = %f", output.signal); break; case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY: compHumidity = output.signal; - MESH_DEBUG_PRINTLN("\tCompensated humidity = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tCompensated humidity = %f", output.signal); break; case BSEC_OUTPUT_STATIC_IAQ: - readIAQ = output.signal; - MESH_DEBUG_PRINTLN("\tStatic IAQ = %f", String(output.signal)); + readStaticIAQ = output.signal; + MESH_DEBUG_PRINTLN("\tStatic IAQ = %f", output.signal); break; case BSEC_OUTPUT_CO2_EQUIVALENT: readCO2 = output.signal; - MESH_DEBUG_PRINTLN("\tCO2 Equivalent = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tCO2 Equivalent = %f", output.signal); break; case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT: - MESH_DEBUG_PRINTLN("\tbVOC equivalent = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tbVOC equivalent = %f", output.signal); break; case BSEC_OUTPUT_GAS_PERCENTAGE: - MESH_DEBUG_PRINTLN("\tGas percentage = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tGas percentage = %f", output.signal); break; case BSEC_OUTPUT_COMPENSATED_GAS: - MESH_DEBUG_PRINTLN("\tCompensated gas = %f", String(output.signal)); + MESH_DEBUG_PRINTLN("\tCompensated gas = %f", output.signal); break; default: break; @@ -290,7 +292,7 @@ bool RAK4631SensorManager::begin() { #if ENV_INCLUDE_BME680 - bsecSensor sensorList[4] = { + bsecSensor sensorList[5] = { BSEC_OUTPUT_IAQ, // BSEC_OUTPUT_RAW_TEMPERATURE, BSEC_OUTPUT_RAW_PRESSURE, @@ -300,7 +302,7 @@ bool RAK4631SensorManager::begin() { // BSEC_OUTPUT_RUN_IN_STATUS, BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE, BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, - // BSEC_OUTPUT_STATIC_IAQ, + BSEC_OUTPUT_STATIC_IAQ, // BSEC_OUTPUT_CO2_EQUIVALENT, // BSEC_OUTPUT_BREATH_VOC_EQUIVALENT, // BSEC_OUTPUT_GAS_PERCENTAGE, @@ -351,7 +353,8 @@ bool RAK4631SensorManager::querySensors(uint8_t requester_permissions, CayenneLP telemetry.addTemperature(TELEM_CHANNEL_SELF, compTemperature); telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, compHumidity); telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, rawPressure); - telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF+1, readIAQ); + telemetry.addTemperature(TELEM_CHANNEL_SELF+1, readIAQ); + telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF+1, readStaticIAQ); } #endif } From 408ed549a814e341789be5854a3f366f56607426 Mon Sep 17 00:00:00 2001 From: Florent Date: Thu, 26 Jun 2025 13:04:15 +0200 Subject: [PATCH 16/27] wio-e5-sdk: adjust uart location --- variants/wio-e5-dev/platformio.ini | 2 ++ variants/wio-e5-dev/variant.h | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/variants/wio-e5-dev/platformio.ini b/variants/wio-e5-dev/platformio.ini index 22c2d880..ce96ad2a 100644 --- a/variants/wio-e5-dev/platformio.ini +++ b/variants/wio-e5-dev/platformio.ini @@ -7,6 +7,8 @@ build_flags = ${stm32_base.build_flags} -D WRAPPER_CLASS=CustomSTM32WLxWrapper -D SPI_INTERFACES_COUNT=0 -D RX_BOOSTED_GAIN=true + -D PIN_SERIAL_RX=PB7 + -D PIN_SERIAL_TX=PB6 -I variants/wio-e5-dev build_src_filter = ${stm32_base.build_src_filter} +<../variants/wio-e5-dev> diff --git a/variants/wio-e5-dev/variant.h b/variants/wio-e5-dev/variant.h index 821fc410..ffd366f9 100644 --- a/variants/wio-e5-dev/variant.h +++ b/variants/wio-e5-dev/variant.h @@ -1,10 +1,5 @@ #pragma once -// UART Definitions -// #ifndef SERIAL_UART_INSTANCE -// #define SERIAL_UART_INSTANCE 101 -// #endif - #include #undef RNG From 0f259d3b51b07e9c8b594139cdf7c0fb8774260d Mon Sep 17 00:00:00 2001 From: Florent de Lamotte Date: Fri, 27 Jun 2025 11:11:12 +0200 Subject: [PATCH 17/27] CustomSX1262: fix typo that would prevent compile when TXEN or RXEN is not set --- src/helpers/CustomSX1262.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/helpers/CustomSX1262.h b/src/helpers/CustomSX1262.h index 7d5d4269..17673d3a 100644 --- a/src/helpers/CustomSX1262.h +++ b/src/helpers/CustomSX1262.h @@ -67,11 +67,11 @@ class CustomSX1262 : public SX1262 { setRxBoostedGainMode(SX126X_RX_BOOSTED_GAIN); #endif #if defined(SX126X_RXEN) || defined(SX126X_TXEN) - #ifndef SX1262X_RXEN - #define SX1262X_RXEN RADIOLIB_NC + #ifndef SX126X_RXEN + #define SX126X_RXEN RADIOLIB_NC #endif - #ifndef SX1262X_TXEN - #define SX1262X_TXEN RADIOLIB_NC + #ifndef SX126X_TXEN + #define SX126X_TXEN RADIOLIB_NC #endif setRfSwitchPins(SX126X_RXEN, SX126X_TXEN); #endif From 07f25ccac817b36cf29a0b5cd9f95cd2ae4cb802 Mon Sep 17 00:00:00 2001 From: recrof Date: Fri, 27 Jun 2025 15:12:48 +0200 Subject: [PATCH 18/27] sx1276 boards: migrate to std_init() --- src/helpers/CustomSX1276.h | 59 ++++++++++++++++++++++++-- variants/heltec_v2/target.cpp | 21 ++------- variants/lilygo_t3s3_sx1276/target.cpp | 23 ++-------- variants/lilygo_tlora_v2_1/target.cpp | 23 +++------- variants/lilygo_tlora_v2_1/target.h | 3 +- 5 files changed, 69 insertions(+), 60 deletions(-) diff --git a/src/helpers/CustomSX1276.h b/src/helpers/CustomSX1276.h index 35d879fc..8396fe07 100644 --- a/src/helpers/CustomSX1276.h +++ b/src/helpers/CustomSX1276.h @@ -12,10 +12,63 @@ class CustomSX1276 : public SX1276 { public: CustomSX1276(Module *mod) : SX1276(mod) { } + #ifdef RP2040_PLATFORM + bool std_init(SPIClassRP2040* spi = NULL) + #else + bool std_init(SPIClass* spi = NULL) + #endif + { + #ifdef LORA_CR + uint8_t cr = LORA_CR; + #else + uint8_t cr = 5; + #endif + + #if defined(P_LORA_SCLK) + #ifdef NRF52_PLATFORM + if (spi) { spi->setPins(P_LORA_MISO, P_LORA_SCLK, P_LORA_MOSI); spi->begin(); } + #elif defined(RP2040_PLATFORM) + if (spi) { + spi->setMISO(P_LORA_MISO); + //spi->setCS(P_LORA_NSS); // Setting CS results in freeze + spi->setSCK(P_LORA_SCLK); + spi->setMOSI(P_LORA_MOSI); + spi->begin(); + } + #else + if (spi) spi->begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); + #endif + #endif + int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8); + // if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f + if (status != RADIOLIB_ERR_NONE) { + Serial.print("ERROR: radio init failed: "); + Serial.println(status); + return false; // fail + } + #ifdef SX127X_CURRENT_LIMIT + setCurrentLimit(SX127X_CURRENT_LIMIT); + #endif + + #if defined(SX176X_RXEN) || defined(SX176X_TXEN) + #ifndef SX176X_RXEN + #define SX176X_RXEN RADIOLIB_NC + #endif + #ifndef SX176X_TXEN + #define SX176X_TXEN RADIOLIB_NC + #endif + setRfSwitchPins(SX176X_RXEN, SX176X_TXEN); + #endif + + setCRC(1); + + return true; // success + } + bool isReceiving() { return (getModemStatus() & - (RH_RF95_MODEM_STATUS_SIGNAL_DETECTED - | RH_RF95_MODEM_STATUS_SIGNAL_SYNCHRONIZED + (RH_RF95_MODEM_STATUS_SIGNAL_DETECTED + | RH_RF95_MODEM_STATUS_SIGNAL_SYNCHRONIZED | RH_RF95_MODEM_STATUS_HEADER_INFO_VALID)) != 0; } @@ -23,7 +76,7 @@ class CustomSX1276 : public SX1276 { // start CAD int16_t state = startChannelScan(); RADIOLIB_ASSERT(state); - + // wait for channel activity detected or timeout unsigned long timeout = millis() + 16; while(!this->mod->hal->digitalRead(this->mod->getIrq()) && millis() < timeout) { diff --git a/variants/heltec_v2/target.cpp b/variants/heltec_v2/target.cpp index a7e9fa67..d4d21dba 100644 --- a/variants/heltec_v2/target.cpp +++ b/variants/heltec_v2/target.cpp @@ -20,31 +20,16 @@ SensorManager sensors; DISPLAY_CLASS display; #endif -#ifndef LORA_CR - #define LORA_CR 5 -#endif - bool radio_init() { fallback_clock.begin(); rtc_clock.begin(Wire); #if defined(P_LORA_SCLK) spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); + return radio.std_init(&spi); +#else + return radio.std_init(); #endif - int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8); - if (status != RADIOLIB_ERR_NONE) { - Serial.print("ERROR: radio init failed: "); - Serial.println(status); - return false; // fail - } - -#ifdef SX127X_CURRENT_LIMIT - radio.setCurrentLimit(SX127X_CURRENT_LIMIT); -#endif - - radio.setCRC(1); - - return true; // success } uint32_t radio_get_rng_seed() { diff --git a/variants/lilygo_t3s3_sx1276/target.cpp b/variants/lilygo_t3s3_sx1276/target.cpp index db11433a..b2ee4455 100644 --- a/variants/lilygo_t3s3_sx1276/target.cpp +++ b/variants/lilygo_t3s3_sx1276/target.cpp @@ -20,33 +20,16 @@ SensorManager sensors; DISPLAY_CLASS display; #endif -#ifndef LORA_CR - #define LORA_CR 5 -#endif - bool radio_init() { fallback_clock.begin(); rtc_clock.begin(Wire); #if defined(P_LORA_SCLK) spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); + return radio.std_init(&spi); +#else + return radio.std_init(); #endif - int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8); - if (status != RADIOLIB_ERR_NONE) { - Serial.print("ERROR: radio init failed: "); - Serial.println(status); - return false; // fail - } - -#ifdef SX127X_CURRENT_LIMIT - radio.setCurrentLimit(SX127X_CURRENT_LIMIT); -#endif - - radio.setCRC(1); - - radio.setRfSwitchPins(21, 10); - - return true; // success } uint32_t radio_get_rng_seed() { diff --git a/variants/lilygo_tlora_v2_1/target.cpp b/variants/lilygo_tlora_v2_1/target.cpp index 4d513ed9..6f60b979 100644 --- a/variants/lilygo_tlora_v2_1/target.cpp +++ b/variants/lilygo_tlora_v2_1/target.cpp @@ -10,35 +10,22 @@ WRAPPER_CLASS radio_driver(radio, board); ESP32RTCClock fallback_clock; AutoDiscoverRTCClock rtc_clock(fallback_clock); -SensorManager sensors; +EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS DISPLAY_CLASS display; #endif -#ifndef LORA_CR - #define LORA_CR 5 -#endif - bool radio_init() { fallback_clock.begin(); rtc_clock.begin(Wire); +#if defined(P_LORA_SCLK) spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); - int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8); - if (status != RADIOLIB_ERR_NONE) { - Serial.print("ERROR: radio init failed: "); - Serial.println(status); - return false; // fail - } - -#ifdef SX127X_CURRENT_LIMIT - radio.setCurrentLimit(SX127X_CURRENT_LIMIT); + return radio.std_init(&spi); +#else + return radio.std_init(); #endif - - radio.setCRC(1); - - return true; // success } uint32_t radio_get_rng_seed() { diff --git a/variants/lilygo_tlora_v2_1/target.h b/variants/lilygo_tlora_v2_1/target.h index edf28eb4..8e48c3e7 100644 --- a/variants/lilygo_tlora_v2_1/target.h +++ b/variants/lilygo_tlora_v2_1/target.h @@ -7,6 +7,7 @@ #include #include #include +#include #ifdef DISPLAY_CLASS #include #endif @@ -14,7 +15,7 @@ extern LilyGoTLoraBoard board; extern WRAPPER_CLASS radio_driver; extern AutoDiscoverRTCClock rtc_clock; -extern SensorManager sensors; +extern EnvironmentSensorManager sensors; #ifdef DISPLAY_CLASS extern DISPLAY_CLASS display; From f666b8c8cf4f4fe97e11f20418833f22280d8159 Mon Sep 17 00:00:00 2001 From: recrof Date: Fri, 27 Jun 2025 15:16:37 +0200 Subject: [PATCH 19/27] RadioWrapper::std_init: add missing definitions for rx/tx switching --- variants/lilygo_t3s3_sx1276/platformio.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/variants/lilygo_t3s3_sx1276/platformio.ini b/variants/lilygo_t3s3_sx1276/platformio.ini index 1bcbbbf9..74eced9c 100644 --- a/variants/lilygo_t3s3_sx1276/platformio.ini +++ b/variants/lilygo_t3s3_sx1276/platformio.ini @@ -21,6 +21,8 @@ build_flags = -D RADIO_CLASS=CustomSX1276 -D WRAPPER_CLASS=CustomSX1276Wrapper -D SX127X_CURRENT_LIMIT=120 + -D SX176X_RXEN=21 + -D SX176X_TXEN=10 -D LORA_TX_POWER=20 build_src_filter = ${esp32_base.build_src_filter} +<../variants/lilygo_t3s3_sx1276> From 95e69cf27312763fef72b151a2758756adc19beb Mon Sep 17 00:00:00 2001 From: recrof Date: Fri, 27 Jun 2025 15:17:51 +0200 Subject: [PATCH 20/27] RadioWrapper::std_init: add tbeam, unify coding style --- variants/lilygo_tbeam/target.cpp | 78 ++++++++++++-------------------- 1 file changed, 28 insertions(+), 50 deletions(-) diff --git a/variants/lilygo_tbeam/target.cpp b/variants/lilygo_tbeam/target.cpp index 69a980fc..c482dd04 100644 --- a/variants/lilygo_tbeam/target.cpp +++ b/variants/lilygo_tbeam/target.cpp @@ -4,7 +4,7 @@ TBeamBoard board; // Using PMU AXP2102 -#define PMU_WIRE_PORT Wire +#define PMU_WIRE_PORT Wire bool pmuIntFlag = false; static void setPMUIntFlag(){ @@ -32,47 +32,38 @@ SensorManager sensors; #define LORA_CR 5 #endif -bool TBeamBoard::power_init() -{ - if (!PMU) - { +bool TBeamBoard::power_init() { + if (!PMU) { PMU = new XPowersAXP2101(PMU_WIRE_PORT); - if (!PMU->init()) - { + if (!PMU->init()) { // Serial.println("Warning: Failed to find AXP2101 power management"); delete PMU; PMU = NULL; } - else - { + else { // Serial.println("AXP2101 PMU init succeeded, using AXP2101 PMU"); } } - if (!PMU) - { + if (!PMU) { PMU = new XPowersAXP192(PMU_WIRE_PORT); - if (!PMU->init()) - { + if (!PMU->init()) { // Serial.println("Warning: Failed to find AXP192 power management"); delete PMU; PMU = NULL; } - else - { + else { // Serial.println("AXP192 PMU init succeeded, using AXP192 PMU"); } } - if (!PMU) - { + if (!PMU) { MESH_DEBUG_PRINTLN("PMU init failed."); return false; } // Serial.printf("PMU ID:0x%x\n", PMU->getChipID()); // printPMU(); - if (PMU->getChipModel() == XPOWERS_AXP192) - { + if (PMU->getChipModel() == XPOWERS_AXP192) { // lora radio power channel PMU->setPowerChannelVoltage(XPOWERS_LDO2, 3300); PMU->enablePowerOutput(XPOWERS_LDO2); @@ -95,8 +86,7 @@ bool TBeamBoard::power_init() PMU->disableIRQ(XPOWERS_AXP192_ALL_IRQ); PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_550MA); } - else if (PMU->getChipModel() == XPOWERS_AXP2101) - { + else if (PMU->getChipModel() == XPOWERS_AXP2101) { // gnss module power channel PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300); PMU->enablePowerOutput(XPOWERS_ALDO4); @@ -144,21 +134,10 @@ bool radio_init() { #if defined(P_LORA_SCLK) spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); + return radio.std_init(&spi); +#else + return radio.std_init(); #endif - int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8); - if (status != RADIOLIB_ERR_NONE) { - Serial.print("ERROR: radio init failed: "); - Serial.println(status); - return false; // fail - } - -#ifdef SX127X_CURRENT_LIMIT - radio.setCurrentLimit(SX127X_CURRENT_LIMIT); -#endif - - radio.setCRC(1); - - return true; // success } uint32_t radio_get_rng_seed() { @@ -182,22 +161,21 @@ mesh::LocalIdentity radio_new_identity() { } #ifdef MESH_DEBUG -void TBeamBoard::printPMU() -{ - Serial.print("isCharging:"); Serial.println(PMU->isCharging() ? "YES" : "NO"); - Serial.print("isDischarge:"); Serial.println(PMU->isDischarge() ? "YES" : "NO"); - Serial.print("isVbusIn:"); Serial.println(PMU->isVbusIn() ? "YES" : "NO"); - Serial.print("getBattVoltage:"); Serial.print(PMU->getBattVoltage()); Serial.println("mV"); - Serial.print("getVbusVoltage:"); Serial.print(PMU->getVbusVoltage()); Serial.println("mV"); - Serial.print("getSystemVoltage:"); Serial.print(PMU->getSystemVoltage()); Serial.println("mV"); +void TBeamBoard::printPMU() { + Serial.print("isCharging:"); Serial.println(PMU->isCharging() ? "YES" : "NO"); + Serial.print("isDischarge:"); Serial.println(PMU->isDischarge() ? "YES" : "NO"); + Serial.print("isVbusIn:"); Serial.println(PMU->isVbusIn() ? "YES" : "NO"); + Serial.print("getBattVoltage:"); Serial.print(PMU->getBattVoltage()); Serial.println("mV"); + Serial.print("getVbusVoltage:"); Serial.print(PMU->getVbusVoltage()); Serial.println("mV"); + Serial.print("getSystemVoltage:"); Serial.print(PMU->getSystemVoltage()); Serial.println("mV"); - // The battery percentage may be inaccurate at first use, the PMU will automatically - // learn the battery curve and will automatically calibrate the battery percentage - // after a charge and discharge cycle - if (PMU->isBatteryConnect()) { - Serial.print("getBatteryPercent:"); Serial.print(PMU->getBatteryPercent()); Serial.println("%"); - } + // The battery percentage may be inaccurate at first use, the PMU will automatically + // learn the battery curve and will automatically calibrate the battery percentage + // after a charge and discharge cycle + if (PMU->isBatteryConnect()) { + Serial.print("getBatteryPercent:"); Serial.print(PMU->getBatteryPercent()); Serial.println("%"); + } - Serial.println(); + Serial.println(); } #endif \ No newline at end of file From 0e197254a25cbbe1d71cb22051482705132e3dc3 Mon Sep 17 00:00:00 2001 From: recrof Date: Fri, 27 Jun 2025 17:38:07 +0200 Subject: [PATCH 21/27] remove old tbeam def --- variants/lilygo_tbeam/target.cpp | 181 ------------------------------- 1 file changed, 181 deletions(-) delete mode 100644 variants/lilygo_tbeam/target.cpp diff --git a/variants/lilygo_tbeam/target.cpp b/variants/lilygo_tbeam/target.cpp deleted file mode 100644 index c482dd04..00000000 --- a/variants/lilygo_tbeam/target.cpp +++ /dev/null @@ -1,181 +0,0 @@ -#include -#include "target.h" - -TBeamBoard board; - -// Using PMU AXP2102 -#define PMU_WIRE_PORT Wire - -bool pmuIntFlag = false; -static void setPMUIntFlag(){ - pmuIntFlag = true; -} - -#if defined(P_LORA_SCLK) - static SPIClass spi; - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1, spi); -#else - RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_0, P_LORA_RESET, P_LORA_DIO_1); -#endif - -WRAPPER_CLASS radio_driver(radio, board); - -ESP32RTCClock fallback_clock; -AutoDiscoverRTCClock rtc_clock(fallback_clock); -SensorManager sensors; - -#ifdef DISPLAY_CLASS - DISPLAY_CLASS display; -#endif - -#ifndef LORA_CR - #define LORA_CR 5 -#endif - -bool TBeamBoard::power_init() { - if (!PMU) { - PMU = new XPowersAXP2101(PMU_WIRE_PORT); - if (!PMU->init()) { - // Serial.println("Warning: Failed to find AXP2101 power management"); - delete PMU; - PMU = NULL; - } - else { - // Serial.println("AXP2101 PMU init succeeded, using AXP2101 PMU"); - } - } - if (!PMU) { - PMU = new XPowersAXP192(PMU_WIRE_PORT); - if (!PMU->init()) { - // Serial.println("Warning: Failed to find AXP192 power management"); - delete PMU; - PMU = NULL; - } - else { - // Serial.println("AXP192 PMU init succeeded, using AXP192 PMU"); - } - } - - if (!PMU) { - MESH_DEBUG_PRINTLN("PMU init failed."); - return false; - } - - // Serial.printf("PMU ID:0x%x\n", PMU->getChipID()); - // printPMU(); - if (PMU->getChipModel() == XPOWERS_AXP192) { - // lora radio power channel - PMU->setPowerChannelVoltage(XPOWERS_LDO2, 3300); - PMU->enablePowerOutput(XPOWERS_LDO2); - // oled module power channel, - // disable it will cause abnormal communication between boot and AXP power supply, - // do not turn it off - PMU->setPowerChannelVoltage(XPOWERS_DCDC1, 3300); - // enable oled power - PMU->enablePowerOutput(XPOWERS_DCDC1); - // gnss module power channel - PMU->setPowerChannelVoltage(XPOWERS_LDO3, 3300); - // power->enablePowerOutput(XPOWERS_LDO3); - // protected oled power source - PMU->setProtectedChannel(XPOWERS_DCDC1); - // protected esp32 power source - PMU->setProtectedChannel(XPOWERS_DCDC3); - // disable not use channel - PMU->disablePowerOutput(XPOWERS_DCDC2); - // disable all axp chip interrupt - PMU->disableIRQ(XPOWERS_AXP192_ALL_IRQ); - PMU->setChargerConstantCurr(XPOWERS_AXP192_CHG_CUR_550MA); - } - else if (PMU->getChipModel() == XPOWERS_AXP2101) { - // gnss module power channel - PMU->setPowerChannelVoltage(XPOWERS_ALDO4, 3300); - PMU->enablePowerOutput(XPOWERS_ALDO4); - // lora radio power channel - PMU->setPowerChannelVoltage(XPOWERS_ALDO3, 3300); - PMU->enablePowerOutput(XPOWERS_ALDO3); - // m.2 interface - PMU->setPowerChannelVoltage(XPOWERS_DCDC3, 3300); - PMU->enablePowerOutput(XPOWERS_DCDC3); - // power->setPowerChannelVoltage(XPOWERS_DCDC4, 3300); - // power->enablePowerOutput(XPOWERS_DCDC4); - // not use channel - PMU->disablePowerOutput(XPOWERS_DCDC2); // not elicited - PMU->disablePowerOutput(XPOWERS_DCDC5); // not elicited - PMU->disablePowerOutput(XPOWERS_DLDO1); // Invalid power channel, it does not exist - PMU->disablePowerOutput(XPOWERS_DLDO2); // Invalid power channel, it does not exist - PMU->disablePowerOutput(XPOWERS_VBACKUP); - // disable all axp chip interrupt - PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ); - PMU->setChargerConstantCurr(XPOWERS_AXP2101_CHG_CUR_500MA); - - // Set up PMU interrupts - // Serial.println("Setting up PMU interrupts"); - pinMode(PIN_PMU_IRQ, INPUT_PULLUP); - attachInterrupt(PIN_PMU_IRQ, setPMUIntFlag, FALLING); - - // Reset and re-enable PMU interrupts - // Serial.println("Re-enable interrupts"); - PMU->disableIRQ(XPOWERS_AXP2101_ALL_IRQ); - PMU->clearIrqStatus(); - PMU->enableIRQ( - XPOWERS_AXP2101_BAT_INSERT_IRQ | XPOWERS_AXP2101_BAT_REMOVE_IRQ | // Battery interrupts - XPOWERS_AXP2101_VBUS_INSERT_IRQ | XPOWERS_AXP2101_VBUS_REMOVE_IRQ | // VBUS interrupts - XPOWERS_AXP2101_PKEY_SHORT_IRQ | XPOWERS_AXP2101_PKEY_LONG_IRQ | // Power Key interrupts - XPOWERS_AXP2101_BAT_CHG_DONE_IRQ | XPOWERS_AXP2101_BAT_CHG_START_IRQ // Charging interrupts - ); - } - - return true; -} - -bool radio_init() { - fallback_clock.begin(); - rtc_clock.begin(Wire); - -#if defined(P_LORA_SCLK) - spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); - return radio.std_init(&spi); -#else - return radio.std_init(); -#endif -} - -uint32_t radio_get_rng_seed() { - return radio.random(0x7FFFFFFF); -} - -void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) { - radio.setFrequency(freq); - radio.setSpreadingFactor(sf); - radio.setBandwidth(bw); - radio.setCodingRate(cr); -} - -void radio_set_tx_power(uint8_t dbm) { - radio.setOutputPower(dbm); -} - -mesh::LocalIdentity radio_new_identity() { - RadioNoiseListener rng(radio); - return mesh::LocalIdentity(&rng); // create new random identity -} - -#ifdef MESH_DEBUG -void TBeamBoard::printPMU() { - Serial.print("isCharging:"); Serial.println(PMU->isCharging() ? "YES" : "NO"); - Serial.print("isDischarge:"); Serial.println(PMU->isDischarge() ? "YES" : "NO"); - Serial.print("isVbusIn:"); Serial.println(PMU->isVbusIn() ? "YES" : "NO"); - Serial.print("getBattVoltage:"); Serial.print(PMU->getBattVoltage()); Serial.println("mV"); - Serial.print("getVbusVoltage:"); Serial.print(PMU->getVbusVoltage()); Serial.println("mV"); - Serial.print("getSystemVoltage:"); Serial.print(PMU->getSystemVoltage()); Serial.println("mV"); - - // The battery percentage may be inaccurate at first use, the PMU will automatically - // learn the battery curve and will automatically calibrate the battery percentage - // after a charge and discharge cycle - if (PMU->isBatteryConnect()) { - Serial.print("getBatteryPercent:"); Serial.print(PMU->getBatteryPercent()); Serial.println("%"); - } - - Serial.println(); -} -#endif \ No newline at end of file From 3bd1dc3ffa993ef483c598fc79e58381dc14279e Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Sat, 28 Jun 2025 16:10:53 +1000 Subject: [PATCH 22/27] * minor tidy ups --- variants/rak4631/target.cpp | 31 ++++++++++++++----------------- variants/rak4631/target.h | 8 -------- 2 files changed, 14 insertions(+), 25 deletions(-) diff --git a/variants/rak4631/target.cpp b/variants/rak4631/target.cpp index 45d10975..e9d80421 100644 --- a/variants/rak4631/target.cpp +++ b/variants/rak4631/target.cpp @@ -25,14 +25,14 @@ RAK4631SensorManager sensors; #endif #include static Bsec2 BME680; -float rawPressure = 0; -float rawTemperature = 0; -float compTemperature = 0; -float rawHumidity = 0; -float compHumidity = 0; -float readIAQ = 0; -float readStaticIAQ = 0; -float readCO2 = 0; +static float rawPressure = 0; +static float rawTemperature = 0; +static float compTemperature = 0; +static float rawHumidity = 0; +static float compHumidity = 0; +static float readIAQ = 0; +static float readStaticIAQ = 0; +static float readCO2 = 0; #endif #ifdef DISPLAY_CLASS @@ -41,7 +41,7 @@ float readCO2 = 0; #ifdef MESH_DEBUG uint32_t deviceOnline = 0x00; -void scanDevices(TwoWire *w) +static void scanDevices(TwoWire *w) { uint8_t err, addr; int nDevices = 0; @@ -168,8 +168,7 @@ bool RAK4631SensorManager::gpsIsAwake(uint32_t ioPin){ #endif #if ENV_INCLUDE_BME680 -void checkBMEStatus(Bsec2 bsec) -{ +static void checkBMEStatus(Bsec2 bsec) { if (bsec.status < BSEC_OK) { MESH_DEBUG_PRINTLN("BSEC error code : %f", float(bsec.status)); @@ -188,17 +187,15 @@ void checkBMEStatus(Bsec2 bsec) MESH_DEBUG_PRINTLN("BME68X warning code : %f", bsec.sensor.status); } } -void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec) -{ - if (!outputs.nOutputs) - { + +static void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec) { + if (!outputs.nOutputs) { MESH_DEBUG_PRINTLN("No new data to report out"); return; } MESH_DEBUG_PRINTLN("BSEC outputs:\n\tTime stamp = %f", (int) (outputs.output[0].time_stamp / INT64_C(1000000))); - for (uint8_t i = 0; i < outputs.nOutputs; i++) - { + for (uint8_t i = 0; i < outputs.nOutputs; i++) { const bsecData output = outputs.output[i]; switch (output.sensor_id) { diff --git a/variants/rak4631/target.h b/variants/rak4631/target.h index 0460c9e8..3f26ab33 100644 --- a/variants/rak4631/target.h +++ b/variants/rak4631/target.h @@ -11,9 +11,6 @@ #include #include #endif -#if ENV_INCLUDE_BME680 - #include "bsec2.h" -#endif #ifdef DISPLAY_CLASS #include #endif @@ -84,11 +81,6 @@ enum { RAK12500_ONLINE = _BV(14), }; -#if ENV_INCLUDE_BME680 - void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec); - void checkBMEStatus(Bsec2 bsec); -#endif - bool radio_init(); uint32_t radio_get_rng_seed(); void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr); From 1ce180d6ea5ca427b69e237b6a3ac192aff0da9c Mon Sep 17 00:00:00 2001 From: recrof Date: Sat, 28 Jun 2025 11:00:13 +0200 Subject: [PATCH 23/27] remove spi.begin in targets --- variants/heltec_v2/target.cpp | 1 - variants/lilygo_tbeam_SX1276/target.cpp | 22 +++------------------- variants/lilygo_tlora_v2_1/target.cpp | 1 - 3 files changed, 3 insertions(+), 21 deletions(-) diff --git a/variants/heltec_v2/target.cpp b/variants/heltec_v2/target.cpp index d4d21dba..418f1f7f 100644 --- a/variants/heltec_v2/target.cpp +++ b/variants/heltec_v2/target.cpp @@ -25,7 +25,6 @@ bool radio_init() { rtc_clock.begin(Wire); #if defined(P_LORA_SCLK) - spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); return radio.std_init(&spi); #else return radio.std_init(); diff --git a/variants/lilygo_tbeam_SX1276/target.cpp b/variants/lilygo_tbeam_SX1276/target.cpp index d340dedb..7e2537bb 100644 --- a/variants/lilygo_tbeam_SX1276/target.cpp +++ b/variants/lilygo_tbeam_SX1276/target.cpp @@ -27,31 +27,15 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock); DISPLAY_CLASS display; #endif -#ifndef LORA_CR - #define LORA_CR 5 -#endif - bool radio_init() { fallback_clock.begin(); rtc_clock.begin(Wire); #if defined(P_LORA_SCLK) - spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); + return radio.std_init(&spi); +#else + return radio.std_init(); #endif - int status = radio.begin(LORA_FREQ, LORA_BW, LORA_SF, LORA_CR, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8); - if (status != RADIOLIB_ERR_NONE) { - Serial.print("ERROR: radio init failed: "); - Serial.println(status); - return false; // fail - } - -#ifdef SX127X_CURRENT_LIMIT - radio.setCurrentLimit(SX127X_CURRENT_LIMIT); -#endif - - radio.setCRC(1); - - return true; // success } uint32_t radio_get_rng_seed() { diff --git a/variants/lilygo_tlora_v2_1/target.cpp b/variants/lilygo_tlora_v2_1/target.cpp index 6f60b979..5e8f15b2 100644 --- a/variants/lilygo_tlora_v2_1/target.cpp +++ b/variants/lilygo_tlora_v2_1/target.cpp @@ -21,7 +21,6 @@ bool radio_init() { rtc_clock.begin(Wire); #if defined(P_LORA_SCLK) - spi.begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); return radio.std_init(&spi); #else return radio.std_init(); From 9530744ff4073c641cbe12ea11d86098f59294c6 Mon Sep 17 00:00:00 2001 From: recrof Date: Sun, 29 Jun 2025 00:17:46 +0200 Subject: [PATCH 24/27] add support for BMP280 temperature+pressure sensor --- .../sensors/EnvironmentSensorManager.cpp | 41 ++++++++++++++++--- .../sensors/EnvironmentSensorManager.h | 5 ++- variants/heltec_v3/platformio.ini | 6 ++- variants/lilygo_tlora_v2_1/platformio.ini | 12 ++++++ variants/promicro/platformio.ini | 28 +++++++------ 5 files changed, 69 insertions(+), 23 deletions(-) diff --git a/src/helpers/sensors/EnvironmentSensorManager.cpp b/src/helpers/sensors/EnvironmentSensorManager.cpp index b3de0568..b672cdd4 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.cpp +++ b/src/helpers/sensors/EnvironmentSensorManager.cpp @@ -15,6 +15,16 @@ static Adafruit_AHTX0 AHTX0; static Adafruit_BME280 BME280; #endif +#if ENV_INCLUDE_BMP280 +#ifndef TELEM_BMP280_ADDRESS +#define TELEM_BMP280_ADDRESS 0x76 // BMP280 environmental sensor I2C address +#endif +#define TELEM_BMP280_SEALEVELPRESSURE_HPA (1013.25) // Athmospheric pressure at sea level +#include +static Adafruit_BMP280 BMP280; +#endif + + #if ENV_INCLUDE_INA3221 #define TELEM_INA3221_ADDRESS 0x42 // INA3221 3 channel current sensor I2C address #define TELEM_INA3221_SHUNT_VALUE 0.100 // most variants will have a 0.1 ohm shunts @@ -55,6 +65,17 @@ bool EnvironmentSensorManager::begin() { } #endif + #if ENV_INCLUDE_BMP280 + if (BMP280.begin(TELEM_BMP280_ADDRESS)) { + MESH_DEBUG_PRINTLN("Found BMP280 at address: %02X", TELEM_BMP280_ADDRESS); + MESH_DEBUG_PRINTLN("BMP sensor ID: %02X", BMP280.sensorID()); + BMP280_initialized = true; + } else { + BMP280_initialized = false; + MESH_DEBUG_PRINTLN("BMP280 was not found at I2C address %02X", TELEM_BMP280_ADDRESS); + } + #endif + #if ENV_INCLUDE_INA3221 if (INA3221.begin(TELEM_INA3221_ADDRESS, &Wire)) { MESH_DEBUG_PRINTLN("Found INA3221 at address: %02X", TELEM_INA3221_ADDRESS); @@ -97,7 +118,7 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen sensors_event_t humidity, temp; AHTX0.getEvent(&humidity, &temp); telemetry.addTemperature(TELEM_CHANNEL_SELF, temp.temperature); - telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, humidity.relative_humidity); + telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, humidity.relative_humidity); } #endif @@ -110,6 +131,14 @@ bool EnvironmentSensorManager::querySensors(uint8_t requester_permissions, Cayen } #endif + #if ENV_INCLUDE_BMP280 + if (BMP280_initialized) { + telemetry.addTemperature(TELEM_CHANNEL_SELF, BMP280.readTemperature()); + telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, BMP280.readPressure()); + telemetry.addAltitude(TELEM_CHANNEL_SELF, BME280.readAltitude(TELEM_BME280_SEALEVELPRESSURE_HPA)); + } + #endif + #if ENV_INCLUDE_INA3221 if (INA3221_initialized) { for(int i = 0; i < TELEM_INA3221_NUM_CHANNELS; i++) { @@ -152,7 +181,7 @@ int EnvironmentSensorManager::getNumSettings() const { const char* EnvironmentSensorManager::getSettingName(int i) const { #if ENV_INCLUDE_GPS return (gps_detected && i == 0) ? "gps" : NULL; - #else + #else return NULL; #endif } @@ -184,7 +213,7 @@ bool EnvironmentSensorManager::setSettingValue(const char* name, const char* val void EnvironmentSensorManager::initBasicGPS() { Serial1.setPins(PIN_GPS_TX, PIN_GPS_RX); - + #ifdef GPS_BAUD_RATE Serial1.begin(GPS_BAUD_RATE); #else @@ -200,7 +229,7 @@ void EnvironmentSensorManager::initBasicGPS() { #ifndef PIN_GPS_EN MESH_DEBUG_PRINTLN("No GPS wake/reset pin found for this board. Continuing on..."); #endif - + // Give GPS a moment to power up and send data delay(1000); @@ -226,7 +255,7 @@ void EnvironmentSensorManager::start_gps() { gps_active = true; #ifdef PIN_GPS_EN pinMode(PIN_GPS_EN, OUTPUT); - digitalWrite(PIN_GPS_EN, HIGH); + digitalWrite(PIN_GPS_EN, HIGH); return; #endif @@ -241,7 +270,7 @@ void EnvironmentSensorManager::stop_gps() { return; #endif - MESH_DEBUG_PRINTLN("Stop GPS is N/A on this board. Actual GPS state unchanged"); + MESH_DEBUG_PRINTLN("Stop GPS is N/A on this board. Actual GPS state unchanged"); } void EnvironmentSensorManager::loop() { diff --git a/src/helpers/sensors/EnvironmentSensorManager.h b/src/helpers/sensors/EnvironmentSensorManager.h index c9ec6870..76bffc48 100644 --- a/src/helpers/sensors/EnvironmentSensorManager.h +++ b/src/helpers/sensors/EnvironmentSensorManager.h @@ -10,9 +10,10 @@ protected: bool AHTX0_initialized = false; bool BME280_initialized = false; + bool BMP280_initialized = false; bool INA3221_initialized = false; bool INA219_initialized = false; - + bool gps_detected = false; bool gps_active = false; @@ -31,7 +32,7 @@ public: EnvironmentSensorManager(){}; #endif bool begin() override; - bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; + bool querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) override; #if ENV_INCLUDE_GPS void loop() override; #endif diff --git a/variants/heltec_v3/platformio.ini b/variants/heltec_v3/platformio.ini index 8f9b1a27..17a0899a 100644 --- a/variants/heltec_v3/platformio.ini +++ b/variants/heltec_v3/platformio.ini @@ -19,15 +19,16 @@ build_flags = -D SX126X_RX_BOOSTED_GAIN=1 -D ENV_INCLUDE_AHTX0=1 -D ENV_INCLUDE_BME280=1 + -D ENV_INCLUDE_BMP280=1 -D ENV_INCLUDE_INA3221=1 - -D ENV_INCLUDE_INA219=1 + -D ENV_INCLUDE_INA219=1 -D ENV_INCLUDE_GPS=1 -D PIN_GPS_RX=45 -D PIN_GPS_TX=46 -D PIN_GPS_EN=-1 build_src_filter = ${esp32_base.build_src_filter} +<../variants/heltec_v3> - + + + lib_deps = ${esp32_base.lib_deps} adafruit/Adafruit SSD1306 @ ^2.5.13 @@ -35,6 +36,7 @@ lib_deps = adafruit/Adafruit INA219 @ ^1.2.3 adafruit/Adafruit AHTX0 @ ^2.0.5 adafruit/Adafruit BME280 Library @ ^2.3.0 + adafruit/Adafruit BMP280 Library@^2.6.8 stevemarple/MicroNMEA @ ^2.0.6 [env:Heltec_v3_repeater] diff --git a/variants/lilygo_tlora_v2_1/platformio.ini b/variants/lilygo_tlora_v2_1/platformio.ini index d9cecfc2..1ecaf664 100644 --- a/variants/lilygo_tlora_v2_1/platformio.ini +++ b/variants/lilygo_tlora_v2_1/platformio.ini @@ -17,6 +17,8 @@ build_flags = -D P_LORA_MISO=19 ; SPI MISO -D P_LORA_MOSI=27 ; SPI MOSI -D P_LORA_TX_LED=2 ; LED pin for TX indication + -D PIN_BOARD_SDA=21 + -D PIN_BOARD_SCL=22 -D PIN_VBAT_READ=35 ; Battery voltage reading (analog pin) -D PIN_USER_BTN=0 -D ARDUINO_LOOP_STACK_SIZE=16384 @@ -25,11 +27,21 @@ build_flags = -D WRAPPER_CLASS=CustomSX1276Wrapper -D SX127X_CURRENT_LIMIT=120 -D LORA_TX_POWER=20 + -D ENV_INCLUDE_AHTX0=1 + -D ENV_INCLUDE_BME280=1 + -D ENV_INCLUDE_BMP280=1 + -D ENV_INCLUDE_INA3221=1 + -D ENV_INCLUDE_INA219=1 build_src_filter = ${esp32_base.build_src_filter} +<../variants/lilygo_tlora_v2_1> + + lib_deps = ${esp32_base.lib_deps} adafruit/Adafruit SSD1306 @ ^2.5.13 + adafruit/Adafruit INA3221 Library @ ^1.0.1 + adafruit/Adafruit INA219 @ ^1.2.3 + adafruit/Adafruit AHTX0 @ ^2.0.5 + adafruit/Adafruit BME280 Library @ ^2.3.0 ; === LILYGO T-LoRa V2.1-1.6 with SX1276 environments === [env:LilyGo_TLora_V2_1_1_6_Repeater] diff --git a/variants/promicro/platformio.ini b/variants/promicro/platformio.ini index e7099d1e..246019c2 100644 --- a/variants/promicro/platformio.ini +++ b/variants/promicro/platformio.ini @@ -1,7 +1,7 @@ [Faketec] -extends = nrf52840_base +extends = nrf52_base board = promicro_nrf52840 -build_flags = ${nrf52840_base.build_flags} +build_flags = ${nrf52_base.build_flags} -I variants/promicro -D FAKETEC -D RADIO_CLASS=CustomSX1262 @@ -19,20 +19,22 @@ build_flags = ${nrf52840_base.build_flags} -D ENV_INCLUDE_GPS=1 -D ENV_INCLUDE_AHTX0=1 -D ENV_INCLUDE_BME280=1 + -D ENV_INCLUDE_BMP280=1 -D ENV_INCLUDE_INA3221=1 -D ENV_INCLUDE_INA219=1 -build_src_filter = ${nrf52840_base.build_src_filter} +build_src_filter = ${nrf52_base.build_src_filter} + - + + + +<../variants/promicro> -lib_deps= ${nrf52840_base.lib_deps} +lib_deps= ${nrf52_base.lib_deps} adafruit/Adafruit SSD1306 @ ^2.5.13 adafruit/Adafruit INA3221 Library @ ^1.0.1 adafruit/Adafruit INA219 @ ^1.2.3 adafruit/Adafruit AHTX0 @ ^2.0.5 - adafruit/Adafruit BME280 Library @ ^2.3.0 + adafruit/Adafruit BME280 Library @ ^2.3.0 + adafruit/Adafruit BMP280 Library@^2.6.8 stevemarple/MicroNMEA @ ^2.0.6 - + [env:Faketec_Repeater] extends = Faketec build_src_filter = ${Faketec.build_src_filter} @@ -116,9 +118,9 @@ lib_deps = ${Faketec.lib_deps} densaugeo/base64 @ ~1.4.0 [ProMicroLLCC68] -extends = nrf52840_base +extends = nrf52_base board = promicro_nrf52840 -build_flags = ${nrf52840_base.build_flags} +build_flags = ${nrf52_base.build_flags} -I variants/promicro -D PROMICROLLCC68 -D RADIO_CLASS=CustomLLCC68 @@ -127,15 +129,15 @@ build_flags = ${nrf52840_base.build_flags} -D SX126X_CURRENT_LIMIT=140 -D SX126X_RX_BOOSTED_GAIN=1 build_src_filter = - ${nrf52840_base.build_src_filter} + ${nrf52_base.build_src_filter} + - + + + +<../variants/promicro> -lib_deps= ${nrf52840_base.lib_deps} +lib_deps= ${nrf52_base.lib_deps} adafruit/Adafruit INA3221 Library @ ^1.0.1 adafruit/Adafruit INA219 @ ^1.2.3 adafruit/Adafruit AHTX0 @ ^2.0.5 - adafruit/Adafruit BME280 Library @ ^2.3.0 + adafruit/Adafruit BME280 Library @ ^2.3.0 [env:ProMicroLLCC68_Repeater] extends = ProMicroLLCC68 From bcd31b7cdfea5f67c4957fcabda4f1ff3496a541 Mon Sep 17 00:00:00 2001 From: recrof Date: Sun, 29 Jun 2025 00:28:01 +0200 Subject: [PATCH 25/27] fix: missing dependency --- variants/lilygo_tlora_v2_1/platformio.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/variants/lilygo_tlora_v2_1/platformio.ini b/variants/lilygo_tlora_v2_1/platformio.ini index 1ecaf664..71b49aab 100644 --- a/variants/lilygo_tlora_v2_1/platformio.ini +++ b/variants/lilygo_tlora_v2_1/platformio.ini @@ -42,6 +42,7 @@ lib_deps = adafruit/Adafruit INA219 @ ^1.2.3 adafruit/Adafruit AHTX0 @ ^2.0.5 adafruit/Adafruit BME280 Library @ ^2.3.0 + adafruit/Adafruit BMP280 Library @ ^2.6.8 ; === LILYGO T-LoRa V2.1-1.6 with SX1276 environments === [env:LilyGo_TLora_V2_1_1_6_Repeater] From 187eea1b18f698d5e6a6dd0e1d462da7908cf46f Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Sun, 29 Jun 2025 20:03:10 +1000 Subject: [PATCH 26/27] * Preamble now 16 (for most variants) --- src/helpers/CustomLLCC68.h | 4 ++-- src/helpers/CustomSX1262.h | 4 ++-- src/helpers/CustomSX1268.h | 4 ++-- src/helpers/CustomSX1276.h | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/helpers/CustomLLCC68.h b/src/helpers/CustomLLCC68.h index 52b37a0e..c239cc41 100644 --- a/src/helpers/CustomLLCC68.h +++ b/src/helpers/CustomLLCC68.h @@ -42,12 +42,12 @@ class CustomLLCC68 : public LLCC68 { if (spi) spi->begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); #endif #endif - int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); // if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) { #define SX126X_DIO3_TCXO_VOLTAGE (0.0f); tcxo = SX126X_DIO3_TCXO_VOLTAGE; - status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); } if (status != RADIOLIB_ERR_NONE) { Serial.print("ERROR: radio init failed: "); diff --git a/src/helpers/CustomSX1262.h b/src/helpers/CustomSX1262.h index 17673d3a..bfaea7c7 100644 --- a/src/helpers/CustomSX1262.h +++ b/src/helpers/CustomSX1262.h @@ -42,12 +42,12 @@ class CustomSX1262 : public SX1262 { if (spi) spi->begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); #endif #endif - int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); // if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) { #define SX126X_DIO3_TCXO_VOLTAGE (0.0f); tcxo = SX126X_DIO3_TCXO_VOLTAGE; - status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); } if (status != RADIOLIB_ERR_NONE) { Serial.print("ERROR: radio init failed: "); diff --git a/src/helpers/CustomSX1268.h b/src/helpers/CustomSX1268.h index eb2d4f12..1e2e2620 100644 --- a/src/helpers/CustomSX1268.h +++ b/src/helpers/CustomSX1268.h @@ -42,12 +42,12 @@ class CustomSX1268 : public SX1268 { if (spi) spi->begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); #endif #endif - int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); // if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f if (status == RADIOLIB_ERR_SPI_CMD_FAILED || status == RADIOLIB_ERR_SPI_CMD_INVALID) { #define SX126X_DIO3_TCXO_VOLTAGE (0.0f); tcxo = SX126X_DIO3_TCXO_VOLTAGE; - status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8, tcxo); + status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16, tcxo); } if (status != RADIOLIB_ERR_NONE) { Serial.print("ERROR: radio init failed: "); diff --git a/src/helpers/CustomSX1276.h b/src/helpers/CustomSX1276.h index 8396fe07..bee25274 100644 --- a/src/helpers/CustomSX1276.h +++ b/src/helpers/CustomSX1276.h @@ -39,7 +39,7 @@ class CustomSX1276 : public SX1276 { if (spi) spi->begin(P_LORA_SCLK, P_LORA_MISO, P_LORA_MOSI); #endif #endif - int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 8); + int status = begin(LORA_FREQ, LORA_BW, LORA_SF, cr, RADIOLIB_SX126X_SYNC_WORD_PRIVATE, LORA_TX_POWER, 16); // if radio init fails with -707/-706, try again with tcxo voltage set to 0.0f if (status != RADIOLIB_ERR_NONE) { Serial.print("ERROR: radio init failed: "); From 165fb33d5cd37901f2c58e695e67dbd7d24b89e2 Mon Sep 17 00:00:00 2001 From: Scott Powell Date: Sun, 29 Jun 2025 20:06:24 +1000 Subject: [PATCH 27/27] * ver bump to v1.7.1 --- examples/companion_radio/MyMesh.h | 4 ++-- examples/simple_repeater/main.cpp | 4 ++-- examples/simple_room_server/main.cpp | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/examples/companion_radio/MyMesh.h b/examples/companion_radio/MyMesh.h index eeeff75f..891a390e 100644 --- a/examples/companion_radio/MyMesh.h +++ b/examples/companion_radio/MyMesh.h @@ -10,11 +10,11 @@ #define FIRMWARE_VER_CODE 6 #ifndef FIRMWARE_BUILD_DATE -#define FIRMWARE_BUILD_DATE "7 Jun 2025" +#define FIRMWARE_BUILD_DATE "29 Jun 2025" #endif #ifndef FIRMWARE_VERSION -#define FIRMWARE_VERSION "v1.7.0" +#define FIRMWARE_VERSION "v1.7.1" #endif #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) diff --git a/examples/simple_repeater/main.cpp b/examples/simple_repeater/main.cpp index c33cadda..8b797991 100644 --- a/examples/simple_repeater/main.cpp +++ b/examples/simple_repeater/main.cpp @@ -22,11 +22,11 @@ /* ------------------------------ Config -------------------------------- */ #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "7 Jun 2025" + #define FIRMWARE_BUILD_DATE "29 Jun 2025" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.7.0" + #define FIRMWARE_VERSION "v1.7.1" #endif #ifndef LORA_FREQ diff --git a/examples/simple_room_server/main.cpp b/examples/simple_room_server/main.cpp index f5c1e9dc..3d6cf80b 100644 --- a/examples/simple_room_server/main.cpp +++ b/examples/simple_room_server/main.cpp @@ -22,11 +22,11 @@ /* ------------------------------ Config -------------------------------- */ #ifndef FIRMWARE_BUILD_DATE - #define FIRMWARE_BUILD_DATE "7 Jun 2025" + #define FIRMWARE_BUILD_DATE "29 Jun 2025" #endif #ifndef FIRMWARE_VERSION - #define FIRMWARE_VERSION "v1.7.0" + #define FIRMWARE_VERSION "v1.7.1" #endif #ifndef LORA_FREQ