Skip to content

Commit 7c9cf2a

Browse files
authored
Merge pull request #446 from cod3doomy/dev
RAK4631: BME680 add and GPS cleanup
2 parents ba34cff + 6324766 commit 7c9cf2a

File tree

3 files changed

+288
-42
lines changed

3 files changed

+288
-42
lines changed

variants/rak4631/platformio.ini

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ lib_deps =
2323
${nrf52840_base.lib_deps}
2424
adafruit/Adafruit SSD1306 @ ^2.5.13
2525
stevemarple/MicroNMEA @ ^2.0.6
26-
sparkfun/SparkFun u-blox GNSS Arduino Library @ ^2.2.27
2726

2827
[env:RAK_4631_Repeater]
2928
extends = rak4631
@@ -41,6 +40,30 @@ build_src_filter = ${rak4631.build_src_filter}
4140
+<helpers/ui/SSD1306Display.cpp>
4241
+<../examples/simple_repeater>
4342

43+
[env:RAK_4631_GPS_Repeater]
44+
extends = rak4631
45+
build_flags =
46+
${rak4631.build_flags}
47+
-D DISPLAY_CLASS=SSD1306Display
48+
-D ADVERT_NAME='"RAK4631 GPS Repeater"'
49+
-D ADVERT_LAT=0.0
50+
-D ADVERT_LON=0.0
51+
-D ADMIN_PASSWORD='"password"'
52+
-D MAX_NEIGHBOURS=8
53+
-D FORCE_GPS_ALIVE=1
54+
-D ENV_INCLUDE_GPS=1
55+
-D ENV_INCLUDE_BME680=1
56+
; -D MESH_PACKET_LOGGING=1
57+
; -D MESH_DEBUG=1
58+
build_src_filter = ${rak4631.build_src_filter}
59+
+<helpers/ui/SSD1306Display.cpp>
60+
+<../examples/simple_repeater>
61+
lib_deps =
62+
${rak4631.lib_deps}
63+
sparkfun/SparkFun u-blox GNSS Arduino Library @ ^2.2.27
64+
https://github.com/boschsensortec/Bosch-BSEC2-Library
65+
https://github.com/boschsensortec/Bosch-BME68x-Library
66+
4467
[env:RAK_4631_room_server]
4568
extends = rak4631
4669
build_flags =
@@ -104,6 +127,7 @@ build_flags =
104127
-D BLE_DEBUG_LOGGING=1
105128
-D OFFLINE_QUEUE_SIZE=256
106129
-D ENV_INCLUDE_GPS=1
130+
-D ENV_INCLUDE_BME680=1
107131
; -D MESH_PACKET_LOGGING=1
108132
; -D MESH_DEBUG=1
109133
build_src_filter = ${rak4631.build_src_filter}
@@ -112,6 +136,9 @@ build_src_filter = ${rak4631.build_src_filter}
112136
+<../examples/companion_radio>
113137
lib_deps =
114138
${rak4631.lib_deps}
139+
sparkfun/SparkFun u-blox GNSS Arduino Library @ ^2.2.27
140+
https://github.com/boschsensortec/Bosch-BSEC2-Library
141+
https://github.com/boschsensortec/Bosch-BME68x-Library
115142
densaugeo/base64 @ ~1.4.0
116143

117144
[env:RAK_4631_terminal_chat]

variants/rak4631/target.cpp

Lines changed: 237 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,22 @@ RAK4631SensorManager sensors = RAK4631SensorManager(nmea);
1919
RAK4631SensorManager sensors;
2020
#endif
2121

