BME680 support (experimental); LoRa Time sync (experimental)
This commit is contained in:
1 parent
dbc3d28d31
commit
4ae4633a15
41 files changed
+11540
-169
No files matched your search
@@ -0,0 +1,65 @@
|
||||
#ifdef HAS_BME
|
||||
|
||||
#include "globals.h"
|
||||
|
||||
// Local logging tag
|
||||
static const char TAG[] = "main";
|
||||
|
||||
#include <Wire.h>
|
||||
#include <SPI.h>
|
||||
#include <Adafruit_Sensor.h>
|
||||
#include "Adafruit_BME680.h"
|
||||
|
||||
#define SEALEVELPRESSURE_HPA (1013.25)
|
||||
|
||||
// I2C Bus interface
|
||||
Adafruit_BME680 bme;
|
||||
|
||||
bmeStatus_t bme_status;
|
||||
TaskHandle_t BmeTask;
|
||||
|
||||
// BME680 read loop Task
|
||||
void bme_loop(void *pvParameters) {
|
||||
|
||||
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
|
||||
|
||||
// initialize BME680 sensor
|
||||
if (!bme.begin()) {
|
||||
ESP_LOGE(TAG, "BME680 chip not found on i2c bus, bus error %d. "
|
||||
"Stopping BME task.");
|
||||
vTaskDelete(BmeTask);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "BME680 chip found.");
|
||||
}
|
||||
|
||||
// Set up oversampling and filter initialization
|
||||
bme.setTemperatureOversampling(BME680_OS_8X);
|
||||
bme.setHumidityOversampling(BME680_OS_2X);
|
||||
bme.setPressureOversampling(BME680_OS_4X);
|
||||
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
|
||||
bme.setGasHeater(320, 150); // 320*C for 150 ms
|
||||
|
||||
// read loop
|
||||
while (1) {
|
||||
|
||||
vTaskDelay(10000 / portTICK_PERIOD_MS);
|
||||
|
||||
if (!bme.performReading()) {
|
||||
ESP_LOGE(TAG, "BME680 read error");
|
||||
continue;
|
||||
}
|
||||
|
||||
// read BME data and cast to global struct
|
||||
bme_status.temperature = (uint16_t)bme.temperature;
|
||||
bme_status.pressure = (uint16_t)(bme.pressure / 100.0);
|
||||
bme_status.humidity = (uint16_t)bme.humidity;
|
||||
bme_status.gas_resistance = (uint16_t)(bme.gas_resistance / 1000.0);
|
||||
bme_status.altitude = (uint16_t)bme.readAltitude(SEALEVELPRESSURE_HPA);
|
||||
|
||||
} // end of infinite loop
|
||||
|
||||
vTaskDelete(NULL); // shoud never be reached
|
||||
|
||||
} // bme_loop()
|
||||
|
||||
#endif // HAS_BME
|
||||
+26
-17
@@ -3,12 +3,12 @@
|
||||
|
||||
// Basic config
|
||||
#include "cyclic.h"
|
||||
#include "rcommand.h"
|
||||
#include "spislave.h"
|
||||
|
||||
// Local logging tag
|
||||
static const char TAG[] = "main";
|
||||
|
||||
uint32_t userUTCTime; // Seconds since the UTC epoch
|
||||
|
||||
// do all housekeeping
|
||||
void doHousekeeping() {
|
||||
|
||||
@@ -19,7 +19,10 @@ void doHousekeeping() {
|
||||
if (cfg.runmode == 1)
|
||||
do_reset();
|
||||
|
||||
// task storage debugging //
|
||||
spi_housekeeping();
|
||||
do_timesync();
|
||||
|
||||
// task storage debugging //
|
||||
ESP_LOGD(TAG, "Wifiloop %d bytes left",
|
||||
uxTaskGetStackHighWaterMark(wifiSwitchTask));
|
||||
ESP_LOGD(TAG, "IRQhandler %d bytes left",
|
||||
@@ -28,10 +31,9 @@ void doHousekeeping() {
|
||||
ESP_LOGD(TAG, "Gpsloop %d bytes left", uxTaskGetStackHighWaterMark(GpsTask));
|
||||
#endif
|
||||
|
||||
spi_housekeeping();
|
||||
|
||||
#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",
|
||||
uxTaskGetStackHighWaterMark(ledLoopTask));
|
||||
#endif
|
||||
|
||||
// read battery voltage into global variable
|
||||
@@ -40,17 +42,6 @@ void doHousekeeping() {
|
||||
ESP_LOGI(TAG, "Measured Voltage: %dmV", batt_voltage);
|
||||
#endif
|
||||
|
||||
// sync time & date if we have valid gps time
|
||||
#ifdef HAS_GPS
|
||||
if (gps.time.isValid()) {
|
||||
setTime(gps.time.hour(), gps.time.minute(), gps.time.second(),
|
||||
gps.date.day(), gps.date.month(), gps.date.year());
|
||||
ESP_LOGI(TAG, "Time synced to %02d:%02d:%02d", hour(), minute(), second());
|
||||
} else {
|
||||
ESP_LOGI(TAG, "No valid GPS time");
|
||||
}
|
||||
#endif
|
||||
|
||||
// check free memory
|
||||
if (esp_get_minimum_free_heap_size() <= MEM_LOW) {
|
||||
ESP_LOGI(TAG,
|
||||
@@ -83,6 +74,24 @@ void reset_counters() {
|
||||
macs_ble = 0;
|
||||
}
|
||||
|
||||
void do_timesync() {
|
||||
// sync time & date if we have valid gps time
|
||||
#ifdef HAS_GPS
|
||||
if (gps.time.isValid()) {
|
||||
setTime(gps.time.hour(), gps.time.minute(), gps.time.second(),
|
||||
gps.date.day(), gps.date.month(), gps.date.year());
|
||||
ESP_LOGI(TAG, "Time synced by GPS to %02d:%02d:%02d", hour(), minute(),
|
||||
second());
|
||||
return;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "No valid GPS time");
|
||||
}
|
||||
#endif
|
||||
// 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");
|
||||
}
|
||||
|
||||
#ifndef VERBOSE
|
||||
int redirect_log(const char *fmt, va_list args) {
|
||||
// do nothing
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
#define SPI_SCLK GPIO_NUM_18
|
||||
#define SPI_CS GPIO_NUM_5
|
||||
|
||||
#define HAS_BME 1 // BME680 sensor on I2C bus (SDA=4/SCL=15); comment out if not present
|
||||
|
||||
#define CFG_sx1276_radio 1 // select LoRa chip
|
||||
//#define CFG_sx1272_radio 1 // select LoRa chip
|
||||
#define BOARD_HAS_PSRAM // use if board has external PSRAM
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define HAS_BME 1 // BME680 sensor on I2C bus (SDA=4/SCL=15); comment out if not present
|
||||
|
||||
// Hardware related definitions for Heltec LoRa-32 Board
|
||||
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
|
||||
+3
-1
@@ -21,6 +21,8 @@
|
||||
|
||||
//#define LMIC_USE_INTERRUPTS
|
||||
|
||||
#define LMIC_ENABLE_DeviceTimeReq 1
|
||||
|
||||
// 16 μs per tick
|
||||
// LMIC requires ticks to be 15.5μs - 100 μs long
|
||||
#define US_PER_OSTICK_EXPONENT 4
|
||||
@@ -38,7 +40,7 @@
|
||||
// enable more verbose output. Make sure that printf is actually
|
||||
// configured (e.g. on AVR it is not by default), otherwise using it can
|
||||
// cause crashing.
|
||||
//#define LMIC_DEBUG_LEVEL 1
|
||||
#define LMIC_DEBUG_LEVEL 2
|
||||
|
||||
// Enable this to allow using printf() to print to the given serial port
|
||||
// (or any other Print object). This can be easy for debugging. The
|
||||
|
||||
+48
-3
@@ -328,9 +328,9 @@ void lora_send(osjob_t *job) {
|
||||
// waiting for LoRa getting ready
|
||||
} else {
|
||||
if (xQueueReceive(LoraSendQueue, &SendBuffer, (TickType_t)0) == pdTRUE) {
|
||||
// SendBuffer gets struct MessageBuffer with next payload from queue
|
||||
// SendBuffer now filled with next payload from queue
|
||||
if (!LMIC_setTxData2(SendBuffer.MessagePort, SendBuffer.Message,
|
||||
SendBuffer.MessageSize, (cfg.countermode & 0x02))) {
|
||||
SendBuffer.MessageSize, (cfg.countermode & 0x02))) {
|
||||
ESP_LOGI(TAG, "%d byte(s) sent to LoRa", SendBuffer.MessageSize);
|
||||
} else {
|
||||
ESP_LOGE(TAG, "could not send %d byte(s) to LoRa",
|
||||
@@ -384,7 +384,7 @@ esp_err_t lora_stack_init() {
|
||||
if (!LMIC_startJoining()) { // start joining
|
||||
ESP_LOGI(TAG, "Already joined");
|
||||
}
|
||||
|
||||
|
||||
return ESP_OK; // continue main program
|
||||
#endif
|
||||
}
|
||||
@@ -414,3 +414,48 @@ void lora_housekeeping(void) {
|
||||
// uxTaskGetStackHighWaterMark(LoraTask));
|
||||
#endif
|
||||
}
|
||||
|
||||
void user_request_network_time_callback(void *pVoidUserUTCTime,
|
||||
int flagSuccess) {
|
||||
// Explicit conversion from void* to uint32_t* to avoid compiler errors
|
||||
uint32_t *pUserUTCTime = (uint32_t *)pVoidUserUTCTime;
|
||||
|
||||
// A struct that will be populated by LMIC_getNetworkTimeReference.
|
||||
// It contains the following fields:
|
||||
// - tLocal: the value returned by os_GetTime() when the time
|
||||
// request was sent to the gateway, and
|
||||
// - tNetwork: the seconds between the GPS epoch and the time
|
||||
// the gateway received the time request
|
||||
lmic_time_reference_t lmicTimeReference;
|
||||
|
||||
if (flagSuccess != 1) {
|
||||
ESP_LOGW(TAG, "Network time request callback error");
|
||||
return;
|
||||
}
|
||||
|
||||
// Populate "lmic_time_reference"
|
||||
flagSuccess = LMIC_getNetworkTimeReference(&lmicTimeReference);
|
||||
if (flagSuccess != 1) {
|
||||
ESP_LOGW(TAG, "Network time request failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Update userUTCTime, considering the difference between the GPS and UTC
|
||||
// epoch, and the leap seconds
|
||||
*pUserUTCTime = lmicTimeReference.tNetwork + 315964800;
|
||||
|
||||
// Add the delay between the instant the time was transmitted and
|
||||
// the current time
|
||||
|
||||
// Current time, in ticks
|
||||
ostime_t ticksNow = os_getTime();
|
||||
// Time when the request was sent, in ticks
|
||||
ostime_t ticksRequestSent = lmicTimeReference.tLocal;
|
||||
uint32_t requestDelaySec = osticks2ms(ticksNow - ticksRequestSent) / 1000;
|
||||
*pUserUTCTime += requestDelaySec;
|
||||
|
||||
// Update the system time with the time read from the network
|
||||
setTime(*pUserUTCTime);
|
||||
ESP_LOGI(TAG, "Time synced by LoRa network to %02d:%02d:%02d", hour(),
|
||||
minute(), second());
|
||||
}
|
||||
@@ -35,6 +35,7 @@ IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
|
||||
looptask 1 1 arduino core -> runs the LMIC LoRa stack
|
||||
irqhandler 1 1 executes tasks triggered by irq
|
||||
gpsloop 1 2 reads data from GPS over serial or i2c
|
||||
bmeloop 1 2 reads data from BME680 over i2c
|
||||
IDLE 1 0 ESP32 arduino scheduler
|
||||
|
||||
ESP32 hardware timers
|
||||
@@ -157,6 +158,11 @@ void setup() {
|
||||
strcat_P(features, " GPS");
|
||||
#endif
|
||||
|
||||
// initialize gps
|
||||
#ifdef HAS_BME
|
||||
strcat_P(features, " BME");
|
||||
#endif
|
||||
|
||||
// initialize LoRa
|
||||
#ifdef HAS_LORA
|
||||
strcat_P(features, " LORA");
|
||||
@@ -275,6 +281,17 @@ void setup() {
|
||||
1); // CPU core
|
||||
#endif
|
||||
|
||||
#ifdef HAS_BME
|
||||
ESP_LOGI(TAG, "Starting BMEloop...");
|
||||
xTaskCreatePinnedToCore(bme_loop, // task function
|
||||
"bmeloop", // name of task
|
||||
2048, // stack size of task
|
||||
(void *)1, // parameter of the task
|
||||
2, // priority of the task
|
||||
&BmeTask, // task handle
|
||||
1); // CPU core
|
||||
#endif
|
||||
|
||||
// start state machine
|
||||
ESP_LOGI(TAG, "Starting IRQ Handler...");
|
||||
xTaskCreatePinnedToCore(irqHandler, // task function
|
||||
|
||||
Reference in new issue
Block a user