@@ -19,6 +19,21 @@ 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 readCO2 = 0 ;
35+ #endif
36+
2237#ifdef DISPLAY_CLASS
2338 DISPLAY_CLASS display;
2439#endif
@@ -43,6 +58,10 @@ void scanDevices(TwoWire *w)
4358 Serial.println (" \t Found RAK12500 GPS Sensor" );
4459 deviceOnline |= RAK12500_ONLINE;
4560 break ;
61+ case 0x76 :
62+ Serial.println (" \t Found RAK1906 Environment Sensor" );
63+ deviceOnline |= BME680_ONLINE;
64+ break ;
4665 default :
4766 Serial.print (" \t I2C device found at address 0x" );
4867 if (addr < 16 ) {
@@ -137,7 +156,7 @@ bool RAK4631SensorManager::gpsIsAwake(uint32_t ioPin){
137156 ublox_GNSS.saveConfigSelective (VAL_CFG_SUBSEC_IOPORT);
138157 disStandbyPin = ioPin;
139158 gps_active = true ;
140- gps_present = true ;
159+ gps_detected = true ;
141160 return true ;
142161 }
143162 else
@@ -147,83 +166,266 @@ bool RAK4631SensorManager::gpsIsAwake(uint32_t ioPin){
147166}
148167#endif
149168
169+ #if ENV_INCLUDE_BME680
170+ void checkBMEStatus (Bsec2 bsec)
171+ {
172+ if (bsec.status < BSEC_OK)
173+ {
174+ MESH_DEBUG_PRINTLN (" BSEC error code : %f" , String (bsec.status ));
175+ }
176+ else if (bsec.status > BSEC_OK)
177+ {
178+ MESH_DEBUG_PRINTLN (" BSEC warning code : %f" , String (bsec.status ));
179+ }
180+
181+ if (bsec.sensor .status < BME68X_OK)
182+ {
183+ MESH_DEBUG_PRINTLN (" BME68X error code : %f" , String (bsec.sensor .status ));
184+ }
185+ else if (bsec.sensor .status > BME68X_OK)
186+ {
187+ MESH_DEBUG_PRINTLN (" BME68X warning code : %f" , String (bsec.sensor .status ));
188+ }
189+ }
190+ void newDataCallback (const bme68xData data, const bsecOutputs outputs, Bsec2 bsec)
191+ {
192+ if (!outputs.nOutputs )
193+ {
194+ MESH_DEBUG_PRINTLN (" No new data to report out" );
195+ return ;
196+ }
197+
198+ MESH_DEBUG_PRINTLN (" BSEC outputs:\n\t Time stamp = %f" , String ((int ) (outputs.output [0 ].time_stamp / INT64_C (1000000 ))));
199+ for (uint8_t i = 0 ; i < outputs.nOutputs ; i++)
200+ {
201+ const bsecData output = outputs.output [i];
202+ switch (output.sensor_id )
203+ {
204+ case BSEC_OUTPUT_IAQ:
205+ MESH_DEBUG_PRINTLN (" \t IAQ = %f" , String (output.signal ));
206+ MESH_DEBUG_PRINTLN (" \t IAQ accuracy = %f" , String ((int ) output.accuracy ));
207+ break ;
208+ case BSEC_OUTPUT_RAW_TEMPERATURE:
209+ rawTemperature = output.signal ;
210+ MESH_DEBUG_PRINTLN (" \t Temperature = %f" , String (output.signal ));
211+ break ;
212+ case BSEC_OUTPUT_RAW_PRESSURE:
213+ rawPressure = output.signal ;
214+ MESH_DEBUG_PRINTLN (" \t Pressure = %f" , String (output.signal ));
215+ break ;
216+ case BSEC_OUTPUT_RAW_HUMIDITY:
217+ rawHumidity = output.signal ;
218+ MESH_DEBUG_PRINTLN (" \t Humidity = %f" , String (output.signal ));
219+ break ;
220+ case BSEC_OUTPUT_RAW_GAS:
221+ MESH_DEBUG_PRINTLN (" \t Gas resistance = %f" , String (output.signal ));
222+ break ;
223+ case BSEC_OUTPUT_STABILIZATION_STATUS:
224+ MESH_DEBUG_PRINTLN (" \t Stabilization status = %f" , String (output.signal ));
225+ break ;
226+ case BSEC_OUTPUT_RUN_IN_STATUS:
227+ MESH_DEBUG_PRINTLN (" \t Run in status = %f" , String (output.signal ));
228+ break ;
229+ case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE:
230+ compTemperature = output.signal ;
231+ MESH_DEBUG_PRINTLN (" \t Compensated temperature = %f" , String (output.signal ));
232+ break ;
233+ case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY:
234+ compHumidity = output.signal ;
235+ MESH_DEBUG_PRINTLN (" \t Compensated humidity = %f" , String (output.signal ));
236+ break ;
237+ case BSEC_OUTPUT_STATIC_IAQ:
238+ readIAQ = output.signal ;
239+ MESH_DEBUG_PRINTLN (" \t Static IAQ = %f" , String (output.signal ));
240+ break ;
241+ case BSEC_OUTPUT_CO2_EQUIVALENT:
242+ readCO2 = output.signal ;
243+ MESH_DEBUG_PRINTLN (" \t CO2 Equivalent = %f" , String (output.signal ));
244+ break ;
245+ case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT:
246+ MESH_DEBUG_PRINTLN (" \t bVOC equivalent = %f" , String (output.signal ));
247+ break ;
248+ case BSEC_OUTPUT_GAS_PERCENTAGE:
249+ MESH_DEBUG_PRINTLN (" \t Gas percentage = %f" , String (output.signal ));
250+ break ;
251+ case BSEC_OUTPUT_COMPENSATED_GAS:
252+ MESH_DEBUG_PRINTLN (" \t Compensated gas = %f" , String (output.signal ));
253+ break ;
254+ default :
255+ break ;
256+ }
257+ }
258+ }
259+ #endif
260+
150261bool RAK4631SensorManager::begin () {
151262
152263 #ifdef MESH_DEBUG
153264 scanDevices (&Wire);
154265 #endif
155266
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- }
267+ #if ENV_INCLUDE_GPS
268+ // search for the correct IO standby pin depending on socket used
269+ if (gpsIsAwake (P_GPS_STANDBY_A)){
270+ MESH_DEBUG_PRINTLN (" GPS is on socket A" );
271+ }
272+ else if (gpsIsAwake (P_GPS_STANDBY_C)){
273+ MESH_DEBUG_PRINTLN (" GPS is on socket C" );
274+ }
275+ else if (gpsIsAwake (P_GPS_STANDBY_F)){
276+ MESH_DEBUG_PRINTLN (" GPS is on socket F" );
277+ }
278+ else {
279+ MESH_DEBUG_PRINTLN (" Error: No GPS found on sockets A, C or F" );
280+ gps_active = false ;
281+ gps_detected = false ;
282+ return false ;
283+ }
173284
174- // Now that GPS is found and set up, set to sleep for initial state
175- stop_gps ();
176- #endif
285+ #ifndef FORCE_GPS_ALIVE
286+ // Now that GPS is found and set up, set to sleep for initial state
287+ stop_gps ();
288+ #endif
289+ #endif
290+
291+ #if ENV_INCLUDE_BME680
292+
293+ bsecSensor sensorList[4 ] = {
294+ BSEC_OUTPUT_IAQ,
295+ // BSEC_OUTPUT_RAW_TEMPERATURE,
296+ BSEC_OUTPUT_RAW_PRESSURE,
297+ // BSEC_OUTPUT_RAW_HUMIDITY,
298+ // BSEC_OUTPUT_RAW_GAS,
299+ // BSEC_OUTPUT_STABILIZATION_STATUS,
300+ // BSEC_OUTPUT_RUN_IN_STATUS,
301+ BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
302+ BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
303+ // BSEC_OUTPUT_STATIC_IAQ,
304+ // BSEC_OUTPUT_CO2_EQUIVALENT,
305+ // BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
306+ // BSEC_OUTPUT_GAS_PERCENTAGE,
307+ // BSEC_OUTPUT_COMPENSATED_GAS
308+ };
309+
310+ if (!BME680.begin (TELEM_BME680_ADDRESS, Wire)){
311+ checkBMEStatus (BME680);
312+ bme680_present = false ;
313+ bme680_active = false ;
314+ return false ;
315+ }
316+
317+ MESH_DEBUG_PRINTLN (" Found BME680 at address: %02X" , TELEM_BME680_ADDRESS);
318+ bme680_present = true ;
319+ bme680_active = true ;
320+
321+ if (SAMPLING_RATE == BSEC_SAMPLE_RATE_ULP)
322+ {
323+ BME680.setTemperatureOffset (BSEC_SAMPLE_RATE_ULP);
324+ }
325+ else if (SAMPLING_RATE == BSEC_SAMPLE_RATE_LP)
326+ {
327+ BME680.setTemperatureOffset (TEMP_OFFSET_LP);
328+ }
329+
330+ if (!BME680.updateSubscription (sensorList, ARRAY_LEN (sensorList), SAMPLING_RATE))
331+ {
332+ checkBMEStatus (BME680);
333+ }
334+
335+ BME680.attachCallback (newDataCallback);
336+
337+ #endif
177338}
178339
179- #if ENV_INCLUDE_GPS
180340bool RAK4631SensorManager::querySensors (uint8_t requester_permissions, CayenneLPP& telemetry) {
341+ #ifdef ENV_INCLUDE_GPS
181342 if (requester_permissions & TELEM_PERM_LOCATION && gps_active) { // does requester have permission?
182343 telemetry.addGPS (TELEM_CHANNEL_SELF, node_lat, node_lon, node_altitude);
183344 }
345+ #endif
346+
347+ if (requester_permissions & TELEM_PERM_ENVIRONMENT) {
348+
349+ #if ENV_INCLUDE_BME680
350+ if (bme680_active) {
351+ telemetry.addTemperature (TELEM_CHANNEL_SELF, compTemperature);
352+ telemetry.addRelativeHumidity (TELEM_CHANNEL_SELF, compHumidity);
353+ telemetry.addBarometricPressure (TELEM_CHANNEL_SELF, rawPressure);
354+ telemetry.addRelativeHumidity (TELEM_CHANNEL_SELF+1 , readIAQ);
355+ }
356+ #endif
357+ }
184358 return true ;
185359}
186360
187361void RAK4631SensorManager::loop () {
188362 static long next_update = 0 ;
189363
364+ #ifdef ENV_INCLUDE_GPS
190365 _nmea->loop ();
366+ #endif
191367
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);
368+ if (millis () > next_update) {
197369
370+ #ifdef ENV_INCLUDE_GPS
371+ if (gps_active){
372+ node_lat = (double )ublox_GNSS.getLatitude ()/10000000 .;
373+ node_lon = (double )ublox_GNSS.getLongitude ()/10000000 .;
374+ node_altitude = (double )ublox_GNSS.getAltitude ()/1000 .;
375+ MESH_DEBUG_PRINT (" lat %f lon %f alt %f\r\n " , node_lat, node_lon, node_altitude);
376+ }
377+ #endif
378+
379+ #ifdef ENV_INCLUDE_BME680
380+ if (bme680_active){
381+ if (!BME680.run ()){
382+ checkBMEStatus (BME680);
383+ }
384+ }
385+ #endif
198386 next_update = millis () + 1000 ;
199387 }
388+
200389}
201390
202- int RAK4631SensorManager::getNumSettings () const { return 1 ; } // just one supported: "gps" (power switch)
391+ int RAK4631SensorManager::getNumSettings () const {
392+ #if ENV_INCLUDE_GPS
393+ return gps_detected ? 1 : 0 ; // only show GPS setting if GPS is detected
394+ #else
395+ return 0 ;
396+ #endif
397+ }
203398
204399const char * RAK4631SensorManager::getSettingName (int i) const {
205- return i == 0 ? " gps" : NULL ;
400+ #if ENV_INCLUDE_GPS
401+ return (gps_detected && i == 0 ) ? " gps" : NULL ;
402+ #else
403+ return NULL ;
404+ #endif
206405}
207406
208407const char * RAK4631SensorManager::getSettingValue (int i) const {
209- if (i == 0 ) {
408+ #if ENV_INCLUDE_GPS
409+ if (gps_detected && i == 0 ) {
210410 return gps_active ? " 1" : " 0" ;
211411 }
412+ #endif
212413 return NULL ;
213414}
214415
215416bool RAK4631SensorManager::setSettingValue (const char * name, const char * value) {
216- if (strcmp (name, " gps" ) == 0 ) {
417+ #if ENV_INCLUDE_GPS
418+ if (gps_detected && strcmp (name, " gps" ) == 0 ) {
217419 if (strcmp (value, " 0" ) == 0 ) {
218420 stop_gps ();
219421 } else {
220422 start_gps ();
221423 }
222424 return true ;
223425 }
426+ #endif
224427 return false ; // not supported
225428}
226- #endif
227429
228430mesh::LocalIdentity radio_new_identity () {
229431 RadioNoiseListener rng (radio);
0 commit comments