first fully functional integration (experimental)
This commit is contained in:
1 parent
eb5dac2dea
commit
76600a86b1
10 files changed
+488
-446
No files matched your search
+64
-53
@@ -7,60 +7,63 @@ static const char TAG[] = "main";
|
||||
|
||||
bmeStatus_t bme_status;
|
||||
TaskHandle_t BmeTask;
|
||||
float bme_offset = (float)BME_TEMP_OFFSET;
|
||||
|
||||
Bsec iaqSensor;
|
||||
|
||||
bsec_virtual_sensor_t sensorList[10] = {
|
||||
BSEC_OUTPUT_RAW_TEMPERATURE,
|
||||
BSEC_OUTPUT_RAW_PRESSURE,
|
||||
BSEC_OUTPUT_RAW_HUMIDITY,
|
||||
BSEC_OUTPUT_RAW_GAS,
|
||||
BSEC_OUTPUT_IAQ,
|
||||
BSEC_OUTPUT_STATIC_IAQ,
|
||||
BSEC_OUTPUT_CO2_EQUIVALENT,
|
||||
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
|
||||
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
|
||||
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
|
||||
};
|
||||
|
||||
// initialize BME680 sensor
|
||||
int bme_init(void) {
|
||||
|
||||
Wire.begin(HAS_BME);
|
||||
iaqSensor.begin(BME_ADDR, Wire);
|
||||
// block i2c bus access
|
||||
if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) ==
|
||||
pdTRUE) {
|
||||
|
||||
ESP_LOGI(TAG, "BSEC v%d.%d.%d.%d", iaqSensor.version.major,
|
||||
iaqSensor.version.minor, iaqSensor.version.major_bugfix,
|
||||
iaqSensor.version.minor_bugfix);
|
||||
Wire.begin(HAS_BME);
|
||||
iaqSensor.begin(BME_ADDR, Wire);
|
||||
|
||||
iaqSensor.setConfig(bsec_config_iaq);
|
||||
ESP_LOGI(TAG, "BSEC v%d.%d.%d.%d", iaqSensor.version.major,
|
||||
iaqSensor.version.minor, iaqSensor.version.major_bugfix,
|
||||
iaqSensor.version.minor_bugfix);
|
||||
|
||||
if (checkIaqSensorStatus())
|
||||
ESP_LOGI(TAG, "BME680 sensor found and initialized");
|
||||
else {
|
||||
ESP_LOGE(TAG, "BME680 sensor not found");
|
||||
iaqSensor.setConfig(bsec_config_iaq);
|
||||
|
||||
if (checkIaqSensorStatus())
|
||||
ESP_LOGI(TAG, "BME680 sensor found and initialized");
|
||||
else {
|
||||
ESP_LOGE(TAG, "BME680 sensor not found");
|
||||
return 1;
|
||||
}
|
||||
|
||||
iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET);
|
||||
iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);
|
||||
|
||||
if (checkIaqSensorStatus())
|
||||
ESP_LOGI(TAG, "BSEC subscription succesful");
|
||||
else {
|
||||
ESP_LOGE(TAG, "BSEC subscription error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
xSemaphoreGive(I2Caccess); // release i2c bus access
|
||||
|
||||
} else {
|
||||
ESP_LOGE(TAG, "I2c bus busy - BME680 initialization error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bsec_virtual_sensor_t sensorList[10] = {
|
||||
BSEC_OUTPUT_RAW_TEMPERATURE,
|
||||
BSEC_OUTPUT_RAW_PRESSURE,
|
||||
BSEC_OUTPUT_RAW_HUMIDITY,
|
||||
BSEC_OUTPUT_RAW_GAS,
|
||||
BSEC_OUTPUT_IAQ,
|
||||
BSEC_OUTPUT_STATIC_IAQ,
|
||||
BSEC_OUTPUT_CO2_EQUIVALENT,
|
||||
BSEC_OUTPUT_BREATH_VOC_EQUIVALENT,
|
||||
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE,
|
||||
BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY,
|
||||
};
|
||||
|
||||
iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP);
|
||||
|
||||
if (checkIaqSensorStatus())
|
||||
ESP_LOGI(TAG, "BSEC subscription succesful");
|
||||
else {
|
||||
ESP_LOGE(TAG, "BSEC subscription error");
|
||||
return 1;
|
||||
}
|
||||
|
||||
iaqSensor.setTemperatureOffset(bme_offset);
|
||||
|
||||
if (checkIaqSensorStatus())
|
||||
ESP_LOGI(TAG, "Ttemperature offset initialized succesful");
|
||||
else {
|
||||
ESP_LOGE(TAG, "Temperature offset initialization error");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
} // bme_init()
|
||||
|
||||
// Helper function definitions
|
||||
int checkIaqSensorStatus(void) {
|
||||
@@ -83,7 +86,7 @@ int checkIaqSensorStatus(void) {
|
||||
}
|
||||
|
||||
return rslt;
|
||||
}
|
||||
} // checkIaqSensorStatus()
|
||||
|
||||
// loop function which reads and processes data based on sensor settings
|
||||
void bme_loop(void *pvParameters) {
|
||||
@@ -92,16 +95,24 @@ void bme_loop(void *pvParameters) {
|
||||
|
||||
#ifdef HAS_BME
|
||||
while (checkIaqSensorStatus()) {
|
||||
if (iaqSensor.run()) { // If new data is available
|
||||
bme_status.raw_temperature = iaqSensor.rawTemperature;
|
||||
bme_status.raw_humidity = iaqSensor.rawHumidity;
|
||||
bme_status.temperature = iaqSensor.temperature;
|
||||
bme_status.humidity = iaqSensor.humidity;
|
||||
bme_status.pressure =
|
||||
(iaqSensor.pressure / 100.0); // conversion Pa -> hPa
|
||||
bme_status.iaq = iaqSensor.iaqEstimate;
|
||||
bme_status.iaq_accuracy = iaqSensor.iaqAccuracy;
|
||||
bme_status.gas = iaqSensor.gasResistance;
|
||||
|
||||
// block i2c bus access
|
||||
if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) ==
|
||||
pdTRUE) {
|
||||
|
||||
if (iaqSensor.run()) { // If new data is available
|
||||
bme_status.raw_temperature = iaqSensor.rawTemperature;
|
||||
bme_status.raw_humidity = iaqSensor.rawHumidity;
|
||||
bme_status.temperature = iaqSensor.temperature;
|
||||
bme_status.humidity = iaqSensor.humidity;
|
||||
bme_status.pressure =
|
||||
(iaqSensor.pressure / 100.0); // conversion Pa -> hPa
|
||||
bme_status.iaq = iaqSensor.iaqEstimate;
|
||||
bme_status.iaq_accuracy = iaqSensor.iaqAccuracy;
|
||||
bme_status.gas = iaqSensor.gasResistance;
|
||||
}
|
||||
|
||||
xSemaphoreGive(I2Caccess); // release i2c bus access
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
+6
-1
@@ -52,7 +52,12 @@ void doHousekeeping() {
|
||||
// read battery voltage into global variable
|
||||
#ifdef HAS_BATTERY_PROBE
|
||||
batt_voltage = read_voltage();
|
||||
ESP_LOGI(TAG, "Measured Voltage: %dmV", batt_voltage);
|
||||
ESP_LOGI(TAG, "Voltage: %dmV", batt_voltage);
|
||||
#endif
|
||||
|
||||
// display BME sensor data if present
|
||||
#ifdef HAS_BME
|
||||
ESP_LOGI(TAG, "BME680 Temp: %.2f°C | IAQ: %.2f", bme_status.temperature, bme_status.iaq);
|
||||
#endif
|
||||
|
||||
// check free heap memory
|
||||
|
||||
+72
-64
@@ -98,96 +98,104 @@ void init_display(const char *Productname, const char *Version) {
|
||||
|
||||
void refreshtheDisplay() {
|
||||
|
||||
// set display on/off according to current device configuration
|
||||
if (DisplayState != cfg.screenon) {
|
||||
DisplayState = cfg.screenon;
|
||||
u8x8.setPowerSave(!cfg.screenon);
|
||||
}
|
||||
// block i2c bus access
|
||||
if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) ==
|
||||
pdTRUE) {
|
||||
|
||||
// if display is switched off we don't refresh it and save time
|
||||
if (!DisplayState)
|
||||
return;
|
||||
// set display on/off according to current device configuration
|
||||
if (DisplayState != cfg.screenon) {
|
||||
DisplayState = cfg.screenon;
|
||||
u8x8.setPowerSave(!cfg.screenon);
|
||||
}
|
||||
|
||||
uint8_t msgWaiting;
|
||||
char buff[16]; // 16 chars line buffer
|
||||
// if display is switched off we don't refresh it and save time
|
||||
if (!DisplayState)
|
||||
return;
|
||||
|
||||
// update counter (lines 0-1)
|
||||
snprintf(
|
||||
buff, sizeof(buff), "PAX:%-4d",
|
||||
(int)macs.size()); // convert 16-bit MAC counter to decimal counter value
|
||||
u8x8.draw2x2String(0, 0,
|
||||
buff); // display number on unique macs total Wifi + BLE
|
||||
uint8_t msgWaiting;
|
||||
char buff[16]; // 16 chars line buffer
|
||||
|
||||
// update counter (lines 0-1)
|
||||
snprintf(
|
||||
buff, sizeof(buff), "PAX:%-4d",
|
||||
(int)
|
||||
macs.size()); // convert 16-bit MAC counter to decimal counter value
|
||||
u8x8.draw2x2String(0, 0,
|
||||
buff); // display number on unique macs total Wifi + BLE
|
||||
|
||||
// update Battery status (line 2)
|
||||
#ifdef HAS_BATTERY_PROBE
|
||||
u8x8.setCursor(0, 2);
|
||||
u8x8.printf("B:%.1fV", batt_voltage / 1000.0);
|
||||
u8x8.setCursor(0, 2);
|
||||
u8x8.printf("B:%.1fV", batt_voltage / 1000.0);
|
||||
#endif
|
||||
|
||||
// update GPS status (line 2)
|
||||
#ifdef HAS_GPS
|
||||
u8x8.setCursor(9, 2);
|
||||
if (!gps.location.isValid()) // if no fix then display Sats value inverse
|
||||
{
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.printf("Sats:%.2d", gps.satellites.value());
|
||||
u8x8.setInverseFont(0);
|
||||
} else
|
||||
u8x8.printf("Sats:%.2d", gps.satellites.value());
|
||||
u8x8.setCursor(9, 2);
|
||||
if (!gps.location.isValid()) // if no fix then display Sats value inverse
|
||||
{
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.printf("Sats:%.2d", gps.satellites.value());
|
||||
u8x8.setInverseFont(0);
|
||||
} else
|
||||
u8x8.printf("Sats:%.2d", gps.satellites.value());
|
||||
#endif
|
||||
|
||||
// update bluetooth counter + LoRa SF (line 3)
|
||||
// update bluetooth counter + LoRa SF (line 3)
|
||||
#ifdef BLECOUNTER
|
||||
u8x8.setCursor(0, 3);
|
||||
if (cfg.blescan)
|
||||
u8x8.printf("BLTH:%-4d", macs_ble);
|
||||
else
|
||||
u8x8.printf("%s", "BLTH:off");
|
||||
u8x8.setCursor(0, 3);
|
||||
if (cfg.blescan)
|
||||
u8x8.printf("BLTH:%-4d", macs_ble);
|
||||
else
|
||||
u8x8.printf("%s", "BLTH:off");
|
||||
#endif
|
||||
|
||||
#ifdef HAS_LORA
|
||||
u8x8.setCursor(11, 3);
|
||||
u8x8.printf("SF:");
|
||||
if (cfg.adrmode) // if ADR=on then display SF value inverse
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.printf("%c%c", lora_datarate[LMIC.datarate * 2],
|
||||
lora_datarate[LMIC.datarate * 2 + 1]);
|
||||
if (cfg.adrmode) // switch off inverse if it was turned on
|
||||
u8x8.setInverseFont(0);
|
||||
u8x8.setCursor(11, 3);
|
||||
u8x8.printf("SF:");
|
||||
if (cfg.adrmode) // if ADR=on then display SF value inverse
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.printf("%c%c", lora_datarate[LMIC.datarate * 2],
|
||||
lora_datarate[LMIC.datarate * 2 + 1]);
|
||||
if (cfg.adrmode) // switch off inverse if it was turned on
|
||||
u8x8.setInverseFont(0);
|
||||
#endif // HAS_LORA
|
||||
|
||||
// update wifi counter + channel display (line 4)
|
||||
u8x8.setCursor(0, 4);
|
||||
u8x8.printf("WIFI:%-4d", macs_wifi);
|
||||
u8x8.setCursor(11, 4);
|
||||
u8x8.printf("ch:%02d", channel);
|
||||
// update wifi counter + channel display (line 4)
|
||||
u8x8.setCursor(0, 4);
|
||||
u8x8.printf("WIFI:%-4d", macs_wifi);
|
||||
u8x8.setCursor(11, 4);
|
||||
u8x8.printf("ch:%02d", channel);
|
||||
|
||||
// update RSSI limiter status & free memory display (line 5)
|
||||
u8x8.setCursor(0, 5);
|
||||
u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit);
|
||||
u8x8.setCursor(10, 5);
|
||||
u8x8.printf("%4dKB", getFreeRAM() / 1024);
|
||||
// update RSSI limiter status & free memory display (line 5)
|
||||
u8x8.setCursor(0, 5);
|
||||
u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit);
|
||||
u8x8.setCursor(10, 5);
|
||||
u8x8.printf("%4dKB", getFreeRAM() / 1024);
|
||||
|
||||
#ifdef HAS_LORA
|
||||
// update LoRa status display (line 6)
|
||||
u8x8.setCursor(0, 6);
|
||||
u8x8.printf("%-16s", display_line6);
|
||||
// update LoRa status display (line 6)
|
||||
u8x8.setCursor(0, 6);
|
||||
u8x8.printf("%-16s", display_line6);
|
||||
|
||||
// update LMiC event display (line 7)
|
||||
u8x8.setCursor(0, 7);
|
||||
u8x8.printf("%-14s", display_line7);
|
||||
// update LMiC event display (line 7)
|
||||
u8x8.setCursor(0, 7);
|
||||
u8x8.printf("%-14s", display_line7);
|
||||
|
||||
// update LoRa send queue display (line 7)
|
||||
msgWaiting = uxQueueMessagesWaiting(LoraSendQueue);
|
||||
if (msgWaiting) {
|
||||
sprintf(buff, "%2d", msgWaiting);
|
||||
u8x8.setCursor(14, 7);
|
||||
u8x8.printf("%-2s", msgWaiting == SEND_QUEUE_SIZE ? "<>" : buff);
|
||||
} else
|
||||
u8x8.printf(" ");
|
||||
// update LoRa send queue display (line 7)
|
||||
msgWaiting = uxQueueMessagesWaiting(LoraSendQueue);
|
||||
if (msgWaiting) {
|
||||
sprintf(buff, "%2d", msgWaiting);
|
||||
u8x8.setCursor(14, 7);
|
||||
u8x8.printf("%-2s", msgWaiting == SEND_QUEUE_SIZE ? "<>" : buff);
|
||||
} else
|
||||
u8x8.printf(" ");
|
||||
|
||||
#endif // HAS_LORA
|
||||
|
||||
xSemaphoreGive(I2Caccess); // release i2c bus access
|
||||
}
|
||||
|
||||
} // refreshDisplay()
|
||||
|
||||
#endif // HAS_DISPLAY
|
||||
@@ -19,10 +19,10 @@
|
||||
// user defined sensors
|
||||
//#define HAS_SENSORS 1 // comment out if device has user defined sensors
|
||||
|
||||
//#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
//#define MY_OLED_SDA (21)
|
||||
//#define MY_OLED_SCL (22)
|
||||
//#define MY_OLED_RST (NOT_A_PIN)
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define MY_OLED_SDA (21)
|
||||
#define MY_OLED_SCL (22)
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
//#define DISPLAY_FLIP 1 // use if display is rotated
|
||||
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
//#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
//#define MY_OLED_SDA (21)
|
||||
//#define MY_OLED_SCL (22)
|
||||
//#define MY_OLED_RST (NOT_A_PIN)
|
||||
//#define MY_OLED_RST U8X8_PIN_NONE
|
||||
//#define DISPLAY_FLIP 1 // use if display is rotated
|
||||
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
|
||||
+15
-3
@@ -35,11 +35,14 @@ 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 via serial or i2c
|
||||
bmeloop 1 0 reads data from BME sensor via i2c
|
||||
bmeloop 1 1 reads data from BME sensor via i2c
|
||||
IDLE 1 0 ESP32 arduino scheduler
|
||||
|
||||
Low priority numbers denote low priority tasks.
|
||||
|
||||
Tasks using i2c bus all must have same priority, because using mutex semaphore
|
||||
(irqhandler, bmeloop)
|
||||
|
||||
ESP32 hardware timers
|
||||
==========================
|
||||
0 Trigger display refresh
|
||||
@@ -60,6 +63,7 @@ uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0,
|
||||
hw_timer_t *channelSwitch = NULL, *sendCycle = NULL, *homeCycle = NULL,
|
||||
*displaytimer = NULL; // irq tasks
|
||||
TaskHandle_t irqHandlerTask, wifiSwitchTask;
|
||||
SemaphoreHandle_t I2Caccess;
|
||||
|
||||
// container holding unique MAC address hashes with Memory Alloctor using PSRAM,
|
||||
// if present
|
||||
@@ -78,6 +82,14 @@ void setup() {
|
||||
|
||||
char features[100] = "";
|
||||
|
||||
if (I2Caccess == NULL) // Check that semaphore has not already been created
|
||||
{
|
||||
I2Caccess = xSemaphoreCreateMutex(); // Create a mutex semaphore we will use
|
||||
// to manage the i2c bus
|
||||
if ((I2Caccess) != NULL)
|
||||
xSemaphoreGive((I2Caccess)); // Flag the i2c bus available for use
|
||||
}
|
||||
|
||||
// disable brownout detection
|
||||
#ifdef DISABLE_BROWNOUT
|
||||
// register with brownout is at address DR_REG_RTCCNTL_BASE + 0xd4
|
||||
@@ -343,11 +355,11 @@ void setup() {
|
||||
"bmeloop", // name of task
|
||||
4096, // stack size of task
|
||||
(void *)1, // parameter of the task
|
||||
0, // priority of the task
|
||||
//0, // priority of the task
|
||||
1, // priority of the task
|
||||
&BmeTask, // task handle
|
||||
1); // CPU core
|
||||
}
|
||||
delay(2000); // time for initializing i2c sensor
|
||||
#endif
|
||||
|
||||
// start timer triggered interrupts
|
||||
|
||||
Reference in new issue
Block a user