RAK4631 ESM Migration

Changes to migrate sensor code to the ESM.

Added a separate GPS init sequence for the RAK that scans I2C and Serial1 on the various sockets of the various base boards to find the RAK12500. (and soon the RAK12501)

Removed the GPS specific envs from platformio.ini and enabled GPS for all envs.

Verified working with RAK12500 on RAK19007 sockets A and D, as well as RAK19003.
This commit is contained in:
cod3doomy
2025-07-16 19:04:50 -07:00
parent 6a6221f44e
commit 660ab0692f
6 changed files with 146 additions and 520 deletions

View File

@@ -1,10 +1,13 @@
#include <Arduino.h>
#include "target.h"
#include <helpers/ArduinoHelpers.h>
#include <helpers/sensors/MicroNMEALocationProvider.h>
RAK4631Board board;
#ifdef DISPLAY_CLASS
DISPLAY_CLASS display;
#endif
RADIO_CLASS radio = new Module(P_LORA_NSS, P_LORA_DIO_1, P_LORA_RESET, P_LORA_BUSY, SPI);
WRAPPER_CLASS radio_driver(radio, board);
@@ -13,80 +16,11 @@ VolatileRTCClock fallback_clock;
AutoDiscoverRTCClock rtc_clock(fallback_clock);
#if ENV_INCLUDE_GPS
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Wire);
RAK4631SensorManager sensors = RAK4631SensorManager(nmea);
#include <helpers/sensors/MicroNMEALocationProvider.h>
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1);
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
#else
RAK4631SensorManager sensors;
#endif
#if ENV_INCLUDE_BME680
#ifndef TELEM_BME680_ADDRESS
#define TELEM_BME680_ADDRESS 0x76 // BME680 environmental sensor I2C address
#endif
#include <bsec2.h>
static Bsec2 BME680;
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
DISPLAY_CLASS display;
#endif
#ifdef MESH_DEBUG
uint32_t deviceOnline = 0x00;
static void scanDevices(TwoWire *w)
{
uint8_t err, addr;
int nDevices = 0;
uint32_t start = 0;
Serial.println("Scanning I2C for Devices");
for (addr = 1; addr < 127; addr++) {
start = millis();
w->beginTransmission(addr); delay(2);
err = w->endTransmission();
if (err == 0) {
nDevices++;
switch (addr) {
case 0x42:
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) {
Serial.print("0");
}
Serial.print(addr, HEX);
Serial.println(" !");
break;
}
} else if (err == 4) {
Serial.print("Unknow error at address 0x");
if (addr < 16) {
Serial.print("0");
}
Serial.println(addr, HEX);
}
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
Serial.println("Scan for devices is complete.");
Serial.println("\n");
}
EnvironmentSensorManager sensors;
#endif
bool radio_init() {
@@ -109,324 +43,6 @@ void radio_set_tx_power(uint8_t dbm) {
radio.setOutputPower(dbm);
}
#if ENV_INCLUDE_GPS
void RAK4631SensorManager::start_gps()
{
//function currently not used
gps_active = true;
pinMode(disStandbyPin, OUTPUT);
digitalWrite(disStandbyPin, 1);
MESH_DEBUG_PRINTLN("GPS should be on now");
}
void RAK4631SensorManager::stop_gps()
{
//function currently not used
gps_active = false;
pinMode(disStandbyPin, OUTPUT);
digitalWrite(disStandbyPin, 0);
MESH_DEBUG_PRINTLN("GPS should be off now");
}
void RAK4631SensorManager::sleep_gps() {
gps_active = false;
ublox_GNSS.powerSaveMode();
MESH_DEBUG_PRINTLN("GPS should be sleeping now");
}
void RAK4631SensorManager::wake_gps() {
gps_active = true;
ublox_GNSS.powerSaveMode(false);
MESH_DEBUG_PRINTLN("GPS should be waking now");
}
bool RAK4631SensorManager::gpsIsAwake(uint32_t ioPin){
int pinInitialState = 0;
//set initial waking state
pinMode(ioPin,OUTPUT);
digitalWrite(ioPin,0);
delay(1000);
digitalWrite(ioPin,1);
delay(1000);
if (ublox_GNSS.begin(Wire) == true){
MESH_DEBUG_PRINTLN("GPS init correctly and GPS is turned on");
ublox_GNSS.setI2COutput(COM_TYPE_NMEA);
ublox_GNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT);
disStandbyPin = ioPin;
gps_active = true;
gps_detected = true;
return true;
}
else
MESH_DEBUG_PRINTLN("GPS failed to init on this IO pin... try the next");
//digitalWrite(ioPin,pinInitialState); //reset the IO pin to initial state
return false;
}
#endif
#if ENV_INCLUDE_BME680
static void checkBMEStatus(Bsec2 bsec) {
if (bsec.status < BSEC_OK)
{
MESH_DEBUG_PRINTLN("BSEC error code : %f", float(bsec.status));
}
else if (bsec.status > BSEC_OK)
{
MESH_DEBUG_PRINTLN("BSEC warning code : %f", float(bsec.status));
}
if (bsec.sensor.status < BME68X_OK)
{
MESH_DEBUG_PRINTLN("BME68X error code : %f", bsec.sensor.status);
}
else if (bsec.sensor.status > BME68X_OK)
{
MESH_DEBUG_PRINTLN("BME68X warning code : %f", bsec.sensor.status);
}
}
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++) {
const bsecData output = outputs.output[i];
switch (output.sensor_id)
{
case BSEC_OUTPUT_IAQ:
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", output.signal);
break;
case BSEC_OUTPUT_RAW_PRESSURE:
rawPressure = output.signal;
MESH_DEBUG_PRINTLN("\tPressure = %f", output.signal);
break;
case BSEC_OUTPUT_RAW_HUMIDITY:
rawHumidity = output.signal;
MESH_DEBUG_PRINTLN("\tHumidity = %f", output.signal);
break;
case BSEC_OUTPUT_RAW_GAS:
MESH_DEBUG_PRINTLN("\tGas resistance = %f", output.signal);
break;
case BSEC_OUTPUT_STABILIZATION_STATUS:
MESH_DEBUG_PRINTLN("\tStabilization status = %f", output.signal);
break;
case BSEC_OUTPUT_RUN_IN_STATUS:
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", output.signal);
break;
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
compHumidity = output.signal;
MESH_DEBUG_PRINTLN("\tCompensated humidity = %f", output.signal);
break;
case BSEC_OUTPUT_STATIC_IAQ:
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", output.signal);
break;
case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
MESH_DEBUG_PRINTLN("\tbVOC equivalent = %f", output.signal);
break;
case BSEC_OUTPUT_GAS_PERCENTAGE:
MESH_DEBUG_PRINTLN("\tGas percentage = %f", output.signal);
break;
case BSEC_OUTPUT_COMPENSATED_GAS:
MESH_DEBUG_PRINTLN("\tCompensated gas = %f", 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_detected = false;
return false;
}
#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[5] = {
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
}
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.addTemperature(TELEM_CHANNEL_SELF+1, readIAQ);
telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF+1, readStaticIAQ);
}
#endif
}
return true;
}
void RAK4631SensorManager::loop() {
static long next_update = 0;
#ifdef ENV_INCLUDE_GPS
_nmea->loop();
#endif
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 {
#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 {
#if ENV_INCLUDE_GPS
return (gps_detected && i == 0) ? "gps" : NULL;
#else
return NULL;
#endif
}
const char* RAK4631SensorManager::getSettingValue(int i) const {
#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 ENV_INCLUDE_GPS
if (gps_detected && strcmp(name, "gps") == 0) {
if (strcmp(value, "0") == 0) {
stop_gps();
} else {
start_gps();
}
return true;
}
#endif
return false; // not supported
}
mesh::LocalIdentity radio_new_identity() {
RadioNoiseListener rng(radio);
return mesh::LocalIdentity(&rng); // create new random identity