From decb8b71814fb32f0336fa5a033ae844a07c9e65 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 2 Dec 2018 14:08:50 +0100 Subject: [PATCH 01/37] change default to bluetooth disabled --- README.md | 3 +- include/coexist_internal.h | 77 +++++++++++++++++++++++++++++++++++++ include/globals.h | 9 +++-- include/main.h | 3 ++ include/payload.h | 2 +- include/wifiscan.h | 3 -- platformio.ini | 8 ++-- src/TTN/packed_converter.js | 9 ++++- src/TTN/packed_decoder.js | 6 ++- src/TTN/plain_decoder.js | 7 +++- src/blecsan.cpp | 8 +++- src/configmanager.cpp | 2 +- src/main.cpp | 1 + src/paxcounter.conf | 4 +- src/payload.cpp | 43 +++++++++++---------- src/rcommand.cpp | 4 -- src/senddata.cpp | 4 +- src/wifiscan.cpp | 19 ++++++++- 18 files changed, 163 insertions(+), 49 deletions(-) create mode 100644 include/coexist_internal.h diff --git a/README.md b/README.md index 22a73ff0..0cd998ce 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,8 @@ Hardware dependent settings (pinout etc.) are stored in board files in /hal dire 3D printable cases can be found (and, if wanted so, ordered) on Thingiverse, see Heltec, TTGOv2, TTGOv2.1, T-BEAM for example.
-Power consumption was metered at around 450 - 1000mW, depending on board and user settings in paxcounter.conf. If you are limited on battery, you may want to save around 30% power by disabling bluetooth (commenting out line *#define BLECOUNTER* in paxcounter.conf). +Power consumption was metered at around 450 - 1000mW, depending on board and user settings in paxcounter.conf. +By default bluetooth sniffing is disabled (line *#define BLECOUNTER* in paxcounter.conf is commented out). Enabling bluetooth costs 30% more power + 30% flash storage for the software stack. Proof of concept showed that for passenger flow metering purpose wifi sniffing shows better results than bluetooth sniffing. If you enable bluetooth be aware that this goes on expense of wifi sniffing results, because then wifi stack gets less access to RF ressources of ESP32. # Preparing diff --git a/include/coexist_internal.h b/include/coexist_internal.h new file mode 100644 index 00000000..6b4c47cc --- /dev/null +++ b/include/coexist_internal.h @@ -0,0 +1,77 @@ +// Copyright 2018-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __COEXIST_INTERNAL_H__ +#define __COEXIST_INTERNAL_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + COEX_PREFER_WIFI = 0, + COEX_PREFER_BT, + COEX_PREFER_BALANCE, + COEX_PREFER_NUM, +} coex_prefer_t; + +/** + * @brief Init software coexist + * extern function for internal use. + * + * @return Init ok or failed. + */ +esp_err_t coex_init(void); + +/** + * @brief De-init software coexist + * extern function for internal use. + */ +void coex_deinit(void); + +/** + * @brief Pause software coexist + * extern function for internal use. + */ +void coex_pause(void); + +/** + * @brief Resume software coexist + * extern function for internal use. + */ +void coex_resume(void); + +/** + * @brief Get software coexist version string + * extern function for internal use. + * @return : version string + */ +const char *coex_version_get(void); + +/** + * @brief Coexist performance preference set from libbt.a + * extern function for internal use. + * + * @param prefer : the prefer enumeration value + * @return : ESP_OK - success, other - failed + */ +esp_err_t coex_preference_set(coex_prefer_t prefer); + +#ifdef __cplusplus +} +#endif + +#endif /* __COEXIST_INTERNAL_H__ */ \ No newline at end of file diff --git a/include/globals.h b/include/globals.h index fda41d0d..83fa1677 100644 --- a/include/globals.h +++ b/include/globals.h @@ -9,6 +9,10 @@ #include #include +// sniffing types +#define MAC_SNIFF_WIFI 0 +#define MAC_SNIFF_BLE 1 + // bits in payloadmask for filtering payload data #define GPS_DATA (0x01) #define ALARM_DATA (0x02) @@ -93,6 +97,7 @@ extern TaskHandle_t irqHandlerTask, wifiSwitchTask; #include "led.h" #include "payload.h" +#include "blescan.h" #ifdef HAS_GPS #include "gpsread.h" @@ -114,10 +119,6 @@ extern TaskHandle_t irqHandlerTask, wifiSwitchTask; #include "button.h" #endif -#ifdef BLECOUNTER -#include "blescan.h" -#endif - #ifdef HAS_BATTERY_PROBE #include "battery.h" #endif diff --git a/include/main.h b/include/main.h index 6bc1b377..f86e14ef 100644 --- a/include/main.h +++ b/include/main.h @@ -16,4 +16,7 @@ #include "spislave.h" #include "lorawan.h" +#include +#include "coexist_internal.h" + #endif \ No newline at end of file diff --git a/include/payload.h b/include/payload.h index 0ae02705..24b5ece6 100644 --- a/include/payload.h +++ b/include/payload.h @@ -39,7 +39,7 @@ public: void reset(void); uint8_t getSize(void); uint8_t *getBuffer(void); - void addCount(uint16_t value1, uint16_t value2); + void addCount(uint16_t value, uint8_t sniffytpe); void addConfig(configData_t value); void addStatus(uint16_t voltage, uint64_t uptime, float cputemp, uint32_t mem, uint8_t reset1, uint8_t reset2); diff --git a/include/wifiscan.h b/include/wifiscan.h index d5e2f456..0e6962a2 100644 --- a/include/wifiscan.h +++ b/include/wifiscan.h @@ -7,9 +7,6 @@ // Hash function for scrambling MAC addresses #include "hash.h" -#define MAC_SNIFF_WIFI 0 -#define MAC_SNIFF_BLE 1 - void wifi_sniffer_init(void); void IRAM_ATTR wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type); void switchWifiChannel(void * parameter); diff --git a/platformio.ini b/platformio.ini index 0ad2e113..bb202905 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,7 +29,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.6.971 +release_version = 1.6.98 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 0 @@ -38,12 +38,12 @@ upload_protocol = esptool ;upload_protocol = custom extra_scripts = pre:build.py keyfile = ota.conf -platform_espressif32 = espressif32@1.5.0 -;platform_espressif32 = https://github.com/platformio/platform-espressif32.git#a7b1fe6 +;platform_espressif32 = espressif32@1.5.0 +platform_espressif32 = https://github.com/platformio/platform-espressif32.git#feature/stage board_build.partitions = min_spiffs.csv monitor_speed = 115200 lib_deps_lora = - MCCI LoRaWAN LMIC library@2.3.0 + MCCI LoRaWAN LMIC library@2.3.1 lib_deps_display = U8g2@>=2.25.0 lib_deps_rgbled = diff --git a/src/TTN/packed_converter.js b/src/TTN/packed_converter.js index 02f17cf3..8585aa42 100644 --- a/src/TTN/packed_converter.js +++ b/src/TTN/packed_converter.js @@ -4,9 +4,16 @@ function Converter(decoded, port) { var converted = decoded; + var pax = 0; if (port === 1) { - converted.pax = converted.ble + converted.wifi; + + for (var x in converted) { + pax += converted[x]; + } + + converted.pax = pax; + } if (port === 2) { diff --git a/src/TTN/packed_decoder.js b/src/TTN/packed_decoder.js index 938ab1fb..73f0d960 100644 --- a/src/TTN/packed_decoder.js +++ b/src/TTN/packed_decoder.js @@ -6,7 +6,11 @@ function Decoder(bytes, port) { var decoded = {}; if (port === 1) { - // only counter data, no gps + // only wifi counter data, no gps + if (bytes.length === 2) { + return decode(bytes, [uint16], ['wifi']); + } + // wifi + ble counter data, no gps if (bytes.length === 4) { return decode(bytes, [uint16, uint16], ['wifi', 'ble']); } diff --git a/src/TTN/plain_decoder.js b/src/TTN/plain_decoder.js index 17ce3f41..54cf3b78 100644 --- a/src/TTN/plain_decoder.js +++ b/src/TTN/plain_decoder.js @@ -7,8 +7,11 @@ function Decoder(bytes, port) { if (port === 1) { var i = 0; - decoded.wifi = (bytes[i++] << 8) | bytes[i++]; - decoded.ble = (bytes[i++] << 8) | bytes[i++]; + if (bytes.length >= 2) { + decoded.wifi = (bytes[i++] << 8) | bytes[i++];} + + if (bytes.length >= 4) { + decoded.ble = (bytes[i++] << 8) | bytes[i++];} if (bytes.length > 4) { decoded.latitude = ((bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++]); diff --git a/src/blecsan.cpp b/src/blecsan.cpp index 042d5f34..c838cd12 100644 --- a/src/blecsan.cpp +++ b/src/blecsan.cpp @@ -243,7 +243,10 @@ esp_err_t register_ble_callback(void) { } // register_ble_callback +#endif // BLECOUNTER + void start_BLEscan(void) { +#ifdef BLECOUNTER ESP_LOGI(TAG, "Initializing bluetooth scanner ..."); // Initialize BT controller to allocate task and other resource. @@ -255,15 +258,16 @@ void start_BLEscan(void) { ESP_ERROR_CHECK(register_ble_callback()); ESP_LOGI(TAG, "Bluetooth scanner started"); +#endif // BLECOUNTER } // start_BLEscan void stop_BLEscan(void) { +#ifdef BLECOUNTER ESP_LOGI(TAG, "Shutting down bluetooth scanner ..."); ESP_ERROR_CHECK(esp_ble_gap_register_callback(NULL)); ESP_ERROR_CHECK(esp_bluedroid_disable()); ESP_ERROR_CHECK(esp_bluedroid_deinit()); btStop(); // disable & deinit bt_controller ESP_LOGI(TAG, "Bluetooth scanner stopped"); -} // stop_BLEscan - #endif // BLECOUNTER +} // stop_BLEscan diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 7222447f..5c6ebf98 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -25,7 +25,7 @@ void defaultConfig() { cfg.blescantime = BLESCANINTERVAL / 10; // BT channel scan cycle [seconds/100], default 1 (= 10ms) - cfg.blescan = 1; // 0=disabled, 1=enabled + cfg.blescan = 0; // 0=disabled, 1=enabled cfg.wifiant = 0; // 0=internal, 1=external (for LoPy/LoPy4) cfg.vendorfilter = 1; // 0=disabled, 1=enabled cfg.rgblum = RGBLUMINOSITY; // RGB Led luminosity (0..100%) diff --git a/src/main.cpp b/src/main.cpp index 4f28e064..7d5e4968 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -106,6 +106,7 @@ void setup() { (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); ESP_LOGI(TAG, "ESP32 SDK: %s", ESP.getSdkVersion()); + ESP_LOGI(TAG, "Wifi/BT software coexist version: %s", esp_coex_version_get()); ESP_LOGI(TAG, "Free RAM: %d bytes", ESP.getFreeHeap()); #ifdef HAS_GPS diff --git a/src/paxcounter.conf b/src/paxcounter.conf index fbec195f..7496d34d 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -15,7 +15,7 @@ // Set this to include BLE counting and vendor filter functions #define VENDORFILTER 1 // comment out if you want to count things, not people -#define BLECOUNTER 1 // comment out if you don't want BLE count, saves power & memory +//#define BLECOUNTER 1 // activate if you want BLE count, at expense of power & memory // BLE scan parameters #define BLESCANTIME 0 // [seconds] scan duration, 0 means infinite [default], see note below @@ -74,7 +74,7 @@ #define BME_TEMP_OFFSET 5.0f // Offset sensor on chip temp <-> ambient temp [default = 5°C] // OTA settings -//#define USE_OTA 1 // Comment out to disable OTA update +#define USE_OTA 1 // Comment out to disable OTA update #define WIFI_MAX_TRY 5 // maximum number of wifi connect attempts for OTA update [default = 20] #define OTA_MAX_TRY 5 // maximum number of attempts for OTA download and write to flash [default = 3] #define OTA_MIN_BATT 3600 // minimum battery level for OTA [millivolt] diff --git a/src/payload.cpp b/src/payload.cpp index ea68b481..bc950634 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -18,11 +18,9 @@ uint8_t *PayloadConvert::getBuffer(void) { return buffer; } #if PAYLOAD_ENCODER == 1 -void PayloadConvert::addCount(uint16_t value1, uint16_t value2) { - buffer[cursor++] = highByte(value1); - buffer[cursor++] = lowByte(value1); - buffer[cursor++] = highByte(value2); - buffer[cursor++] = lowByte(value2); +void PayloadConvert::addCount(uint16_t value, uint8_t snifftype) { + buffer[cursor++] = highByte(value); + buffer[cursor++] = lowByte(value); } void PayloadConvert::addAlarm(int8_t rssi, uint8_t msg) { @@ -135,10 +133,7 @@ void PayloadConvert::addButton(uint8_t value) { #elif PAYLOAD_ENCODER == 2 -void PayloadConvert::addCount(uint16_t value1, uint16_t value2) { - writeUint16(value1); - writeUint16(value2); -} +void PayloadConvert::addCount(uint16_t value, uint8_t snifftype) { writeUint16(value); } void PayloadConvert::addAlarm(int8_t rssi, uint8_t msg) { writeUint8(rssi); @@ -286,21 +281,27 @@ void PayloadConvert::writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f, #elif (PAYLOAD_ENCODER == 3 || PAYLOAD_ENCODER == 4) -void PayloadConvert::addCount(uint16_t value1, uint16_t value2) { +void PayloadConvert::addCount(uint16_t value, uint8_t snifftype) { + select(snifftype) { + case MAC_SNIFF_WIFI: #if (PAYLOAD_ENCODER == 3) - buffer[cursor++] = LPP_COUNT_WIFI_CHANNEL; + buffer[cursor++] = LPP_COUNT_WIFI_CHANNEL; #endif - buffer[cursor++] = - LPP_LUMINOSITY; // workaround since cayenne has no data type meter - buffer[cursor++] = highByte(value1); - buffer[cursor++] = lowByte(value1); + buffer[cursor++] = + LPP_LUMINOSITY; // workaround since cayenne has no data type meter + buffer[cursor++] = highByte(value); + buffer[cursor++] = lowByte(value); + break; + case MAC_SNIFF_BLE: #if (PAYLOAD_ENCODER == 3) - buffer[cursor++] = LPP_COUNT_BLE_CHANNEL; + buffer[cursor++] = LPP_COUNT_BLE_CHANNEL; #endif - buffer[cursor++] = - LPP_LUMINOSITY; // workaround since cayenne has no data type meter - buffer[cursor++] = highByte(value2); - buffer[cursor++] = lowByte(value2); + buffer[cursor++] = + LPP_LUMINOSITY; // workaround since cayenne has no data type meter + buffer[cursor++] = highByte(value); + buffer[cursor++] = lowByte(value); + break; + } } void PayloadConvert::addAlarm(int8_t rssi, uint8_t msg) { @@ -317,7 +318,7 @@ void PayloadConvert::addAlarm(int8_t rssi, uint8_t msg) { } void PayloadConvert::addVoltage(uint16_t value) { - uint16_t volt = value / 10; + uint16_t volt = value / 10; #if (PAYLOAD_ENCODER == 3) buffer[cursor++] = LPP_BATT_CHANNEL; #endif diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 44ddfd18..9159d9bf 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -79,13 +79,11 @@ void set_blescantime(uint8_t val[]) { cfg.blescantime = val[0]; ESP_LOGI(TAG, "Remote command: set BLE scan time to %.1f seconds", cfg.blescantime / float(100)); -#ifdef BLECOUNTER // stop & restart BLE scan task to apply new parameter if (cfg.blescan) { stop_BLEscan(); start_BLEscan(); } -#endif } void set_countmode(uint8_t val[]) { @@ -193,14 +191,12 @@ void set_loraadr(uint8_t val[]) { void set_blescan(uint8_t val[]) { ESP_LOGI(TAG, "Remote command: set BLE scanner to %s", val[0] ? "on" : "off"); cfg.blescan = val[0] ? 1 : 0; -#ifdef BLECOUNTER if (cfg.blescan) start_BLEscan(); else { macs_ble = 0; // clear BLE counter stop_BLEscan(); } -#endif } void set_wifiant(uint8_t val[]) { diff --git a/src/senddata.cpp b/src/senddata.cpp index 7762222c..9c99769c 100644 --- a/src/senddata.cpp +++ b/src/senddata.cpp @@ -40,7 +40,9 @@ void sendCounter() { case COUNT_DATA: payload.reset(); - payload.addCount(macs_wifi, cfg.blescan ? macs_ble : 0); + payload.addCount(macs_wifi, MAC_SNIFF_WIFI); + if (cfg.blescan) + payload.addCount(macs_ble, MAC_SNIFF_BLE); SendPayload(COUNTERPORT); // clear counter if not in cumulative counter mode if (cfg.countermode != 1) { diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index d6eaeb2d..0cb7e411 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -1,6 +1,8 @@ // Basic Config #include "globals.h" #include "wifiscan.h" +#include +#include "coexist_internal.h" // Local logging tag static const char TAG[] = "wifi"; @@ -9,6 +11,8 @@ static wifi_country_t wifi_country = {WIFI_MY_COUNTRY, WIFI_CHANNEL_MIN, WIFI_CHANNEL_MAX, 100, WIFI_COUNTRY_POLICY_MANUAL}; +esp_coex_prefer_t coexist_config = ESP_COEX_PREFER_BALANCE; + typedef struct { unsigned frame_ctrl : 16; unsigned duration_id : 16; @@ -27,7 +31,7 @@ typedef struct { // using IRAM_:ATTR here to speed up callback function IRAM_ATTR void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type) { - + const wifi_promiscuous_pkt_t *ppkt = (wifi_promiscuous_pkt_t *)buff; const wifi_ieee80211_packet_t *ipkt = (wifi_ieee80211_packet_t *)ppkt->payload; @@ -41,6 +45,12 @@ IRAM_ATTR void wifi_sniffer_packet_handler(void *buff, mac_add((uint8_t *)hdr->addr2, ppkt->rx_ctrl.rssi, MAC_SNIFF_WIFI); } +const char *esp_coex_version_get(void) { return coex_version_get(); } + +esp_err_t esp_coex_preference_set(esp_coex_prefer_t prefer) { + return coex_preference_set((coex_prefer_t)prefer); +} + void wifi_sniffer_init(void) { wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM @@ -49,6 +59,13 @@ void wifi_sniffer_init(void) { // .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // only MGMT frames .filter_mask = WIFI_PROMIS_FILTER_MASK_ALL}; // we use all frames + coex_pause(); + ESP_ERROR_CHECK( + esp_coex_preference_set(coexist_config)); // configure Wifi/BT coexist lib + coex_resume(); + + //coex_deinit(); + ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg ESP_ERROR_CHECK( esp_wifi_set_country(&wifi_country)); // set locales for RF and channels From 47579414ac627c88063261f74d3c91725f7d7d8c Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 2 Dec 2018 14:29:32 +0100 Subject: [PATCH 02/37] code sanitization --- include/coexist_internal.h | 77 -------------------------------------- include/main.h | 3 -- src/main.cpp | 2 +- src/wifiscan.cpp | 17 ++------- 4 files changed, 5 insertions(+), 94 deletions(-) delete mode 100644 include/coexist_internal.h diff --git a/include/coexist_internal.h b/include/coexist_internal.h deleted file mode 100644 index 6b4c47cc..00000000 --- a/include/coexist_internal.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright 2018-2018 Espressif Systems (Shanghai) PTE LTD -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#ifndef __COEXIST_INTERNAL_H__ -#define __COEXIST_INTERNAL_H__ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - COEX_PREFER_WIFI = 0, - COEX_PREFER_BT, - COEX_PREFER_BALANCE, - COEX_PREFER_NUM, -} coex_prefer_t; - -/** - * @brief Init software coexist - * extern function for internal use. - * - * @return Init ok or failed. - */ -esp_err_t coex_init(void); - -/** - * @brief De-init software coexist - * extern function for internal use. - */ -void coex_deinit(void); - -/** - * @brief Pause software coexist - * extern function for internal use. - */ -void coex_pause(void); - -/** - * @brief Resume software coexist - * extern function for internal use. - */ -void coex_resume(void); - -/** - * @brief Get software coexist version string - * extern function for internal use. - * @return : version string - */ -const char *coex_version_get(void); - -/** - * @brief Coexist performance preference set from libbt.a - * extern function for internal use. - * - * @param prefer : the prefer enumeration value - * @return : ESP_OK - success, other - failed - */ -esp_err_t coex_preference_set(coex_prefer_t prefer); - -#ifdef __cplusplus -} -#endif - -#endif /* __COEXIST_INTERNAL_H__ */ \ No newline at end of file diff --git a/include/main.h b/include/main.h index f86e14ef..6bc1b377 100644 --- a/include/main.h +++ b/include/main.h @@ -16,7 +16,4 @@ #include "spislave.h" #include "lorawan.h" -#include -#include "coexist_internal.h" - #endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 7d5e4968..90a99992 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -106,7 +106,7 @@ void setup() { (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); ESP_LOGI(TAG, "ESP32 SDK: %s", ESP.getSdkVersion()); - ESP_LOGI(TAG, "Wifi/BT software coexist version: %s", esp_coex_version_get()); + ESP_LOGI(TAG, "Wifi/BT software coexist version: %s", coex_version_get()); ESP_LOGI(TAG, "Free RAM: %d bytes", ESP.getFreeHeap()); #ifdef HAS_GPS diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index 0cb7e411..14332b49 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -2,7 +2,6 @@ #include "globals.h" #include "wifiscan.h" #include -#include "coexist_internal.h" // Local logging tag static const char TAG[] = "wifi"; @@ -11,7 +10,7 @@ static wifi_country_t wifi_country = {WIFI_MY_COUNTRY, WIFI_CHANNEL_MIN, WIFI_CHANNEL_MAX, 100, WIFI_COUNTRY_POLICY_MANUAL}; -esp_coex_prefer_t coexist_config = ESP_COEX_PREFER_BALANCE; +esp_coex_prefer_t esp_coexist_config = ESP_COEX_PREFER_BALANCE; typedef struct { unsigned frame_ctrl : 16; @@ -45,12 +44,6 @@ IRAM_ATTR void wifi_sniffer_packet_handler(void *buff, mac_add((uint8_t *)hdr->addr2, ppkt->rx_ctrl.rssi, MAC_SNIFF_WIFI); } -const char *esp_coex_version_get(void) { return coex_version_get(); } - -esp_err_t esp_coex_preference_set(esp_coex_prefer_t prefer) { - return coex_preference_set((coex_prefer_t)prefer); -} - void wifi_sniffer_init(void) { wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM @@ -59,12 +52,10 @@ void wifi_sniffer_init(void) { // .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // only MGMT frames .filter_mask = WIFI_PROMIS_FILTER_MASK_ALL}; // we use all frames - coex_pause(); + //coex_pause(); ESP_ERROR_CHECK( - esp_coex_preference_set(coexist_config)); // configure Wifi/BT coexist lib - coex_resume(); - - //coex_deinit(); + esp_coex_preference_set(esp_coexist_config)); // configure Wifi/BT coexist lib + //coex_resume(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg ESP_ERROR_CHECK( From 664d58bb4f39014985752f6e262422b6bfc145c1 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 2 Dec 2018 18:22:57 +0100 Subject: [PATCH 03/37] Bluetooth init ode changes --- src/blecsan.cpp | 7 +++++++ src/main.cpp | 30 ++++++++++++++---------------- src/wifiscan.cpp | 6 +----- 3 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/blecsan.cpp b/src/blecsan.cpp index c838cd12..a708948a 100644 --- a/src/blecsan.cpp +++ b/src/blecsan.cpp @@ -13,6 +13,7 @@ https://github.com/nkolban/esp32-snippets/tree/master/BLE/scanner #include #include #include // needed for BLE_ADDR types, do not remove +#include #define BT_BD_ADDR_HEX(addr) \ addr[0], addr[1], addr[2], addr[3], addr[4], addr[5] @@ -249,6 +250,10 @@ void start_BLEscan(void) { #ifdef BLECOUNTER ESP_LOGI(TAG, "Initializing bluetooth scanner ..."); + ESP_ERROR_CHECK(esp_coex_preference_set( + (esp_coex_prefer_t) + ESP_COEX_PREFER_BALANCE)); // configure Wifi/BT coexist lib + // Initialize BT controller to allocate task and other resource. btStart(); ESP_ERROR_CHECK(esp_bluedroid_init()); @@ -268,6 +273,8 @@ void stop_BLEscan(void) { ESP_ERROR_CHECK(esp_bluedroid_disable()); ESP_ERROR_CHECK(esp_bluedroid_deinit()); btStop(); // disable & deinit bt_controller + ESP_ERROR_CHECK(esp_coex_preference_set(( + esp_coex_prefer_t)ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib ESP_LOGI(TAG, "Bluetooth scanner stopped"); #endif // BLECOUNTER } // stop_BLEscan diff --git a/src/main.cpp b/src/main.cpp index 90a99992..bd5d9b01 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -149,13 +149,6 @@ void setup() { antenna_select(cfg.wifiant); #endif -// switch off bluetooth, if not compiled -#ifdef BLECOUNTER - strcat_P(features, " BLE"); -#else - bool btstop = btStop(); -#endif - // initialize battery status #ifdef HAS_BATTERY_PROBE strcat_P(features, " BATT"); @@ -173,7 +166,20 @@ void setup() { } #endif - // initialize button +// start BLE scan callback if BLE function is enabled in NVRAM configuration +// or switch off bluetooth, if not compiled +#ifdef BLECOUNTER + strcat_P(features, " BLE"); + if (cfg.blescan) { + ESP_LOGI(TAG, "Starting Bluetooth..."); + start_BLEscan(); + } else + btStop(); +#else + btStop(); +#endif + +// initialize button #ifdef HAS_BUTTON strcat_P(features, " BTN_"); #ifdef BUTTON_PULLUP @@ -291,14 +297,6 @@ void setup() { #endif #endif -// start BLE scan callback if BLE function is enabled in NVRAM configuration -#ifdef BLECOUNTER - if (cfg.blescan) { - ESP_LOGI(TAG, "Starting Bluetooth..."); - start_BLEscan(); - } -#endif - // start wifi in monitor mode and start channel rotation task on core 0 ESP_LOGI(TAG, "Starting Wifi..."); wifi_sniffer_init(); diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index 14332b49..80f159c3 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -10,8 +10,6 @@ static wifi_country_t wifi_country = {WIFI_MY_COUNTRY, WIFI_CHANNEL_MIN, WIFI_CHANNEL_MAX, 100, WIFI_COUNTRY_POLICY_MANUAL}; -esp_coex_prefer_t esp_coexist_config = ESP_COEX_PREFER_BALANCE; - typedef struct { unsigned frame_ctrl : 16; unsigned duration_id : 16; @@ -52,10 +50,8 @@ void wifi_sniffer_init(void) { // .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // only MGMT frames .filter_mask = WIFI_PROMIS_FILTER_MASK_ALL}; // we use all frames - //coex_pause(); ESP_ERROR_CHECK( - esp_coex_preference_set(esp_coexist_config)); // configure Wifi/BT coexist lib - //coex_resume(); + esp_coex_preference_set((esp_coex_prefer_t) ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg ESP_ERROR_CHECK( From e733dba9f4a9b0ad3200239f027fd7343689f26c Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 9 Dec 2018 13:48:03 +0100 Subject: [PATCH 04/37] v1.6.991 --- README.md | 2 +- include/coexist_internal.h | 77 ++++++++++++++++++++++++++++++++++++++ include/main.h | 1 + platformio.ini | 9 +++-- src/TTN/packed_decoder.js | 5 +++ src/hal/heltecv2.h | 6 +-- src/lorawan.cpp | 7 ---- src/main.cpp | 2 +- src/paxcounter.conf | 2 +- src/sensor.cpp | 2 + src/spislave.cpp | 3 +- src/wifiscan.cpp | 7 +++- 12 files changed, 102 insertions(+), 21 deletions(-) create mode 100644 include/coexist_internal.h diff --git a/README.md b/README.md index 0cd998ce..87178ece 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Hardware dependent settings (pinout etc.) are stored in board files in /hal dire Heltec, TTGOv2, TTGOv2.1, T-BEAM for example.
Power consumption was metered at around 450 - 1000mW, depending on board and user settings in paxcounter.conf. -By default bluetooth sniffing is disabled (line *#define BLECOUNTER* in paxcounter.conf is commented out). Enabling bluetooth costs 30% more power + 30% flash storage for the software stack. Proof of concept showed that for passenger flow metering purpose wifi sniffing shows better results than bluetooth sniffing. If you enable bluetooth be aware that this goes on expense of wifi sniffing results, because then wifi stack gets less access to RF ressources of ESP32. +By default bluetooth sniffing is disabled (line *#define BLECOUNTER* in paxcounter.conf is commented out). Enabling bluetooth costs 30% more power + 30% flash storage for the software stack. Proof of concept showed that for passenger flow metering wifi sniffing shows better results than bluetooth sniffing. If you enable bluetooth be aware that this goes on expense of wifi sniffing results, because then wifi and bt stack must share the 2,4 GHz RF ressources of ESP32. If you need to sniff wifi and bt in parallel and need best possible results, use two boards - one for wifi only and one for bt only - and add counted results. # Preparing diff --git a/include/coexist_internal.h b/include/coexist_internal.h new file mode 100644 index 00000000..6b4c47cc --- /dev/null +++ b/include/coexist_internal.h @@ -0,0 +1,77 @@ +// Copyright 2018-2018 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef __COEXIST_INTERNAL_H__ +#define __COEXIST_INTERNAL_H__ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum { + COEX_PREFER_WIFI = 0, + COEX_PREFER_BT, + COEX_PREFER_BALANCE, + COEX_PREFER_NUM, +} coex_prefer_t; + +/** + * @brief Init software coexist + * extern function for internal use. + * + * @return Init ok or failed. + */ +esp_err_t coex_init(void); + +/** + * @brief De-init software coexist + * extern function for internal use. + */ +void coex_deinit(void); + +/** + * @brief Pause software coexist + * extern function for internal use. + */ +void coex_pause(void); + +/** + * @brief Resume software coexist + * extern function for internal use. + */ +void coex_resume(void); + +/** + * @brief Get software coexist version string + * extern function for internal use. + * @return : version string + */ +const char *coex_version_get(void); + +/** + * @brief Coexist performance preference set from libbt.a + * extern function for internal use. + * + * @param prefer : the prefer enumeration value + * @return : ESP_OK - success, other - failed + */ +esp_err_t coex_preference_set(coex_prefer_t prefer); + +#ifdef __cplusplus +} +#endif + +#endif /* __COEXIST_INTERNAL_H__ */ \ No newline at end of file diff --git a/include/main.h b/include/main.h index 6bc1b377..af6ff496 100644 --- a/include/main.h +++ b/include/main.h @@ -4,6 +4,7 @@ #include // needed for reading ESP32 chip attributes #include // needed for Wifi event handler #include // needed for timers +#include // needed for showing coex sw version #include "globals.h" #include "wifiscan.h" diff --git a/platformio.ini b/platformio.ini index bb202905..4af315b6 100644 --- a/platformio.ini +++ b/platformio.ini @@ -29,7 +29,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.6.98 +release_version = 1.6.991 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 0 @@ -43,7 +43,7 @@ platform_espressif32 = https://github.com/platformio/platform-espressif32.git#fe board_build.partitions = min_spiffs.csv monitor_speed = 115200 lib_deps_lora = - MCCI LoRaWAN LMIC library@2.3.1 + MCCI LoRaWAN LMIC library@^2.3.1 lib_deps_display = U8g2@>=2.25.0 lib_deps_rgbled = @@ -205,7 +205,8 @@ monitor_speed = ${common.monitor_speed} [env:ttgobeam] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev +;board = esp32dev +board = t-beam board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = @@ -238,7 +239,7 @@ monitor_speed = ${common.monitor_speed} [env:lopy] platform = ${common.platform_espressif32} framework = arduino -board = lopy4 +board = lopy board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = diff --git a/src/TTN/packed_decoder.js b/src/TTN/packed_decoder.js index 73f0d960..331024d1 100644 --- a/src/TTN/packed_decoder.js +++ b/src/TTN/packed_decoder.js @@ -50,6 +50,11 @@ function Decoder(bytes, port) { return decode(bytes, [float, uint16, ufloat, ufloat], ['temperature', 'pressure', 'humidity', 'air']); } + if (port === 8) { + // battery voltage + return decode(bytes, [uint16], ['voltage']); + } + } diff --git a/src/hal/heltecv2.h b/src/hal/heltecv2.h index 36deb4d3..30e47847 100644 --- a/src/hal/heltecv2.h +++ b/src/hal/heltecv2.h @@ -18,9 +18,9 @@ #define HAS_BUTTON (0) // button "PROG" on board // Pins for I2C interface of OLED Display -#define OLED_SDA (4) -#define OLED_SCL (15) -#define OLED_RST (16) +#define MY_OLED_SDA (4) +#define MY_OLED_SCL (15) +#define MY_OLED_RST (16) // Pins for LORA chip SPI interface come from board file, we need some // additional definitions for LMIC diff --git a/src/lorawan.cpp b/src/lorawan.cpp index 9102376c..05cab168 100644 --- a/src/lorawan.cpp +++ b/src/lorawan.cpp @@ -222,13 +222,6 @@ void onEvent(ev_t ev) { : PSTR("TX_COMPLETE")); sprintf(display_line6, " "); // clear previous lmic status - // if (LMIC.dataLen) { - // ESP_LOGI(TAG, "Received %d bytes of payload, RSSI %d SNR %d", - // LMIC.dataLen, (signed char)LMIC.rssi, (signed - // char)LMIC.snr); - // sprintf(display_line6, "RSSI %d SNR %d", (signed char)LMIC.rssi, - // (signed char)LMIC.snr); - if (LMIC.dataLen) { ESP_LOGI(TAG, "Received %d bytes of payload, RSSI -%d SNR %d", LMIC.dataLen, LMIC.rssi, LMIC.snr / 4); diff --git a/src/main.cpp b/src/main.cpp index bd5d9b01..192f7973 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -106,7 +106,7 @@ void setup() { (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); ESP_LOGI(TAG, "ESP32 SDK: %s", ESP.getSdkVersion()); - ESP_LOGI(TAG, "Wifi/BT software coexist version: %s", coex_version_get()); + ESP_LOGI(TAG, "Wifi/BT software coexist version: %s", esp_coex_version_get()); ESP_LOGI(TAG, "Free RAM: %d bytes", ESP.getFreeHeap()); #ifdef HAS_GPS diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 7496d34d..370a5ce3 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -15,7 +15,7 @@ // Set this to include BLE counting and vendor filter functions #define VENDORFILTER 1 // comment out if you want to count things, not people -//#define BLECOUNTER 1 // activate if you want BLE count, at expense of power & memory +#define BLECOUNTER 1 // activate if you want to use BLE count, at expense of memory // BLE scan parameters #define BLESCANTIME 0 // [seconds] scan duration, 0 means infinite [default], see note below diff --git a/src/sensor.cpp b/src/sensor.cpp index 147572d0..0892f4dd 100644 --- a/src/sensor.cpp +++ b/src/sensor.cpp @@ -31,6 +31,8 @@ uint8_t sensor_mask(uint8_t sensor_no) { return (uint8_t)MEMS_DATA; case 7: return (uint8_t)ALARM_DATA; + default: + return 0; } } diff --git a/src/spislave.cpp b/src/spislave.cpp index aefc06a4..5e9ebb1c 100644 --- a/src/spislave.cpp +++ b/src/spislave.cpp @@ -87,8 +87,7 @@ void spi_slave_task(void *param) { // wait until spi master clocks out the data, and read results in rx buffer ESP_LOGI(TAG, "Prepared SPI transaction for %zu byte(s)", transaction_size); ESP_LOG_BUFFER_HEXDUMP(TAG, txbuf, transaction_size, ESP_LOG_DEBUG); - esp_err_t ret = - spi_slave_transmit(HSPI_HOST, &spi_transaction, portMAX_DELAY); + ESP_ERROR_CHECK_WITHOUT_ABORT(spi_slave_transmit(HSPI_HOST, &spi_transaction, portMAX_DELAY)); ESP_LOG_BUFFER_HEXDUMP(TAG, rxbuf, transaction_size, ESP_LOG_DEBUG); ESP_LOGI(TAG, "Transaction finished with size %zu bits", spi_transaction.trans_len); diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index 80f159c3..5a7a77a6 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -2,6 +2,7 @@ #include "globals.h" #include "wifiscan.h" #include +#include "coexist_internal.h" // Local logging tag static const char TAG[] = "wifi"; @@ -50,8 +51,10 @@ void wifi_sniffer_init(void) { // .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // only MGMT frames .filter_mask = WIFI_PROMIS_FILTER_MASK_ALL}; // we use all frames - ESP_ERROR_CHECK( - esp_coex_preference_set((esp_coex_prefer_t) ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib + ESP_ERROR_CHECK(esp_coex_preference_set( + ESP_COEX_PREFER_BALANCE)); // configure Wifi/BT coexist lib + + coex_deinit(); ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg ESP_ERROR_CHECK( From dadab1bd14849e6f4878b14ce59b8f88e2128dff Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 9 Dec 2018 22:11:45 +0100 Subject: [PATCH 05/37] payload.cpp: bugfix cayenne --- src/payload.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/payload.cpp b/src/payload.cpp index bc950634..71534a24 100644 --- a/src/payload.cpp +++ b/src/payload.cpp @@ -282,7 +282,7 @@ void PayloadConvert::writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f, #elif (PAYLOAD_ENCODER == 3 || PAYLOAD_ENCODER == 4) void PayloadConvert::addCount(uint16_t value, uint8_t snifftype) { - select(snifftype) { + switch(snifftype) { case MAC_SNIFF_WIFI: #if (PAYLOAD_ENCODER == 3) buffer[cursor++] = LPP_COUNT_WIFI_CHANNEL; From b4888ecbe9d2893fa96c22ad66858b46eed9ff1e Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Tue, 11 Dec 2018 08:55:02 +0100 Subject: [PATCH 06/37] platformio.ini: fixed path settings --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index 4af315b6..d81a5547 100644 --- a/platformio.ini +++ b/platformio.ini @@ -60,8 +60,8 @@ lib_deps_all = ${common.lib_deps_rgbled} ${common.lib_deps_gps} build_flags_basic = - -include $PROJECTSRC_DIR/hal/${PIOENV}.h - -include $PROJECTSRC_DIR/paxcounter.conf + -include $PROJECT_DIR/src/hal/${PIOENV}.h + -include $PROJECT_DIR/src/paxcounter.conf -w '-DARDUINO_LMIC_PROJECT_CONFIG_H=../../../src/lmic_config.h' '-DCORE_DEBUG_LEVEL=${common.debug_level}' From 74ac3f852511287bf763f31bb1ad967b08e7035a Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Tue, 11 Dec 2018 23:17:57 +0100 Subject: [PATCH 07/37] platformio.ini: include path changed --- platformio.ini | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/platformio.ini b/platformio.ini index d81a5547..34823ec9 100644 --- a/platformio.ini +++ b/platformio.ini @@ -60,8 +60,8 @@ lib_deps_all = ${common.lib_deps_rgbled} ${common.lib_deps_gps} build_flags_basic = - -include $PROJECT_DIR/src/hal/${PIOENV}.h - -include $PROJECT_DIR/src/paxcounter.conf + -include "src/hal/${PIOENV}.h" + -include "src/paxcounter.conf" -w '-DARDUINO_LMIC_PROJECT_CONFIG_H=../../../src/lmic_config.h' '-DCORE_DEBUG_LEVEL=${common.debug_level}' From 9e079fe642e985786fce259418bf68448585bec3 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 16 Dec 2018 15:38:59 +0100 Subject: [PATCH 08/37] packed_decoder.js: errorhandling NULL input --- src/TTN/packed_decoder.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/TTN/packed_decoder.js b/src/TTN/packed_decoder.js index 331024d1..c8f319a2 100644 --- a/src/TTN/packed_decoder.js +++ b/src/TTN/packed_decoder.js @@ -5,6 +5,10 @@ function Decoder(bytes, port) { var decoded = {}; + if (bytes.length === 0) { + return {}; + } + if (port === 1) { // only wifi counter data, no gps if (bytes.length === 2) { From ad33f8fc762768ac887009d6d1e8587cec06b636 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 16 Dec 2018 16:50:37 +0100 Subject: [PATCH 09/37] deinit Bluetooth while device starts if not compiled --- src/blecsan.cpp | 2 +- src/main.cpp | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/blecsan.cpp b/src/blecsan.cpp index a708948a..c4d10865 100644 --- a/src/blecsan.cpp +++ b/src/blecsan.cpp @@ -272,7 +272,7 @@ void stop_BLEscan(void) { ESP_ERROR_CHECK(esp_ble_gap_register_callback(NULL)); ESP_ERROR_CHECK(esp_bluedroid_disable()); ESP_ERROR_CHECK(esp_bluedroid_deinit()); - btStop(); // disable & deinit bt_controller + btStop(); // disable bt_controller ESP_ERROR_CHECK(esp_coex_preference_set(( esp_coex_prefer_t)ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib ESP_LOGI(TAG, "Bluetooth scanner stopped"); diff --git a/src/main.cpp b/src/main.cpp index 192f7973..57ea9fcb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -176,7 +176,14 @@ void setup() { } else btStop(); #else + // remove bluetooth stack to gain more free memory + ESP_ERROR_CHECK(esp_bluedroid_disable()); + ESP_ERROR_CHECK(esp_bluedroid_deinit()); btStop(); + ESP_ERROR_CHECK(esp_bt_controller_deinit()); + ESP_ERROR_CHECK(esp_bt_mem_release(ESP_BT_MODE_BTDM)); + ESP_ERROR_CHECK(esp_coex_preference_set(( + esp_coex_prefer_t)ESP_COEX_PREFER_WIFI)); // configure Wifi/BT coexist lib #endif // initialize button From 39204ef7fc971d597a0c863fc9dcb4a41e5786a2 Mon Sep 17 00:00:00 2001 From: cyberman54 Date: Sun, 16 Dec 2018 23:36:17 +0100 Subject: [PATCH 10/37] Lmic AES changed to MbedTLS hw AES (experimental) --- src/lmic_config.h | 4 +++- src/mbedtls_aes.c | 28 ++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/mbedtls_aes.c diff --git a/src/lmic_config.h b/src/lmic_config.h index 5197f046..33e336aa 100644 --- a/src/lmic_config.h +++ b/src/lmic_config.h @@ -89,10 +89,12 @@ // implementation is optimized for speed on 32-bit processors using // fairly big lookup tables, but it takes up big amounts of flash on the // AVR architecture. -#define USE_ORIGINAL_AES +//#define USE_ORIGINAL_AES // // This selects the AES implementation written by Ideetroon for their // own LoRaWAN library. It also uses lookup tables, but smaller // byte-oriented ones, making it use a lot less flash space (but it is // also about twice as slow as the original). // #define USE_IDEETRON_AES +// +#define USE_MBEDTLS_AES diff --git a/src/mbedtls_aes.c b/src/mbedtls_aes.c new file mode 100644 index 00000000..0a40ed3c --- /dev/null +++ b/src/mbedtls_aes.c @@ -0,0 +1,28 @@ +/******************************************************************************* + * + * ttn-esp32 - The Things Network device library for ESP-IDF / SX127x + * + * Copyright (c) 2018 Manuel Bleichenbacher + * + * Licensed under MIT License + * https://opensource.org/licenses/MIT + * + * AES encryption using ESP32's hardware AES unit. + *******************************************************************************/ + +#include "mbedtls/aes.h" +#include "lmic/oslmic.h" + +#if defined(USE_MBEDTLS_AES) + +void lmic_aes_encrypt(u1_t *data, u1_t *key) +{ + mbedtls_aes_context ctx; + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, key, 128); + mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, data, data); + mbedtls_aes_free(&ctx); +} + + +#endif \ No newline at end of file From 616d66c5fbfa11ee963ba5a19845062abba49273 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 17 Dec 2018 10:30:56 +0100 Subject: [PATCH 11/37] ttgobeam HAL files added --- platformio.ini | 28 +++++++++++++--- src/hal/ttgobeam_new.h | 45 ++++++++++++++++++++++++++ src/hal/{ttgobeam.h => ttgobeam_old.h} | 11 ++++--- 3 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 src/hal/ttgobeam_new.h rename src/hal/{ttgobeam.h => ttgobeam_old.h} (84%) diff --git a/platformio.ini b/platformio.ini index 34823ec9..04daa59d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,7 +15,8 @@ env_default = generic ;env_default = ttgov2 ;env_default = ttgov21old ;env_default = ttgov21new -;env_default = ttgobeam +;env_default = ttgobeam_old +;env_default = ttgobeam_new ;env_default = lopy ;env_default = lopy4 ;env_default = fipy @@ -202,11 +203,11 @@ upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} -[env:ttgobeam] +[env:ttgobeam_old] platform = ${common.platform_espressif32} framework = arduino -;board = esp32dev -board = t-beam +board = esp32dev +;board = t-beam board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = @@ -220,6 +221,25 @@ upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} +[env:ttgobeam_new] +platform = ${common.platform_espressif32} +framework = arduino +board = esp32dev +;board = t-beam +board_build.partitions = ${common.board_build.partitions} +upload_speed = 921600 +lib_deps = + ${common.lib_deps_basic} + ${common.lib_deps_lora} + ${common.lib_deps_gps} +build_flags = + ${common.build_flags_all} + -mfix-esp32-psram-cache-issue +upload_protocol = ${common.upload_protocol} +extra_scripts = ${common.extra_scripts} +monitor_speed = ${common.monitor_speed} + + [env:fipy] platform = ${common.platform_espressif32} framework = arduino diff --git a/src/hal/ttgobeam_new.h b/src/hal/ttgobeam_new.h new file mode 100644 index 00000000..5bbdd620 --- /dev/null +++ b/src/hal/ttgobeam_new.h @@ -0,0 +1,45 @@ +// clang-format off + +#ifndef _TTGOBEAM_H +#define _TTGOBEAM_H + +#include + +// Hardware related definitions for TTGO T-Beam board + +// enable only if device has these sensors, otherwise comment these lines +// BME680 sensor on I2C bus +// attention: Pin21 is also LED! set HAS_LED to NOT_A_PIN if using BME280 +// don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 +//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +//#define HAS_LED NOT_A_PIN // on board green LED + +#define HAS_LED GPIO_NUM_14 // on board green LED + +// user defined sensors +//#define HAS_SENSORS 1 // comment out if device has user defined sensors + +#define HAS_LORA 1 // comment out if device shall not send data via LoRa +#define CFG_sx1276_radio 1 // HPD13A LoRa SoC +#define BOARD_HAS_PSRAM // use extra 4MB external RAM + +//#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature + +#define HAS_BUTTON GPIO_NUM_39 // on board button "BOOT" (next to reset button) + +#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 +#define BATT_FACTOR 2 // voltage divider 100k/100k on board +#define HAS_GPS 1 // use on board GPS +#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration + +// Pins for LORA chip SPI interface, reset line and interrupt lines +#define LORA_SCK (5) +#define LORA_CS (18) +#define LORA_MISO (19) +#define LORA_MOSI (27) +#define LORA_RST LMIC_UNUSED_PIN +#define LORA_IRQ (26) +#define LORA_IO1 (33) // for T-Beam T22_V05 and T22_V07, for other versions use ttgobeam_old.h +#define LORA_IO2 (32) + +#endif \ No newline at end of file diff --git a/src/hal/ttgobeam.h b/src/hal/ttgobeam_old.h similarity index 84% rename from src/hal/ttgobeam.h rename to src/hal/ttgobeam_old.h index 8691c79f..e7d39287 100644 --- a/src/hal/ttgobeam.h +++ b/src/hal/ttgobeam_old.h @@ -11,17 +11,19 @@ // BME680 sensor on I2C bus // attention: Pin21 is also LED! set HAS_LED to NOT_A_PIN if using BME280 // don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 -#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL -#define HAS_LED NOT_A_PIN // on board green LED +//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +//#define HAS_LED NOT_A_PIN // on board green LED + +#define HAS_LED GPIO_NUM_21 // on board green LED // user defined sensors //#define HAS_SENSORS 1 // comment out if device has user defined sensors #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define CFG_sx1276_radio 1 // HPD13A LoRa SoC - #define BOARD_HAS_PSRAM // use extra 4MB external RAM -//#define HAS_LED GPIO_NUM_21 // on board green LED + +//#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature #define HAS_BUTTON GPIO_NUM_39 // on board button "BOOT" (next to reset button) @@ -38,7 +40,6 @@ #define LORA_RST LMIC_UNUSED_PIN #define LORA_IRQ (26) #define LORA_IO1 (32) // !! NEEDS EXTERNAL WIRING !! -//#define LORA_IO1 (33) // for T-Beam T22_V05 and T22_V07, other versions may need external wiring #define LORA_IO2 LMIC_UNUSED_PIN #endif From 82c831e4e4a7d2410e25f1318efbeb51e636307b Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 17 Dec 2018 10:42:34 +0100 Subject: [PATCH 12/37] update ttgobeam_new.h --- src/hal/ttgobeam_new.h | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/hal/ttgobeam_new.h b/src/hal/ttgobeam_new.h index 5bbdd620..93f729a3 100644 --- a/src/hal/ttgobeam_new.h +++ b/src/hal/ttgobeam_new.h @@ -6,13 +6,14 @@ #include // Hardware related definitions for TTGO T-Beam board - +// +// pinouts taken from http://tinymicros.com/wiki/TTGO_T-Beam +// // enable only if device has these sensors, otherwise comment these lines // BME680 sensor on I2C bus -// attention: Pin21 is also LED! set HAS_LED to NOT_A_PIN if using BME280 // don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 +// //#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL -//#define HAS_LED NOT_A_PIN // on board green LED #define HAS_LED GPIO_NUM_14 // on board green LED @@ -25,7 +26,7 @@ //#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature -#define HAS_BUTTON GPIO_NUM_39 // on board button "BOOT" (next to reset button) +#define HAS_BUTTON GPIO_NUM_39 // on board button "SW5" #define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 #define BATT_FACTOR 2 // voltage divider 100k/100k on board @@ -37,7 +38,7 @@ #define LORA_CS (18) #define LORA_MISO (19) #define LORA_MOSI (27) -#define LORA_RST LMIC_UNUSED_PIN +#define LORA_RST (23) #define LORA_IRQ (26) #define LORA_IO1 (33) // for T-Beam T22_V05 and T22_V07, for other versions use ttgobeam_old.h #define LORA_IO2 (32) From ea9f462675ab95ad26ae225045d9d2140895b836 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Tue, 18 Dec 2018 10:43:12 +0100 Subject: [PATCH 13/37] plan_decoder.js: bugfix --- src/TTN/plain_decoder.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/TTN/plain_decoder.js b/src/TTN/plain_decoder.js index 54cf3b78..ec55dc2c 100644 --- a/src/TTN/plain_decoder.js +++ b/src/TTN/plain_decoder.js @@ -33,6 +33,15 @@ function Decoder(bytes, port) { decoded.reset1 = bytes[i++]; } + if (port === 4) { + var i = 0; + decoded.latitude = ((bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++]); + decoded.longitude = ((bytes[i++] << 24) | (bytes[i++] << 16) | (bytes[i++] << 8) | bytes[i++]); + decoded.sats = bytes[i++]; + decoded.hdop = (bytes[i++] << 8) | (bytes[i++]); + decoded.altitude = (bytes[i++] << 8) | (bytes[i++]); + } + if (port === 5) { var i = 0; decoded.button = bytes[i++]; From 48cbcd40cd1b5a51e06d6c60d16d3720f85c2d87 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Wed, 19 Dec 2018 12:32:25 +0100 Subject: [PATCH 14/37] delay function sanitized --- platformio.ini | 2 +- src/bme680mems.cpp | 2 +- src/display.cpp | 6 +++--- src/gpsread.cpp | 4 ++-- src/led.cpp | 2 +- src/main.cpp | 2 +- src/ota.cpp | 6 +++--- src/rcommand.cpp | 2 +- 8 files changed, 13 insertions(+), 13 deletions(-) diff --git a/platformio.ini b/platformio.ini index 04daa59d..2f557886 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,7 +30,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.6.991 +release_version = 1.6.995 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 0 diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index 6203d928..86bb7ac1 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -173,7 +173,7 @@ uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer) { return sizeof(bsec_config_iaq); } -void user_delay_ms(uint32_t period) { vTaskDelay(period / portTICK_PERIOD_MS); } +void user_delay_ms(uint32_t period) { delay(period); } int64_t get_timestamp_us() { return (int64_t)millis() * 1000; } diff --git a/src/display.cpp b/src/display.cpp index ec187da4..ae7120c5 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -43,14 +43,14 @@ void init_display(const char *Productname, const char *Version) { u8x8.draw2x2String(0, 0, Productname); u8x8.setInverseFont(0); u8x8.draw2x2String(2, 2, Productname); - vTaskDelay(1500 / portTICK_PERIOD_MS); + delay(1500); u8x8.clear(); u8x8.setFlipMode(1); u8x8.setInverseFont(1); u8x8.draw2x2String(0, 0, Productname); u8x8.setInverseFont(0); u8x8.draw2x2String(2, 2, Productname); - vTaskDelay(1500 / portTICK_PERIOD_MS); + delay(1500); u8x8.setFlipMode(0); u8x8.clear(); @@ -81,7 +81,7 @@ void init_display(const char *Productname, const char *Version) { DisplayKey(buf, 8, true); #endif // HAS_LORA - vTaskDelay(3000 / portTICK_PERIOD_MS); + delay(3000); u8x8.clear(); u8x8.setPowerSave(!cfg.screenon); // set display off if disabled u8x8.draw2x2String(0, 0, "PAX:0"); diff --git a/src/gpsread.cpp b/src/gpsread.cpp index e804630f..48f5a451 100644 --- a/src/gpsread.cpp +++ b/src/gpsread.cpp @@ -70,12 +70,12 @@ void gps_loop(void *pvParameters) { Wire.requestFrom(GPS_ADDR, 32); // caution: this is a blocking call while (Wire.available()) { gps.encode(Wire.read()); - vTaskDelay(2 / portTICK_PERIOD_MS); // 2ms delay according L76 datasheet + delay(2); // 2ms delay according L76 datasheet } #endif } // if - vTaskDelay(2 / portTICK_PERIOD_MS); // yield to CPU + delay(2); // yield to CPU } // end of infinite loop diff --git a/src/led.cpp b/src/led.cpp index 8a90f9ec..a52315c5 100644 --- a/src/led.cpp +++ b/src/led.cpp @@ -190,7 +190,7 @@ void ledLoop(void *parameter) { previousLEDState = LEDState; } // give yield to CPU - vTaskDelay(2 / portTICK_PERIOD_MS); + delay(2); } // while(1) vTaskDelete(ledLoopTask); // shoud never be reached }; // ledloop() diff --git a/src/main.cpp b/src/main.cpp index 57ea9fcb..42d1c48f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -358,7 +358,7 @@ void loop() { #ifdef HAS_LORA os_runloop_once(); // execute lmic scheduled jobs and events #endif - vTaskDelay(2 / portTICK_PERIOD_MS); // yield to CPU + delay(2); // yield to CPU } vTaskDelete(NULL); // shoud never be reached diff --git a/src/ota.cpp b/src/ota.cpp index bf9f30e2..4210b704 100644 --- a/src/ota.cpp +++ b/src/ota.cpp @@ -77,7 +77,7 @@ void start_ota_update() { while (i--) { ESP_LOGI(TAG, "Trying to connect to %s, attempt %u of %u", WIFI_SSID, WIFI_MAX_TRY - i, WIFI_MAX_TRY); - vTaskDelay(10000 / portTICK_PERIOD_MS); // wait for stable connect + delay(10000); // wait for stable connect if (WiFi.status() == WL_CONNECTED) { // we now have wifi connection and try to do an OTA over wifi update ESP_LOGI(TAG, "Connected to %s", WIFI_SSID); @@ -98,13 +98,13 @@ void start_ota_update() { // wifi did not connect ESP_LOGI(TAG, "Could not connect to %s", WIFI_SSID); display(1, " E", "no WiFi connect"); - vTaskDelay(5000 / portTICK_PERIOD_MS); + delay(5000); end: switch_LED(LED_OFF); ESP_LOGI(TAG, "Rebooting to %s firmware", (ret == 0) ? "new" : "current"); display(5, "**", ""); // mark line rebooting - vTaskDelay(5000 / portTICK_PERIOD_MS); + delay(5000); ESP.restart(); } // start_ota_update diff --git a/src/rcommand.cpp b/src/rcommand.cpp index 9159d9bf..eebd7f30 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -9,7 +9,7 @@ static const char TAG[] = "main"; void do_reset() { ESP_LOGI(TAG, "Remote command: restart device"); LMIC_shutdown(); - vTaskDelay(3000 / portTICK_PERIOD_MS); + delay(3000); esp_restart(); } From 9574a194fd47f15bc14fd1e107ad38a2b934cc8e Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 21 Dec 2018 00:35:21 +0100 Subject: [PATCH 15/37] v1.6.996 --- README.md | 3 ++- include/bme680mems.h | 1 + include/globals.h | 22 +++++++++++----------- platformio.ini | 6 +++--- src/bme680mems.cpp | 4 ++-- src/cyclic.cpp | 16 +++++++++++----- src/display.cpp | 3 +-- src/hal/ttgobeam_new.h | 9 ++++++++- src/irqhandler.cpp | 2 +- src/lmic_config.h | 4 ++-- src/main.cpp | 12 +++++++++--- src/paxcounter.conf | 2 +- src/wifiscan.cpp | 2 -- 13 files changed, 52 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index 87178ece..2214012c 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,8 @@ Target platform must be selected in [platformio.ini](https://github.com/cyberman 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.
3D printable cases can be found (and, if wanted so, ordered) on Thingiverse, see -Heltec, TTGOv2, TTGOv2.1, T-BEAM for example.
+Heltec, TTGOv2, TTGOv2.1, T-BEAM, +T-BEAM parts for example.
Power consumption was metered at around 450 - 1000mW, depending on board and user settings in paxcounter.conf. By default bluetooth sniffing is disabled (line *#define BLECOUNTER* in paxcounter.conf is commented out). Enabling bluetooth costs 30% more power + 30% flash storage for the software stack. Proof of concept showed that for passenger flow metering wifi sniffing shows better results than bluetooth sniffing. If you enable bluetooth be aware that this goes on expense of wifi sniffing results, because then wifi and bt stack must share the 2,4 GHz RF ressources of ESP32. If you need to sniff wifi and bt in parallel and need best possible results, use two boards - one for wifi only and one for bt only - and add counted results. diff --git a/include/bme680mems.h b/include/bme680mems.h index 70dd8fec..ad66c7cb 100644 --- a/include/bme680mems.h +++ b/include/bme680mems.h @@ -4,6 +4,7 @@ #include "globals.h" #include #include "bsec_integration.h" +#include "irqhandler.h" extern const uint8_t bsec_config_iaq[454]; diff --git a/include/globals.h b/include/globals.h index 83fa1677..da547af3 100644 --- a/include/globals.h +++ b/include/globals.h @@ -71,14 +71,14 @@ typedef struct { } gpsStatus_t; typedef struct { -float iaq; // IAQ signal -uint8_t iaq_accuracy; // accuracy of IAQ signal -float temperature; // temperature signal -float humidity; // humidity signal -float pressure; // pressure signal -float raw_temperature; // raw temperature signal -float raw_humidity; // raw humidity signal -float gas; // raw gas sensor signal + float iaq; // IAQ signal + uint8_t iaq_accuracy; // accuracy of IAQ signal + float temperature; // temperature signal + float humidity; // humidity signal + float pressure; // pressure signal + float raw_temperature; // raw temperature signal + float raw_humidity; // raw humidity signal + float gas; // raw gas sensor signal } bmeStatus_t; // global variables @@ -86,9 +86,9 @@ extern configData_t cfg; // current device configuration extern char display_line6[], display_line7[]; // screen buffers extern uint8_t volatile channel; // wifi channel rotation counter extern uint16_t volatile macs_total, macs_wifi, macs_ble, - batt_voltage; // display values -extern std::set macs; // temp storage for MACs -extern hw_timer_t *channelSwitch, *sendCycle; + batt_voltage; // display values +extern std::set macs; // temp storage for MACs +extern hw_timer_t *channelSwitch, *sendCycle, *displaytimer; extern std::array::iterator it; extern std::array beacons; diff --git a/platformio.ini b/platformio.ini index 2f557886..e3423f2e 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,13 +30,13 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.6.995 +release_version = 1.6.996 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 0 ; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA -upload_protocol = esptool -;upload_protocol = custom +;upload_protocol = esptool +upload_protocol = custom extra_scripts = pre:build.py keyfile = ota.conf ;platform_espressif32 = espressif32@1.5.0 diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index 86bb7ac1..468e85da 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -8,7 +8,7 @@ static const char TAG[] = "main"; bmeStatus_t bme_status; TaskHandle_t BmeTask; -float bme_offset = (float) BME_TEMP_OFFSET; +float bme_offset = (float)BME_TEMP_OFFSET; // --- Bosch BSEC library configuration --- // 3,3V supply voltage; 3s max time between sensor_control calls; 4 days @@ -59,7 +59,7 @@ int bme_init(void) { return_values_init ret = bsec_iot_init(BSEC_SAMPLE_RATE_LP, bme_offset, i2c_write, i2c_read, user_delay_ms, state_load, config_load); - + if ((int)ret.bme680_status) { ESP_LOGE(TAG, "Could not initialize BME680, error %d", (int)ret.bme680_status); diff --git a/src/cyclic.cpp b/src/cyclic.cpp index b0bc812d..137ea7f6 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -26,8 +26,8 @@ void doHousekeeping() { // time sync once per TIME_SYNC_INTERVAL #ifdef TIME_SYNC_INTERVAL if (millis() >= nextTimeSync) { - nextTimeSync = millis() + TIME_SYNC_INTERVAL * - 60000; // set up next time sync period + nextTimeSync = + millis() + TIME_SYNC_INTERVAL * 60000; // set up next time sync period do_timesync(); } #endif @@ -62,8 +62,8 @@ void doHousekeeping() { "free heap = %d bytes)", esp_get_minimum_free_heap_size(), ESP.getFreeHeap()); SendPayload(COUNTERPORT); // send data before clearing counters - reset_counters(); // clear macs container and reset all counters - get_salt(); // get new salt for salting hashes + reset_counters(); // clear macs container and reset all counters + get_salt(); // get new salt for salting hashes if (esp_get_minimum_free_heap_size() <= MEM_LOW) // check again do_reset(); // memory leak, reset device @@ -89,7 +89,8 @@ void reset_counters() { void do_timesync() { #ifdef TIME_SYNC_INTERVAL -// sync time & date if we have valid gps time + +// sync time & date by GPS if we have valid gps time #ifdef HAS_GPS if (gps.time.isValid()) { setTime(gps.time.hour(), gps.time.minute(), gps.time.second(), @@ -101,9 +102,14 @@ void do_timesync() { ESP_LOGI(TAG, "No valid GPS time"); } #endif // HAS_GPS + +// sync time by LoRa Network if network supports DevTimeReq +#ifdef LMIC_ENABLE_DeviceTimeReq // Schedule a network time request at the next possible time LMIC_requestNetworkTime(user_request_network_time_callback, &userUTCTime); ESP_LOGI(TAG, "Network time request scheduled"); +#endif + #endif // TIME_SYNC_INTERVAL } // do_timesync() diff --git a/src/display.cpp b/src/display.cpp index ae7120c5..63f56831 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -121,8 +121,7 @@ void refreshtheDisplay() { // update Battery status (line 2) #ifdef HAS_BATTERY_PROBE u8x8.setCursor(0, 2); - u8x8.printf(batt_voltage > 4000 ? "B:USB " : "B:%.1fV", - batt_voltage / 1000.0); + u8x8.printf("B:%.1fV", batt_voltage / 1000.0); #endif // update GPS status (line 2) diff --git a/src/hal/ttgobeam_new.h b/src/hal/ttgobeam_new.h index 93f729a3..45f77d3c 100644 --- a/src/hal/ttgobeam_new.h +++ b/src/hal/ttgobeam_new.h @@ -13,13 +13,20 @@ // BME680 sensor on I2C bus // don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 // -//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL #define HAS_LED GPIO_NUM_14 // on board green LED // user defined sensors //#define HAS_SENSORS 1 // comment out if device has user defined sensors +#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C +// Pins for I2C interface of OLED Display +#define MY_OLED_SDA (21) +#define MY_OLED_SCL (22) +#define MY_OLED_RST (NOT_A_PIN) +//#define DISPLAY_FLIP 1 // use if display is rotated + #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define CFG_sx1276_radio 1 // HPD13A LoRa SoC #define BOARD_HAS_PSRAM // use extra 4MB external RAM diff --git a/src/irqhandler.cpp b/src/irqhandler.cpp index f79e035e..a9192a2b 100644 --- a/src/irqhandler.cpp +++ b/src/irqhandler.cpp @@ -61,7 +61,7 @@ void IRAM_ATTR SendCycleIRQ() { #ifdef HAS_DISPLAY void IRAM_ATTR DisplayIRQ() { - xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits, NULL); + xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits, NULL); portYIELD_FROM_ISR(); } #endif diff --git a/src/lmic_config.h b/src/lmic_config.h index 33e336aa..a28f24a5 100644 --- a/src/lmic_config.h +++ b/src/lmic_config.h @@ -22,7 +22,7 @@ //#define LMIC_USE_INTERRUPTS //time sync via LoRaWAN network, is not yet supported by TTN (LoRaWAN spec v1.0.3) -#define LMIC_ENABLE_DeviceTimeReq 1 +//#define LMIC_ENABLE_DeviceTimeReq 1 // 16 μs per tick // LMIC requires ticks to be 15.5μs - 100 μs long @@ -34,7 +34,7 @@ // faster or slower. This causes the transceiver to be earlier switched on, // so consuming more power. You may sharpen (reduce) this value if you are // limited on battery. -#define CLOCK_ERROR_PROCENTAGE 20 +#define CLOCK_ERROR_PROCENTAGE 3 // Set this to 1 to enable some basic debug output (using printf) about // RF settings used during transmission and reception. Set to 2 to diff --git a/src/main.cpp b/src/main.cpp index 42d1c48f..50eed5a8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,7 +54,7 @@ configData_t cfg; // struct holds current device configuration char display_line6[16], display_line7[16]; // display buffers 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 + batt_voltage = 0; // globals for display hw_timer_t *channelSwitch = NULL, *sendCycle = NULL, *homeCycle = NULL, *displaytimer = NULL; // irq tasks @@ -105,9 +105,15 @@ void setup() { chip_info.revision, spi_flash_get_chip_size() / (1024 * 1024), (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external"); - ESP_LOGI(TAG, "ESP32 SDK: %s", ESP.getSdkVersion()); + ESP_LOGI(TAG, "Internal Total heap %d, internal Free Heap %d", + ESP.getHeapSize(), ESP.getFreeHeap()); + ESP_LOGI(TAG, "SPIRam Total heap %d, SPIRam Free Heap %d", ESP.getPsramSize(), + ESP.getFreePsram()); + ESP_LOGI(TAG, "ChipRevision %d, Cpu Freq %d, SDK Version %s", + ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion()); + ESP_LOGI(TAG, "Flash Size %d, Flash Speed %d", ESP.getFlashChipSize(), + ESP.getFlashChipSpeed()); ESP_LOGI(TAG, "Wifi/BT software coexist version: %s", esp_coex_version_get()); - ESP_LOGI(TAG, "Free RAM: %d bytes", ESP.getFreeHeap()); #ifdef HAS_GPS ESP_LOGI(TAG, "TinyGPS+ v%s", TinyGPSPlus::libraryVersion()); diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 370a5ce3..94cdfd1d 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -81,7 +81,7 @@ #define RESPONSE_TIMEOUT_MS 60000 // firmware binary server connection timeout [milliseconds] // setting for syncing time of node -//#define TIME_SYNC_INTERVAL 60 // sync time each ... minutes [default = 60], comment out means off +#define TIME_SYNC_INTERVAL 60 // sync time each ... minutes [default = 60], comment out means off // LMIC settings // moved to src/lmic_config.h \ No newline at end of file diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index 5a7a77a6..675d511b 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -54,8 +54,6 @@ void wifi_sniffer_init(void) { ESP_ERROR_CHECK(esp_coex_preference_set( ESP_COEX_PREFER_BALANCE)); // configure Wifi/BT coexist lib - coex_deinit(); - ESP_ERROR_CHECK(esp_wifi_init(&cfg)); // configure Wifi with cfg ESP_ERROR_CHECK( esp_wifi_set_country(&wifi_country)); // set locales for RF and channels From 3140ab9214df36586b7c7f3ac97ec1f4d8b2b9a0 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 22 Dec 2018 14:37:47 +0100 Subject: [PATCH 16/37] v1.7.01 (PSRAM support, timesync off) --- include/cyclic.h | 1 + include/display.h | 1 + include/globals.h | 3 ++- include/macsniff.h | 2 +- include/mallocator.h | 54 ++++++++++++++++++++++++++++++++++++++++++ include/rcommand.h | 1 + platformio.ini | 13 ++++++---- src/cyclic.cpp | 30 +++++++++++++++++++---- src/display.cpp | 2 +- src/hal/ttgobeam_new.h | 11 ++++----- src/hal/ttgobeam_old.h | 6 +++++ src/macsniff.cpp | 3 ++- src/main.cpp | 20 ++++++++++++---- src/paxcounter.conf | 2 +- src/rcommand.cpp | 2 +- 15 files changed, 126 insertions(+), 25 deletions(-) create mode 100644 include/mallocator.h diff --git a/include/cyclic.h b/include/cyclic.h index e263a678..1c4da4dd 100644 --- a/include/cyclic.h +++ b/include/cyclic.h @@ -12,5 +12,6 @@ void do_timesync(void); uint64_t uptime(void); void reset_counters(void); int redirect_log(const char *fmt, va_list args); +uint32_t getFreeRAM(); #endif \ No newline at end of file diff --git a/include/display.h b/include/display.h index 492af565..99379b58 100644 --- a/include/display.h +++ b/include/display.h @@ -2,6 +2,7 @@ #define _DISPLAY_H #include +#include "cyclic.h" extern uint8_t volatile DisplayState; extern HAS_DISPLAY u8x8; diff --git a/include/globals.h b/include/globals.h index da547af3..8c429048 100644 --- a/include/globals.h +++ b/include/globals.h @@ -8,6 +8,7 @@ #include #include #include +#include "Mallocator.h" // sniffing types #define MAC_SNIFF_WIFI 0 @@ -87,9 +88,9 @@ extern char display_line6[], display_line7[]; // screen buffers extern uint8_t volatile channel; // wifi channel rotation counter extern uint16_t volatile macs_total, macs_wifi, macs_ble, batt_voltage; // display values -extern std::set macs; // temp storage for MACs extern hw_timer_t *channelSwitch, *sendCycle, *displaytimer; +extern std::set, Mallocator> macs; extern std::array::iterator it; extern std::array beacons; diff --git a/include/macsniff.h b/include/macsniff.h index 81e5a2ed..d41fc787 100644 --- a/include/macsniff.h +++ b/include/macsniff.h @@ -6,8 +6,8 @@ // Hash function for scrambling MAC addresses #include "hash.h" - #include "senddata.h" +#include "cyclic.h" #define MAC_SNIFF_WIFI 0 #define MAC_SNIFF_BLE 1 diff --git a/include/mallocator.h b/include/mallocator.h new file mode 100644 index 00000000..7d32d409 --- /dev/null +++ b/include/mallocator.h @@ -0,0 +1,54 @@ +/* + +This Mallocator code was taken from: + +CppCon2014 Presentations +STL Features And Implementation Techniques +Stephan T. Lavavej + +https://github.com/CppCon/CppCon2014 + +*/ + + +#ifndef _MALLOCATOR_H +#define _MALLOCATOR_H + +#include // size_t, malloc, free +#include // bad_alloc, bad_array_new_length +#include "esp32-hal-psram.h" // ps_malloc + +template struct Mallocator { + typedef T value_type; + Mallocator() noexcept {} // default ctor not required + template Mallocator(const Mallocator &) noexcept {} + template bool operator==(const Mallocator &) const noexcept { + return true; + } + template bool operator!=(const Mallocator &) const noexcept { + return false; + } + + T *allocate(const size_t n) const { + if (n == 0) { + return nullptr; + } + if (n > static_cast(-1) / sizeof(T)) { + throw std::bad_array_new_length(); + } + +#ifndef BOARD_HAS_PSRAM + void *const pv = malloc(n * sizeof(T)); +#else + void *const pv = ps_malloc(n * sizeof(T)); +#endif + + if (!pv) { + throw std::bad_alloc(); + } + return static_cast(pv); + } + void deallocate(T *const p, size_t) const noexcept { free(p); } +}; + +#endif \ No newline at end of file diff --git a/include/rcommand.h b/include/rcommand.h index 806f911a..269caf91 100644 --- a/include/rcommand.h +++ b/include/rcommand.h @@ -7,6 +7,7 @@ #include "lorawan.h" #include "macsniff.h" #include +#include "cyclic.h" // table of remote commands and assigned functions typedef struct { diff --git a/platformio.ini b/platformio.ini index e3423f2e..461cc403 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,13 +30,13 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.6.996 +release_version = 1.7.01 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 0 ; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA -;upload_protocol = esptool -upload_protocol = custom +upload_protocol = esptool +;upload_protocol = custom extra_scripts = pre:build.py keyfile = ota.conf ;platform_espressif32 = espressif32@1.5.0 @@ -207,7 +207,7 @@ monitor_speed = ${common.monitor_speed} platform = ${common.platform_espressif32} framework = arduino board = esp32dev -;board = t-beam +;board = ttgo-t-beam board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = @@ -217,6 +217,7 @@ lib_deps = build_flags = ${common.build_flags_all} -mfix-esp32-psram-cache-issue + -DBOARD_HAS_PSRAM upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} @@ -225,7 +226,7 @@ monitor_speed = ${common.monitor_speed} platform = ${common.platform_espressif32} framework = arduino board = esp32dev -;board = t-beam +;board = ttgo-t-beam board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = @@ -235,6 +236,7 @@ lib_deps = build_flags = ${common.build_flags_all} -mfix-esp32-psram-cache-issue + -DBOARD_HAS_PSRAM upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} @@ -287,6 +289,7 @@ lib_deps = build_flags = ${common.build_flags_basic} -mfix-esp32-psram-cache-issue + -DBOARD_HAS_PSRAM upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 137ea7f6..80e16f1f 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -55,19 +55,33 @@ void doHousekeeping() { ESP_LOGI(TAG, "Measured Voltage: %dmV", batt_voltage); #endif - // check free memory - if (esp_get_minimum_free_heap_size() <= MEM_LOW) { + // check free heap memory + if (ESP.getMinFreeHeap() <= MEM_LOW) { ESP_LOGI(TAG, "Memory full, counter cleared (heap low water mark = %d Bytes / " "free heap = %d bytes)", - esp_get_minimum_free_heap_size(), ESP.getFreeHeap()); + ESP.getMinFreeHeap() , ESP.getFreeHeap()); SendPayload(COUNTERPORT); // send data before clearing counters reset_counters(); // clear macs container and reset all counters get_salt(); // get new salt for salting hashes - if (esp_get_minimum_free_heap_size() <= MEM_LOW) // check again + if (ESP.getMinFreeHeap() <= MEM_LOW) // check again do_reset(); // memory leak, reset device } + +// check free PSRAM memory +#ifdef BOARD_HAS_PSRAM + if (ESP.getMinFreePsram() <= MEM_LOW) { + ESP_LOGI(TAG, "PSRAM full, counter cleared"); + SendPayload(COUNTERPORT); // send data before clearing counters + reset_counters(); // clear macs container and reset all counters + get_salt(); // get new salt for salting hashes + + if (ESP.getMinFreePsram() <= MEM_LOW) // check again + do_reset(); // memory leak, reset device + } +#endif + } // doHousekeeping() // uptime counter 64bit to prevent millis() rollover after 49 days @@ -80,6 +94,14 @@ uint64_t uptime() { return (uint64_t)high32 << 32 | low32; } +uint32_t getFreeRAM() { +#ifndef BOARD_HAS_PSRAM + return ESP.getFreeHeap(); +#else + return ESP.getFreePsram(); +#endif +} + void reset_counters() { macs.clear(); // clear all macs container macs_total = 0; // reset all counters diff --git a/src/display.cpp b/src/display.cpp index 63f56831..ff78ec2b 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -166,7 +166,7 @@ void refreshtheDisplay() { u8x8.setCursor(0, 5); u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit); u8x8.setCursor(10, 5); - u8x8.printf("%4dKB", ESP.getFreeHeap() / 1024); + u8x8.printf("%4dKB", getFreeRAM() / 1024); #ifdef HAS_LORA // update LoRa status display (line 6) diff --git a/src/hal/ttgobeam_new.h b/src/hal/ttgobeam_new.h index 45f77d3c..1a4552a9 100644 --- a/src/hal/ttgobeam_new.h +++ b/src/hal/ttgobeam_new.h @@ -13,18 +13,17 @@ // BME680 sensor on I2C bus // don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 // -#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL #define HAS_LED GPIO_NUM_14 // on board green LED // user defined sensors //#define HAS_SENSORS 1 // comment out if device has user defined sensors -#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C -// Pins for I2C interface of OLED Display -#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 (NOT_A_PIN) //#define DISPLAY_FLIP 1 // use if display is rotated #define HAS_LORA 1 // comment out if device shall not send data via LoRa diff --git a/src/hal/ttgobeam_old.h b/src/hal/ttgobeam_old.h index e7d39287..f8e530fc 100644 --- a/src/hal/ttgobeam_old.h +++ b/src/hal/ttgobeam_old.h @@ -19,6 +19,12 @@ // 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 DISPLAY_FLIP 1 // use if display is rotated + #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define CFG_sx1276_radio 1 // HPD13A LoRa SoC #define BOARD_HAS_PSRAM // use extra 4MB external RAM diff --git a/src/macsniff.cpp b/src/macsniff.cpp index 920ec091..b1e5ffcc 100644 --- a/src/macsniff.cpp +++ b/src/macsniff.cpp @@ -119,7 +119,8 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) { "%d Bytes left", added ? "new " : "known", sniff_type == MAC_SNIFF_WIFI ? "WiFi" : "BLTH", rssi, buff, - hashedmac, macs_wifi, macs_ble, ESP.getFreeHeap()); + hashedmac, macs_wifi, macs_ble, getFreeRAM()); + #ifdef VENDORFILTER } else { // Very noisy diff --git a/src/main.cpp b/src/main.cpp index 50eed5a8..2ba2268e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,13 +54,14 @@ configData_t cfg; // struct holds current device configuration char display_line6[16], display_line7[16]; // display buffers 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 - + batt_voltage = 0; // globals for display 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 +// container holding unique MAC address hashes with Memory Alloctor using PSRAM, +// if present +std::set, Mallocator> macs; // initialize payload encoder PayloadConvert payload(PAYLOAD_BUFFER_SIZE); @@ -107,8 +108,10 @@ void setup() { : "external"); ESP_LOGI(TAG, "Internal Total heap %d, internal Free Heap %d", ESP.getHeapSize(), ESP.getFreeHeap()); +#ifdef BOARD_HAS_PSRAM ESP_LOGI(TAG, "SPIRam Total heap %d, SPIRam Free Heap %d", ESP.getPsramSize(), ESP.getFreePsram()); +#endif ESP_LOGI(TAG, "ChipRevision %d, Cpu Freq %d, SDK Version %s", ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion()); ESP_LOGI(TAG, "Flash Size %d, Flash Speed %d", ESP.getFlashChipSize(), @@ -124,7 +127,16 @@ void setup() { // read (and initialize on first run) runtime settings from NVRAM loadConfig(); // includes initialize if necessary - // initialize leds +#ifdef BOARD_HAS_PSRAM + if (psramFound()) { + ESP_LOGI(TAG, "PSRAM found and initialized"); + strcat_P(features, " PSRAM"); + } else + ESP_LOGI(TAG, "No PSRAM found"); +#else +#endif + + // initialize leds #if (HAS_LED != NOT_A_PIN) pinMode(HAS_LED, OUTPUT); strcat_P(features, " LED"); diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 94cdfd1d..370a5ce3 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -81,7 +81,7 @@ #define RESPONSE_TIMEOUT_MS 60000 // firmware binary server connection timeout [milliseconds] // setting for syncing time of node -#define TIME_SYNC_INTERVAL 60 // sync time each ... minutes [default = 60], comment out means off +//#define TIME_SYNC_INTERVAL 60 // sync time each ... minutes [default = 60], comment out means off // LMIC settings // moved to src/lmic_config.h \ No newline at end of file diff --git a/src/rcommand.cpp b/src/rcommand.cpp index eebd7f30..3b6bccc6 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -245,7 +245,7 @@ void get_status(uint8_t val[]) { #endif payload.reset(); payload.addStatus(voltage, uptime() / 1000, temperatureRead(), - ESP.getFreeHeap(), rtc_get_reset_reason(0), + getFreeRAM(), rtc_get_reset_reason(0), rtc_get_reset_reason(1)); SendPayload(STATUSPORT); }; From 2f51a65b8fec40c3fb83a476071e49733c861945 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 22 Dec 2018 18:01:45 +0100 Subject: [PATCH 17/37] bugfix lopy.h + lopy4.h --- src/hal/lopy.h | 3 +-- src/hal/lopy4.h | 15 ++++++++------- src/main.cpp | 11 ++++------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/src/hal/lopy.h b/src/hal/lopy.h index 5fe522b2..83ba8290 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -14,8 +14,7 @@ // Pins for LORA chip SPI interface come from board file, we need some // additional definitions for LMIC -#define LORA_IO1 (23) // Pin tied via diode to DIO0 -#define LORA_IO2 (23) // Pin tied via diode to DIO0 +#define LORA_IRQ (23) // select WIFI antenna (internal = onboard / external = u.fl socket) #define HAS_ANTENNA_SWITCH (16) // pin for switching wifi antenna diff --git a/src/hal/lopy4.h b/src/hal/lopy4.h index 248fc3bc..e7ef88ba 100644 --- a/src/hal/lopy4.h +++ b/src/hal/lopy4.h @@ -9,12 +9,12 @@ #define HAS_LORA 1 // comment out if device shall not send data via LoRa -#define HAS_SPI 1 // comment out if device shall not send data via SPI +//#defin HAS_SPI 1 // comment out if device shall not send data via SPI // pin definitions for local wired SPI slave interface -#define SPI_MOSI GPIO_NUM_22 -#define SPI_MISO GPIO_NUM_33 -#define SPI_SCLK GPIO_NUM_26 -#define SPI_CS GPIO_NUM_36 +//#define SPI_MOSI GPIO_NUM_22 +//#define SPI_MISO GPIO_NUM_33 +//#define SPI_SCLK GPIO_NUM_26 +//#define SPI_CS GPIO_NUM_36 #define CFG_sx1276_radio 1 //#define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED @@ -23,8 +23,9 @@ // Pins for LORA chip SPI interface come from board file, we need some // additional definitions for LMIC -#define LORA_IO1 (23) // Pin tied via diode to DIO0 -#define LORA_IO2 (23) // Pin tied via diode to DIO0 +#define LORA_IRQ (23) +#define LORA_RST NOT_A_PIN +#define SS 18 // select WIFI antenna (internal = onboard / external = u.fl socket) #define HAS_ANTENNA_SWITCH (21) // pin for switching wifi antenna (P12) diff --git a/src/main.cpp b/src/main.cpp index 2ba2268e..5a0604cc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -128,15 +128,12 @@ void setup() { loadConfig(); // includes initialize if necessary #ifdef BOARD_HAS_PSRAM - if (psramFound()) { - ESP_LOGI(TAG, "PSRAM found and initialized"); - strcat_P(features, " PSRAM"); - } else - ESP_LOGI(TAG, "No PSRAM found"); -#else + assert(psramFound()); + ESP_LOGI(TAG, "PSRAM found and initialized"); + strcat_P(features, " PSRAM"); #endif - // initialize leds + // initialize leds #if (HAS_LED != NOT_A_PIN) pinMode(HAS_LED, OUTPUT); strcat_P(features, " LED"); From 2940561c26a151ea39db04feefd4b25c3e7be258 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 22 Dec 2018 18:18:28 +0100 Subject: [PATCH 18/37] display.cpp: removed inverse display for send queue length --- src/display.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/display.cpp b/src/display.cpp index ff78ec2b..7427562d 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -182,9 +182,7 @@ void refreshtheDisplay() { if (msgWaiting) { sprintf(buff, "%2d", msgWaiting); u8x8.setCursor(14, 7); - u8x8.setInverseFont(1); u8x8.printf("%-2s", msgWaiting == SEND_QUEUE_SIZE ? "<>" : buff); - u8x8.setInverseFont(0); } else u8x8.printf(" "); From b328dd61a046afe5e26c076c07dccc6b8b7eea3e Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sat, 22 Dec 2018 21:40:43 +0100 Subject: [PATCH 19/37] BME680 optimizations --- src/bme680mems.cpp | 20 +++++++------------- src/main.cpp | 8 +++++--- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index 468e85da..08795f31 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -101,34 +101,28 @@ void bme_loop(void *pvParameters) { int8_t i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) { - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - uint16_t i; - + int8_t rslt = 0; Wire.beginTransmission(dev_id); Wire.write(reg_addr); - rslt = Wire.endTransmission(); + rslt = Wire.endTransmission(false); Wire.requestFrom((int)dev_id, (int)len); - for (i = 0; (i < len) && Wire.available(); i++) { + for (uint16_t i = 0; (i < len) && Wire.available(); i++) { reg_data[i] = Wire.read(); } - + // return 0 for success, non-zero for failure return rslt; } int8_t i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, uint16_t len) { - int8_t rslt = 0; /* Return 0 for Success, non-zero for failure */ - uint16_t i; - Wire.beginTransmission(dev_id); Wire.write(reg_addr); - for (i = 0; i < len; i++) { + for (uint16_t i = 0; i < len; i++) { Wire.write(reg_data[i]); } - rslt = Wire.endTransmission(); - - return rslt; + // return 0 for success, non-zero for failure + return Wire.endTransmission(true); } /*! diff --git a/src/main.cpp b/src/main.cpp index 5a0604cc..f6e88b75 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,9 +35,11 @@ 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 2 reads data from BME sensor via i2c +bmeloop 1 0 reads data from BME sensor via i2c IDLE 1 0 ESP32 arduino scheduler +Low priority numbers denote low priority tasks. + ESP32 hardware timers ========================== 0 Trigger display refresh @@ -239,7 +241,7 @@ void setup() { "bmeloop", // name of task 4096, // stack size of task (void *)1, // parameter of the task - 2, // priority of the task + 0, // priority of the task &BmeTask, // task handle 1); // CPU core } @@ -331,7 +333,7 @@ void setup() { ESP_LOGI(TAG, "Starting IRQ Handler..."); xTaskCreatePinnedToCore(irqHandler, // task function "irqhandler", // name of task - 2048, // stack size of task + 4096, // stack size of task (void *)1, // parameter of the task 1, // priority of the task &irqHandlerTask, // task handle From 7f066f338fa16d519ce5d2e021d77a5a961de70a Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Wed, 26 Dec 2018 13:00:32 +0100 Subject: [PATCH 20/37] changed init order of BME loop --- src/main.cpp | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index f6e88b75..37d71674 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -232,21 +232,6 @@ void setup() { } #endif -// initialize bme -#ifdef HAS_BME - strcat_P(features, " BME"); - if (bme_init()) { - ESP_LOGI(TAG, "Starting BMEloop..."); - xTaskCreatePinnedToCore(bme_loop, // task function - "bmeloop", // name of task - 4096, // stack size of task - (void *)1, // parameter of the task - 0, // priority of the task - &BmeTask, // task handle - 1); // CPU core - } -#endif - // initialize sensors #ifdef HAS_SENSORS strcat_P(features, " SENS"); @@ -349,6 +334,22 @@ void setup() { &wifiSwitchTask, // task handle 0); // CPU core + // initialize bme +#ifdef HAS_BME + strcat_P(features, " BME"); + if (bme_init()) { + ESP_LOGI(TAG, "Starting BMEloop..."); + xTaskCreatePinnedToCore(bme_loop, // task function + "bmeloop", // name of task + 4096, // stack size of task + (void *)1, // parameter of the task + 0, // priority of the task + &BmeTask, // task handle + 1); // CPU core + } + delay(2000); // time for initializing i2c sensor +#endif + // start timer triggered interrupts ESP_LOGI(TAG, "Starting Interrupts..."); #ifdef HAS_DISPLAY From 5009ec056399b674fab5251d27cd14ae7e474bbd Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Wed, 26 Dec 2018 23:01:54 +0100 Subject: [PATCH 21/37] initial --- include/bme680mems.h | 56 +++-- lib/Bosch-BSEC/bsec.cpp | 493 ++++++++++++++++++++++++++++++++++++++++ lib/Bosch-BSEC/bsec.h | 230 +++++++++++++++++++ platformio.ini | 8 +- src/bme680mems.cpp | 214 +++++++---------- src/hal/generic.h | 2 +- src/hal/octopus32.h | 4 +- src/hal/ttgobeam_new.h | 7 +- 8 files changed, 848 insertions(+), 166 deletions(-) create mode 100644 lib/Bosch-BSEC/bsec.cpp create mode 100644 lib/Bosch-BSEC/bsec.h diff --git a/include/bme680mems.h b/include/bme680mems.h index ad66c7cb..5ac87588 100644 --- a/include/bme680mems.h +++ b/include/bme680mems.h @@ -3,30 +3,52 @@ #include "globals.h" #include -#include "bsec_integration.h" #include "irqhandler.h" - -extern const uint8_t bsec_config_iaq[454]; +#include "bsec.h" extern bmeStatus_t bme_status; // Make struct for storing gps data globally available extern TaskHandle_t BmeTask; +// --- Bosch BSEC library configuration --- +// 3,3V supply voltage; 3s max time between sensor_control calls; 4 days +// calibration. Change this const if not applicable for your application (see +// BME680 datasheet) +const uint8_t bsec_config_iaq[454] = { + 1, 7, 4, 1, 61, 0, 0, 0, 0, 0, 0, 0, 174, 1, 0, + 0, 48, 0, 1, 0, 137, 65, 0, 63, 205, 204, 204, 62, 0, 0, + 64, 63, 205, 204, 204, 62, 0, 0, 225, 68, 0, 192, 168, 71, 64, + 49, 119, 76, 0, 0, 0, 0, 0, 80, 5, 95, 0, 0, 0, 0, + 0, 0, 0, 0, 28, 0, 2, 0, 0, 244, 1, 225, 0, 25, 0, + 0, 128, 64, 0, 0, 32, 65, 144, 1, 0, 0, 112, 65, 0, 0, + 0, 63, 16, 0, 3, 0, 10, 215, 163, 60, 10, 215, 35, 59, 10, + 215, 35, 59, 9, 0, 5, 0, 0, 0, 0, 0, 1, 88, 0, 9, + 0, 229, 208, 34, 62, 0, 0, 0, 0, 0, 0, 0, 0, 218, 27, + 156, 62, 225, 11, 67, 64, 0, 0, 160, 64, 0, 0, 0, 0, 0, + 0, 0, 0, 94, 75, 72, 189, 93, 254, 159, 64, 66, 62, 160, 191, + 0, 0, 0, 0, 0, 0, 0, 0, 33, 31, 180, 190, 138, 176, 97, + 64, 65, 241, 99, 190, 0, 0, 0, 0, 0, 0, 0, 0, 167, 121, + 71, 61, 165, 189, 41, 192, 184, 30, 189, 64, 12, 0, 10, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 229, 0, 254, 0, 2, 1, 5, 48, + 117, 100, 0, 44, 1, 112, 23, 151, 7, 132, 3, 197, 0, 92, 4, + 144, 1, 64, 1, 64, 1, 144, 1, 48, 117, 48, 117, 48, 117, 48, + 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 48, 117, 100, 0, + 100, 0, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 100, 0, 48, + 117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, + 100, 0, 100, 0, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, + 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, + 44, 1, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, + 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, + 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, + 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 255, 255, + 255, 255, 255, 255, 255, 255, 220, 5, 220, 5, 220, 5, 255, 255, 255, + 255, 255, 255, 220, 5, 220, 5, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 44, 1, 0, 0, 0, 0, + 239, 79, 0, 0}; + int bme_init(); void bme_loop(void *pvParameters); -int8_t i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, - uint16_t len); -int8_t i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, - uint16_t len); -void output_ready(int64_t timestamp, float iaq, uint8_t iaq_accuracy, - float temperature, float humidity, float pressure, - float raw_temperature, float raw_humidity, float gas, - bsec_library_return_t bsec_status, float static_iaq, - float co2_equivalent, float breath_voc_equivalent); -uint32_t state_load(uint8_t *state_buffer, uint32_t n_buffer); -void state_save(const uint8_t *state_buffer, uint32_t length); -uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer); -void user_delay_ms(uint32_t period); -int64_t get_timestamp_us(); +int checkIaqSensorStatus(void); #endif \ No newline at end of file diff --git a/lib/Bosch-BSEC/bsec.cpp b/lib/Bosch-BSEC/bsec.cpp new file mode 100644 index 00000000..d9ac1868 --- /dev/null +++ b/lib/Bosch-BSEC/bsec.cpp @@ -0,0 +1,493 @@ +/** + * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of the + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * @file bsec.cpp + * @date 31 Jan 2018 + * @version 1.0 + * + */ + +#include "bsec.h" + +TwoWire* Bsec::wireObj = NULL; +SPIClass* Bsec::spiObj = NULL; + +/** + * @brief Constructor + */ +Bsec::Bsec() +{ + nextCall = 0; + version.major = 0; + version.minor = 0; + version.major_bugfix = 0; + version.minor_bugfix = 0; + millisOverflowCounter = 0; + lastTime = 0; + bme680Status = BME680_OK; + outputTimestamp = 0; + _tempOffset = 0.0f; + status = BSEC_OK; + zeroOutputs(); +} + +/** + * @brief Function to initialize the BSEC library and the BME680 sensor + */ +void Bsec::begin(uint8_t devId, enum bme680_intf intf, bme680_com_fptr_t read, bme680_com_fptr_t write, bme680_delay_fptr_t idleTask) +{ + _bme680.dev_id = devId; + _bme680.intf = intf; + _bme680.read = read; + _bme680.write = write; + _bme680.delay_ms = idleTask; + _bme680.amb_temp = 25; + _bme680.power_mode = BME680_FORCED_MODE; + + beginCommon(); +} + +/** + * @brief Function to initialize the BSEC library and the BME680 sensor + */ +void Bsec::begin(uint8_t i2cAddr, TwoWire &i2c) +{ + _bme680.dev_id = i2cAddr; + _bme680.intf = BME680_I2C_INTF; + _bme680.read = Bsec::i2cRead; + _bme680.write = Bsec::i2cWrite; + _bme680.delay_ms = Bsec::delay_ms; + _bme680.amb_temp = 25; + _bme680.power_mode = BME680_FORCED_MODE; + + Bsec::wireObj = &i2c; + Bsec::wireObj->begin(); + + beginCommon(); +} + +/** + * @brief Function to initialize the BSEC library and the BME680 sensor + */ +void Bsec::begin(uint8_t chipSelect, SPIClass &spi) +{ + _bme680.dev_id = chipSelect; + _bme680.intf = BME680_SPI_INTF; + _bme680.read = Bsec::spiTransfer; + _bme680.write = Bsec::spiTransfer; + _bme680.delay_ms = Bsec::delay_ms; + _bme680.amb_temp = 25; + _bme680.power_mode = BME680_FORCED_MODE; + + pinMode(chipSelect, OUTPUT); + digitalWrite(chipSelect, HIGH); + Bsec::spiObj = &spi; + Bsec::spiObj->begin(); + + beginCommon(); +} + +/** + * @brief Common code for the begin function + */ +void Bsec::beginCommon(void) +{ + status = bsec_init(); + + getVersion(); + + bme680Status = bme680_init(&_bme680); +} + +/** + * @brief Function that sets the desired sensors and the sample rates + */ +void Bsec::updateSubscription(bsec_virtual_sensor_t sensorList[], uint8_t nSensors, float sampleRate) +{ + bsec_sensor_configuration_t virtualSensors[BSEC_NUMBER_OUTPUTS], + sensorSettings[BSEC_MAX_PHYSICAL_SENSOR]; + uint8_t nVirtualSensors = 0, nSensorSettings = BSEC_MAX_PHYSICAL_SENSOR; + + for (uint8_t i = 0; i < nSensors; i++) { + virtualSensors[nVirtualSensors].sensor_id = sensorList[i]; + virtualSensors[nVirtualSensors].sample_rate = sampleRate; + nVirtualSensors++; + } + + status = bsec_update_subscription(virtualSensors, nVirtualSensors, sensorSettings, &nSensorSettings); + return; +} + +/** + * @brief Callback from the user to trigger reading of data from the BME680, process and store outputs + */ +bool Bsec::run(void) +{ + bool newData = false; + /* Check if the time has arrived to call do_steps() */ + int64_t callTimeMs = getTimeMs(); + + if (callTimeMs >= nextCall) { + + bsec_bme_settings_t bme680Settings; + + int64_t callTimeNs = callTimeMs * INT64_C(1000000); + + status = bsec_sensor_control(callTimeNs, &bme680Settings); + if (status < BSEC_OK) + return false; + + nextCall = bme680Settings.next_call / INT64_C(1000000); // Convert from ns to ms + + bme680Status = setBme680Config(bme680Settings); + if (bme680Status != BME680_OK) { + return false; + } + + bme680Status = bme680_set_sensor_mode(&_bme680); + if (bme680Status != BME680_OK) { + return false; + } + + /* Wait for measurement to complete */ + uint16_t meas_dur = 0; + + bme680_get_profile_dur(&meas_dur, &_bme680); + delay_ms(meas_dur); + + newData = readProcessData(callTimeNs, bme680Settings); + } + + return newData; +} + +/** + * @brief Function to get the state of the algorithm to save to non-volatile memory + */ +void Bsec::getState(uint8_t *state) +{ + uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE]; + uint32_t n_serialized_state = BSEC_MAX_STATE_BLOB_SIZE; + status = bsec_get_state(0, state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, BSEC_MAX_STATE_BLOB_SIZE, &n_serialized_state); +} + +/** + * @brief Function to set the state of the algorithm from non-volatile memory + */ +void Bsec::setState(uint8_t *state) +{ + uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE]; + + status = bsec_set_state(state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, BSEC_MAX_STATE_BLOB_SIZE); +} + +/** + * @brief Function to set the configuration of the algorithm from memory + */ +void Bsec::setConfig(const uint8_t *state) +{ + uint8_t workBuffer[BSEC_MAX_PROPERTY_BLOB_SIZE]; + + status = bsec_set_configuration(state, BSEC_MAX_PROPERTY_BLOB_SIZE, workBuffer, sizeof(workBuffer)); +} + +/* Private functions */ + +/** + * @brief Get the version of the BSEC library + */ +void Bsec::getVersion(void) +{ + bsec_get_version(&version); +} + +/** + * @brief Read data from the BME680 and process it + */ +bool Bsec::readProcessData(int64_t currTimeNs, bsec_bme_settings_t bme680Settings) +{ + bme680Status = bme680_get_sensor_data(&_data, &_bme680); + if (bme680Status != BME680_OK) { + return false; + } + + bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temp, Pres, Hum & Gas + uint8_t nInputs = 0, nOutputs = 0; + + if (_data.status & BME680_NEW_DATA_MSK) { + if (bme680Settings.process_data & BSEC_PROCESS_TEMPERATURE) { + inputs[nInputs].sensor_id = BSEC_INPUT_TEMPERATURE; + inputs[nInputs].signal = _data.temperature; + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + /* Temperature offset from the real temperature due to external heat sources */ + inputs[nInputs].sensor_id = BSEC_INPUT_HEATSOURCE; + inputs[nInputs].signal = _tempOffset; + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + if (bme680Settings.process_data & BSEC_PROCESS_HUMIDITY) { + inputs[nInputs].sensor_id = BSEC_INPUT_HUMIDITY; + inputs[nInputs].signal = _data.humidity; + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + if (bme680Settings.process_data & BSEC_PROCESS_PRESSURE) { + inputs[nInputs].sensor_id = BSEC_INPUT_PRESSURE; + inputs[nInputs].signal = _data.pressure; + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + if (bme680Settings.process_data & BSEC_PROCESS_GAS) { + inputs[nInputs].sensor_id = BSEC_INPUT_GASRESISTOR; + inputs[nInputs].signal = _data.gas_resistance; + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + } + + if (nInputs > 0) { + nOutputs = BSEC_NUMBER_OUTPUTS; + bsec_output_t _outputs[BSEC_NUMBER_OUTPUTS]; + + status = bsec_do_steps(inputs, nInputs, _outputs, &nOutputs); + if (status != BSEC_OK) + return false; + + zeroOutputs(); + + if (nOutputs > 0) { + outputTimestamp = _outputs[0].time_stamp / 1000000; // Convert from ns to ms + + for (uint8_t i = 0; i < nOutputs; i++) { + switch (_outputs[i].sensor_id) { + case BSEC_OUTPUT_IAQ: + iaqEstimate = _outputs[i].signal; + iaqAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_STATIC_IAQ: + staticIaq = _outputs[i].signal; + staticIaqAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_CO2_EQUIVALENT: + co2Equivalent = _outputs[i].signal; + co2Accuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT: + breathVocEquivalent = _outputs[i].signal; + breathVocAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_RAW_TEMPERATURE: + rawTemperature = _outputs[i].signal; + break; + case BSEC_OUTPUT_RAW_PRESSURE: + pressure = _outputs[i].signal; + break; + case BSEC_OUTPUT_RAW_HUMIDITY: + rawHumidity = _outputs[i].signal; + break; + case BSEC_OUTPUT_RAW_GAS: + gasResistance = _outputs[i].signal; + break; + case BSEC_OUTPUT_STABILIZATION_STATUS: + stabStatus = _outputs[i].signal; + break; + case BSEC_OUTPUT_RUN_IN_STATUS: + runInStatus = _outputs[i].signal; + break; + case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE: + temperature = _outputs[i].signal; + break; + case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY: + humidity = _outputs[i].signal; + break; + case BSEC_OUTPUT_COMPENSATED_GAS: + compGasValue = _outputs[i].signal; + compGasAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_GAS_PERCENTAGE: + gasPercentage = _outputs[i].signal; + gasPercentageAcccuracy = _outputs[i].accuracy; + break; + default: + break; + } + } + return true; + } + } + + return false; +} + +/** + * @brief Set the BME680 sensor's configuration + */ +int8_t Bsec::setBme680Config(bsec_bme_settings_t bme680Settings) +{ + _bme680.gas_sett.run_gas = bme680Settings.run_gas; + _bme680.tph_sett.os_hum = bme680Settings.humidity_oversampling; + _bme680.tph_sett.os_temp = bme680Settings.temperature_oversampling; + _bme680.tph_sett.os_pres = bme680Settings.pressure_oversampling; + _bme680.gas_sett.heatr_temp = bme680Settings.heater_temperature; + _bme680.gas_sett.heatr_dur = bme680Settings.heating_duration; + uint16_t desired_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL + | BME680_GAS_SENSOR_SEL; + return bme680_set_sensor_settings(desired_settings, &_bme680); +} + +/** + * @brief Function to zero the outputs + */ +void Bsec::zeroOutputs(void) +{ + temperature = 0.0f; + pressure = 0.0f; + humidity = 0.0f; + gasResistance = 0.0f; + rawTemperature = 0.0f; + rawHumidity = 0.0f; + stabStatus = 0.0f; + runInStatus = 0.0f; + iaqEstimate = 0.0f; + iaqAccuracy = 0; + staticIaq = 0.0f; + staticIaqAccuracy = 0; + co2Equivalent = 0.0f; + co2Accuracy = 0; + breathVocEquivalent = 0.0f; + breathVocAccuracy = 0; + compGasValue = 0.0f; + compGasAccuracy = 0; + gasPercentage = 0.0f; + gasPercentageAcccuracy = 0; +} + +/** + * @brief Function to calculate an int64_t timestamp in milliseconds + */ +int64_t Bsec::getTimeMs(void) +{ + int64_t timeMs = millis(); + + if (lastTime > timeMs) { // An overflow occured + lastTime = timeMs; + millisOverflowCounter++; + } + + return timeMs + (millisOverflowCounter * 0xFFFFFFFF); +} + +/** + @brief Task that delays for a ms period of time + */ +void Bsec::delay_ms(uint32_t period) +{ + // Wait for a period amount of ms + // The system may simply idle, sleep or even perform background tasks + delay(period); +} + +/** + @brief Callback function for reading registers over I2C + */ +int8_t Bsec::i2cRead(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length) +{ + uint16_t i; + int8_t rslt = 0; + if(Bsec::wireObj) { + Bsec::wireObj->beginTransmission(devId); + Bsec::wireObj->write(regAddr); + rslt = Bsec::wireObj->endTransmission(); + Bsec::wireObj->requestFrom((int) devId, (int) length); + for (i = 0; (i < length) && Bsec::wireObj->available(); i++) { + regData[i] = Bsec::wireObj->read(); + } + } else { + rslt = -1; + } + return rslt; +} + +/** + * @brief Callback function for writing registers over I2C + */ +int8_t Bsec::i2cWrite(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length) +{ + uint16_t i; + int8_t rslt = 0; + if(Bsec::wireObj) { + Bsec::wireObj->beginTransmission(devId); + Bsec::wireObj->write(regAddr); + for (i = 0; i < length; i++) { + Bsec::wireObj->write(regData[i]); + } + rslt = Bsec::wireObj->endTransmission(); + } else { + rslt = -1; + } + + return rslt; +} + +/** + * @brief Callback function for reading and writing registers over SPI + */ +int8_t Bsec::spiTransfer(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length) +{ + int8_t rslt = 0; + if(Bsec::spiObj) { + Bsec::spiObj->beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); // Can be upto 10MHz + + digitalWrite(devId, LOW); + + Bsec::spiObj->transfer(regAddr); // Write the register address, ignore the return + for (uint16_t i = 0; i < length; i++) + regData[i] = Bsec::spiObj->transfer(regData[i]); + + digitalWrite(devId, HIGH); + Bsec::spiObj->endTransaction(); + } else { + rslt = -1; + } + + return rslt;; +} \ No newline at end of file diff --git a/lib/Bosch-BSEC/bsec.h b/lib/Bosch-BSEC/bsec.h new file mode 100644 index 00000000..3c881c6b --- /dev/null +++ b/lib/Bosch-BSEC/bsec.h @@ -0,0 +1,230 @@ +/** + * Copyright (C) 2017 - 2018 Bosch Sensortec GmbH + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * Neither the name of the copyright holder nor the names of the + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER + * OR CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE + * + * The information provided is believed to be accurate and reliable. + * The copyright holder assumes no responsibility + * for the consequences of use + * of such information nor for any infringement of patents or + * other rights of third parties which may result from its use. + * No license is granted by implication or otherwise under any patent or + * patent rights of the copyright holder. + * + * @file bsec.h + * @date 31 Jan 2018 + * @version 1.0 + * + */ + +#ifndef BSEC_CLASS_H +#define BSEC_CLASS_H + +/* Includes */ +#include "Arduino.h" +#include "Wire.h" +#include "SPI.h" +#include "bsec_datatypes.h" +#include "bsec_interface.h" +#include "bme680.h" + +/* BSEC class definition */ +class Bsec +{ +public: + /* Public variables */ + bsec_version_t version; // Stores the version of the BSEC algorithm + int64_t nextCall; // Stores the time when the algorithm has to be called next in ms + int8_t bme680Status; // Placeholder for the BME680 driver's error codes + bsec_library_return_t status; + float iaqEstimate, rawTemperature, pressure, rawHumidity, gasResistance, stabStatus, runInStatus, temperature, humidity, + staticIaq, co2Equivalent, breathVocEquivalent, compGasValue, gasPercentage; + uint8_t iaqAccuracy, staticIaqAccuracy, co2Accuracy, breathVocAccuracy, compGasAccuracy, gasPercentageAcccuracy; + int64_t outputTimestamp; // Timestamp in ms of the output + static TwoWire *wireObj; + static SPIClass *spiObj; + + /* Public APIs */ + /** + * @brief Constructor + */ + Bsec(); + + /** + * @brief Function to initialize the BSEC library and the BME680 sensor + * @param devId : Device identifier parameter for the read/write interface functions + * @param intf : Physical communication interface + * @param read : Pointer to the read function + * @param write : Pointer to the write function + * @param idleTask : Pointer to the idling task + */ + void begin(uint8_t devId, enum bme680_intf intf, bme680_com_fptr_t read, bme680_com_fptr_t write, bme680_delay_fptr_t idleTask); + + /** + * @brief Function to initialize the BSEC library and the BME680 sensor + * @param i2cAddr : I2C address + * @param i2c : Pointer to the TwoWire object + */ + void begin(uint8_t i2cAddr, TwoWire &i2c); + + /** + * @brief Function to initialize the BSEC library and the BME680 sensor + * @param chipSelect : SPI chip select + * @param spi : Pointer to the SPIClass object + */ + void begin(uint8_t chipSelect, SPIClass &spi); + + /** + * @brief Function that sets the desired sensors and the sample rates + * @param sensorList : The list of output sensors + * @param nSensors : Number of outputs requested + * @param sampleRate : The sample rate of requested sensors + */ + void updateSubscription(bsec_virtual_sensor_t sensorList[], uint8_t nSensors, float sampleRate = BSEC_SAMPLE_RATE_ULP); + + /** + * @brief Callback from the user to trigger reading of data from the BME680, process and store outputs + * @return true if there are new outputs. false otherwise + */ + bool run(void); + + /** + * @brief Function to get the state of the algorithm to save to non-volatile memory + * @param state : Pointer to a memory location that contains the state + */ + void getState(uint8_t *state); + + /** + * @brief Function to set the state of the algorithm from non-volatile memory + * @param state : Pointer to a memory location that contains the state + */ + void setState(uint8_t *state); + + /** + * @brief Function to set the configuration of the algorithm from memory + * @param state : Pointer to a memory location that contains the configuration + */ + void setConfig(const uint8_t *config); + + /** + * @brief Function to set the temperature offset + * @param tempOffset : Temperature offset in degree Celsius + */ + void setTemperatureOffset(float tempOffset) + { + _tempOffset = tempOffset; + } + + + /** + * @brief Function to calculate an int64_t timestamp in milliseconds + */ + int64_t getTimeMs(void); + + /** + * @brief Task that delays for a ms period of time + * @param period : Period of time in ms + */ + static void delay_ms(uint32_t period); + + /** + * @brief Callback function for reading registers over I2C + * @param devId : Library agnostic parameter to identify the device to communicate with + * @param regAddr : Register address + * @param regData : Pointer to the array containing the data to be read + * @param length : Length of the array of data + * @return Zero for success, non-zero otherwise + */ + static int8_t i2cRead(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length); + + /** + * @brief Callback function for writing registers over I2C + * @param devId : Library agnostic parameter to identify the device to communicate with + * @param regAddr : Register address + * @param regData : Pointer to the array containing the data to be written + * @param length : Length of the array of data + * @return Zero for success, non-zero otherwise + */ + static int8_t i2cWrite(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length); + + /** + * @brief Callback function for reading and writing registers over SPI + * @param devId : Library agnostic parameter to identify the device to communicate with + * @param regAddr : Register address + * @param regData : Pointer to the array containing the data to be read or written + * @param length : Length of the array of data + * @return Zero for success, non-zero otherwise + */ + static int8_t spiTransfer(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length); + +private: + /* Private variables */ + struct bme680_dev _bme680; + struct bme680_field_data _data; + float _tempOffset; + // Global variables to help create a millisecond timestamp that doesn't overflow every 51 days. + // If it overflows, it will have a negative value. Something that should never happen. + uint32_t millisOverflowCounter; + uint32_t lastTime; + + /* Private APIs */ + /** + * @brief Get the version of the BSEC library + */ + void getVersion(void); + + /** + * @brief Read data from the BME680 and process it + * @param currTimeNs: Current time in ns + * @param bme680Settings: BME680 sensor's settings + * @return true if there are new outputs. false otherwise + */ + bool readProcessData(int64_t currTimeNs, bsec_bme_settings_t bme680Settings); + + /** + * @brief Set the BME680 sensor's configuration + * @param bme680Settings: Settings to configure the BME680 + * @return BME680 return code. BME680_OK for success, failure otherwise + */ + int8_t setBme680Config(bsec_bme_settings_t bme680Settings); + + /** + * @brief Common code for the begin function + */ + void beginCommon(void); + + /** + * @brief Function to zero the outputs + */ + void zeroOutputs(void); +}; + +#endif diff --git a/platformio.ini b/platformio.ini index f8aa7392..31a35718 100644 --- a/platformio.ini +++ b/platformio.ini @@ -6,7 +6,7 @@ ; ---> SELECT TARGET PLATFORM HERE! <--- [platformio] -env_default = generic +;env_default = generic ;env_default = ebox ;env_default = eboxtube ;env_default = heltec @@ -16,7 +16,7 @@ env_default = generic ;env_default = ttgov21old ;env_default = ttgov21new ;env_default = ttgobeam_old -;env_default = ttgobeam_new +env_default = ttgobeam_new ;env_default = lopy ;env_default = lopy4 ;env_default = fipy @@ -30,10 +30,10 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.7.01 +release_version = 1.7.03 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose -debug_level = 0 +debug_level = 4 ; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA upload_protocol = esptool ;upload_protocol = custom diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index 08795f31..dd7fc2d1 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -1,88 +1,89 @@ #ifdef HAS_BME #include "bme680mems.h" +#include "bsec.h" // Local logging tag static const char TAG[] = "main"; bmeStatus_t bme_status; TaskHandle_t BmeTask; - float bme_offset = (float)BME_TEMP_OFFSET; -// --- Bosch BSEC library configuration --- -// 3,3V supply voltage; 3s max time between sensor_control calls; 4 days -// calibration. Change this const if not applicable for your application (see -// BME680 datasheet) -const uint8_t bsec_config_iaq[454] = { - 1, 7, 4, 1, 61, 0, 0, 0, 0, 0, 0, 0, 174, 1, 0, - 0, 48, 0, 1, 0, 137, 65, 0, 63, 205, 204, 204, 62, 0, 0, - 64, 63, 205, 204, 204, 62, 0, 0, 225, 68, 0, 192, 168, 71, 64, - 49, 119, 76, 0, 0, 0, 0, 0, 80, 5, 95, 0, 0, 0, 0, - 0, 0, 0, 0, 28, 0, 2, 0, 0, 244, 1, 225, 0, 25, 0, - 0, 128, 64, 0, 0, 32, 65, 144, 1, 0, 0, 112, 65, 0, 0, - 0, 63, 16, 0, 3, 0, 10, 215, 163, 60, 10, 215, 35, 59, 10, - 215, 35, 59, 9, 0, 5, 0, 0, 0, 0, 0, 1, 88, 0, 9, - 0, 229, 208, 34, 62, 0, 0, 0, 0, 0, 0, 0, 0, 218, 27, - 156, 62, 225, 11, 67, 64, 0, 0, 160, 64, 0, 0, 0, 0, 0, - 0, 0, 0, 94, 75, 72, 189, 93, 254, 159, 64, 66, 62, 160, 191, - 0, 0, 0, 0, 0, 0, 0, 0, 33, 31, 180, 190, 138, 176, 97, - 64, 65, 241, 99, 190, 0, 0, 0, 0, 0, 0, 0, 0, 167, 121, - 71, 61, 165, 189, 41, 192, 184, 30, 189, 64, 12, 0, 10, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 229, 0, 254, 0, 2, 1, 5, 48, - 117, 100, 0, 44, 1, 112, 23, 151, 7, 132, 3, 197, 0, 92, 4, - 144, 1, 64, 1, 64, 1, 144, 1, 48, 117, 48, 117, 48, 117, 48, - 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, 48, 117, 100, 0, - 100, 0, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 100, 0, 48, - 117, 48, 117, 48, 117, 100, 0, 100, 0, 100, 0, 48, 117, 48, 117, - 100, 0, 100, 0, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, - 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, - 44, 1, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, - 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, 8, 7, - 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, - 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 112, 23, 255, 255, - 255, 255, 255, 255, 255, 255, 220, 5, 220, 5, 220, 5, 255, 255, 255, - 255, 255, 255, 220, 5, 220, 5, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 44, 1, 0, 0, 0, 0, - 239, 79, 0, 0}; +Bsec iaqSensor; // initialize BME680 sensor int bme_init(void) { - // struct bme680_dev gas_sensor; - Wire.begin(HAS_BME, 400000); // I2C connect to BME680 sensor with 400 KHz + Wire.begin(HAS_BME); + iaqSensor.begin(BME_ADDR, Wire); - // Call to the function which initializes the BSEC library - // Switch on low-power mode and provide no temperature offset + ESP_LOGI(TAG, "BSEC v%d.%d.%d.%d", iaqSensor.version.major, + iaqSensor.version.minor, iaqSensor.version.major_bugfix, + iaqSensor.version.minor_bugfix); - return_values_init ret = - bsec_iot_init(BSEC_SAMPLE_RATE_LP, bme_offset, i2c_write, i2c_read, - user_delay_ms, state_load, config_load); + iaqSensor.setConfig(bsec_config_iaq); - if ((int)ret.bme680_status) { - ESP_LOGE(TAG, "Could not initialize BME680, error %d", - (int)ret.bme680_status); - } else if ((int)ret.bsec_status) { - ESP_LOGE(TAG, "Could not initialize BSEC library, error %d", - (int)ret.bsec_status); - } else { + if (checkIaqSensorStatus()) ESP_LOGI(TAG, "BME680 sensor found and initialized"); + else { + ESP_LOGE(TAG, "BME680 sensor not found"); + 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; } - return 0; } -void output_ready(int64_t timestamp, float iaq, uint8_t iaq_accuracy, - float temperature, float humidity, float pressure, - float raw_temperature, float raw_humidity, float gas, - bsec_library_return_t bsec_status, float static_iaq, - float co2_equivalent, float breath_voc_equivalent) { +// Helper function definitions +int checkIaqSensorStatus(void) { + int rslt = 1; // true = 1 = no error, false = 0 = error - bme_status.temperature = temperature; - bme_status.humidity = humidity; - bme_status.pressure = (pressure / 100.0); // conversion Pa -> hPa - bme_status.iaq = iaq; + if (iaqSensor.status != BSEC_OK) { + rslt = 0; + if (iaqSensor.status < BSEC_OK) + ESP_LOGE(TAG, "BSEC error %d", iaqSensor.status); + else + ESP_LOGW(TAG, "BSEC warning %d", iaqSensor.status); + } + + if (iaqSensor.bme680Status != BME680_OK) { + rslt = 0; + if (iaqSensor.bme680Status < BME680_OK) + ESP_LOGE(TAG, "BME680 error %d", iaqSensor.bme680Status); + else + ESP_LOGW(TAG, "BME680 warning %d", iaqSensor.bme680Status); + } + + return rslt; } // loop function which reads and processes data based on sensor settings @@ -91,84 +92,23 @@ void bme_loop(void *pvParameters) { configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check #ifdef HAS_BME - // State is saved every 10.000 samples, which means every 10.000 * 3 secs = - // 500 minutes - bsec_iot_loop(user_delay_ms, get_timestamp_us, output_ready, state_save, - 10000); + 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; + } + } #endif + ESP_LOGE(TAG, "BME task ended"); vTaskDelete(BmeTask); // should never be reached + } // bme_loop() -int8_t i2c_read(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, - uint16_t len) { - int8_t rslt = 0; - Wire.beginTransmission(dev_id); - Wire.write(reg_addr); - rslt = Wire.endTransmission(false); - - Wire.requestFrom((int)dev_id, (int)len); - for (uint16_t i = 0; (i < len) && Wire.available(); i++) { - reg_data[i] = Wire.read(); - } - // return 0 for success, non-zero for failure - return rslt; -} - -int8_t i2c_write(uint8_t dev_id, uint8_t reg_addr, uint8_t *reg_data, - uint16_t len) { - Wire.beginTransmission(dev_id); - Wire.write(reg_addr); - for (uint16_t i = 0; i < len; i++) { - Wire.write(reg_data[i]); - } - // return 0 for success, non-zero for failure - return Wire.endTransmission(true); -} - -/*! - * @brief Load previous library state from non-volatile memory - * - * @param[in,out] state_buffer buffer to hold the loaded state string - * @param[in] n_buffer size of the allocated state buffer - * - * @return number of bytes copied to state_buffer - */ -uint32_t state_load(uint8_t *state_buffer, uint32_t n_buffer) { - // ... - // Load a previous library state from non-volatile memory, if available. - // - // Return zero if loading was unsuccessful or no state was available, - // otherwise return length of loaded state string. - // ... - return 0; -} - -/*! - * @brief Save library state to non-volatile memory - * - * @param[in] state_buffer buffer holding the state to be stored - * @param[in] length length of the state string to be stored - * - * @return none - */ -void state_save(const uint8_t *state_buffer, uint32_t length) { - // ... - // Save the string some form of non-volatile memory, if possible. - // ... -} - -uint32_t config_load(uint8_t *config_buffer, uint32_t n_buffer) { - - // Load a library config from non-volatile memory, if available. - // Return zero if loading was unsuccessful or no config was available, - // otherwise return length of loaded config string. - - memcpy(config_buffer, bsec_config_iaq, sizeof(bsec_config_iaq)); - return sizeof(bsec_config_iaq); -} - -void user_delay_ms(uint32_t period) { delay(period); } - -int64_t get_timestamp_us() { return (int64_t)millis() * 1000; } - #endif // HAS_BME \ No newline at end of file diff --git a/src/hal/generic.h b/src/hal/generic.h index ad88536f..c4e6deb9 100644 --- a/src/hal/generic.h +++ b/src/hal/generic.h @@ -17,8 +17,8 @@ // enable only if device has these sensors, otherwise comment these lines // BME680 sensor on I2C bus -// don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 #define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND // user defined sensors //#define HAS_SENSORS 1 // comment out if device has user defined sensors diff --git a/src/hal/octopus32.h b/src/hal/octopus32.h index a63b399b..288c286b 100644 --- a/src/hal/octopus32.h +++ b/src/hal/octopus32.h @@ -11,11 +11,9 @@ // disable brownout detection (avoid unexpected reset on some boards) #define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature -// enable only if device has these sensors, otherwise comment these lines -// BME680 sensor on I2C bus // Octopus32 has a pre-populated BME680 on i2c addr 0x76 #define HAS_BME GPIO_NUM_23, GPIO_NUM_22 // SDA, SCL -//#define HAS_BME 0x76 +#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND // user defined sensors //#define HAS_SENSORS 1 // comment out if device has user defined sensors diff --git a/src/hal/ttgobeam_new.h b/src/hal/ttgobeam_new.h index 1a4552a9..814e59c1 100644 --- a/src/hal/ttgobeam_new.h +++ b/src/hal/ttgobeam_new.h @@ -8,12 +8,11 @@ // Hardware related definitions for TTGO T-Beam board // // pinouts taken from http://tinymicros.com/wiki/TTGO_T-Beam -// + // enable only if device has these sensors, otherwise comment these lines // BME680 sensor on I2C bus -// don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 -// -//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND #define HAS_LED GPIO_NUM_14 // on board green LED From eb5dac2dea78ed80fa649689f6e43d71f36a37f0 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Wed, 26 Dec 2018 23:21:28 +0100 Subject: [PATCH 22/37] new bsec tree --- include/bme680mems.h | 2 +- lib/Bosch-BSEC/bsec_integration.c | 559 ------------------ lib/Bosch-BSEC/bsec_integration.h | 165 ------ lib/Bosch-BSEC/{ => src/bme680}/README.md | 0 lib/Bosch-BSEC/{ => src/bme680}/bme680.c | 0 lib/Bosch-BSEC/{ => src/bme680}/bme680.h | 0 lib/Bosch-BSEC/{ => src/bme680}/bme680_defs.h | 0 lib/Bosch-BSEC/{ => src}/bsec.cpp | 0 lib/Bosch-BSEC/{ => src}/bsec.h | 6 +- lib/Bosch-BSEC/{ => src/esp32}/libalgobsec.a | Bin lib/Bosch-BSEC/{ => src/inc}/bsec_datatypes.h | 0 lib/Bosch-BSEC/{ => src/inc}/bsec_interface.h | 0 platformio.ini | 4 +- src/bme680mems.cpp | 1 - 14 files changed, 6 insertions(+), 731 deletions(-) delete mode 100644 lib/Bosch-BSEC/bsec_integration.c delete mode 100644 lib/Bosch-BSEC/bsec_integration.h rename lib/Bosch-BSEC/{ => src/bme680}/README.md (100%) rename lib/Bosch-BSEC/{ => src/bme680}/bme680.c (100%) rename lib/Bosch-BSEC/{ => src/bme680}/bme680.h (100%) rename lib/Bosch-BSEC/{ => src/bme680}/bme680_defs.h (100%) rename lib/Bosch-BSEC/{ => src}/bsec.cpp (100%) rename lib/Bosch-BSEC/{ => src}/bsec.h (98%) rename lib/Bosch-BSEC/{ => src/esp32}/libalgobsec.a (100%) rename lib/Bosch-BSEC/{ => src/inc}/bsec_datatypes.h (100%) rename lib/Bosch-BSEC/{ => src/inc}/bsec_interface.h (100%) diff --git a/include/bme680mems.h b/include/bme680mems.h index 5ac87588..5532f0cc 100644 --- a/include/bme680mems.h +++ b/include/bme680mems.h @@ -4,7 +4,7 @@ #include "globals.h" #include #include "irqhandler.h" -#include "bsec.h" +#include "../lib/Bosch-BSEC/src/bsec.h" extern bmeStatus_t bme_status; // Make struct for storing gps data globally available diff --git a/lib/Bosch-BSEC/bsec_integration.c b/lib/Bosch-BSEC/bsec_integration.c deleted file mode 100644 index 0dc5dc2d..00000000 --- a/lib/Bosch-BSEC/bsec_integration.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * Copyright (C) 2017 Robert Bosch. All Rights Reserved. - * - * Disclaimer - * - * Common: - * Bosch Sensortec products are developed for the consumer goods industry. They may only be used - * within the parameters of the respective valid product data sheet. Bosch Sensortec products are - * provided with the express understanding that there is no warranty of fitness for a particular purpose. - * They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device - * that may lead to bodily harm or property damage if the system or device malfunctions. In addition, - * Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems. - * The resale and/or use of products are at the purchasers own risk and his own responsibility. The - * examination of fitness for the intended use is the sole responsibility of the Purchaser. - * - * The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for - * incidental, or consequential damages, arising from any product use not covered by the parameters of - * the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch - * Sensortec for all costs in connection with such claims. - * - * The purchaser must monitor the market for the purchased products, particularly with regard to - * product safety and inform Bosch Sensortec without delay of all security relevant incidents. - * - * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid - * technical specifications of the product series. They are therefore not intended or fit for resale to third - * parties or for use in end products. Their sole purpose is internal client testing. The testing of an - * engineering sample may in no way replace the testing of a product series. Bosch Sensortec - * assumes no liability for the use of engineering samples. By accepting the engineering samples, the - * Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering - * samples. - * - * Special: - * This software module (hereinafter called "Software") and any information on application-sheets - * (hereinafter called "Information") is provided free of charge for the sole purpose to support your - * application work. The Software and Information is subject to the following terms and conditions: - * - * The Software is specifically designed for the exclusive use for Bosch Sensortec products by - * personnel who have special experience and training. Do not use this Software if you do not have the - * proper experience or training. - * - * This Software package is provided `` as is `` and without any expressed or implied warranties, - * including without limitation, the implied warranties of merchantability and fitness for a particular - * purpose. - * - * Bosch Sensortec and their representatives and agents deny any liability for the functional impairment - * of this Software in terms of fitness, performance and safety. Bosch Sensortec and their - * representatives and agents shall not be liable for any direct or indirect damages or injury, except as - * otherwise stipulated in mandatory applicable law. - * - * The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no - * responsibility for the consequences of use of such Information nor for any infringement of patents or - * other rights of third parties which may result from its use. No license is granted by implication or - * otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are - * subject to change without notice. - * - * It is not allowed to deliver the source code of the Software to any third party without permission of - * Bosch Sensortec. - * - */ - -/*! - * @file bsec_integration.c - * - * @brief - * Private part of the example for using of BSEC library. - */ - -/*! - * @addtogroup bsec_examples BSEC Examples - * @brief BSEC usage examples - * @{*/ - -/**********************************************************************************************************************/ -/* header files */ -/**********************************************************************************************************************/ - -#include -#include -#include - -#include "bsec_integration.h" - -/**********************************************************************************************************************/ -/* local macro definitions */ -/**********************************************************************************************************************/ - -#define NUM_USED_OUTPUTS 8 - -/**********************************************************************************************************************/ -/* global variable declarations */ -/**********************************************************************************************************************/ - -/* Global sensor APIs data structure */ -static struct bme680_dev bme680_g; - -/* Global temperature offset to be subtracted */ -static float bme680_temperature_offset_g = 0.0f; - -/**********************************************************************************************************************/ -/* functions */ -/**********************************************************************************************************************/ - -/*! - * @brief Virtual sensor subscription - * Please call this function before processing of data using bsec_do_steps function - * - * @param[in] sample_rate mode to be used (either BSEC_SAMPLE_RATE_ULP or BSEC_SAMPLE_RATE_LP) - * - * @return subscription result, zero when successful - */ -static bsec_library_return_t bme680_bsec_update_subscription(float sample_rate) -{ - bsec_sensor_configuration_t requested_virtual_sensors[NUM_USED_OUTPUTS]; - uint8_t n_requested_virtual_sensors = NUM_USED_OUTPUTS; - - bsec_sensor_configuration_t required_sensor_settings[BSEC_MAX_PHYSICAL_SENSOR]; - uint8_t n_required_sensor_settings = BSEC_MAX_PHYSICAL_SENSOR; - - bsec_library_return_t status = BSEC_OK; - - /* note: Virtual sensors as desired to be added here */ - requested_virtual_sensors[0].sensor_id = BSEC_OUTPUT_IAQ; - requested_virtual_sensors[0].sample_rate = sample_rate; - requested_virtual_sensors[1].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE; - requested_virtual_sensors[1].sample_rate = sample_rate; - requested_virtual_sensors[2].sensor_id = BSEC_OUTPUT_RAW_PRESSURE; - requested_virtual_sensors[2].sample_rate = sample_rate; - requested_virtual_sensors[3].sensor_id = BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY; - requested_virtual_sensors[3].sample_rate = sample_rate; - requested_virtual_sensors[4].sensor_id = BSEC_OUTPUT_RAW_GAS; - requested_virtual_sensors[4].sample_rate = sample_rate; - requested_virtual_sensors[5].sensor_id = BSEC_OUTPUT_RAW_TEMPERATURE; - requested_virtual_sensors[5].sample_rate = sample_rate; - requested_virtual_sensors[6].sensor_id = BSEC_OUTPUT_RAW_HUMIDITY; - requested_virtual_sensors[6].sample_rate = sample_rate; - requested_virtual_sensors[7].sensor_id = BSEC_OUTPUT_STATIC_IAQ; - requested_virtual_sensors[7].sample_rate = sample_rate; - - /* Call bsec_update_subscription() to enable/disable the requested virtual sensors */ - status = bsec_update_subscription(requested_virtual_sensors, n_requested_virtual_sensors, required_sensor_settings, - &n_required_sensor_settings); - - return status; -} - -/*! - * @brief Initialize the BME680 sensor and the BSEC library - * - * @param[in] sample_rate mode to be used (either BSEC_SAMPLE_RATE_ULP or BSEC_SAMPLE_RATE_LP) - * @param[in] temperature_offset device-specific temperature offset (due to self-heating) - * @param[in] bus_write pointer to the bus writing function - * @param[in] bus_read pointer to the bus reading function - * @param[in] sleep pointer to the system specific sleep function - * @param[in] state_load pointer to the system-specific state load function - * @param[in] config_load pointer to the system-specific config load function - * - * @return zero if successful, negative otherwise - */ -return_values_init bsec_iot_init(float sample_rate, float temperature_offset, bme680_com_fptr_t bus_write, - bme680_com_fptr_t bus_read, sleep_fct sleep, state_load_fct state_load, config_load_fct config_load) -{ - return_values_init ret = {BME680_OK, BSEC_OK}; - bsec_library_return_t bsec_status = BSEC_OK; - - uint8_t bsec_state[BSEC_MAX_PROPERTY_BLOB_SIZE] = {0}; - uint8_t bsec_config[BSEC_MAX_PROPERTY_BLOB_SIZE] = {0}; - uint8_t work_buffer[BSEC_MAX_PROPERTY_BLOB_SIZE] = {0}; - int bsec_state_len, bsec_config_len; - - /* Fixed I2C configuration */ - bme680_g.dev_id = BME680_I2C_ADDR_PRIMARY; - bme680_g.intf = BME680_I2C_INTF; - /* User configurable I2C configuration */ - bme680_g.write = bus_write; - bme680_g.read = bus_read; - bme680_g.delay_ms = sleep; - - /* Initialize BME680 API */ - ret.bme680_status = bme680_init(&bme680_g); - if (ret.bme680_status != BME680_OK) - { - return ret; - } - - /* Initialize BSEC library */ - ret.bsec_status = bsec_init(); - if (ret.bsec_status != BSEC_OK) - { - return ret; - } - - /* Load library config, if available */ - bsec_config_len = config_load(bsec_config, sizeof(bsec_config)); - if (bsec_config_len != 0) - { - ret.bsec_status = bsec_set_configuration(bsec_config, bsec_config_len, work_buffer, sizeof(work_buffer)); - if (ret.bsec_status != BSEC_OK) - { - return ret; - } - } - - /* Load previous library state, if available */ - bsec_state_len = state_load(bsec_state, sizeof(bsec_state)); - if (bsec_state_len != 0) - { - ret.bsec_status = bsec_set_state(bsec_state, bsec_state_len, work_buffer, sizeof(work_buffer)); - if (ret.bsec_status != BSEC_OK) - { - return ret; - } - } - - /* Set temperature offset */ - bme680_temperature_offset_g = temperature_offset; - - /* Call to the function which sets the library with subscription information */ - ret.bsec_status = bme680_bsec_update_subscription(sample_rate); - if (ret.bsec_status != BSEC_OK) - { - return ret; - } - - return ret; -} - -/*! - * @brief Trigger the measurement based on sensor settings - * - * @param[in] sensor_settings settings of the BME680 sensor adopted by sensor control function - * @param[in] sleep pointer to the system specific sleep function - * - * @return none - */ -static void bme680_bsec_trigger_measurement(bsec_bme_settings_t *sensor_settings, sleep_fct sleep) -{ - uint16_t meas_period; - uint8_t set_required_settings; - int8_t bme680_status = BME680_OK; - - /* Check if a forced-mode measurement should be triggered now */ - if (sensor_settings->trigger_measurement) - { - /* Set sensor configuration */ - - bme680_g.tph_sett.os_hum = sensor_settings->humidity_oversampling; - bme680_g.tph_sett.os_pres = sensor_settings->pressure_oversampling; - bme680_g.tph_sett.os_temp = sensor_settings->temperature_oversampling; - bme680_g.gas_sett.run_gas = sensor_settings->run_gas; - bme680_g.gas_sett.heatr_temp = sensor_settings->heater_temperature; /* degree Celsius */ - bme680_g.gas_sett.heatr_dur = sensor_settings->heating_duration; /* milliseconds */ - - /* Select the power mode */ - /* Must be set before writing the sensor configuration */ - bme680_g.power_mode = BME680_FORCED_MODE; - /* Set the required sensor settings needed */ - set_required_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_GAS_SENSOR_SEL; - - /* Set the desired sensor configuration */ - bme680_status = bme680_set_sensor_settings(set_required_settings, &bme680_g); - - /* Set power mode as forced mode and trigger forced mode measurement */ - bme680_status = bme680_set_sensor_mode(&bme680_g); - - /* Get the total measurement duration so as to sleep or wait till the measurement is complete */ - bme680_get_profile_dur(&meas_period, &bme680_g); - - /* Delay till the measurement is ready. Timestamp resolution in ms */ - sleep((uint32_t)meas_period); - } - - /* Call the API to get current operation mode of the sensor */ - bme680_status = bme680_get_sensor_mode(&bme680_g); - /* When the measurement is completed and data is ready for reading, the sensor must be in BME680_SLEEP_MODE. - * Read operation mode to check whether measurement is completely done and wait until the sensor is no more - * in BME680_FORCED_MODE. */ - while (bme680_g.power_mode == BME680_FORCED_MODE) - { - /* sleep for 5 ms */ - sleep(5); - bme680_status = bme680_get_sensor_mode(&bme680_g); - } -} - -/*! - * @brief Read the data from registers and populate the inputs structure to be passed to do_steps function - * - * @param[in] time_stamp_trigger settings of the sensor returned from sensor control function - * @param[in] inputs input structure containing the information on sensors to be passed to do_steps - * @param[in] num_bsec_inputs number of inputs to be passed to do_steps - * @param[in] bsec_process_data process data variable returned from sensor_control - * - * @return none - */ -static void bme680_bsec_read_data(int64_t time_stamp_trigger, bsec_input_t *inputs, uint8_t *num_bsec_inputs, - int32_t bsec_process_data) -{ - static struct bme680_field_data data; - int8_t bme680_status = BME680_OK; - - /* We only have to read data if the previous call the bsec_sensor_control() actually asked for it */ - if (bsec_process_data) - { - bme680_status = bme680_get_sensor_data(&data, &bme680_g); - - if (data.status & BME680_NEW_DATA_MSK) - { - /* Pressure to be processed by BSEC */ - if (bsec_process_data & BSEC_PROCESS_PRESSURE) - { - /* Place presssure sample into input struct */ - inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_PRESSURE; - inputs[*num_bsec_inputs].signal = data.pressure; - inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger; - (*num_bsec_inputs)++; - } - /* Temperature to be processed by BSEC */ - if (bsec_process_data & BSEC_PROCESS_TEMPERATURE) - { - /* Place temperature sample into input struct */ - inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_TEMPERATURE; - #ifdef BME680_FLOAT_POINT_COMPENSATION - inputs[*num_bsec_inputs].signal = data.temperature; - #else - inputs[*num_bsec_inputs].signal = data.temperature / 100.0f; - #endif - inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger; - (*num_bsec_inputs)++; - - /* Also add optional heatsource input which will be subtracted from the temperature reading to - * compensate for device-specific self-heating (supported in BSEC IAQ solution)*/ - inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_HEATSOURCE; - inputs[*num_bsec_inputs].signal = bme680_temperature_offset_g; - inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger; - (*num_bsec_inputs)++; - } - /* Humidity to be processed by BSEC */ - if (bsec_process_data & BSEC_PROCESS_HUMIDITY) - { - /* Place humidity sample into input struct */ - inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_HUMIDITY; - #ifdef BME680_FLOAT_POINT_COMPENSATION - inputs[*num_bsec_inputs].signal = data.humidity; - #else - inputs[*num_bsec_inputs].signal = data.humidity / 1000.0f; - #endif - inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger; - (*num_bsec_inputs)++; - } - /* Gas to be processed by BSEC */ - if (bsec_process_data & BSEC_PROCESS_GAS) - { - /* Check whether gas_valid flag is set */ - if(data.status & BME680_GASM_VALID_MSK) - { - /* Place sample into input struct */ - inputs[*num_bsec_inputs].sensor_id = BSEC_INPUT_GASRESISTOR; - inputs[*num_bsec_inputs].signal = data.gas_resistance; - inputs[*num_bsec_inputs].time_stamp = time_stamp_trigger; - (*num_bsec_inputs)++; - } - } - } - } -} - -/*! - * @brief This function is written to process the sensor data for the requested virtual sensors - * - * @param[in] bsec_inputs input structure containing the information on sensors to be passed to do_steps - * @param[in] num_bsec_inputs number of inputs to be passed to do_steps - * @param[in] output_ready pointer to the function processing obtained BSEC outputs - * - * @return none - */ -static void bme680_bsec_process_data(bsec_input_t *bsec_inputs, uint8_t num_bsec_inputs, output_ready_fct output_ready) -{ - /* Output buffer set to the maximum virtual sensor outputs supported */ - bsec_output_t bsec_outputs[BSEC_NUMBER_OUTPUTS]; - uint8_t num_bsec_outputs = 0; - uint8_t index = 0; - - bsec_library_return_t bsec_status = BSEC_OK; - - int64_t timestamp = 0; - float iaq = 0.0f; - uint8_t iaq_accuracy = 0; - float temp = 0.0f; - float raw_temp = 0.0f; - float raw_pressure = 0.0f; - float humidity = 0.0f; - float raw_humidity = 0.0f; - float raw_gas = 0.0f; - float static_iaq = 0.0f; - uint8_t static_iaq_accuracy = 0; - float co2_equivalent = 0.0f; - uint8_t co2_accuracy = 0; - float breath_voc_equivalent = 0.0f; - uint8_t breath_voc_accuracy = 0; - float comp_gas_value = 0.0f; - uint8_t comp_gas_accuracy = 0; - float gas_percentage = 0.0f; - uint8_t gas_percentage_acccuracy = 0; - - /* Check if something should be processed by BSEC */ - if (num_bsec_inputs > 0) - { - /* Set number of outputs to the size of the allocated buffer */ - /* BSEC_NUMBER_OUTPUTS to be defined */ - num_bsec_outputs = BSEC_NUMBER_OUTPUTS; - - /* Perform processing of the data by BSEC - Note: - * The number of outputs you get depends on what you asked for during bsec_update_subscription(). This is - handled under bme680_bsec_update_subscription() function in this example file. - * The number of actual outputs that are returned is written to num_bsec_outputs. */ - bsec_status = bsec_do_steps(bsec_inputs, num_bsec_inputs, bsec_outputs, &num_bsec_outputs); - - /* Iterate through the outputs and extract the relevant ones. */ - for (index = 0; index < num_bsec_outputs; index++) - { - switch (bsec_outputs[index].sensor_id) - { - case BSEC_OUTPUT_IAQ: - iaq = bsec_outputs[index].signal; - iaq_accuracy = bsec_outputs[index].accuracy; - break; - case BSEC_OUTPUT_STATIC_IAQ: - static_iaq = bsec_outputs[index].signal; - static_iaq_accuracy = bsec_outputs[index].accuracy; - break; - case BSEC_OUTPUT_CO2_EQUIVALENT: - co2_equivalent = bsec_outputs[index].signal; - co2_accuracy = bsec_outputs[index].accuracy; - break; - case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT: - breath_voc_equivalent = bsec_outputs[index].signal; - breath_voc_accuracy = bsec_outputs[index].accuracy; - break; - case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE: - temp = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_RAW_PRESSURE: - raw_pressure = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY: - humidity = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_RAW_GAS: - raw_gas = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_RAW_TEMPERATURE: - raw_temp = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_RAW_HUMIDITY: - raw_humidity = bsec_outputs[index].signal; - break; - case BSEC_OUTPUT_COMPENSATED_GAS: - comp_gas_value = bsec_outputs[index].signal; - comp_gas_accuracy = bsec_outputs[index].accuracy; - break; - case BSEC_OUTPUT_GAS_PERCENTAGE: - gas_percentage = bsec_outputs[index].signal; - gas_percentage_acccuracy = bsec_outputs[index].accuracy; - break; - default: - continue; - } - - /* Assume that all the returned timestamps are the same */ - timestamp = bsec_outputs[index].time_stamp; - } - - /* Pass the extracted outputs to the user provided output_ready() function. */ - output_ready(timestamp, iaq, iaq_accuracy, temp, humidity, raw_pressure, raw_temp, - raw_humidity, raw_gas, bsec_status, static_iaq, co2_equivalent, breath_voc_equivalent); - } -} - -/*! - * @brief Runs the main (endless) loop that queries sensor settings, applies them, and processes the measured data - * - * @param[in] sleep pointer to the system specific sleep function - * @param[in] get_timestamp_us pointer to the system specific timestamp derivation function - * @param[in] output_ready pointer to the function processing obtained BSEC outputs - * @param[in] state_save pointer to the system-specific state save function - * @param[in] save_intvl interval at which BSEC state should be saved (in samples) - * - * @return none - */ -void bsec_iot_loop(sleep_fct sleep, get_timestamp_us_fct get_timestamp_us, output_ready_fct output_ready, - state_save_fct state_save, uint32_t save_intvl) -{ - /* Timestamp variables */ - int64_t time_stamp = 0; - int64_t time_stamp_interval_ms = 0; - - /* Allocate enough memory for up to BSEC_MAX_PHYSICAL_SENSOR physical inputs*/ - bsec_input_t bsec_inputs[BSEC_MAX_PHYSICAL_SENSOR]; - - /* Number of inputs to BSEC */ - uint8_t num_bsec_inputs = 0; - - /* BSEC sensor settings struct */ - bsec_bme_settings_t sensor_settings; - - /* Save state variables */ - uint8_t bsec_state[BSEC_MAX_STATE_BLOB_SIZE]; - uint8_t work_buffer[BSEC_MAX_STATE_BLOB_SIZE]; - uint32_t bsec_state_len = 0; - uint32_t n_samples = 0; - - bsec_library_return_t bsec_status = BSEC_OK; - - while (1) - { - /* get the timestamp in nanoseconds before calling bsec_sensor_control() */ - time_stamp = get_timestamp_us() * 1000; - - /* Retrieve sensor settings to be used in this time instant by calling bsec_sensor_control */ - bsec_sensor_control(time_stamp, &sensor_settings); - - /* Trigger a measurement if necessary */ - bme680_bsec_trigger_measurement(&sensor_settings, sleep); - - /* Read data from last measurement */ - num_bsec_inputs = 0; - bme680_bsec_read_data(time_stamp, bsec_inputs, &num_bsec_inputs, sensor_settings.process_data); - - /* Time to invoke BSEC to perform the actual processing */ - bme680_bsec_process_data(bsec_inputs, num_bsec_inputs, output_ready); - - /* Increment sample counter */ - n_samples++; - - /* Retrieve and store state if the passed save_intvl */ - if (n_samples >= save_intvl) - { - bsec_status = bsec_get_state(0, bsec_state, sizeof(bsec_state), work_buffer, sizeof(work_buffer), &bsec_state_len); - if (bsec_status == BSEC_OK) - { - state_save(bsec_state, bsec_state_len); - } - n_samples = 0; - } - - - /* Compute how long we can sleep until we need to call bsec_sensor_control() next */ - /* Time_stamp is converted from microseconds to nanoseconds first and then the difference to milliseconds */ - time_stamp_interval_ms = (sensor_settings.next_call - get_timestamp_us() * 1000) / 1000000; - if (time_stamp_interval_ms > 0) - { - sleep((uint32_t)time_stamp_interval_ms); - } - } -} - -/*! @}*/ - diff --git a/lib/Bosch-BSEC/bsec_integration.h b/lib/Bosch-BSEC/bsec_integration.h deleted file mode 100644 index 5155a001..00000000 --- a/lib/Bosch-BSEC/bsec_integration.h +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2017 Robert Bosch. All Rights Reserved. - * - * Disclaimer - * - * Common: - * Bosch Sensortec products are developed for the consumer goods industry. They may only be used - * within the parameters of the respective valid product data sheet. Bosch Sensortec products are - * provided with the express understanding that there is no warranty of fitness for a particular purpose. - * They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device - * that may lead to bodily harm or property damage if the system or device malfunctions. In addition, - * Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems. - * The resale and/or use of products are at the purchasers own risk and his own responsibility. The - * examination of fitness for the intended use is the sole responsibility of the Purchaser. - * - * The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for - * incidental, or consequential damages, arising from any product use not covered by the parameters of - * the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch - * Sensortec for all costs in connection with such claims. - * - * The purchaser must monitor the market for the purchased products, particularly with regard to - * product safety and inform Bosch Sensortec without delay of all security relevant incidents. - * - * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid - * technical specifications of the product series. They are therefore not intended or fit for resale to third - * parties or for use in end products. Their sole purpose is internal client testing. The testing of an - * engineering sample may in no way replace the testing of a product series. Bosch Sensortec - * assumes no liability for the use of engineering samples. By accepting the engineering samples, the - * Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering - * samples. - * - * Special: - * This software module (hereinafter called "Software") and any information on application-sheets - * (hereinafter called "Information") is provided free of charge for the sole purpose to support your - * application work. The Software and Information is subject to the following terms and conditions: - * - * The Software is specifically designed for the exclusive use for Bosch Sensortec products by - * personnel who have special experience and training. Do not use this Software if you do not have the - * proper experience or training. - * - * This Software package is provided `` as is `` and without any expressed or implied warranties, - * including without limitation, the implied warranties of merchantability and fitness for a particular - * purpose. - * - * Bosch Sensortec and their representatives and agents deny any liability for the functional impairment - * of this Software in terms of fitness, performance and safety. Bosch Sensortec and their - * representatives and agents shall not be liable for any direct or indirect damages or injury, except as - * otherwise stipulated in mandatory applicable law. - * - * The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no - * responsibility for the consequences of use of such Information nor for any infringement of patents or - * other rights of third parties which may result from its use. No license is granted by implication or - * otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are - * subject to change without notice. - * - * It is not allowed to deliver the source code of the Software to any third party without permission of - * Bosch Sensortec. - * - */ - -/*! - * @file bsec_integration.h - * - * @brief - * Contains BSEC integration API - */ - -/*! - * @addtogroup bsec_examples BSEC Examples - * @brief BSEC usage examples - * @{*/ - -#ifndef __BSEC_INTEGRATION_H__ -#define __BSEC_INTEGRATION_H__ - -#ifdef __cplusplus -extern "C" -{ -#endif - -/**********************************************************************************************************************/ -/* header files */ -/**********************************************************************************************************************/ - -/* Use the following bme680 driver: https://github.com/BoschSensortec/BME680_driver/releases/tag/bme680_v3.5.1 */ -#include "bme680.h" -/* BSEC header files are available in the inc/ folder of the release package */ -#include "bsec_interface.h" -#include "bsec_datatypes.h" - - -/**********************************************************************************************************************/ -/* type definitions */ -/**********************************************************************************************************************/ - -/* function pointer to the system specific sleep function */ -typedef void (*sleep_fct)(uint32_t t_ms); - -/* function pointer to the system specific timestamp derivation function */ -typedef int64_t (*get_timestamp_us_fct)(); - -/* function pointer to the function processing obtained BSEC outputs */ -typedef void (*output_ready_fct)(int64_t timestamp, float iaq, uint8_t iaq_accuracy, float temperature, float humidity, - float pressure, float raw_temperature, float raw_humidity, float gas, bsec_library_return_t bsec_status, - float static_iaq, float co2_equivalent, float breath_voc_equivalent); - -/* function pointer to the function loading a previous BSEC state from NVM */ -typedef uint32_t (*state_load_fct)(uint8_t *state_buffer, uint32_t n_buffer); - -/* function pointer to the function saving BSEC state to NVM */ -typedef void (*state_save_fct)(const uint8_t *state_buffer, uint32_t length); - -/* function pointer to the function loading the BSEC configuration string from NVM */ -typedef uint32_t (*config_load_fct)(uint8_t *state_buffer, uint32_t n_buffer); - -/* structure definitions */ - -/* Structure with the return value from bsec_iot_init() */ -typedef struct{ - /*! Result of API execution status */ - int8_t bme680_status; - /*! Result of BSEC library */ - bsec_library_return_t bsec_status; -}return_values_init; -/**********************************************************************************************************************/ -/* function declarations */ -/**********************************************************************************************************************/ - -/*! - * @brief Initialize the BME680 sensor and the BSEC library - * - * @param[in] sample_rate mode to be used (either BSEC_SAMPLE_RATE_ULP or BSEC_SAMPLE_RATE_LP) - * @param[in] temperature_offset device-specific temperature offset (due to self-heating) - * @param[in] bus_write pointer to the bus writing function - * @param[in] bus_read pointer to the bus reading function - * @param[in] sleep pointer to the system-specific sleep function - * @param[in] state_load pointer to the system-specific state load function - * - * @return zero if successful, negative otherwise - */ -return_values_init bsec_iot_init(float sample_rate, float temperature_offset, bme680_com_fptr_t bus_write, bme680_com_fptr_t bus_read, - sleep_fct sleep, state_load_fct state_load, config_load_fct config_load); - -/*! - * @brief Runs the main (endless) loop that queries sensor settings, applies them, and processes the measured data - * - * @param[in] sleep pointer to the system-specific sleep function - * @param[in] get_timestamp_us pointer to the system-specific timestamp derivation function - * @param[in] output_ready pointer to the function processing obtained BSEC outputs - * @param[in] state_save pointer to the system-specific state save function - * @param[in] save_intvl interval at which BSEC state should be saved (in samples) - * - * @return return_values_init struct with the result of the API and the BSEC library - */ -void bsec_iot_loop(sleep_fct sleep, get_timestamp_us_fct get_timestamp_us, output_ready_fct output_ready, - state_save_fct state_save, uint32_t save_intvl); - -#ifdef __cplusplus -} -#endif - -#endif /* __BSEC_INTEGRATION_H__ */ - -/*! @}*/ - diff --git a/lib/Bosch-BSEC/README.md b/lib/Bosch-BSEC/src/bme680/README.md similarity index 100% rename from lib/Bosch-BSEC/README.md rename to lib/Bosch-BSEC/src/bme680/README.md diff --git a/lib/Bosch-BSEC/bme680.c b/lib/Bosch-BSEC/src/bme680/bme680.c similarity index 100% rename from lib/Bosch-BSEC/bme680.c rename to lib/Bosch-BSEC/src/bme680/bme680.c diff --git a/lib/Bosch-BSEC/bme680.h b/lib/Bosch-BSEC/src/bme680/bme680.h similarity index 100% rename from lib/Bosch-BSEC/bme680.h rename to lib/Bosch-BSEC/src/bme680/bme680.h diff --git a/lib/Bosch-BSEC/bme680_defs.h b/lib/Bosch-BSEC/src/bme680/bme680_defs.h similarity index 100% rename from lib/Bosch-BSEC/bme680_defs.h rename to lib/Bosch-BSEC/src/bme680/bme680_defs.h diff --git a/lib/Bosch-BSEC/bsec.cpp b/lib/Bosch-BSEC/src/bsec.cpp similarity index 100% rename from lib/Bosch-BSEC/bsec.cpp rename to lib/Bosch-BSEC/src/bsec.cpp diff --git a/lib/Bosch-BSEC/bsec.h b/lib/Bosch-BSEC/src/bsec.h similarity index 98% rename from lib/Bosch-BSEC/bsec.h rename to lib/Bosch-BSEC/src/bsec.h index 3c881c6b..bf2c0a61 100644 --- a/lib/Bosch-BSEC/bsec.h +++ b/lib/Bosch-BSEC/src/bsec.h @@ -52,9 +52,9 @@ #include "Arduino.h" #include "Wire.h" #include "SPI.h" -#include "bsec_datatypes.h" -#include "bsec_interface.h" -#include "bme680.h" +#include "inc/bsec_datatypes.h" +#include "inc/bsec_interface.h" +#include "bme680/bme680.h" /* BSEC class definition */ class Bsec diff --git a/lib/Bosch-BSEC/libalgobsec.a b/lib/Bosch-BSEC/src/esp32/libalgobsec.a similarity index 100% rename from lib/Bosch-BSEC/libalgobsec.a rename to lib/Bosch-BSEC/src/esp32/libalgobsec.a diff --git a/lib/Bosch-BSEC/bsec_datatypes.h b/lib/Bosch-BSEC/src/inc/bsec_datatypes.h similarity index 100% rename from lib/Bosch-BSEC/bsec_datatypes.h rename to lib/Bosch-BSEC/src/inc/bsec_datatypes.h diff --git a/lib/Bosch-BSEC/bsec_interface.h b/lib/Bosch-BSEC/src/inc/bsec_interface.h similarity index 100% rename from lib/Bosch-BSEC/bsec_interface.h rename to lib/Bosch-BSEC/src/inc/bsec_interface.h diff --git a/platformio.ini b/platformio.ini index 31a35718..0922cb7a 100644 --- a/platformio.ini +++ b/platformio.ini @@ -70,8 +70,8 @@ build_flags_basic = '-DBINTRAY_PACKAGE="${PIOENV}"' '-DPROGVERSION="${common.release_version}"' build_flags_sensors = - -Llib/Bosch-BSEC - -llibalgobsec.a + -Llib/Bosch-BSEC/src/esp32/ + -lalgobsec build_flags_all = ${common.build_flags_basic} ${common.build_flags_sensors} diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index dd7fc2d1..d5f08662 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -1,7 +1,6 @@ #ifdef HAS_BME #include "bme680mems.h" -#include "bsec.h" // Local logging tag static const char TAG[] = "main"; From 76600a86b156c1d5ebaf54e15166c5774e984b54 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Thu, 27 Dec 2018 17:09:40 +0100 Subject: [PATCH 23/37] first fully functional integration (experimental) --- include/globals.h | 1 + lib/Bosch-BSEC/src/bme680/bme680_defs.h | 2 +- lib/Bosch-BSEC/src/bsec.cpp | 641 ++++++++++++------------ platformio.ini | 2 +- src/bme680mems.cpp | 117 +++-- src/cyclic.cpp | 7 +- src/display.cpp | 136 ++--- src/hal/ttgobeam_new.h | 8 +- src/hal/ttgobeam_old.h | 2 +- src/main.cpp | 18 +- 10 files changed, 488 insertions(+), 446 deletions(-) diff --git a/include/globals.h b/include/globals.h index 8c429048..7fda0d29 100644 --- a/include/globals.h +++ b/include/globals.h @@ -89,6 +89,7 @@ extern uint8_t volatile channel; // wifi channel rotation counter extern uint16_t volatile macs_total, macs_wifi, macs_ble, batt_voltage; // display values extern hw_timer_t *channelSwitch, *sendCycle, *displaytimer; +extern SemaphoreHandle_t I2Caccess; extern std::set, Mallocator> macs; extern std::array::iterator it; diff --git a/lib/Bosch-BSEC/src/bme680/bme680_defs.h b/lib/Bosch-BSEC/src/bme680/bme680_defs.h index 495edfe0..79fd7782 100644 --- a/lib/Bosch-BSEC/src/bme680/bme680_defs.h +++ b/lib/Bosch-BSEC/src/bme680/bme680_defs.h @@ -103,7 +103,7 @@ /** BME680 configuration macros */ /** Enable or un-comment the macro to provide floating point data output */ #ifndef BME680_FLOAT_POINT_COMPENSATION -/* #define BME680_FLOAT_POINT_COMPENSATION */ +//#define BME680_FLOAT_POINT_COMPENSATION #endif /** BME680 General config */ diff --git a/lib/Bosch-BSEC/src/bsec.cpp b/lib/Bosch-BSEC/src/bsec.cpp index d9ac1868..cf85d77f 100644 --- a/lib/Bosch-BSEC/src/bsec.cpp +++ b/lib/Bosch-BSEC/src/bsec.cpp @@ -47,186 +47,185 @@ #include "bsec.h" -TwoWire* Bsec::wireObj = NULL; -SPIClass* Bsec::spiObj = NULL; +TwoWire *Bsec::wireObj = NULL; +SPIClass *Bsec::spiObj = NULL; /** * @brief Constructor */ -Bsec::Bsec() -{ - nextCall = 0; - version.major = 0; - version.minor = 0; - version.major_bugfix = 0; - version.minor_bugfix = 0; - millisOverflowCounter = 0; - lastTime = 0; - bme680Status = BME680_OK; - outputTimestamp = 0; - _tempOffset = 0.0f; - status = BSEC_OK; - zeroOutputs(); +Bsec::Bsec() { + nextCall = 0; + version.major = 0; + version.minor = 0; + version.major_bugfix = 0; + version.minor_bugfix = 0; + millisOverflowCounter = 0; + lastTime = 0; + bme680Status = BME680_OK; + outputTimestamp = 0; + _tempOffset = 0.0f; + status = BSEC_OK; + zeroOutputs(); } /** * @brief Function to initialize the BSEC library and the BME680 sensor */ -void Bsec::begin(uint8_t devId, enum bme680_intf intf, bme680_com_fptr_t read, bme680_com_fptr_t write, bme680_delay_fptr_t idleTask) -{ - _bme680.dev_id = devId; - _bme680.intf = intf; - _bme680.read = read; - _bme680.write = write; - _bme680.delay_ms = idleTask; - _bme680.amb_temp = 25; - _bme680.power_mode = BME680_FORCED_MODE; +void Bsec::begin(uint8_t devId, enum bme680_intf intf, bme680_com_fptr_t read, + bme680_com_fptr_t write, bme680_delay_fptr_t idleTask) { + _bme680.dev_id = devId; + _bme680.intf = intf; + _bme680.read = read; + _bme680.write = write; + _bme680.delay_ms = idleTask; + _bme680.amb_temp = 25; + _bme680.power_mode = BME680_FORCED_MODE; - beginCommon(); + beginCommon(); } /** * @brief Function to initialize the BSEC library and the BME680 sensor */ -void Bsec::begin(uint8_t i2cAddr, TwoWire &i2c) -{ - _bme680.dev_id = i2cAddr; - _bme680.intf = BME680_I2C_INTF; - _bme680.read = Bsec::i2cRead; - _bme680.write = Bsec::i2cWrite; - _bme680.delay_ms = Bsec::delay_ms; - _bme680.amb_temp = 25; - _bme680.power_mode = BME680_FORCED_MODE; +void Bsec::begin(uint8_t i2cAddr, TwoWire &i2c) { + _bme680.dev_id = i2cAddr; + _bme680.intf = BME680_I2C_INTF; + _bme680.read = Bsec::i2cRead; + _bme680.write = Bsec::i2cWrite; + _bme680.delay_ms = Bsec::delay_ms; + _bme680.amb_temp = 25; + _bme680.power_mode = BME680_FORCED_MODE; - Bsec::wireObj = &i2c; - Bsec::wireObj->begin(); + Bsec::wireObj = &i2c; + Bsec::wireObj->begin(); - beginCommon(); + beginCommon(); } /** * @brief Function to initialize the BSEC library and the BME680 sensor */ -void Bsec::begin(uint8_t chipSelect, SPIClass &spi) -{ - _bme680.dev_id = chipSelect; - _bme680.intf = BME680_SPI_INTF; - _bme680.read = Bsec::spiTransfer; - _bme680.write = Bsec::spiTransfer; - _bme680.delay_ms = Bsec::delay_ms; - _bme680.amb_temp = 25; - _bme680.power_mode = BME680_FORCED_MODE; +void Bsec::begin(uint8_t chipSelect, SPIClass &spi) { + _bme680.dev_id = chipSelect; + _bme680.intf = BME680_SPI_INTF; + _bme680.read = Bsec::spiTransfer; + _bme680.write = Bsec::spiTransfer; + _bme680.delay_ms = Bsec::delay_ms; + _bme680.amb_temp = 25; + _bme680.power_mode = BME680_FORCED_MODE; - pinMode(chipSelect, OUTPUT); - digitalWrite(chipSelect, HIGH); - Bsec::spiObj = &spi; - Bsec::spiObj->begin(); + pinMode(chipSelect, OUTPUT); + digitalWrite(chipSelect, HIGH); + Bsec::spiObj = &spi; + Bsec::spiObj->begin(); - beginCommon(); + beginCommon(); } /** * @brief Common code for the begin function */ -void Bsec::beginCommon(void) -{ - status = bsec_init(); +void Bsec::beginCommon(void) { + status = bsec_init(); - getVersion(); - - bme680Status = bme680_init(&_bme680); + getVersion(); + + bme680Status = bme680_init(&_bme680); } /** * @brief Function that sets the desired sensors and the sample rates */ -void Bsec::updateSubscription(bsec_virtual_sensor_t sensorList[], uint8_t nSensors, float sampleRate) -{ - bsec_sensor_configuration_t virtualSensors[BSEC_NUMBER_OUTPUTS], - sensorSettings[BSEC_MAX_PHYSICAL_SENSOR]; - uint8_t nVirtualSensors = 0, nSensorSettings = BSEC_MAX_PHYSICAL_SENSOR; +void Bsec::updateSubscription(bsec_virtual_sensor_t sensorList[], + uint8_t nSensors, float sampleRate) { + bsec_sensor_configuration_t virtualSensors[BSEC_NUMBER_OUTPUTS], + sensorSettings[BSEC_MAX_PHYSICAL_SENSOR]; + uint8_t nVirtualSensors = 0, nSensorSettings = BSEC_MAX_PHYSICAL_SENSOR; - for (uint8_t i = 0; i < nSensors; i++) { - virtualSensors[nVirtualSensors].sensor_id = sensorList[i]; - virtualSensors[nVirtualSensors].sample_rate = sampleRate; - nVirtualSensors++; - } + for (uint8_t i = 0; i < nSensors; i++) { + virtualSensors[nVirtualSensors].sensor_id = sensorList[i]; + virtualSensors[nVirtualSensors].sample_rate = sampleRate; + nVirtualSensors++; + } - status = bsec_update_subscription(virtualSensors, nVirtualSensors, sensorSettings, &nSensorSettings); - return; + status = bsec_update_subscription(virtualSensors, nVirtualSensors, + sensorSettings, &nSensorSettings); + return; } /** - * @brief Callback from the user to trigger reading of data from the BME680, process and store outputs + * @brief Callback from the user to trigger reading of data from the BME680, + * process and store outputs */ -bool Bsec::run(void) -{ - bool newData = false; - /* Check if the time has arrived to call do_steps() */ - int64_t callTimeMs = getTimeMs(); - - if (callTimeMs >= nextCall) { - - bsec_bme_settings_t bme680Settings; +bool Bsec::run(void) { + bool newData = false; + /* Check if the time has arrived to call do_steps() */ + int64_t callTimeMs = getTimeMs(); - int64_t callTimeNs = callTimeMs * INT64_C(1000000); + if (callTimeMs >= nextCall) { - status = bsec_sensor_control(callTimeNs, &bme680Settings); - if (status < BSEC_OK) - return false; + bsec_bme_settings_t bme680Settings; - nextCall = bme680Settings.next_call / INT64_C(1000000); // Convert from ns to ms + int64_t callTimeNs = callTimeMs * INT64_C(1000000); - bme680Status = setBme680Config(bme680Settings); - if (bme680Status != BME680_OK) { - return false; - } + status = bsec_sensor_control(callTimeNs, &bme680Settings); + if (status < BSEC_OK) + return false; - bme680Status = bme680_set_sensor_mode(&_bme680); - if (bme680Status != BME680_OK) { - return false; - } + nextCall = + bme680Settings.next_call / INT64_C(1000000); // Convert from ns to ms - /* Wait for measurement to complete */ - uint16_t meas_dur = 0; + bme680Status = setBme680Config(bme680Settings); + if (bme680Status != BME680_OK) { + return false; + } - bme680_get_profile_dur(&meas_dur, &_bme680); - delay_ms(meas_dur); + bme680Status = bme680_set_sensor_mode(&_bme680); + if (bme680Status != BME680_OK) { + return false; + } - newData = readProcessData(callTimeNs, bme680Settings); - } - - return newData; + /* Wait for measurement to complete */ + uint16_t meas_dur = 0; + + bme680_get_profile_dur(&meas_dur, &_bme680); + delay_ms(meas_dur); + + newData = readProcessData(callTimeNs, bme680Settings); + } + + return newData; } /** - * @brief Function to get the state of the algorithm to save to non-volatile memory + * @brief Function to get the state of the algorithm to save to non-volatile + * memory */ -void Bsec::getState(uint8_t *state) -{ - uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE]; - uint32_t n_serialized_state = BSEC_MAX_STATE_BLOB_SIZE; - status = bsec_get_state(0, state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, BSEC_MAX_STATE_BLOB_SIZE, &n_serialized_state); +void Bsec::getState(uint8_t *state) { + uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE]; + uint32_t n_serialized_state = BSEC_MAX_STATE_BLOB_SIZE; + status = bsec_get_state(0, state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, + BSEC_MAX_STATE_BLOB_SIZE, &n_serialized_state); } /** * @brief Function to set the state of the algorithm from non-volatile memory */ -void Bsec::setState(uint8_t *state) -{ - uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE]; +void Bsec::setState(uint8_t *state) { + uint8_t workBuffer[BSEC_MAX_STATE_BLOB_SIZE]; - status = bsec_set_state(state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, BSEC_MAX_STATE_BLOB_SIZE); + status = bsec_set_state(state, BSEC_MAX_STATE_BLOB_SIZE, workBuffer, + BSEC_MAX_STATE_BLOB_SIZE); } /** * @brief Function to set the configuration of the algorithm from memory */ -void Bsec::setConfig(const uint8_t *state) -{ - uint8_t workBuffer[BSEC_MAX_PROPERTY_BLOB_SIZE]; +void Bsec::setConfig(const uint8_t *state) { + uint8_t workBuffer[BSEC_MAX_PROPERTY_BLOB_SIZE]; - status = bsec_set_configuration(state, BSEC_MAX_PROPERTY_BLOB_SIZE, workBuffer, sizeof(workBuffer)); + status = bsec_set_configuration(state, BSEC_MAX_PROPERTY_BLOB_SIZE, + workBuffer, sizeof(workBuffer)); } /* Private functions */ @@ -234,260 +233,266 @@ void Bsec::setConfig(const uint8_t *state) /** * @brief Get the version of the BSEC library */ -void Bsec::getVersion(void) -{ - bsec_get_version(&version); -} +void Bsec::getVersion(void) { bsec_get_version(&version); } /** * @brief Read data from the BME680 and process it */ -bool Bsec::readProcessData(int64_t currTimeNs, bsec_bme_settings_t bme680Settings) -{ - bme680Status = bme680_get_sensor_data(&_data, &_bme680); - if (bme680Status != BME680_OK) { - return false; - } +bool Bsec::readProcessData(int64_t currTimeNs, + bsec_bme_settings_t bme680Settings) { + bme680Status = bme680_get_sensor_data(&_data, &_bme680); + if (bme680Status != BME680_OK) { + return false; + } - bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temp, Pres, Hum & Gas - uint8_t nInputs = 0, nOutputs = 0; + bsec_input_t inputs[BSEC_MAX_PHYSICAL_SENSOR]; // Temp, Pres, Hum & Gas + uint8_t nInputs = 0, nOutputs = 0; - if (_data.status & BME680_NEW_DATA_MSK) { - if (bme680Settings.process_data & BSEC_PROCESS_TEMPERATURE) { - inputs[nInputs].sensor_id = BSEC_INPUT_TEMPERATURE; - inputs[nInputs].signal = _data.temperature; - inputs[nInputs].time_stamp = currTimeNs; - nInputs++; - /* Temperature offset from the real temperature due to external heat sources */ - inputs[nInputs].sensor_id = BSEC_INPUT_HEATSOURCE; - inputs[nInputs].signal = _tempOffset; - inputs[nInputs].time_stamp = currTimeNs; - nInputs++; - } - if (bme680Settings.process_data & BSEC_PROCESS_HUMIDITY) { - inputs[nInputs].sensor_id = BSEC_INPUT_HUMIDITY; - inputs[nInputs].signal = _data.humidity; - inputs[nInputs].time_stamp = currTimeNs; - nInputs++; - } - if (bme680Settings.process_data & BSEC_PROCESS_PRESSURE) { - inputs[nInputs].sensor_id = BSEC_INPUT_PRESSURE; - inputs[nInputs].signal = _data.pressure; - inputs[nInputs].time_stamp = currTimeNs; - nInputs++; - } - if (bme680Settings.process_data & BSEC_PROCESS_GAS) { - inputs[nInputs].sensor_id = BSEC_INPUT_GASRESISTOR; - inputs[nInputs].signal = _data.gas_resistance; - inputs[nInputs].time_stamp = currTimeNs; - nInputs++; - } - } + if (_data.status & BME680_NEW_DATA_MSK) { + if (bme680Settings.process_data & BSEC_PROCESS_TEMPERATURE) { + inputs[nInputs].sensor_id = BSEC_INPUT_TEMPERATURE; +#ifdef BME680_FLOAT_POINT_COMPENSATION + inputs[nInputs].signal = _data.temperature; +#else + inputs[nInputs].signal = _data.temperature / 100.0f; +#endif + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + /* Temperature offset from the real temperature due to external heat + * sources */ + inputs[nInputs].sensor_id = BSEC_INPUT_HEATSOURCE; + inputs[nInputs].signal = _tempOffset; + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + if (bme680Settings.process_data & BSEC_PROCESS_HUMIDITY) { + inputs[nInputs].sensor_id = BSEC_INPUT_HUMIDITY; +#ifdef BME680_FLOAT_POINT_COMPENSATION + inputs[nInputs].signal = _data.humidity; +#else + inputs[nInputs].signal = _data.humidity / 1000.0f; +#endif + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + if (bme680Settings.process_data & BSEC_PROCESS_PRESSURE) { + inputs[nInputs].sensor_id = BSEC_INPUT_PRESSURE; + inputs[nInputs].signal = _data.pressure; + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + if (bme680Settings.process_data & BSEC_PROCESS_GAS) { + inputs[nInputs].sensor_id = BSEC_INPUT_GASRESISTOR; + inputs[nInputs].signal = _data.gas_resistance; + inputs[nInputs].time_stamp = currTimeNs; + nInputs++; + } + } - if (nInputs > 0) { - nOutputs = BSEC_NUMBER_OUTPUTS; - bsec_output_t _outputs[BSEC_NUMBER_OUTPUTS]; + if (nInputs > 0) { + nOutputs = BSEC_NUMBER_OUTPUTS; + bsec_output_t _outputs[BSEC_NUMBER_OUTPUTS]; - status = bsec_do_steps(inputs, nInputs, _outputs, &nOutputs); - if (status != BSEC_OK) - return false; + status = bsec_do_steps(inputs, nInputs, _outputs, &nOutputs); + if (status != BSEC_OK) + return false; - zeroOutputs(); + zeroOutputs(); - if (nOutputs > 0) { - outputTimestamp = _outputs[0].time_stamp / 1000000; // Convert from ns to ms + if (nOutputs > 0) { + outputTimestamp = + _outputs[0].time_stamp / 1000000; // Convert from ns to ms - for (uint8_t i = 0; i < nOutputs; i++) { - switch (_outputs[i].sensor_id) { - case BSEC_OUTPUT_IAQ: - iaqEstimate = _outputs[i].signal; - iaqAccuracy = _outputs[i].accuracy; - break; - case BSEC_OUTPUT_STATIC_IAQ: - staticIaq = _outputs[i].signal; - staticIaqAccuracy = _outputs[i].accuracy; - break; - case BSEC_OUTPUT_CO2_EQUIVALENT: - co2Equivalent = _outputs[i].signal; - co2Accuracy = _outputs[i].accuracy; - break; - case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT: - breathVocEquivalent = _outputs[i].signal; - breathVocAccuracy = _outputs[i].accuracy; - break; - case BSEC_OUTPUT_RAW_TEMPERATURE: - rawTemperature = _outputs[i].signal; - break; - case BSEC_OUTPUT_RAW_PRESSURE: - pressure = _outputs[i].signal; - break; - case BSEC_OUTPUT_RAW_HUMIDITY: - rawHumidity = _outputs[i].signal; - break; - case BSEC_OUTPUT_RAW_GAS: - gasResistance = _outputs[i].signal; - break; - case BSEC_OUTPUT_STABILIZATION_STATUS: - stabStatus = _outputs[i].signal; - break; - case BSEC_OUTPUT_RUN_IN_STATUS: - runInStatus = _outputs[i].signal; - break; - case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE: - temperature = _outputs[i].signal; - break; - case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY: - humidity = _outputs[i].signal; - break; - case BSEC_OUTPUT_COMPENSATED_GAS: - compGasValue = _outputs[i].signal; - compGasAccuracy = _outputs[i].accuracy; - break; - case BSEC_OUTPUT_GAS_PERCENTAGE: - gasPercentage = _outputs[i].signal; - gasPercentageAcccuracy = _outputs[i].accuracy; - break; - default: - break; - } - } - return true; - } - } + for (uint8_t i = 0; i < nOutputs; i++) { + switch (_outputs[i].sensor_id) { + case BSEC_OUTPUT_IAQ: + iaqEstimate = _outputs[i].signal; + iaqAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_STATIC_IAQ: + staticIaq = _outputs[i].signal; + staticIaqAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_CO2_EQUIVALENT: + co2Equivalent = _outputs[i].signal; + co2Accuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_BREATH_VOC_EQUIVALENT: + breathVocEquivalent = _outputs[i].signal; + breathVocAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_RAW_TEMPERATURE: + rawTemperature = _outputs[i].signal; + break; + case BSEC_OUTPUT_RAW_PRESSURE: + pressure = _outputs[i].signal; + break; + case BSEC_OUTPUT_RAW_HUMIDITY: + rawHumidity = _outputs[i].signal; + break; + case BSEC_OUTPUT_RAW_GAS: + gasResistance = _outputs[i].signal; + break; + case BSEC_OUTPUT_STABILIZATION_STATUS: + stabStatus = _outputs[i].signal; + break; + case BSEC_OUTPUT_RUN_IN_STATUS: + runInStatus = _outputs[i].signal; + break; + case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_TEMPERATURE: + temperature = _outputs[i].signal; + break; + case BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY: + humidity = _outputs[i].signal; + break; + case BSEC_OUTPUT_COMPENSATED_GAS: + compGasValue = _outputs[i].signal; + compGasAccuracy = _outputs[i].accuracy; + break; + case BSEC_OUTPUT_GAS_PERCENTAGE: + gasPercentage = _outputs[i].signal; + gasPercentageAcccuracy = _outputs[i].accuracy; + break; + default: + break; + } + } + return true; + } + } - return false; + return false; } /** * @brief Set the BME680 sensor's configuration */ -int8_t Bsec::setBme680Config(bsec_bme_settings_t bme680Settings) -{ - _bme680.gas_sett.run_gas = bme680Settings.run_gas; - _bme680.tph_sett.os_hum = bme680Settings.humidity_oversampling; - _bme680.tph_sett.os_temp = bme680Settings.temperature_oversampling; - _bme680.tph_sett.os_pres = bme680Settings.pressure_oversampling; - _bme680.gas_sett.heatr_temp = bme680Settings.heater_temperature; - _bme680.gas_sett.heatr_dur = bme680Settings.heating_duration; - uint16_t desired_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | BME680_FILTER_SEL - | BME680_GAS_SENSOR_SEL; - return bme680_set_sensor_settings(desired_settings, &_bme680); +int8_t Bsec::setBme680Config(bsec_bme_settings_t bme680Settings) { + _bme680.gas_sett.run_gas = bme680Settings.run_gas; + _bme680.tph_sett.os_hum = bme680Settings.humidity_oversampling; + _bme680.tph_sett.os_temp = bme680Settings.temperature_oversampling; + _bme680.tph_sett.os_pres = bme680Settings.pressure_oversampling; + _bme680.gas_sett.heatr_temp = bme680Settings.heater_temperature; + _bme680.gas_sett.heatr_dur = bme680Settings.heating_duration; + uint16_t desired_settings = BME680_OST_SEL | BME680_OSP_SEL | BME680_OSH_SEL | + BME680_FILTER_SEL | BME680_GAS_SENSOR_SEL; + return bme680_set_sensor_settings(desired_settings, &_bme680); } /** * @brief Function to zero the outputs */ -void Bsec::zeroOutputs(void) -{ - temperature = 0.0f; - pressure = 0.0f; - humidity = 0.0f; - gasResistance = 0.0f; - rawTemperature = 0.0f; - rawHumidity = 0.0f; - stabStatus = 0.0f; - runInStatus = 0.0f; - iaqEstimate = 0.0f; - iaqAccuracy = 0; - staticIaq = 0.0f; - staticIaqAccuracy = 0; - co2Equivalent = 0.0f; - co2Accuracy = 0; - breathVocEquivalent = 0.0f; - breathVocAccuracy = 0; - compGasValue = 0.0f; - compGasAccuracy = 0; - gasPercentage = 0.0f; - gasPercentageAcccuracy = 0; +void Bsec::zeroOutputs(void) { + temperature = 0.0f; + pressure = 0.0f; + humidity = 0.0f; + gasResistance = 0.0f; + rawTemperature = 0.0f; + rawHumidity = 0.0f; + stabStatus = 0.0f; + runInStatus = 0.0f; + iaqEstimate = 0.0f; + iaqAccuracy = 0; + staticIaq = 0.0f; + staticIaqAccuracy = 0; + co2Equivalent = 0.0f; + co2Accuracy = 0; + breathVocEquivalent = 0.0f; + breathVocAccuracy = 0; + compGasValue = 0.0f; + compGasAccuracy = 0; + gasPercentage = 0.0f; + gasPercentageAcccuracy = 0; } /** * @brief Function to calculate an int64_t timestamp in milliseconds */ -int64_t Bsec::getTimeMs(void) -{ - int64_t timeMs = millis(); +int64_t Bsec::getTimeMs(void) { + int64_t timeMs = millis(); - if (lastTime > timeMs) { // An overflow occured - lastTime = timeMs; - millisOverflowCounter++; - } + if (lastTime > timeMs) { // An overflow occured + lastTime = timeMs; + millisOverflowCounter++; + } - return timeMs + (millisOverflowCounter * 0xFFFFFFFF); + return timeMs + (millisOverflowCounter * 0xFFFFFFFF); } /** @brief Task that delays for a ms period of time */ -void Bsec::delay_ms(uint32_t period) -{ - // Wait for a period amount of ms - // The system may simply idle, sleep or even perform background tasks - delay(period); +void Bsec::delay_ms(uint32_t period) { + // Wait for a period amount of ms + // The system may simply idle, sleep or even perform background tasks + delay(period); } /** @brief Callback function for reading registers over I2C */ -int8_t Bsec::i2cRead(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length) -{ - uint16_t i; - int8_t rslt = 0; - if(Bsec::wireObj) { - Bsec::wireObj->beginTransmission(devId); - Bsec::wireObj->write(regAddr); - rslt = Bsec::wireObj->endTransmission(); - Bsec::wireObj->requestFrom((int) devId, (int) length); - for (i = 0; (i < length) && Bsec::wireObj->available(); i++) { - regData[i] = Bsec::wireObj->read(); - } - } else { - rslt = -1; - } - return rslt; +int8_t Bsec::i2cRead(uint8_t devId, uint8_t regAddr, uint8_t *regData, + uint16_t length) { + uint16_t i; + int8_t rslt = 0; + if (Bsec::wireObj) { + Bsec::wireObj->beginTransmission(devId); + Bsec::wireObj->write(regAddr); + rslt = Bsec::wireObj->endTransmission(); + Bsec::wireObj->requestFrom((int)devId, (int)length); + for (i = 0; (i < length) && Bsec::wireObj->available(); i++) { + regData[i] = Bsec::wireObj->read(); + } + } else { + rslt = -1; + } + return rslt; } /** * @brief Callback function for writing registers over I2C */ -int8_t Bsec::i2cWrite(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length) -{ - uint16_t i; - int8_t rslt = 0; - if(Bsec::wireObj) { - Bsec::wireObj->beginTransmission(devId); - Bsec::wireObj->write(regAddr); - for (i = 0; i < length; i++) { - Bsec::wireObj->write(regData[i]); - } - rslt = Bsec::wireObj->endTransmission(); - } else { - rslt = -1; - } +int8_t Bsec::i2cWrite(uint8_t devId, uint8_t regAddr, uint8_t *regData, + uint16_t length) { + uint16_t i; + int8_t rslt = 0; + if (Bsec::wireObj) { + Bsec::wireObj->beginTransmission(devId); + Bsec::wireObj->write(regAddr); + for (i = 0; i < length; i++) { + Bsec::wireObj->write(regData[i]); + } + rslt = Bsec::wireObj->endTransmission(); + } else { + rslt = -1; + } - return rslt; + return rslt; } /** * @brief Callback function for reading and writing registers over SPI */ -int8_t Bsec::spiTransfer(uint8_t devId, uint8_t regAddr, uint8_t *regData, uint16_t length) -{ - int8_t rslt = 0; - if(Bsec::spiObj) { - Bsec::spiObj->beginTransaction(SPISettings(4000000, MSBFIRST, SPI_MODE0)); // Can be upto 10MHz - - digitalWrite(devId, LOW); +int8_t Bsec::spiTransfer(uint8_t devId, uint8_t regAddr, uint8_t *regData, + uint16_t length) { + int8_t rslt = 0; + if (Bsec::spiObj) { + Bsec::spiObj->beginTransaction( + SPISettings(4000000, MSBFIRST, SPI_MODE0)); // Can be upto 10MHz - Bsec::spiObj->transfer(regAddr); // Write the register address, ignore the return - for (uint16_t i = 0; i < length; i++) - regData[i] = Bsec::spiObj->transfer(regData[i]); + digitalWrite(devId, LOW); - digitalWrite(devId, HIGH); - Bsec::spiObj->endTransaction(); - } else { - rslt = -1; - } + Bsec::spiObj->transfer( + regAddr); // Write the register address, ignore the return + for (uint16_t i = 0; i < length; i++) + regData[i] = Bsec::spiObj->transfer(regData[i]); - return rslt;; + digitalWrite(devId, HIGH); + Bsec::spiObj->endTransaction(); + } else { + rslt = -1; + } + + return rslt; + ; } \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index 0922cb7a..ecbbf0de 100644 --- a/platformio.ini +++ b/platformio.ini @@ -33,7 +33,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng release_version = 1.7.03 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose -debug_level = 4 +debug_level = 3 ; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA upload_protocol = esptool ;upload_protocol = custom diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index d5f08662..58570dda 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -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 diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 80e16f1f..0ce0c657 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -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 diff --git a/src/display.cpp b/src/display.cpp index 7427562d..861328fd 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -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 \ No newline at end of file diff --git a/src/hal/ttgobeam_new.h b/src/hal/ttgobeam_new.h index 814e59c1..d177e033 100644 --- a/src/hal/ttgobeam_new.h +++ b/src/hal/ttgobeam_new.h @@ -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 diff --git a/src/hal/ttgobeam_old.h b/src/hal/ttgobeam_old.h index f8e530fc..f6fd4531 100644 --- a/src/hal/ttgobeam_old.h +++ b/src/hal/ttgobeam_old.h @@ -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 diff --git a/src/main.cpp b/src/main.cpp index 37d71674..29aa32cb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 From 330b3045d47d5ffbb249ce5333a5dca778737691 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 28 Dec 2018 20:23:17 +0100 Subject: [PATCH 24/37] append gps data to counter data --- src/senddata.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/senddata.cpp b/src/senddata.cpp index 9c99769c..fe03be25 100644 --- a/src/senddata.cpp +++ b/src/senddata.cpp @@ -43,6 +43,18 @@ void sendCounter() { payload.addCount(macs_wifi, MAC_SNIFF_WIFI); if (cfg.blescan) payload.addCount(macs_ble, MAC_SNIFF_BLE); + +#ifdef HAS_GPS + if (gps.location.isValid()) { // send GPS position only if we have a fix + gps_read(); + payload.addGPS(gps_status); + } else { + ESP_LOGD( + TAG, + "No valid GPS position. GPS data not appended to counter data."); + } +#endif + SendPayload(COUNTERPORT); // clear counter if not in cumulative counter mode if (cfg.countermode != 1) { From 184e1e7d8465d4f73e96900c3fe4ac1e524dfc94 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 28 Dec 2018 21:04:11 +0100 Subject: [PATCH 25/37] hal files lopy.h, lopy4.h adapted to current pins_arduino.h --- src/hal/lopy.h | 4 +--- src/hal/lopy4.h | 6 +----- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/hal/lopy.h b/src/hal/lopy.h index 55699366..be36175b 100644 --- a/src/hal/lopy.h +++ b/src/hal/lopy.h @@ -12,9 +12,7 @@ #define HAS_LED NOT_A_PIN // LoPy4 has no on board mono LED, we use on board RGB LED #define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 -// Pins for LORA chip SPI interface come from board file, we need some -// additional definitions for LMIC -#define LORA_IRQ (23) +// Note: Pins for LORA chip SPI interface come from board file pins_arduino.h // select WIFI antenna (internal = onboard / external = u.fl socket) #define HAS_ANTENNA_SWITCH (16) // pin for switching wifi antenna diff --git a/src/hal/lopy4.h b/src/hal/lopy4.h index 242fe275..badd4f8b 100644 --- a/src/hal/lopy4.h +++ b/src/hal/lopy4.h @@ -21,11 +21,7 @@ #define HAS_RGB_LED (0) // WS2812B RGB LED on GPIO0 (P2) #define BOARD_HAS_PSRAM // use extra 4MB extern RAM -// Pins for LORA chip SPI interface come from board file, we need some -// additional definitions for LMIC -#define LORA_IRQ (23) -#define LORA_RST NOT_A_PIN -#define SS 18 +// Note: Pins for LORA chip SPI interface come from board file pins_arduino.h // select WIFI antenna (internal = onboard / external = u.fl socket) #define HAS_ANTENNA_SWITCH (21) // pin for switching wifi antenna (P12) From f26b7a545c3e6559ea42570cacac25d32c55c435 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 31 Dec 2018 11:26:05 +0100 Subject: [PATCH 26/37] bsecstate load/save implemented; bugfix packed_decoder.js --- include/bme680mems.h | 3 +++ include/cyclic.h | 4 ++++ include/globals.h | 3 ++- platformio.ini | 8 +++---- src/TTN/packed_decoder.js | 6 ++++- src/bme680mems.cpp | 48 ++++++++++++++++++++++++++++++++++++--- src/configmanager.cpp | 19 +++++++++++++++- src/cyclic.cpp | 1 + src/hal/ttgobeam_new.h | 12 +++++----- src/paxcounter.conf | 2 ++ 10 files changed, 90 insertions(+), 16 deletions(-) diff --git a/include/bme680mems.h b/include/bme680mems.h index 5532f0cc..00742ff9 100644 --- a/include/bme680mems.h +++ b/include/bme680mems.h @@ -47,8 +47,11 @@ const uint8_t bsec_config_iaq[454] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 44, 1, 0, 0, 0, 0, 239, 79, 0, 0}; +// Helper functions declarations int bme_init(); void bme_loop(void *pvParameters); int checkIaqSensorStatus(void); +void loadState(void); +void updateState(void); #endif \ No newline at end of file diff --git a/include/cyclic.h b/include/cyclic.h index 1c4da4dd..6e5df0cd 100644 --- a/include/cyclic.h +++ b/include/cyclic.h @@ -7,6 +7,10 @@ #include "spislave.h" #include +#ifdef HAS_BME +#include "bme680mems.h" +#endif + void doHousekeeping(void); void do_timesync(void); uint64_t uptime(void); diff --git a/include/globals.h b/include/globals.h index 7fda0d29..261c1fb8 100644 --- a/include/globals.h +++ b/include/globals.h @@ -54,6 +54,7 @@ typedef struct { uint8_t runmode; // 0=normal, 1=update uint8_t payloadmask; // bitswitches for payload data char version[10]; // Firmware version + char bsecstate[BSEC_MAX_STATE_BLOB_SIZE+1]; // init BSEC state for BME680 sensor } configData_t; // Struct holding payload for data send queue @@ -87,7 +88,7 @@ extern configData_t cfg; // current device configuration extern char display_line6[], display_line7[]; // screen buffers extern uint8_t volatile channel; // wifi channel rotation counter extern uint16_t volatile macs_total, macs_wifi, macs_ble, - batt_voltage; // display values + batt_voltage; // display values extern hw_timer_t *channelSwitch, *sendCycle, *displaytimer; extern SemaphoreHandle_t I2Caccess; diff --git a/platformio.ini b/platformio.ini index ecbbf0de..59e70845 100644 --- a/platformio.ini +++ b/platformio.ini @@ -6,7 +6,7 @@ ; ---> SELECT TARGET PLATFORM HERE! <--- [platformio] -;env_default = generic +env_default = generic ;env_default = ebox ;env_default = eboxtube ;env_default = heltec @@ -16,7 +16,7 @@ ;env_default = ttgov21old ;env_default = ttgov21new ;env_default = ttgobeam_old -env_default = ttgobeam_new +;env_default = ttgobeam_new ;env_default = lopy ;env_default = lopy4 ;env_default = fipy @@ -30,10 +30,10 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.7.03 +release_version = 1.7.06 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose -debug_level = 3 +debug_level = 0 ; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA upload_protocol = esptool ;upload_protocol = custom diff --git a/src/TTN/packed_decoder.js b/src/TTN/packed_decoder.js index c8f319a2..a99f44c6 100644 --- a/src/TTN/packed_decoder.js +++ b/src/TTN/packed_decoder.js @@ -18,7 +18,11 @@ function Decoder(bytes, port) { if (bytes.length === 4) { return decode(bytes, [uint16, uint16], ['wifi', 'ble']); } - // combined counter and gps data + // combined wifi counter and gps data + if (bytes.length === 15) { + return decode(bytes, [uint16, latLng, latLng, uint8, hdop, uint16], ['wifi', 'latitude', 'longitude', 'sats', 'hdop', 'altitude']); + } + // combined wifi + ble counter and gps data if (bytes.length === 17) { return decode(bytes, [uint16, uint16, latLng, latLng, uint8, hdop, uint16], ['wifi', 'ble', 'latitude', 'longitude', 'sats', 'hdop', 'altitude']); } diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index 58570dda..19111ba3 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -23,9 +23,12 @@ bsec_virtual_sensor_t sensorList[10] = { BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, }; +uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0}; +uint16_t stateUpdateCounter = 0; + // initialize BME680 sensor int bme_init(void) { - + // block i2c bus access if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == pdTRUE) { @@ -46,6 +49,8 @@ int bme_init(void) { return 1; } + loadState(); + iaqSensor.setTemperatureOffset((float)BME_TEMP_OFFSET); iaqSensor.updateSubscription(sensorList, 10, BSEC_SAMPLE_RATE_LP); @@ -99,7 +104,6 @@ void bme_loop(void *pvParameters) { // 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; @@ -111,7 +115,6 @@ void bme_loop(void *pvParameters) { bme_status.iaq_accuracy = iaqSensor.iaqAccuracy; bme_status.gas = iaqSensor.gasResistance; } - xSemaphoreGive(I2Caccess); // release i2c bus access } } @@ -121,4 +124,43 @@ void bme_loop(void *pvParameters) { } // bme_loop() +void loadState(void) { + if (cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] == BSEC_MAX_STATE_BLOB_SIZE) { + // Existing state in NVS stored + ESP_LOGI(TAG, "restoring BSEC state from NVRAM"); + memcpy(bsecState, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); + iaqSensor.setState(bsecState); + checkIaqSensorStatus(); + } else // no state stored + ESP_LOGI(TAG, + "no BSEC state stored in NVRAM, starting sensor with defaults"); +} + +void updateState(void) { + bool update = false; + + if (stateUpdateCounter == 0) { + /* First state update when IAQ accuracy is >= 1 */ + if (iaqSensor.iaqAccuracy >= 3) { + update = true; + stateUpdateCounter++; + } + } else { + /* Update every STATE_SAVE_PERIOD minutes */ + if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) { + update = true; + stateUpdateCounter++; + } + } + + if (update) { + memcpy(bsecState, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); + cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] = BSEC_MAX_STATE_BLOB_SIZE; + iaqSensor.getState(bsecState); + checkIaqSensorStatus(); + ESP_LOGI(TAG, "saving BSEC state to NVRAM"); + saveConfig(); + } +} + #endif // HAS_BME \ No newline at end of file diff --git a/src/configmanager.cpp b/src/configmanager.cpp index 5c6ebf98..ba5ed25e 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -32,6 +32,8 @@ void defaultConfig() { cfg.monitormode = 0; // 0=disabled, 1=enabled cfg.runmode = 0; // 0=normal, 1=update cfg.payloadmask = 0xFF; // all payload switched on + cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] = { + 0}; // init BSEC state for BME680 sensor strncpy(cfg.version, PROGVERSION, sizeof(cfg.version) - 1); } @@ -78,6 +80,12 @@ void saveConfig() { int16_t flash16 = 0; size_t required_size; char storedversion[10]; + char bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; + + if (nvs_get_str(my_handle, "bsecstate", bsecstate, &required_size) != + ESP_OK || + strcmp(bsecstate, cfg.bsecstate) != 0) + nvs_set_str(my_handle, "bsecstate", cfg.bsecstate); if (nvs_get_str(my_handle, "version", storedversion, &required_size) != ESP_OK || @@ -202,7 +210,16 @@ void loadConfig() { migrateVersion(); } - // overwrite defaults with valid values from NVRAM + // populate pre set defaults with current values from NVRAM + + char bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; + + if (nvs_get_str(my_handle, "bsecstate", NULL, &required_size) == ESP_OK) { + nvs_get_str(my_handle, "bsecstate", cfg.bsecstate, &required_size); + ESP_LOGI(TAG, "bsecstate = %d", + cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]); + } + if (nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK) { cfg.lorasf = flash8; ESP_LOGI(TAG, "lorasf = %d", flash8); diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 0ce0c657..237a86be 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -58,6 +58,7 @@ void doHousekeeping() { // display BME sensor data if present #ifdef HAS_BME ESP_LOGI(TAG, "BME680 Temp: %.2f°C | IAQ: %.2f", bme_status.temperature, bme_status.iaq); + updateState(); #endif // check free heap memory diff --git a/src/hal/ttgobeam_new.h b/src/hal/ttgobeam_new.h index d177e033..3751e436 100644 --- a/src/hal/ttgobeam_new.h +++ b/src/hal/ttgobeam_new.h @@ -11,18 +11,18 @@ // enable only if device has these sensors, otherwise comment these lines // BME680 sensor on I2C bus -#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL -#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND +//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +//#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND #define HAS_LED GPIO_NUM_14 // on board green LED // 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 U8X8_PIN_NONE +//#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 diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 2254533a..6293b4af 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -72,6 +72,8 @@ // Settings for BME680 environmental sensor (if present) #define BME_TEMP_OFFSET 5.0f // Offset sensor on chip temp <-> ambient temp [default = 5°C] +#define BSEC_MAX_STATE_BLOB_SIZE 134 // size of Bosch BME680 state data blob +#define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // update every 360 minutes = 4 times a day // OTA settings #define USE_OTA 1 // Comment out to disable OTA update From 7040408513cf2489c89ef93521d636c9fe73c7f5 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 31 Dec 2018 11:32:19 +0100 Subject: [PATCH 27/37] update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2214012c..74f8a44c 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,8 @@ Hereafter described is the default *plain* format, which uses MSB bit numbering. **Port #1:** Paxcount data byte 1-2: Number of unique pax, first seen on Wifi - byte 3-4: Number of unique pax, first seen on Bluetooth [0 if BT disabled] + byte 3-4: Number of unique pax, first seen on Bluetooth [omited if BT disabled] + bytes 5-17: GPS data, if present, in same format as for Port #4 **Port #2:** Device status query result From 998e122f3a9101883cd4a8c5313a28cba8be872e Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 31 Dec 2018 15:46:52 +0100 Subject: [PATCH 28/37] BME680 bugfixes --- include/bme680mems.h | 1 - include/globals.h | 12 +++++++----- src/bme680mems.cpp | 29 ++++++++++++++++++----------- src/configmanager.cpp | 10 ++++------ src/paxcounter.conf | 1 - 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/include/bme680mems.h b/include/bme680mems.h index 00742ff9..a97e0605 100644 --- a/include/bme680mems.h +++ b/include/bme680mems.h @@ -3,7 +3,6 @@ #include "globals.h" #include -#include "irqhandler.h" #include "../lib/Bosch-BSEC/src/bsec.h" extern bmeStatus_t diff --git a/include/globals.h b/include/globals.h index 261c1fb8..4203cef9 100644 --- a/include/globals.h +++ b/include/globals.h @@ -9,6 +9,7 @@ #include #include #include "Mallocator.h" +#include "inc/bsec_datatypes.h" // sniffing types #define MAC_SNIFF_WIFI 0 @@ -54,7 +55,7 @@ typedef struct { uint8_t runmode; // 0=normal, 1=update uint8_t payloadmask; // bitswitches for payload data char version[10]; // Firmware version - char bsecstate[BSEC_MAX_STATE_BLOB_SIZE+1]; // init BSEC state for BME680 sensor + char bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 2]; // init BSEC state for BME680 sensor } configData_t; // Struct holding payload for data send queue @@ -98,6 +99,7 @@ extern std::array beacons; extern TaskHandle_t irqHandlerTask, wifiSwitchTask; +// application includes #include "led.h" #include "payload.h" #include "blescan.h" @@ -106,10 +108,6 @@ extern TaskHandle_t irqHandlerTask, wifiSwitchTask; #include "gpsread.h" #endif -#ifdef HAS_BME -#include "bme680mems.h" -#endif - #ifdef HAS_LORA #include "lorawan.h" #endif @@ -134,4 +132,8 @@ extern TaskHandle_t irqHandlerTask, wifiSwitchTask; #include "sensor.h" #endif +#ifdef HAS_BME +#include "bme680mems.h" +#endif + #endif \ No newline at end of file diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index 19111ba3..802221e3 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -23,12 +23,14 @@ bsec_virtual_sensor_t sensorList[10] = { BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, }; -uint8_t bsecState[BSEC_MAX_STATE_BLOB_SIZE] = {0}; +uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE] = {0}; uint16_t stateUpdateCounter = 0; // initialize BME680 sensor int bme_init(void) { - + + // return = 0 -> error / return = 1 -> success + // block i2c bus access if (xSemaphoreTake(I2Caccess, (DISPLAYREFRESH_MS / portTICK_PERIOD_MS)) == pdTRUE) { @@ -46,7 +48,7 @@ int bme_init(void) { ESP_LOGI(TAG, "BME680 sensor found and initialized"); else { ESP_LOGE(TAG, "BME680 sensor not found"); - return 1; + goto error; } loadState(); @@ -58,16 +60,21 @@ int bme_init(void) { ESP_LOGI(TAG, "BSEC subscription succesful"); else { ESP_LOGE(TAG, "BSEC subscription error"); - return 1; + goto error; } - xSemaphoreGive(I2Caccess); // release i2c bus access - } else { ESP_LOGE(TAG, "I2c bus busy - BME680 initialization error"); - return 1; + goto error; } + xSemaphoreGive(I2Caccess); // release i2c bus access + return 1; + +error: + xSemaphoreGive(I2Caccess); // release i2c bus access + return 0; + } // bme_init() // Helper function definitions @@ -128,8 +135,8 @@ void loadState(void) { if (cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] == BSEC_MAX_STATE_BLOB_SIZE) { // Existing state in NVS stored ESP_LOGI(TAG, "restoring BSEC state from NVRAM"); - memcpy(bsecState, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); - iaqSensor.setState(bsecState); + memcpy(bsecstate_buffer, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); + iaqSensor.setState(bsecstate_buffer); checkIaqSensorStatus(); } else // no state stored ESP_LOGI(TAG, @@ -154,9 +161,9 @@ void updateState(void) { } if (update) { - memcpy(bsecState, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); + memcpy(bsecstate_buffer, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] = BSEC_MAX_STATE_BLOB_SIZE; - iaqSensor.getState(bsecState); + iaqSensor.getState(bsecstate_buffer); checkIaqSensorStatus(); ESP_LOGI(TAG, "saving BSEC state to NVRAM"); saveConfig(); diff --git a/src/configmanager.cpp b/src/configmanager.cpp index ba5ed25e..b59349ad 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -80,11 +80,11 @@ void saveConfig() { int16_t flash16 = 0; size_t required_size; char storedversion[10]; - char bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; + char bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE + 1]; - if (nvs_get_str(my_handle, "bsecstate", bsecstate, &required_size) != + if (nvs_get_str(my_handle, "bsecstate", bsecstate_buffer, &required_size) != ESP_OK || - strcmp(bsecstate, cfg.bsecstate) != 0) + strcmp(bsecstate_buffer, cfg.bsecstate) != 0) nvs_set_str(my_handle, "bsecstate", cfg.bsecstate); if (nvs_get_str(my_handle, "version", storedversion, &required_size) != @@ -212,12 +212,10 @@ void loadConfig() { // populate pre set defaults with current values from NVRAM - char bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; - if (nvs_get_str(my_handle, "bsecstate", NULL, &required_size) == ESP_OK) { nvs_get_str(my_handle, "bsecstate", cfg.bsecstate, &required_size); ESP_LOGI(TAG, "bsecstate = %d", - cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]); + (int)(cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1])); } if (nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK) { diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 6293b4af..007561c2 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -72,7 +72,6 @@ // Settings for BME680 environmental sensor (if present) #define BME_TEMP_OFFSET 5.0f // Offset sensor on chip temp <-> ambient temp [default = 5°C] -#define BSEC_MAX_STATE_BLOB_SIZE 134 // size of Bosch BME680 state data blob #define STATE_SAVE_PERIOD UINT32_C(360 * 60 * 1000) // update every 360 minutes = 4 times a day // OTA settings From bdae511c061f8ef6acf7337a5d98db4aa2e7c8da Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 31 Dec 2018 16:42:09 +0100 Subject: [PATCH 29/37] globals.h: BSEC path changed --- include/globals.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/include/globals.h b/include/globals.h index 4203cef9..d279588a 100644 --- a/include/globals.h +++ b/include/globals.h @@ -9,7 +9,8 @@ #include #include #include "Mallocator.h" -#include "inc/bsec_datatypes.h" +//#include "inc/bsec_datatypes.h" +#include "../lib/Bosch-BSEC/src/inc/bsec_datatypes.h" // sniffing types #define MAC_SNIFF_WIFI 0 @@ -55,7 +56,7 @@ typedef struct { uint8_t runmode; // 0=normal, 1=update uint8_t payloadmask; // bitswitches for payload data char version[10]; // Firmware version - char bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 2]; // init BSEC state for BME680 sensor + char bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 2]; // BSEC state for BME680 sensor } configData_t; // Struct holding payload for data send queue From fadbd2d38d7cedd5ba129322c79e9cfe6ffbc1fd Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Mon, 31 Dec 2018 21:53:13 +0100 Subject: [PATCH 30/37] fixes in ttgobeam_old.h --- src/hal/ttgobeam_old.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hal/ttgobeam_old.h b/src/hal/ttgobeam_old.h index f6fd4531..5555636e 100644 --- a/src/hal/ttgobeam_old.h +++ b/src/hal/ttgobeam_old.h @@ -9,10 +9,9 @@ // enable only if device has these sensors, otherwise comment these lines // BME680 sensor on I2C bus -// attention: Pin21 is also LED! set HAS_LED to NOT_A_PIN if using BME280 -// don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 //#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL -//#define HAS_LED NOT_A_PIN // on board green LED +//#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND +//#define HAS_LED NOT_A_PIN // on board green LED uses same GPIO as SDA! #define HAS_LED GPIO_NUM_21 // on board green LED From a0a96b36dd022567ba581e2e6f2f348165e35b46 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Tue, 1 Jan 2019 13:48:32 +0100 Subject: [PATCH 31/37] packed_converter.js: bugfix --- src/TTN/packed_converter.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/TTN/packed_converter.js b/src/TTN/packed_converter.js index 8585aa42..7548e3ce 100644 --- a/src/TTN/packed_converter.js +++ b/src/TTN/packed_converter.js @@ -7,19 +7,19 @@ function Converter(decoded, port) { var pax = 0; if (port === 1) { - - for (var x in converted) { - pax += converted[x]; - } - - converted.pax = pax; - + if('wifi' in converted){ + pax += converted.wifi + } + + if('ble' in converted){ + pax += converted.ble + } + converted.pax = pax; } if (port === 2) { converted.voltage /= 1000; } - return converted; } \ No newline at end of file From 8267e4e3b614c7a8334dd6f47717e51089ad5043 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Tue, 1 Jan 2019 14:59:00 +0100 Subject: [PATCH 32/37] BME680: bugfix save state --- src/bme680mems.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index 802221e3..b11c02e4 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -147,7 +147,7 @@ void updateState(void) { bool update = false; if (stateUpdateCounter == 0) { - /* First state update when IAQ accuracy is >= 1 */ + /* First state update when IAQ accuracy is >= 3 */ if (iaqSensor.iaqAccuracy >= 3) { update = true; stateUpdateCounter++; @@ -161,10 +161,10 @@ void updateState(void) { } if (update) { - memcpy(bsecstate_buffer, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); - cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] = BSEC_MAX_STATE_BLOB_SIZE; iaqSensor.getState(bsecstate_buffer); checkIaqSensorStatus(); + memcpy(cfg.bsecstate, bsecstate_buffer, BSEC_MAX_STATE_BLOB_SIZE); + cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] = BSEC_MAX_STATE_BLOB_SIZE; ESP_LOGI(TAG, "saving BSEC state to NVRAM"); saveConfig(); } From 0fd36b0051547170fc53d029dd0d57265758e9bd Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Tue, 1 Jan 2019 21:23:45 +0100 Subject: [PATCH 33/37] BME680 state load/save bugfixes --- include/globals.h | 2 +- src/bme680mems.cpp | 10 ++++++---- src/configmanager.cpp | 25 +++++++++++++------------ src/cyclic.cpp | 2 +- 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/include/globals.h b/include/globals.h index d279588a..bff3fc78 100644 --- a/include/globals.h +++ b/include/globals.h @@ -56,7 +56,7 @@ typedef struct { uint8_t runmode; // 0=normal, 1=update uint8_t payloadmask; // bitswitches for payload data char version[10]; // Firmware version - char bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 2]; // BSEC state for BME680 sensor + uint8_t bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1]; // BSEC state for BME680 sensor } configData_t; // Struct holding payload for data send queue diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index b11c02e4..f888eb4e 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -23,7 +23,6 @@ bsec_virtual_sensor_t sensorList[10] = { BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, }; -uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE] = {0}; uint16_t stateUpdateCounter = 0; // initialize BME680 sensor @@ -132,7 +131,8 @@ void bme_loop(void *pvParameters) { } // bme_loop() void loadState(void) { - if (cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] == BSEC_MAX_STATE_BLOB_SIZE) { + uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE] = {0}; + if (cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] == BSEC_MAX_STATE_BLOB_SIZE) { // Existing state in NVS stored ESP_LOGI(TAG, "restoring BSEC state from NVRAM"); memcpy(bsecstate_buffer, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE); @@ -145,14 +145,16 @@ void loadState(void) { void updateState(void) { bool update = false; + uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE] = {0}; if (stateUpdateCounter == 0) { - /* First state update when IAQ accuracy is >= 3 */ + // first state update when IAQ accuracy is >= 3 if (iaqSensor.iaqAccuracy >= 3) { update = true; stateUpdateCounter++; } } else { + /* Update every STATE_SAVE_PERIOD minutes */ if ((stateUpdateCounter * STATE_SAVE_PERIOD) < millis()) { update = true; @@ -164,7 +166,7 @@ void updateState(void) { iaqSensor.getState(bsecstate_buffer); checkIaqSensorStatus(); memcpy(cfg.bsecstate, bsecstate_buffer, BSEC_MAX_STATE_BLOB_SIZE); - cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] = BSEC_MAX_STATE_BLOB_SIZE; + cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = BSEC_MAX_STATE_BLOB_SIZE; ESP_LOGI(TAG, "saving BSEC state to NVRAM"); saveConfig(); } diff --git a/src/configmanager.cpp b/src/configmanager.cpp index b59349ad..dd4fdcbd 100644 --- a/src/configmanager.cpp +++ b/src/configmanager.cpp @@ -32,7 +32,7 @@ void defaultConfig() { cfg.monitormode = 0; // 0=disabled, 1=enabled cfg.runmode = 0; // 0=normal, 1=update cfg.payloadmask = 0xFF; // all payload switched on - cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1] = { + cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] = { 0}; // init BSEC state for BME680 sensor strncpy(cfg.version, PROGVERSION, sizeof(cfg.version) - 1); @@ -79,13 +79,14 @@ void saveConfig() { int8_t flash8 = 0; int16_t flash16 = 0; size_t required_size; + uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE + 1]; char storedversion[10]; - char bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE + 1]; - if (nvs_get_str(my_handle, "bsecstate", bsecstate_buffer, &required_size) != - ESP_OK || - strcmp(bsecstate_buffer, cfg.bsecstate) != 0) - nvs_set_str(my_handle, "bsecstate", cfg.bsecstate); + if (nvs_get_blob(my_handle, "bsecstate", bsecstate_buffer, + &required_size) != ESP_OK || + memcmp(bsecstate_buffer, cfg.bsecstate, BSEC_MAX_STATE_BLOB_SIZE + 1) != 0) + nvs_set_blob(my_handle, "bsecstate", cfg.bsecstate, + BSEC_MAX_STATE_BLOB_SIZE + 1); if (nvs_get_str(my_handle, "version", storedversion, &required_size) != ESP_OK || @@ -212,11 +213,11 @@ void loadConfig() { // populate pre set defaults with current values from NVRAM - if (nvs_get_str(my_handle, "bsecstate", NULL, &required_size) == ESP_OK) { - nvs_get_str(my_handle, "bsecstate", cfg.bsecstate, &required_size); + if (nvs_get_blob(my_handle, "bsecstate", NULL, &required_size) == ESP_OK) { + nvs_get_blob(my_handle, "bsecstate", cfg.bsecstate, &required_size); ESP_LOGI(TAG, "bsecstate = %d", - (int)(cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE + 1])); - } + cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE]); + }; if (nvs_get_i8(my_handle, "lorasf", &flash8) == ESP_OK) { cfg.lorasf = flash8; @@ -332,9 +333,9 @@ void loadConfig() { if (nvs_get_i8(my_handle, "payloadmask", &flash8) == ESP_OK) { cfg.payloadmask = flash8; - ESP_LOGI(TAG, "payloadmask = %u", flash8); + ESP_LOGI(TAG, "payloadmask = %d", flash8); } else { - ESP_LOGI(TAG, "payloadmask set to default %u", cfg.payloadmask); + ESP_LOGI(TAG, "payloadmask set to default %d", cfg.payloadmask); saveConfig(); } diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 237a86be..89564b01 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -57,7 +57,7 @@ void doHousekeeping() { // display BME sensor data if present #ifdef HAS_BME - ESP_LOGI(TAG, "BME680 Temp: %.2f°C | IAQ: %.2f", bme_status.temperature, bme_status.iaq); + ESP_LOGI(TAG, "BME680 Temp: %.2f°C | IAQ: %.2f | IAQacc: %d", bme_status.temperature, bme_status.iaq, bme_status.iaq_accuracy); updateState(); #endif From bc4be830ebd896f1a101d751b088da7154ed33d8 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Tue, 1 Jan 2019 21:27:35 +0100 Subject: [PATCH 34/37] v1.7.08 --- platformio.ini | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/platformio.ini b/platformio.ini index 59e70845..43adc611 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,7 +30,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.7.06 +release_version = 1.7.08 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 0 @@ -63,7 +63,7 @@ lib_deps_all = build_flags_basic = -include "src/hal/${PIOENV}.h" -include "src/paxcounter.conf" - -w + ; -w '-DARDUINO_LMIC_PROJECT_CONFIG_H=../../../src/lmic_config.h' '-DCORE_DEBUG_LEVEL=${common.debug_level}' '-DLOG_LOCAL_LEVEL=${common.debug_level}' @@ -217,7 +217,6 @@ lib_deps = build_flags = ${common.build_flags_all} -mfix-esp32-psram-cache-issue - -DBOARD_HAS_PSRAM upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} @@ -236,7 +235,6 @@ lib_deps = build_flags = ${common.build_flags_all} -mfix-esp32-psram-cache-issue - -DBOARD_HAS_PSRAM upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} @@ -289,7 +287,6 @@ lib_deps = build_flags = ${common.build_flags_basic} -mfix-esp32-psram-cache-issue - -DBOARD_HAS_PSRAM upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} From 25a97fbbcc92352210c177904616b32d834f3deb Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 6 Jan 2019 19:41:42 +0100 Subject: [PATCH 35/37] BME680 fixes --- src/bme680mems.cpp | 45 ++++++++++++++++++++++----------------------- src/cyclic.cpp | 35 ++++++++++++++++++++--------------- src/main.cpp | 3 +-- src/wifiscan.cpp | 2 +- 4 files changed, 44 insertions(+), 41 deletions(-) diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index f888eb4e..d8803ead 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -8,8 +8,6 @@ static const char TAG[] = "main"; bmeStatus_t bme_status; TaskHandle_t BmeTask; -Bsec iaqSensor; - bsec_virtual_sensor_t sensorList[10] = { BSEC_OUTPUT_RAW_TEMPERATURE, BSEC_OUTPUT_RAW_PRESSURE, @@ -23,8 +21,11 @@ bsec_virtual_sensor_t sensorList[10] = { BSEC_OUTPUT_SENSOR_HEAT_COMPENSATED_HUMIDITY, }; +uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE] = {0}; uint16_t stateUpdateCounter = 0; +Bsec iaqSensor; + // initialize BME680 sensor int bme_init(void) { @@ -105,25 +106,25 @@ void bme_loop(void *pvParameters) { configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check #ifdef HAS_BME - while (checkIaqSensorStatus()) { + // block i2c bus access + while (xSemaphoreTake(I2Caccess, portMAX_DELAY) == pdTRUE) { - // 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 + if (iaqSensor.run()) { // If new data is available + iaqSensor.run(); + 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; + updateState(); } - } + xSemaphoreGive(I2Caccess); // release i2c bus access + + } // while #endif ESP_LOGE(TAG, "BME task ended"); vTaskDelete(BmeTask); // should never be reached @@ -131,7 +132,6 @@ void bme_loop(void *pvParameters) { } // bme_loop() void loadState(void) { - uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE] = {0}; if (cfg.bsecstate[BSEC_MAX_STATE_BLOB_SIZE] == BSEC_MAX_STATE_BLOB_SIZE) { // Existing state in NVS stored ESP_LOGI(TAG, "restoring BSEC state from NVRAM"); @@ -145,11 +145,10 @@ void loadState(void) { void updateState(void) { bool update = false; - uint8_t bsecstate_buffer[BSEC_MAX_STATE_BLOB_SIZE] = {0}; if (stateUpdateCounter == 0) { - // first state update when IAQ accuracy is >= 3 - if (iaqSensor.iaqAccuracy >= 3) { + // first state update when IAQ accuracy is >= 1 + if (iaqSensor.iaqAccuracy >= 1) { update = true; stateUpdateCounter++; } diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 89564b01..13518cf5 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -33,20 +33,25 @@ void doHousekeeping() { #endif // task storage debugging // - ESP_LOGD(TAG, "Wifiloop %d bytes left", - uxTaskGetStackHighWaterMark(wifiSwitchTask)); - ESP_LOGD(TAG, "IRQhandler %d bytes left", - uxTaskGetStackHighWaterMark(irqHandlerTask)); + ESP_LOGD(TAG, "Wifiloop %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(wifiSwitchTask), + eTaskGetState(wifiSwitchTask)); + ESP_LOGD(TAG, "IRQhandler %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(irqHandlerTask), + eTaskGetState(irqHandlerTask)); #ifdef HAS_GPS - ESP_LOGD(TAG, "Gpsloop %d bytes left", uxTaskGetStackHighWaterMark(GpsTask)); + ESP_LOGD(TAG, "Gpsloop %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(GpsTask), eTaskGetState(GpsTask)); #endif #ifdef HAS_BME - ESP_LOGD(TAG, "Bmeloop %d bytes left", uxTaskGetStackHighWaterMark(BmeTask)); + ESP_LOGD(TAG, "Bmeloop %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(BmeTask), eTaskGetState(BmeTask)); #endif #if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED) - ESP_LOGD(TAG, "LEDloop %d bytes left", - uxTaskGetStackHighWaterMark(ledLoopTask)); + ESP_LOGD(TAG, "LEDloop %d bytes left | Taskstate = %d", + uxTaskGetStackHighWaterMark(ledLoopTask), + eTaskGetState(ledLoopTask)); #endif // read battery voltage into global variable @@ -55,10 +60,10 @@ void doHousekeeping() { ESP_LOGI(TAG, "Voltage: %dmV", batt_voltage); #endif -// display BME sensor data if present +// display BME sensor data #ifdef HAS_BME - ESP_LOGI(TAG, "BME680 Temp: %.2f°C | IAQ: %.2f | IAQacc: %d", bme_status.temperature, bme_status.iaq, bme_status.iaq_accuracy); - updateState(); + ESP_LOGI(TAG, "BME680 Temp: %.2f°C | IAQ: %.2f | IAQacc: %d", + bme_status.temperature, bme_status.iaq, bme_status.iaq_accuracy); #endif // check free heap memory @@ -66,13 +71,13 @@ void doHousekeeping() { ESP_LOGI(TAG, "Memory full, counter cleared (heap low water mark = %d Bytes / " "free heap = %d bytes)", - ESP.getMinFreeHeap() , ESP.getFreeHeap()); + ESP.getMinFreeHeap(), ESP.getFreeHeap()); SendPayload(COUNTERPORT); // send data before clearing counters reset_counters(); // clear macs container and reset all counters get_salt(); // get new salt for salting hashes - if (ESP.getMinFreeHeap() <= MEM_LOW) // check again - do_reset(); // memory leak, reset device + if (ESP.getMinFreeHeap() <= MEM_LOW) // check again + do_reset(); // memory leak, reset device } // check free PSRAM memory @@ -84,7 +89,7 @@ void doHousekeeping() { get_salt(); // get new salt for salting hashes if (ESP.getMinFreePsram() <= MEM_LOW) // check again - do_reset(); // memory leak, reset device + do_reset(); // memory leak, reset device } #endif diff --git a/src/main.cpp b/src/main.cpp index 29aa32cb..609243f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -353,9 +353,8 @@ void setup() { ESP_LOGI(TAG, "Starting BMEloop..."); xTaskCreatePinnedToCore(bme_loop, // task function "bmeloop", // name of task - 4096, // stack size of task + 2048, // stack size of task (void *)1, // parameter of the task - //0, // priority of the task 1, // priority of the task &BmeTask, // task handle 1); // CPU core diff --git a/src/wifiscan.cpp b/src/wifiscan.cpp index 675d511b..dcd8ebc9 100644 --- a/src/wifiscan.cpp +++ b/src/wifiscan.cpp @@ -74,7 +74,7 @@ void switchWifiChannel(void *parameter) { channel = (channel % WIFI_CHANNEL_MAX) + 1; // rotate channel 1..WIFI_CHANNEL_MAX esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); - ESP_LOGD(TAG, "Wifi set channel %d", channel); + //ESP_LOGD(TAG, "Wifi set channel %d", channel); } vTaskDelete(NULL); // shoud never be reached } From 48b68653ab0605e6ac6e16ba2bfa3c4c4436d106 Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Sun, 6 Jan 2019 20:05:15 +0100 Subject: [PATCH 36/37] BME680 bugfix --- src/bme680mems.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bme680mems.cpp b/src/bme680mems.cpp index d8803ead..bb420db4 100644 --- a/src/bme680mems.cpp +++ b/src/bme680mems.cpp @@ -110,7 +110,6 @@ void bme_loop(void *pvParameters) { while (xSemaphoreTake(I2Caccess, portMAX_DELAY) == pdTRUE) { if (iaqSensor.run()) { // If new data is available - iaqSensor.run(); bme_status.raw_temperature = iaqSensor.rawTemperature; bme_status.raw_humidity = iaqSensor.rawHumidity; bme_status.temperature = iaqSensor.temperature; From 613ec488fe30f2c0c07f31b95a2e5de645194e9f Mon Sep 17 00:00:00 2001 From: Klaus K Wilting Date: Fri, 11 Jan 2019 18:32:50 +0100 Subject: [PATCH 37/37] v1.7.11 --- platformio.ini | 38 ++++++------------------ src/hal/{ttgobeam_new.h => ttgobeam.h} | 41 ++++++++++---------------- src/hal/ttgobeam_old.h | 8 ++--- 3 files changed, 29 insertions(+), 58 deletions(-) rename src/hal/{ttgobeam_new.h => ttgobeam.h} (73%) diff --git a/platformio.ini b/platformio.ini index 43adc611..21943a92 100644 --- a/platformio.ini +++ b/platformio.ini @@ -15,8 +15,7 @@ env_default = generic ;env_default = ttgov2 ;env_default = ttgov21old ;env_default = ttgov21new -;env_default = ttgobeam_old -;env_default = ttgobeam_new +;env_default = ttgobeam ;env_default = lopy ;env_default = lopy4 ;env_default = fipy @@ -30,7 +29,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng [common] ; for release_version use max. 10 chars total, use any decimal format like "a.b.c" -release_version = 1.7.08 +release_version = 1.7.11 ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose debug_level = 0 @@ -39,8 +38,8 @@ upload_protocol = esptool ;upload_protocol = custom extra_scripts = pre:build.py keyfile = ota.conf -;platform_espressif32 = espressif32@1.5.0 -platform_espressif32 = https://github.com/platformio/platform-espressif32.git#feature/stage +platform_espressif32 = espressif32@1.6.0 +;platform_espressif32 = https://github.com/platformio/platform-espressif32.git#feature/stage board_build.partitions = min_spiffs.csv monitor_speed = 115200 lib_deps_lora = @@ -63,7 +62,7 @@ lib_deps_all = build_flags_basic = -include "src/hal/${PIOENV}.h" -include "src/paxcounter.conf" - ; -w + -w '-DARDUINO_LMIC_PROJECT_CONFIG_H=../../../src/lmic_config.h' '-DCORE_DEBUG_LEVEL=${common.debug_level}' '-DLOG_LOCAL_LEVEL=${common.debug_level}' @@ -203,17 +202,17 @@ upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} -[env:ttgobeam_old] +[env:ttgobeam] platform = ${common.platform_espressif32} framework = arduino -board = esp32dev -;board = ttgo-t-beam +board = ttgo-t-beam board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = ${common.lib_deps_basic} ${common.lib_deps_lora} ${common.lib_deps_gps} +; ${common.lib_deps_display} build_flags = ${common.build_flags_all} -mfix-esp32-psram-cache-issue @@ -221,25 +220,6 @@ upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} -[env:ttgobeam_new] -platform = ${common.platform_espressif32} -framework = arduino -board = esp32dev -;board = ttgo-t-beam -board_build.partitions = ${common.board_build.partitions} -upload_speed = 921600 -lib_deps = - ${common.lib_deps_basic} - ${common.lib_deps_lora} - ${common.lib_deps_gps} -build_flags = - ${common.build_flags_all} - -mfix-esp32-psram-cache-issue -upload_protocol = ${common.upload_protocol} -extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} - - [env:fipy] platform = ${common.platform_espressif32} framework = arduino @@ -360,4 +340,4 @@ lib_deps = ${common.lib_deps_all} build_flags = ${common.build_flags_all} upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} -monitor_speed = ${common.monitor_speed} +monitor_speed = ${common.monitor_speed} \ No newline at end of file diff --git a/src/hal/ttgobeam_new.h b/src/hal/ttgobeam.h similarity index 73% rename from src/hal/ttgobeam_new.h rename to src/hal/ttgobeam.h index 3751e436..4b823e04 100644 --- a/src/hal/ttgobeam_new.h +++ b/src/hal/ttgobeam.h @@ -6,46 +6,37 @@ #include // Hardware related definitions for TTGO T-Beam board +// (only) for older T-Beam version T22_V05 eternal wiring LORA_IO1 to GPIO33 is needed! // // pinouts taken from http://tinymicros.com/wiki/TTGO_T-Beam +#define HAS_LED GPIO_NUM_14 // on board green LED, only new version TTGO-BEAM V07 +//#define HAS_LED GPIO_NUM_21 // on board green LED, only old verison TTGO-BEAM V05 + +#define HAS_LORA 1 // comment out if device shall not send data via LoRa +#define CFG_sx1276_radio 1 // HPD13A LoRa SoC +#define BOARD_HAS_PSRAM // use extra 4MB external RAM +#define HAS_BUTTON GPIO_NUM_39 // on board button (next to reset) +#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 +#define BATT_FACTOR 2 // voltage divider 100k/100k on board +#define HAS_GPS 1 // use on board GPS +#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration + // enable only if device has these sensors, otherwise comment these lines // BME680 sensor on I2C bus //#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL //#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND -#define HAS_LED GPIO_NUM_14 // on board green LED - -// user defined sensors -//#define HAS_SENSORS 1 // comment out if device has user defined sensors - +// display (if connected) //#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 -#define CFG_sx1276_radio 1 // HPD13A LoRa SoC -#define BOARD_HAS_PSRAM // use extra 4MB external RAM +// user defined sensors (if connected) +//#define HAS_SENSORS 1 // comment out if device has user defined sensors //#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature -#define HAS_BUTTON GPIO_NUM_39 // on board button "SW5" - -#define HAS_BATTERY_PROBE ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7 -#define BATT_FACTOR 2 // voltage divider 100k/100k on board -#define HAS_GPS 1 // use on board GPS -#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_12, GPIO_NUM_15 // UBlox NEO 6M or 7M with default configuration - -// Pins for LORA chip SPI interface, reset line and interrupt lines -#define LORA_SCK (5) -#define LORA_CS (18) -#define LORA_MISO (19) -#define LORA_MOSI (27) -#define LORA_RST (23) -#define LORA_IRQ (26) -#define LORA_IO1 (33) // for T-Beam T22_V05 and T22_V07, for other versions use ttgobeam_old.h -#define LORA_IO2 (32) - #endif \ No newline at end of file diff --git a/src/hal/ttgobeam_old.h b/src/hal/ttgobeam_old.h index 5555636e..4c5d1981 100644 --- a/src/hal/ttgobeam_old.h +++ b/src/hal/ttgobeam_old.h @@ -9,11 +9,11 @@ // enable only if device has these sensors, otherwise comment these lines // BME680 sensor on I2C bus -//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL -//#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND -//#define HAS_LED NOT_A_PIN // on board green LED uses same GPIO as SDA! +#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +#define BME_ADDR BME680_I2C_ADDR_PRIMARY // connect SDIO of BME680 to GND +#define HAS_LED NOT_A_PIN // on board green LED uses same GPIO as SDA! -#define HAS_LED GPIO_NUM_21 // on board green LED +// #define HAS_LED GPIO_NUM_21 // on board green LED // user defined sensors //#define HAS_SENSORS 1 // comment out if device has user defined sensors