Skip to content

Commit ff9699c

Browse files
authored
Merge pull request #482 from recrof/dev
initial support for Seeed Studio SenseCap Solar board
2 parents 2c1f61c + 2941388 commit ff9699c

File tree

8 files changed

+472
-0
lines changed

8 files changed

+472
-0
lines changed

boards/seeed_sensecap_solar.json

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
{
2+
"build": {
3+
"arduino": {
4+
"ldscript": "nrf52840_s140_v7.ld"
5+
},
6+
"core": "nRF5",
7+
"cpu": "cortex-m4",
8+
"extra_flags": "-DARDUINO_Seeed_XIAO_nRF52840 -DNRF52840_XXAA -DSEEED_XIAO_NRF52840 ",
9+
"f_cpu": "64000000L",
10+
"hwids": [
11+
[ "0x2886", "0x0059" ]
12+
],
13+
"mcu": "nrf52840",
14+
"variant": "Seeed_XIAO_nRF52840",
15+
"softdevice": {
16+
"sd_flags": "-DS140",
17+
"sd_name": "s140",
18+
"sd_version": "7.3.0",
19+
"sd_fwid": "0x0123"
20+
},
21+
"bsp": {
22+
"name": "adafruit"
23+
},
24+
"bootloader": {
25+
"settings_addr": "0xFF000"
26+
},
27+
"usb_product": "XIAO nRF52840"
28+
},
29+
"connectivity": [
30+
"bluetooth"
31+
],
32+
"debug": {
33+
"jlink_device": "nRF52840_xxAA",
34+
"openocd_target": "nrf52.cfg",
35+
"svd_path": "nrf52840.svd"
36+
},
37+
"frameworks": [
38+
"arduino"
39+
],
40+
"name": "Seeed Studio XIAO nRF52840",
41+
"upload": {
42+
"maximum_ram_size": 248832,
43+
"maximum_size": 815104,
44+
"protocol": "nrfutil",
45+
"speed": 115200,
46+
"protocols": [
47+
"jlink",
48+
"nrfjprog",
49+
"nrfutil",
50+
"cmsis-dap",
51+
"sam-ba",
52+
"blackmagic"
53+
],
54+
"use_1200bps_touch": true,
55+
"require_upload_port": true,
56+
"wait_for_upload_port": true
57+
},
58+
"url": "https://wiki.seeedstudio.com/meshtastic_solar_node/",
59+
"vendor": "Seeed Studio"
60+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
#include <Arduino.h>
2+
#include "SenseCapSolarBoard.h"
3+
4+
#include <bluefruit.h>
5+
#include <Wire.h>
6+
7+
static BLEDfu bledfu;
8+
9+
static void connect_callback(uint16_t conn_handle) {
10+
(void)conn_handle;
11+
MESH_DEBUG_PRINTLN("BLE client connected");
12+
}
13+
14+
static void disconnect_callback(uint16_t conn_handle, uint8_t reason) {
15+
(void)conn_handle;
16+
(void)reason;
17+
18+
MESH_DEBUG_PRINTLN("BLE client disconnected");
19+
}
20+
21+
void SenseCapSolarBoard::begin() {
22+
// for future use, sub-classes SHOULD call this from their begin()
23+
startup_reason = BD_STARTUP_NORMAL;
24+
25+
#if defined(PIN_WIRE_SDA) && defined(PIN_WIRE_SCL)
26+
Wire.setPins(PIN_WIRE_SDA, PIN_WIRE_SCL);
27+
#endif
28+
29+
Wire.begin();
30+
31+
#ifdef P_LORA_TX_LED
32+
pinMode(P_LORA_TX_LED, OUTPUT);
33+
digitalWrite(P_LORA_TX_LED, HIGH);
34+
#endif
35+
36+
delay(10); // give sx1262 some time to power up
37+
}
38+
39+
bool SenseCapSolarBoard::startOTAUpdate(const char* id, char reply[]) {
40+
// Config the peripheral connection with maximum bandwidth
41+
// more SRAM required by SoftDevice
42+
// Note: All config***() function must be called before begin()
43+
Bluefruit.configPrphBandwidth(BANDWIDTH_MAX);
44+
Bluefruit.configPrphConn(92, BLE_GAP_EVENT_LENGTH_MIN, 16, 16);
45+
46+
Bluefruit.begin(1, 0);
47+
// Set max power. Accepted values are: -40, -30, -20, -16, -12, -8, -4, 0, 4
48+
Bluefruit.setTxPower(4);
49+
// Set the BLE device name
50+
Bluefruit.setName("SENSECAP_SOLAR_OTA");
51+
52+
Bluefruit.Periph.setConnectCallback(connect_callback);
53+
Bluefruit.Periph.setDisconnectCallback(disconnect_callback);
54+
55+
// To be consistent OTA DFU should be added first if it exists
56+
bledfu.begin();
57+
58+
// Set up and start advertising
59+
// Advertising packet
60+
Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
61+
Bluefruit.Advertising.addTxPower();
62+
Bluefruit.Advertising.addName();
63+
64+
/* Start Advertising
65+
- Enable auto advertising if disconnected
66+
- Interval: fast mode = 20 ms, slow mode = 152.5 ms
67+
- Timeout for fast mode is 30 seconds
68+
- Start(timeout) with timeout = 0 will advertise forever (until connected)
69+
70+
For recommended advertising interval
71+
https://developer.apple.com/library/content/qa/qa1931/_index.html
72+
*/
73+
Bluefruit.Advertising.restartOnDisconnect(true);
74+
Bluefruit.Advertising.setInterval(32, 244); // in unit of 0.625 ms
75+
Bluefruit.Advertising.setFastTimeout(30); // number of seconds in fast mode
76+
Bluefruit.Advertising.start(0); // 0 = Don't stop advertising after n seconds
77+
78+
strcpy(reply, "OK - started");
79+
80+
return true;
81+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#pragma once
2+
3+
#include <MeshCore.h>
4+
#include <Arduino.h>
5+
6+
class SenseCapSolarBoard : public mesh::MainBoard {
7+
protected:
8+
uint8_t startup_reason;
9+
10+
public:
11+
void begin();
12+
uint8_t getStartupReason() const override { return startup_reason; }
13+
14+
#if defined(P_LORA_TX_LED)
15+
void onBeforeTransmit() override {
16+
digitalWrite(P_LORA_TX_LED, LOW); // turn TX LED on
17+
}
18+
void onAfterTransmit() override {
19+
digitalWrite(P_LORA_TX_LED, HIGH); // turn TX LED off
20+
}
21+
#endif
22+
23+
uint16_t getBattMilliVolts() override {
24+
digitalWrite(VBAT_ENABLE, LOW);
25+
int adcvalue = 0;
26+
analogReadResolution(12);
27+
analogReference(AR_INTERNAL_3_0);
28+
delay(10);
29+
adcvalue = analogRead(BATTERY_PIN);
30+
return (adcvalue * ADC_MULTIPLIER * AREF_VOLTAGE) / 4.096;
31+
}
32+
33+
const char* getManufacturerName() const override {
34+
return "Seeed SenseCap Solar";
35+
}
36+
37+
void reboot() override {
38+
NVIC_SystemReset();
39+
}
40+
41+
bool startOTAUpdate(const char* id, char reply[]) override;
42+
};
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
[SenseCap_Solar]
2+
extends = nrf52_base
3+
board = seeed_sensecap_solar
4+
board_build.ldscript = boards/nrf52840_s140_v7.ld
5+
build_flags = ${nrf52_base.build_flags}
6+
-I lib/nrf52/s140_nrf52_7.3.0_API/include
7+
-I lib/nrf52/s140_nrf52_7.3.0_API/include/nrf52
8+
-I variants/sensecap_solar
9+
-I src/helpers/nrf52
10+
-D NRF52_PLATFORM=1
11+
-D RADIO_CLASS=CustomSX1262
12+
-D WRAPPER_CLASS=CustomSX1262Wrapper
13+
-D P_LORA_TX_LED=12
14+
-D P_LORA_DIO_1=1
15+
-D P_LORA_RESET=2
16+
-D P_LORA_BUSY=3
17+
-D P_LORA_NSS=4
18+
-D LORA_TX_POWER=22
19+
-D SX126X_RXEN=5
20+
-D SX126X_TXEN=RADIOLIB_NC
21+
-D SX126X_DIO2_AS_RF_SWITCH=1
22+
-D SX126X_DIO3_TCXO_VOLTAGE=1.8
23+
-D SX126X_CURRENT_LIMIT=140
24+
-D SX126X_RX_BOOSTED_GAIN=1
25+
-D ENV_INCLUDE_AHTX0=1
26+
-D ENV_INCLUDE_BME280=1
27+
-D ENV_INCLUDE_BMP280=1
28+
-D ENV_INCLUDE_SHTC3=1
29+
-D ENV_INCLUDE_LPS22HB=1
30+
-D ENV_INCLUDE_INA3221=1
31+
-D ENV_INCLUDE_INA219=1
32+
build_src_filter = ${nrf52_base.build_src_filter}
33+
+<helpers/*.cpp>
34+
+<helpers/sensors>
35+
+<helpers/nrf52/SenseCapSolarBoard.cpp>
36+
+<../variants/SenseCap_Solar>
37+
debug_tool = jlink
38+
upload_protocol = nrfutil
39+
lib_deps =
40+
${nrf52_base.lib_deps}
41+
rweather/Crypto @ ^0.4.0
42+
adafruit/Adafruit INA3221 Library @ ^1.0.1
43+
adafruit/Adafruit INA219 @ ^1.2.3
44+
adafruit/Adafruit AHTX0 @ ^2.0.5
45+
adafruit/Adafruit BME280 Library @ ^2.3.0
46+
adafruit/Adafruit BMP280 Library @ ^2.6.8
47+
adafruit/Adafruit SHTC3 Library @ ^1.0.1
48+
arduino-libraries/Arduino_LPS22HB @ ^1.0.2
49+
50+
[env:SenseCap_Solar_repeater]
51+
extends = SenseCap_Solar
52+
build_flags =
53+
${SenseCap_Solar.build_flags}
54+
-D ADVERT_NAME='"SenseCap_Solar Repeater"'
55+
-D ADVERT_LAT=0.0
56+
-D ADVERT_LON=0.0
57+
-D ADMIN_PASSWORD='"password"'
58+
-D MAX_NEIGHBOURS=8
59+
; -D MESH_PACKET_LOGGING=1
60+
; -D MESH_DEBUG=1
61+
build_src_filter = ${SenseCap_Solar.build_src_filter}
62+
+<../examples/simple_repeater/main.cpp>
63+
64+
[env:SenseCap_Solar_room_server]
65+
extends = SenseCap_Solar
66+
build_flags =
67+
${SenseCap_Solar.build_flags}
68+
-D ADVERT_NAME='"SenseCap_Solar Room"'
69+
-D ADVERT_LAT=0.0
70+
-D ADVERT_LON=0.0
71+
-D ADMIN_PASSWORD='"password"'
72+
; -D MESH_PACKET_LOGGING=1
73+
; -D MESH_DEBUG=1
74+
build_src_filter = ${SenseCap_Solar.build_src_filter}
75+
+<../examples/simple_room_server/main.cpp>

variants/sensecap_solar/target.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#include <Arduino.h>
2+
#include "target.h"
3+
#include <helpers/ArduinoHelpers.h>
4+
5+
SenseCapSolarBoard board;
6+
7+
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
8+
9+
WRAPPER_CLASS radio_driver(radio, board);
10+
11+
VolatileRTCClock fallback_clock;
12+
AutoDiscoverRTCClock rtc_clock(fallback_clock);
13+
EnvironmentSensorManager sensors;
14+
15+
bool radio_init() {
16+
rtc_clock.begin(Wire);
17+
18+
return radio.std_init(&SPI);
19+
}
20+
21+
uint32_t radio_get_rng_seed() {
22+
return radio.random(0x7FFFFFFF);
23+
}
24+
25+
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr) {
26+
radio.setFrequency(freq);
27+
radio.setSpreadingFactor(sf);
28+
radio.setBandwidth(bw);
29+
radio.setCodingRate(cr);
30+
}
31+
32+
void radio_set_tx_power(uint8_t dbm) {
33+
radio.setOutputPower(dbm);
34+
}
35+
36+
mesh::LocalIdentity radio_new_identity() {
37+
RadioNoiseListener rng(radio);
38+
return mesh::LocalIdentity(&rng); // create new random identity
39+
}

variants/sensecap_solar/target.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
3+
#define RADIOLIB_STATIC_ONLY 1
4+
#include <RadioLib.h>
5+
#include <helpers/RadioLibWrappers.h>
6+
#include <SenseCapSolarBoard.h>
7+
#include <helpers/CustomSX1262Wrapper.h>
8+
#include <helpers/AutoDiscoverRTCClock.h>
9+
#include <helpers/ArduinoHelpers.h>
10+
#include <helpers/sensors/EnvironmentSensorManager.h>
11+
12+
extern SenseCapSolarBoard board;
13+
extern WRAPPER_CLASS radio_driver;
14+
extern AutoDiscoverRTCClock rtc_clock;
15+
extern EnvironmentSensorManager sensors;
16+
17+
bool radio_init();
18+
uint32_t radio_get_rng_seed();
19+
void radio_set_params(float freq, float bw, uint8_t sf, uint8_t cr);
20+
void radio_set_tx_power(uint8_t dbm);
21+
mesh::LocalIdentity radio_new_identity();
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include "variant.h"
2+
#include "wiring_constants.h"
3+
#include "wiring_digital.h"
4+
#include "nrf.h"
5+
6+
const uint32_t g_ADigitalPinMap[] = {
7+
// D0 .. D10 - Peripheral control pins
8+
2, // D0 P0.02 (A0) GNSS_WAKEUP
9+
3, // D1 P0.03 (A1) LORA_DIO1
10+
28, // D2 P0.28 (A2) LORA_RESET
11+
29, // D3 P0.29 (A3) LORA_BUSY
12+
4, // D4 P0.04 (A4/SDA) LORA_CS
13+
5, // D5 P0.05 (A5/SCL) LORA_SW
14+
43, // D6 P1.11 (UART_TX) GNSS_TX
15+
44, // D7 P1.12 (UART_RX) GNSS_RX
16+
45, // D8 P1.13 (SPI_SCK) LORA_SCK
17+
46, // D9 P1.14 (SPI_MISO) LORA_MISO
18+
47, // D10 P1.15 (SPI_MOSI) LORA_MOSI
19+
20+
// D11-D12 - LED outputs
21+
15, // D11 P0.15 User LED
22+
19, // D12 P0.19 Breathing LED
23+
24+
// D13 - User input
25+
33, // D13 P1.01 User Button
26+
27+
// D14-D15 - Grove/NFC interface
28+
9, // D14 P0.09 NFC1/GROVE_D1
29+
10, // D15 P0.10 NFC2/GROVE_D0
30+
31+
// D16 - Power management
32+
// 31, // D16 P0.31 VBAT_ADC (Battery voltage)
33+
31, // D16 P0.31 VBAT_ADC (Battery voltage)
34+
// D17 - GNSS control
35+
35, // D17 P1.03 GNSS_RESET
36+
37+
37, // D18 P1.05 GNSS_ENABLE
38+
14, // D19 P0.14 BAT_READ
39+
39, // D20 P1.07 USER_BUTTON
40+
41+
//
42+
21, // D21 P0.21 (QSPI_SCK)
43+
25, // D22 P0.25 (QSPI_CSN)
44+
20, // D23 P0.20 (QSPI_SIO_0 DI)
45+
24, // D24 P0.24 (QSPI_SIO_1 DO)
46+
22, // D25 P0.22 (QSPI_SIO_2 WP)
47+
23, // D26 P0.23 (QSPI_SIO_3 HOLD)
48+
};
49+
50+
void initVariant() {
51+
pinMode(GPS_EN, OUTPUT);
52+
digitalWrite(GPS_EN, LOW);
53+
54+
pinMode(BATTERY_PIN, INPUT);
55+
pinMode(VBAT_ENABLE, OUTPUT);
56+
digitalWrite(VBAT_ENABLE, LOW);
57+
58+
pinMode(PIN_QSPI_CS, OUTPUT);
59+
digitalWrite(PIN_QSPI_CS, HIGH);
60+
61+
pinMode(LED_GREEN, OUTPUT);
62+
digitalWrite(LED_GREEN, LOW);
63+
64+
pinMode(LED_BLUE, OUTPUT);
65+
digitalWrite(LED_BLUE, LOW);
66+
67+
pinMode(GPS_EN, OUTPUT);
68+
digitalWrite(GPS_EN, HIGH);
69+
}

0 commit comments

Comments
 (0)