diff --git a/README.md b/README.md
index b4b6a61f..43afb1c1 100644
--- a/README.md
+++ b/README.md
@@ -47,6 +47,7 @@ Depending on board hardware following features are supported:
- Silicon unique ID
- Battery voltage monitoring
- GPS (Generic serial NMEA, or Quectel L76 I2C)
+- MEMS sensor (Bosch BME680)
Target platform must be selected in [platformio.ini](https://github.com/cyberman54/ESP32-Paxcounter/blob/master/platformio.ini).
Hardware dependent settings (pinout etc.) are stored in board files in /hal directory. If you want to use a ESP32 board which is not yet supported, use hal file generic.h and tailor pin mappings to your needs. Pull requests for new boards welcome.
@@ -198,6 +199,14 @@ Hereafter described is the default *plain* format, which uses MSB bit numbering.
byte 1: Beacon RSSI reception level
byte 2: Beacon identifier (0..255)
+**Port #7:** BME680 query result
+
+ bytes 1-2: Temperature [°C]
+ bytes 3-4: Pressure [hPa]
+ byte 5: Humidity [%]
+ bytes 6-7: Gas resistance [MOhm]
+ bytes 8-9: Altitude [meter]
+
# Remote control
The device listenes for remote control commands on LoRaWAN Port 2. Multiple commands per downlink are possible by concatenating them.
@@ -310,6 +319,10 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
Device answers with it's current status on Port 4.
+0x85 get BME680 sensor data
+
+ Device answers with BME680 sensor data set on Port 7.
+
# License
diff --git a/include/bme680read.h b/include/bme680read.h
index 04f506fc..057cb40d 100644
--- a/include/bme680read.h
+++ b/include/bme680read.h
@@ -2,17 +2,15 @@
#define _HAS_BME
#include "globals.h"
-
#include
-#include
#include
#include "Adafruit_BME680.h"
-extern Adafruit_BME680 bme; // Make TinyGPS++ instance globally availabe
+extern Adafruit_BME680 bme; // Make bme instance globally availabe
extern bmeStatus_t
bme_status; // Make struct for storing gps data globally available
-extern TaskHandle_t BmeTask;
-void bme_loop(void *pvParameters);
+void bme_init();
+bool bme_read();
#endif
\ No newline at end of file
diff --git a/include/globals.h b/include/globals.h
index 0966ba95..b519bb52 100644
--- a/include/globals.h
+++ b/include/globals.h
@@ -47,11 +47,11 @@ typedef struct {
} gpsStatus_t;
typedef struct {
- float_t temperature;
- float_t pressure;
- float_t humidity;
- float_t gas_resistance;
- float_t altitude;
+ uint16_t temperature; // Temperature * 100 in degrees Centigrade
+ uint16_t pressure; // Barometic pressure in hecto pascals
+ uint8_t humidity; // Relative humidity in percent
+ uint32_t gas_resistance; // Resistance in Ohms
+ uint16_t altitude; // Altitude in meters
} bmeStatus_t;
// global variables
diff --git a/src/bme680read.cpp b/src/bme680read.cpp
index f49c11ea..aa75c162 100644
--- a/src/bme680read.cpp
+++ b/src/bme680read.cpp
@@ -1,64 +1,46 @@
#ifdef HAS_BME
-#include "globals.h"
+#include "bme680read.h"
// Local logging tag
static const char TAG[] = "main";
-#include
-#include
-#include
-#include "Adafruit_BME680.h"
-
#define SEALEVELPRESSURE_HPA (1013.25)
// I2C Bus interface
Adafruit_BME680 bme;
bmeStatus_t bme_status;
-TaskHandle_t BmeTask;
-// BME680 read loop Task
-void bme_loop(void *pvParameters) {
+void bme_init(void) {
+ // initialize BME680 sensor using default i2c address 0x77
+ if (bme.begin()) {
+ // Set up oversampling and filter initialization
+ bme.setTemperatureOversampling(BME680_OS_8X);
+ bme.setHumidityOversampling(BME680_OS_2X);
+ bme.setPressureOversampling(BME680_OS_4X);
+ bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
+ bme.setGasHeater(320, 150); // 320*C for 150 ms
+ ESP_LOGI(TAG, "BME680 chip found and initialized");
+ } else
+ ESP_LOGE(TAG, "BME680 chip not found on i2c bus");
+}
- configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
-
- // initialize BME680 sensor
- if (!bme.begin()) {
- ESP_LOGE(TAG, "BME680 chip not found on i2c bus, bus error %d. "
- "Stopping BME task.");
- vTaskDelete(BmeTask);
+bool bme_read(void) {
+ bool ret = bme.performReading();
+ if (ret) {
+ // read current BME data and buffer in global struct
+ bme_status.temperature = (uint16_t)(bme.temperature * 100.0);
+ bme_status.pressure = (uint16_t)(bme.pressure / 100.0);
+ bme_status.humidity = (uint8_t)bme.humidity;
+ bme_status.gas_resistance = (uint16_t)(bme.gas_resistance / 1000.0);
+ bme_status.altitude =
+ (uint16_t)(bme.readAltitude(SEALEVELPRESSURE_HPA / 1000.0));
+ ESP_LOGI(TAG, "BME680 sensor data read success");
} else {
- ESP_LOGI(TAG, "BME680 chip found.");
+ ESP_LOGI(TAG, "BME680 sensor read error");
}
-
- // Set up oversampling and filter initialization
- bme.setTemperatureOversampling(BME680_OS_8X);
- bme.setHumidityOversampling(BME680_OS_2X);
- bme.setPressureOversampling(BME680_OS_4X);
- bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
- bme.setGasHeater(320, 150); // 320*C for 150 ms
-
- // read loop
- while (1) {
-
- vTaskDelay(10000 / portTICK_PERIOD_MS);
-
- if (!bme.performReading()) {
- ESP_LOGE(TAG, "BME680 read error");
- continue;
- } else {
- // read current BME data and buffer in global struct
- bme_status.temperature = bme.temperature;
- bme_status.pressure = bme.pressure / 100.0;
- bme_status.humidity = bme.humidity;
- bme_status.gas_resistance = bme.gas_resistance / 1000.0;
- bme_status.altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
- }
- } // end of infinite loop
-
- vTaskDelete(NULL); // shoud never be reached
-
-} // bme_loop()
+ return ret;
+}
#endif // HAS_BME
\ No newline at end of file
diff --git a/src/cyclic.cpp b/src/cyclic.cpp
index b95f176d..99329040 100644
--- a/src/cyclic.cpp
+++ b/src/cyclic.cpp
@@ -32,6 +32,11 @@ void doHousekeeping() {
}
#endif
+#ifdef HAS_BME
+ // read BME280 sensor if present
+ bme_read();
+#endif
+
// task storage debugging //
ESP_LOGD(TAG, "Wifiloop %d bytes left",
uxTaskGetStackHighWaterMark(wifiSwitchTask));
diff --git a/src/hal/heltec.h b/src/hal/heltec.h
index d3c54ee3..492f3425 100644
--- a/src/hal/heltec.h
+++ b/src/hal/heltec.h
@@ -3,6 +3,8 @@
#include
+//#define HAS_BME 1 // BME680 sensor on I2C bus (SDI=21/SCL=22); comment out if not present
+
// Hardware related definitions for Heltec LoRa-32 Board
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
#define CFG_sx1276_radio 1
diff --git a/src/hal/ttgov21new.h b/src/hal/ttgov21new.h
index 6ef93285..bc41184a 100644
--- a/src/hal/ttgov21new.h
+++ b/src/hal/ttgov21new.h
@@ -8,6 +8,8 @@
// This settings are for boards labeled v1.6 on pcb, NOT for v1.5 or older
*/
+//#define HAS_BME 1 // BME680 sensor on I2C bus (SDI=21/SCL=22); comment out if not present
+
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
diff --git a/src/lorawan.cpp b/src/lorawan.cpp
index f1787c66..5159531c 100644
--- a/src/lorawan.cpp
+++ b/src/lorawan.cpp
@@ -422,14 +422,14 @@ void user_request_network_time_callback(void *pVoidUserUTCTime,
lmic_time_reference_t lmicTimeReference;
if (flagSuccess != 1) {
- ESP_LOGW(TAG, "Network time request callback error");
+ ESP_LOGW(TAG, "LoRaWAN network did not answer time request");
return;
}
// Populate lmic_time_reference
flagSuccess = LMIC_getNetworkTimeReference(&lmicTimeReference);
if (flagSuccess != 1) {
- ESP_LOGW(TAG, "Network time request failed");
+ ESP_LOGW(TAG, "LoRaWAN time request failed");
return;
}
diff --git a/src/main.cpp b/src/main.cpp
index 92abe5bc..0fed89ec 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -35,7 +35,6 @@ IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
looptask 1 1 arduino core -> runs the LMIC LoRa stack
irqhandler 1 1 executes tasks triggered by irq
gpsloop 1 2 reads data from GPS over serial or i2c
-bmeloop 1 2 reads data from BME680 over i2c
IDLE 1 0 ESP32 arduino scheduler
ESP32 hardware timers
@@ -56,7 +55,8 @@ uint8_t volatile channel = 0; // channel rotation counter
uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0,
batt_voltage = 0; // globals for display
-hw_timer_t *channelSwitch = NULL, *sendCycle = NULL, *homeCycle = NULL, *displaytimer = NULL; // irq tasks
+hw_timer_t *channelSwitch = NULL, *sendCycle = NULL, *homeCycle = NULL,
+ *displaytimer = NULL; // irq tasks
TaskHandle_t irqHandlerTask, wifiSwitchTask;
std::set macs; // container holding unique MAC adress hashes
@@ -161,6 +161,7 @@ void setup() {
// initialize gps
#ifdef HAS_BME
strcat_P(features, " BME");
+ bme_init();
#endif
// initialize LoRa
@@ -281,17 +282,6 @@ void setup() {
1); // CPU core
#endif
-#ifdef HAS_BME
- ESP_LOGI(TAG, "Starting BMEloop...");
- xTaskCreatePinnedToCore(bme_loop, // task function
- "bmeloop", // name of task
- 2048, // stack size of task
- (void *)1, // parameter of the task
- 2, // priority of the task
- &BmeTask, // task handle
- 1); // CPU core
-#endif
-
// start state machine
ESP_LOGI(TAG, "Starting IRQ Handler...");
xTaskCreatePinnedToCore(irqHandler, // task function
diff --git a/src/paxcounter.conf b/src/paxcounter.conf
index 2f27acaf..1135963d 100644
--- a/src/paxcounter.conf
+++ b/src/paxcounter.conf
@@ -59,6 +59,7 @@
#define LPP1PORT 1 // Port for Cayenne LPP 1.0 dynamic sensor encoding
#define LPP2PORT 2 // Port for Cayenne LPP 2.0 packed sensor encoding
#define BEACONPORT 6 // Port on which device sends beacon alarms
+#define BMEPORT 7 // Port on which device sends BME680 sensor data
// Some hardware settings
#define RGBLUMINOSITY 30 // RGB LED luminosity [default = 30%]
diff --git a/src/payload.cpp b/src/payload.cpp
index 56c87fce..d328f975 100644
--- a/src/payload.cpp
+++ b/src/payload.cpp
@@ -95,11 +95,15 @@ void PayloadConvert::addGPS(gpsStatus_t value) {
void PayloadConvert::addBME(bmeStatus_t value) {
#ifdef HAS_BME
- buffer[cursor++] = (byte)(value.temperature);
- buffer[cursor++] = (byte)(value.pressure);
+ buffer[cursor++] = highByte(value.temperature);
+ buffer[cursor++] = lowByte(value.temperature);
+ buffer[cursor++] = highByte(value.pressure);
+ buffer[cursor++] = lowByte(value.pressure);
buffer[cursor++] = (byte)(value.humidity);
- buffer[cursor++] = (byte)(value.gas_resistance);
- buffer[cursor++] = (byte)(value.altitude);
+ buffer[cursor++] = highByte(value.gas_resistance);
+ buffer[cursor++] = lowByte(value.gas_resistance);
+ buffer[cursor++] = highByte(value.altitude);
+ buffer[cursor++] = lowByte(value.altitude);
#endif
}
@@ -162,11 +166,11 @@ void PayloadConvert::addGPS(gpsStatus_t value) {
void PayloadConvert::addBME(bmeStatus_t value) {
#ifdef HAS_BME
- writeUint8((byte)value.temperature);
- writeUint8((byte)value.pressure);
- writeUint8((byte)value.humidity);
- writeUint8((byte)value.gas_resistance);
- writeUint8((byte)value.altitude);
+ writeUint16(value.temperature);
+ writeUint16(value.pressure);
+ writeUint8(value.humidity);
+ writeUint16(value.gas_resistance);
+ writeUint16(value.altitude);
#endif
}
diff --git a/src/rcommand.cpp b/src/rcommand.cpp
index ffba3ff0..dc525f44 100644
--- a/src/rcommand.cpp
+++ b/src/rcommand.cpp
@@ -240,6 +240,17 @@ void get_gps(uint8_t val[]) {
#endif
};
+void get_bme(uint8_t val[]) {
+ ESP_LOGI(TAG, "Remote command: get bme680 sensor data");
+#ifdef HAS_BME
+ payload.reset();
+ payload.addBME(bme_status);
+ SendData(BMEPORT);
+#else
+ ESP_LOGW(TAG, "BME680 sensor not supported");
+#endif
+};
+
// assign previously defined functions to set of numeric remote commands
// format: opcode, function, #bytes params,
// flag (true = do make settings persistent / false = don't)
@@ -255,7 +266,8 @@ cmd_t table[] = {
{0x0f, set_wifiant, 1, true}, {0x10, set_rgblum, 1, true},
{0x11, set_monitor, 1, true}, {0x12, set_beacon, 7, false},
{0x80, get_config, 0, false}, {0x81, get_status, 0, false},
- {0x84, get_gps, 0, false}};
+ {0x84, get_gps, 0, false}, {0x85, get_bme, 0, false},
+};
const uint8_t cmdtablesize =
sizeof(table) / sizeof(table[0]); // number of commands in command table