@@ -19,6 +19,22 @@ RAK4631SensorManager sensors = RAK4631SensorManager(nmea);
1919RAK4631SensorManager 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 (" \t Found RAK12500 GPS Sensor" );
4460 deviceOnline |= RAK12500_ONLINE;
4561 break ;
62+ case 0x76 :
63+ Serial.println (" \t Found RAK1906 Environment Sensor" );
64+ deviceOnline |= BME680_ONLINE;
65+ break ;
4666 default :
4767 Serial.print (" \t I2C 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\t Time 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 (" \t IAQ = %f" , output.signal );
208+ MESH_DEBUG_PRINTLN (" \t IAQ accuracy = %f" , output.accuracy );
209+ break ;
210+ case BSEC_OUTPUT_RAW_TEMPERATURE:
211+ rawTemperature = output.signal ;
212+ MESH_DEBUG_PRINTLN (" \t Temperature = %f" , output.signal );
213+ break ;
214+ case BSEC_OUTPUT_RAW_PRESSURE:
215+ rawPressure = output.signal ;
216+ MESH_DEBUG_PRINTLN (" \t Pressure = %f" , output.signal );
217+ break ;
218+ case BSEC_OUTPUT_RAW_HUMIDITY:
219+ rawHumidity = output.signal ;
220+ MESH_DEBUG_PRINTLN (" \t Humidity = %f" , output.signal );
221+ break ;
222+ case BSEC_OUTPUT_RAW_GAS:
223+ MESH_DEBUG_PRINTLN (" \t Gas resistance = %f" , output.signal );
224+ break ;
225+ case BSEC_OUTPUT_STABILIZATION_STATUS:
226+ MESH_DEBUG_PRINTLN (" \t Stabilization status = %f" , output.signal );
227+ break ;
228+ case BSEC_OUTPUT_RUN_IN_STATUS:
229+ MESH_DEBUG_PRINTLN (" \t Run in status = %f" , output.signal );
230+ break ;
231+ case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
232+ compTemperature = output.signal ;
233+ MESH_DEBUG_PRINTLN (" \t Compensated temperature = %f" , output.signal );
234+ break ;
235+ case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
236+ compHumidity = output.signal ;
237+ MESH_DEBUG_PRINTLN (" \t Compensated humidity = %f" , output.signal );
238+ break ;
239+ case BSEC_OUTPUT_STATIC_IAQ:
240+ readStaticIAQ = output.signal ;
241+ MESH_DEBUG_PRINTLN (" \t Static IAQ = %f" , output.signal );
242+ break ;
243+ case BSEC_OUTPUT_CO2_EQUIVALENT:
244+ readCO2 = output.signal ;
245+ MESH_DEBUG_PRINTLN (" \t CO2 Equivalent = %f" , output.signal );
246+ break ;
247+ case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
248+ MESH_DEBUG_PRINTLN (" \t bVOC equivalent = %f" , output.signal );
249+ break ;
250+ case BSEC_OUTPUT_GAS_PERCENTAGE:
251+ MESH_DEBUG_PRINTLN (" \t Gas percentage = %f" , output.signal );
252+ break ;
253+ case BSEC_OUTPUT_COMPENSATED_GAS:
254+ MESH_DEBUG_PRINTLN (" \t Compensated gas = %f" , output.signal );
255+ break ;
256+ default :
257+ break ;
258+ }
259+ }
260+ }
261+ #endif
262+
150263bool 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
180342bool 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
187364void 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
204402const 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
208410const 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
215419bool 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
228433mesh::LocalIdentity radio_new_identity () {
229434 RadioNoiseListener rng (radio);
0 commit comments