22+
#if ENV_INCLUDE_BME680
23+
#ifndef TELEM_BME680_ADDRESS
24+
#define TELEM_BME680_ADDRESS 0x76 // BME680 environmental sensor I2C address
25+
#endif
26+
#include <bsec2.h>
27+
static Bsec2 BME680;
28+
float rawPressure = 0;
29+
float rawTemperature = 0;
30+
float compTemperature = 0;
31+
float rawHumidity = 0;
32+
float compHumidity = 0;
33+
float readIAQ = 0;
34+
float readStaticIAQ = 0;
35+
float readCO2 = 0;
36+
#endif
37+
2238
#ifdef DISPLAY_CLASS
2339
DISPLAY_CLASS display;
2440
#endif
@@ -43,6 +59,10 @@ void scanDevices(TwoWire *w)
4359
Serial.println("\tFound RAK12500 GPS Sensor");
4460
deviceOnline |= RAK12500_ONLINE;
4561
break;
62+
case 0x76:
63+
Serial.println("\tFound RAK1906 Environment Sensor");
64+
deviceOnline |= BME680_ONLINE;
65+
break;
4666
default:
4767
Serial.print("\tI2C device found at address 0x");
4868
if (addr < 16) {
@@ -137,7 +157,7 @@ bool RAK4631SensorManager::gpsIsAwake(uint32_t ioPin){
137157
ublox_GNSS.saveConfigSelective(VAL_CFG_SUBSEC_IOPORT);
138158
disStandbyPin = ioPin;
139159
gps_active = true;
140-
gps_present = true;
160+
gps_detected = true;
141161
return true;
142162
}
143163
else
@@ -147,83 +167,268 @@ bool RAK4631SensorManager::gpsIsAwake(uint32_t ioPin){
147167
}
148168
#endif
149169

170+
#if ENV_INCLUDE_BME680
171+
void checkBMEStatus(Bsec2 bsec)
172+
{
173+
if (bsec.status < BSEC_OK)
174+
{
175+
MESH_DEBUG_PRINTLN("BSEC error code : %f", float(bsec.status));
176+
}
177+
else if (bsec.status > BSEC_OK)
178+
{
179+
MESH_DEBUG_PRINTLN("BSEC warning code : %f", float(bsec.status));
180+
}
181+
182+
if (bsec.sensor.status < BME68X_OK)
183+
{
184+
MESH_DEBUG_PRINTLN("BME68X error code : %f", bsec.sensor.status);
185+
}
186+
else if (bsec.sensor.status > BME68X_OK)
187+
{
188+
MESH_DEBUG_PRINTLN("BME68X warning code : %f", bsec.sensor.status);
189+
}
190+
}
191+
void newDataCallback(const bme68xData data, const bsecOutputs outputs, Bsec2 bsec)
192+
{
193+
if (!outputs.nOutputs)
194+
{
195+
MESH_DEBUG_PRINTLN("No new data to report out");
196+
return;
197+
}
198+
199+
MESH_DEBUG_PRINTLN("BSEC outputs:\n\tTime stamp = %f", (int) (outputs.output[0].time_stamp / INT64_C(1000000)));
200+
for (uint8_t i = 0; i < outputs.nOutputs; i++)
201+
{
202+
const bsecData output = outputs.output[i];
203+
switch (output.sensor_id)
204+
{
205+
case BSEC_OUTPUT_IAQ:
206+
readIAQ = output.signal;
207+
MESH_DEBUG_PRINTLN("\tIAQ = %f", output.signal);
208+
MESH_DEBUG_PRINTLN("\tIAQ accuracy = %f", output.accuracy);
209+
break;
210+
case BSEC_OUTPUT_RAW_TEMPERATURE:
211+
rawTemperature = output.signal;
212+
MESH_DEBUG_PRINTLN("\tTemperature = %f", output.signal);
213+
break;
214+
case BSEC_OUTPUT_RAW_PRESSURE:
215+
rawPressure = output.signal;
216+
MESH_DEBUG_PRINTLN("\tPressure = %f", output.signal);
217+
break;
218+
case BSEC_OUTPUT_RAW_HUMIDITY:
219+
rawHumidity = output.signal;
220+
MESH_DEBUG_PRINTLN("\tHumidity = %f", output.signal);
221+
break;
222+
case BSEC_OUTPUT_RAW_GAS:
223+
MESH_DEBUG_PRINTLN("\tGas resistance = %f", output.signal);
224+
break;
225+
case BSEC_OUTPUT_STABILIZATION_STATUS:
226+
MESH_DEBUG_PRINTLN("\tStabilization status = %f", output.signal);
227+
break;
228+
case BSEC_OUTPUT_RUN_IN_STATUS:
229+
MESH_DEBUG_PRINTLN("\tRun in status = %f", output.signal);
230+
break;
231+
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
232+
compTemperature = output.signal;
233+
MESH_DEBUG_PRINTLN("\tCompensated temperature = %f", output.signal);
234+
break;
235+
case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
236+
compHumidity = output.signal;
237+
MESH_DEBUG_PRINTLN("\tCompensated humidity = %f", output.signal);
238+
break;
239+
case BSEC_OUTPUT_STATIC_IAQ:
240+
readStaticIAQ = output.signal;
241+
MESH_DEBUG_PRINTLN("\tStatic IAQ = %f", output.signal);
242+
break;
243+
case BSEC_OUTPUT_CO2_EQUIVALENT:
244+
readCO2 = output.signal;
245+
MESH_DEBUG_PRINTLN("\tCO2 Equivalent = %f", output.signal);
246+
break;
247+
case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
248+
MESH_DEBUG_PRINTLN("\tbVOC equivalent = %f", output.signal);
249+
break;
250+
case BSEC_OUTPUT_GAS_PERCENTAGE:
251+
MESH_DEBUG_PRINTLN("\tGas percentage = %f", output.signal);
252+
break;
253+
case BSEC_OUTPUT_COMPENSATED_GAS:
254+
MESH_DEBUG_PRINTLN("\tCompensated gas = %f", output.signal);
255+
break;
256+
default:
257+
break;
258+
}
259+
}
260+
}
261+
#endif
262+
150263
bool RAK4631SensorManager::begin() {
151264

152265
#ifdef MESH_DEBUG
153266
scanDevices(&Wire);
154267
#endif
155268

156-
#if ENV_INCLUDE_GPS
157-
//search for the correct IO standby pin depending on socket used
158-
if(gpsIsAwake(P_GPS_STANDBY_A)){
159-
MESH_DEBUG_PRINTLN("GPS is on socket A");
160-
}
161-
else if(gpsIsAwake(P_GPS_STANDBY_C)){
162-
MESH_DEBUG_PRINTLN("GPS is on socket C");
163-
}
164-
else if(gpsIsAwake(P_GPS_STANDBY_F)){
165-
MESH_DEBUG_PRINTLN("GPS is on socket F");
166-
}
167-
else{
168-
MESH_DEBUG_PRINTLN("Error: No GPS found on sockets A, C or F");
169-
gps_active = false;
170-
gps_present = false;
171-
return false;
172-
}
269+
#if ENV_INCLUDE_GPS
270+
//search for the correct IO standby pin depending on socket used
271+
if(gpsIsAwake(P_GPS_STANDBY_A)){
272+
MESH_DEBUG_PRINTLN("GPS is on socket A");
273+
}
274+
else if(gpsIsAwake(P_GPS_STANDBY_C)){
275+
MESH_DEBUG_PRINTLN("GPS is on socket C");
276+
}
277+
else if(gpsIsAwake(P_GPS_STANDBY_F)){
278+
MESH_DEBUG_PRINTLN("GPS is on socket F");
279+
}
280+
else{
281+
MESH_DEBUG_PRINTLN("Error: No GPS found on sockets A, C or F");
282+
gps_active = false;
283+
gps_detected = false;
284+
return false;
285+
}
173286

174-
//Now that GPS is found and set up, set to sleep for initial state
175-
stop_gps();
176-
#endif
287+
#ifndef FORCE_GPS_ALIVE
288+
//Now that GPS is found and set up, set to sleep for initial state
289+
stop_gps();
290+
#endif
291+
#endif
292+
293+
#if ENV_INCLUDE_BME680
294+
295+
bsecSensor sensorList[5] = {
296+
BSEC_OUTPUT_IAQ,
297+
// BSEC_OUTPUT_RAW_TEMPERATURE,
298+
BSEC_OUTPUT_RAW_PRESSURE,
299+
// BSEC_OUTPUT_RAW_HUMIDITY,
300+
// BSEC_OUTPUT_RAW_GAS,
301+
// BSEC_OUTPUT_STABILIZATION_STATUS,
302+
// BSEC_OUTPUT_RUN_IN_STATUS,
303+
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
304+
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
305+
BSEC_OUTPUT_STATIC_IAQ,
306+
// BSEC_OUTPUT_CO2_EQUIVALENT,
307+
// BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
308+
// BSEC_OUTPUT_GAS_PERCENTAGE,
309+
// BSEC_OUTPUT_COMPENSATED_GAS
310+
};
311+
312+
if(!BME680.begin(TELEM_BME680_ADDRESS, Wire)){
313+
checkBMEStatus(BME680);
314+
bme680_present = false;
315+
bme680_active = false;
316+
return false;
317+
}
318+
319+
MESH_DEBUG_PRINTLN("Found BME680 at address: %02X", TELEM_BME680_ADDRESS);
320+
bme680_present = true;
321+
bme680_active = true;
322+
323+
if (SAMPLING_RATE == BSEC_SAMPLE_RATE_ULP)
324+
{
325+
BME680.setTemperatureOffset(BSEC_SAMPLE_RATE_ULP);
326+
}
327+
else if (SAMPLING_RATE == BSEC_SAMPLE_RATE_LP)
328+
{
329+
BME680.setTemperatureOffset(TEMP_OFFSET_LP);
330+
}
331+
332+
if (!BME680.updateSubscription(sensorList, ARRAY_LEN(sensorList), SAMPLING_RATE))
333+
{
334+
checkBMEStatus(BME680);
335+
}
336+
337+
BME680.attachCallback(newDataCallback);
338+
339+
#endif
177340
}
178341

179-
#if ENV_INCLUDE_GPS
180342
bool RAK4631SensorManager::querySensors(uint8_t requester_permissions, CayenneLPP& telemetry) {
343+
#ifdef ENV_INCLUDE_GPS
181344
if (requester_permissions & TELEM_PERM_LOCATION && gps_active) { // does requester have permission?
182345
telemetry.addGPS(TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude);
183346
}
347+
#endif
348+
349+
if (requester_permissions & TELEM_PERM_ENVIRONMENT) {
350+
351+
#if ENV_INCLUDE_BME680
352+
if (bme680_active) {
353+
telemetry.addTemperature(TELEM_CHANNEL_SELF, compTemperature);
354+
telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF, compHumidity);
355+
telemetry.addBarometricPressure(TELEM_CHANNEL_SELF, rawPressure);
356+
telemetry.addTemperature(TELEM_CHANNEL_SELF+1, readIAQ);
357+
telemetry.addRelativeHumidity(TELEM_CHANNEL_SELF+1, readStaticIAQ);
358+
}
359+
#endif
360+
}
184361
return true;
185362
}
186363

