BME680 support (experimental); LoRa Time sync (experimental)

This commit is contained in:
Klaus K Wilting committed 2018-11-14 22:11:23 +01:00
1 parent dbc3d28d31
commit 4ae4633a15
41 files changed
+11540 -169

No files matched your search

+65
View File
@@ -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
View File
@@ -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
+2
View File
@@ -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
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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());
}
+17
View File
@@ -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