187364
void RAK4631SensorManager::loop() {
188365
static long next_update = 0;
189366

367+
#ifdef ENV_INCLUDE_GPS
190368
_nmea->loop();
369+
#endif
191370

192-
if (millis() > next_update && gps_active) {
193-
node_lat = (double)ublox_GNSS.getLatitude()/10000000.;
194-
node_lon = (double)ublox_GNSS.getLongitude()/10000000.;
195-
node_altitude = (double)ublox_GNSS.getAltitude()/1000.;
196-
MESH_DEBUG_PRINT("lat %f lon %f alt %f\r\n", node_lat, node_lon, node_altitude);
371+
if (millis() > next_update) {
197372

373+
#ifdef ENV_INCLUDE_GPS
374+
if(gps_active){
375+
node_lat = (double)ublox_GNSS.getLatitude()/10000000.;
376+
node_lon = (double)ublox_GNSS.getLongitude()/10000000.;
377+
node_altitude = (double)ublox_GNSS.getAltitude()/1000.;
378+
MESH_DEBUG_PRINT("lat %f lon %f alt %f\r\n", node_lat, node_lon, node_altitude);
379+
}
380+
#endif
381+
382+
#ifdef ENV_INCLUDE_BME680
383+
if(bme680_active){
384+
if (!BME680.run()){
385+
checkBMEStatus(BME680);
386+
}
387+
}
388+
#endif
198389
next_update = millis() + 1000;
199390
}
391+
200392
}
201393

202-
int RAK4631SensorManager::getNumSettings() const { return 1; } // just one supported: "gps" (power switch)
394+
int RAK4631SensorManager::getNumSettings() const {
395+
#if ENV_INCLUDE_GPS
396+
return gps_detected ? 1 : 0; // only show GPS setting if GPS is detected
397+
#else
398+
return 0;
399+
#endif
400+
}
203401

204402
const char* RAK4631SensorManager::getSettingName(int i) const {
205-
return i == 0 ? "gps" : NULL;
403+
#if ENV_INCLUDE_GPS
404+
return (gps_detected && i == 0) ? "gps" : NULL;
405+
#else
406+
return NULL;
407+
#endif
206408
}
207409

208410
const char* RAK4631SensorManager::getSettingValue(int i) const {
209-
if (i == 0) {
411+
#if ENV_INCLUDE_GPS
412+
if (gps_detected && i == 0) {
210413
return gps_active ? "1" : "0";
211414
}
415+
#endif
212416
return NULL;
213417
}
214418

215419
bool RAK4631SensorManager::setSettingValue(const char* name, const char* value) {
216-
if (strcmp(name, "gps") == 0) {
420+
#if ENV_INCLUDE_GPS
421+
if (gps_detected && strcmp(name, "gps") == 0) {
217422
if (strcmp(value, "0") == 0) {
218423
stop_gps();
219424
} else {
220425
start_gps();
221426
}
222427
return true;
223428
}
429+
#endif
224430
return false; // not supported
225431
}
226-
#endif
227432

228433
mesh::LocalIdentity radio_new_identity() {
229434
RadioNoiseListener rng(radio);

0 commit comments

Comments
 (0)