Merge pull request #608 from cyberman54/development

v1.9.996
This commit is contained in:
Verkehrsrot authored and GitHub committed 2020-06-06 15:22:21 +02:00
commit 956ea2f879
22 files changed
+430 -59

No files matched your search

+5
View File
@@ -52,6 +52,11 @@ void doHousekeeping() {
ESP_LOGD(TAG, "spiloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(spiTask), eTaskGetState(spiTask));
#endif
#ifdef HAS_MQTT
ESP_LOGD(TAG, "MQTTloop %d bytes left | Taskstate = %d",
uxTaskGetStackHighWaterMark(mqttTask), eTaskGetState(mqttTask));
mqttClient.loop();
#endif
#if (defined HAS_DCF77 || defined HAS_IF482)
ESP_LOGD(TAG, "Clockloop %d bytes left | Taskstate = %d",
+21 -16
View File
@@ -49,24 +49,29 @@ static int dp_row = 0, dp_col = 0, dp_font = 0;
QRCode qrcode;
#ifdef HAS_DISPLAY
#if (HAS_DISPLAY) == 1
SSOLED ssoled;
OBDISP ssoled;
#elif (HAS_DISPLAY) == 2
TFT_eSPI tft = TFT_eSPI();
#else
#error Unknown display type specified in hal file
#endif
#endif
void dp_setup(int contrast) {
#if (HAS_DISPLAY) == 1 // I2C OLED
int rc = oledInit(&ssoled, OLED_TYPE, OLED_ADDR, MY_DISPLAY_FLIP,
MY_DISPLAY_INVERT, USE_HW_I2C, MY_DISPLAY_SDA,
MY_DISPLAY_SCL, MY_DISPLAY_RST,
OLED_FREQUENCY); // use standard I2C bus at 400Khz
int rc = obdI2CInit(&ssoled, OLED_TYPE, OLED_ADDR, MY_DISPLAY_FLIP,
MY_DISPLAY_INVERT, USE_HW_I2C, MY_DISPLAY_SDA,
MY_DISPLAY_SCL, MY_DISPLAY_RST,
OLED_FREQUENCY); // use standard I2C bus at 400Khz
assert(rc != OLED_NOT_FOUND);
// set display buffer
oledSetBackBuffer(&ssoled, displaybuf);
oledSetTextWrap(&ssoled, true);
obdSetBackBuffer(&ssoled, displaybuf);
obdSetTextWrap(&ssoled, true);
dp_font = MY_FONT_NORMAL;
#elif (HAS_DISPLAY) == 2 // SPI TFT
@@ -466,7 +471,7 @@ void dp_setTextCursor(int x, int y) {
#if (HAS_DISPLAY) == 1
dp_row = y;
oledSetCursor(&ssoled, dp_col, dp_row);
obdSetCursor(&ssoled, dp_col, dp_row);
#elif (HAS_DISPLAY) == 2
switch (dp_font >> 1) {
@@ -538,8 +543,8 @@ void dp_printf(const char *format, ...) {
}
va_end(arg);
#if (HAS_DISPLAY) == 1
oledWriteString(&ssoled, 0, -1, dp_row, temp, dp_font >> 1, dp_font & 0x01,
false);
obdWriteString(&ssoled, 0, -1, dp_row, temp, dp_font >> 1, dp_font & 0x01,
false);
#elif (HAS_DISPLAY) == 2
tft.printf(temp);
#endif
@@ -550,7 +555,7 @@ void dp_printf(const char *format, ...) {
void dp_dump(uint8_t *pBuffer) {
#if (HAS_DISPLAY) == 1
oledDumpBuffer(&ssoled, pBuffer);
obdDumpBuffer(&ssoled, pBuffer);
#elif (HAS_DISPLAY) == 2
// probably oled buffer stucture is not suitable for tft -> to be checked
tft.drawBitmap(0, 0, pBuffer, MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT,
@@ -561,7 +566,7 @@ void dp_dump(uint8_t *pBuffer) {
void dp_clear(void) {
dp_setTextCursor(0, 0);
#if (HAS_DISPLAY) == 1
oledFill(&ssoled, 0, 1);
obdFill(&ssoled, 0, 1);
#elif (HAS_DISPLAY) == 2
tft.fillScreen(MY_DISPLAY_BGCOLOR);
#endif
@@ -569,7 +574,7 @@ void dp_clear(void) {
void dp_contrast(uint8_t contrast) {
#if (HAS_DISPLAY) == 1
oledSetContrast(&ssoled, contrast);
obdSetContrast(&ssoled, contrast);
#elif (HAS_DISPLAY) == 2
// to do: gamma correction for TFT
#endif
@@ -577,7 +582,7 @@ void dp_contrast(uint8_t contrast) {
void dp_power(uint8_t screenon) {
#if (HAS_DISPLAY) == 1
oledPower(&ssoled, screenon);
obdPower(&ssoled, screenon);
#elif (HAS_DISPLAY) == 2
// to come
#endif
@@ -590,7 +595,7 @@ void dp_shutdown(void) {
ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
else {
cfg.screenon = 0;
oledPower(&ssoled, false);
obdPower(&ssoled, false);
delay(DISPLAYREFRESH_MS / 1000 * 1.1);
I2C_MUTEX_UNLOCK(); // release i2c bus access
}
@@ -630,7 +635,7 @@ void dp_fillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
uint8_t bRender) {
#if (HAS_DISPLAY) == 1
for (uint16_t xi = x; xi < x + width; xi++)
oledDrawLine(&ssoled, xi, y, xi, y + height - 1, bRender);
obdDrawLine(&ssoled, xi, y, xi, y + height - 1, 1, bRender);
#elif (HAS_DISPLAY) == 2
tft.fillRect(x, y, width, height, MY_DISPLAY_FGCOLOR);
#endif
+1
View File
@@ -1,6 +1,7 @@
// clang-format off
// upload_speed 115200
// board esp32dev
// display_library lib_deps_oled_display
#ifndef _GENERIC_H
#define _GENERIC_H
+6 -1
View File
@@ -37,7 +37,12 @@
#define HAS_LED NOT_A_PIN // no on board LED (?)
#define HAS_BUTTON (39) // on board button A
#define HAS_IP5306 1
// power management settings
#define HAS_IP5306 1 // has IP5306 chip
#define PMU_CHG_CURRENT 2 // battery charge current
// possible values: 0:200mA, 1:400mA, *2:500mA, 3:600mA
#define PMU_CHG_CUTOFF 0 // battery charge cutoff
// possible values: *0:4.2V, 1:4.3V, 2:4.35V, 3:4.4V
// GPS settings
#define HAS_GPS 1 // use on board GPS
+6 -1
View File
@@ -41,7 +41,12 @@
#define HAS_RGB_LED SmartLed rgb_led(LED_SK6812, RGB_LED_COUNT, GPIO_NUM_15) // LED_SK6812 RGB LED on GPIO15
#define HAS_BUTTON (39) // on board button A
#define HAS_IP5306 1
// power management settings
#define HAS_IP5306 1 // has IP5306 chip
#define PMU_CHG_CURRENT 2 // battery charge current
// possible values: 0:200mA, 1:400mA, *2:500mA, 3:600mA
#define PMU_CHG_CUTOFF 0 // battery charge cutoff
// possible values: *0:4.2V, 1:4.3V, 2:4.35V, 3:4.4V
// GPS settings
#define HAS_GPS 0 // use on board GPS
+24
View File
@@ -0,0 +1,24 @@
// clang-format off
// upload_speed 921600
// board esp32-poe-iso
#ifndef _OLIMEXPOEISO_H
#define _OLIMEXPOEISO_H
#include <stdint.h>
// enable only if you want to store a local paxcount table on the device
//#define HAS_SDCARD 2 // this board has a SDMMC card-reader/writer
// enable only if you want to send paxcount via ethernet port to mqtt server
#define HAS_MQTT 1 // use MQTT on ethernet interface
//#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
//#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 470k/470k on board
#define BAT_MEASURE_ADC ADC1_GPIO39_CHANNEL // external power probe GPIO pin
#define BAT_VOLTAGE_DIVIDER 2.1277f // voltage divider 47k/442k on board
#define HAS_BUTTON KEY_BUILTIN // on board button
#define HAS_LED NOT_A_PIN // no on board LED
#endif
+12 -5
View File
@@ -9,7 +9,7 @@
/*
Hardware related definitions for TTGO T-Beam board
(only) for newer T-Beam version T22_V10
for T-Beam versions T22_V10 + T22_V11
pinouts taken from https://github.com/lewisxhe/TTGO-T-Beam
/// Button functions: ///
@@ -20,7 +20,7 @@ User, long press -> send LORA message
Reset -> reset device
*/
#define HAS_DISPLAY 1
//#define HAS_DISPLAY 1
#define MY_DISPLAY_SDA SDA
#define MY_DISPLAY_SCL SCL
#define MY_DISPLAY_RST NOT_A_PIN
@@ -29,11 +29,18 @@ Reset -> reset device
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
#define HAS_BUTTON GPIO_NUM_38 // middle on board button
#define HAS_PMU 1 // AXP192 power management chip
#define PMU_INT GPIO_NUM_35 // AXP192 interrupt
#define HAS_LED NOT_A_PIN
// power management settings
#define HAS_PMU 1 // has AXP192 chip
#define PMU_INT GPIO_NUM_35 // battery interrupt
#define PMU_CHG_CURRENT AXP1XX_CHARGE_CUR_1000MA // battery charge current
// possible values (mA):
// 100/190/280/360/450/550/630/700/780/880/960/1000/1080/1160/1240/1320
#define PMU_CHG_CUTOFF AXP202_TARGET_VOL_4_2V // battery charge cutoff
// possible values (V):
// 4_1/4_15/4_2/4_36
// GPS settings
#define HAS_GPS 1 // use on board GPS
#define GPS_SERIAL 9600, SERIAL_8N1, GPIO_NUM_34, GPIO_NUM_12 // UBlox NEO 6M
+15 -3
View File
@@ -29,6 +29,7 @@ Task Core Prio Purpose
-------------------------------------------------------------------------------
ledloop 0 3 blinks LEDs
spiloop 0 2 reads/writes data on spi interface
mqttloop 0 2 reads/writes data on ETH interface
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
lmictask 1 2 MCCI LMiC LORAWAN stack
@@ -185,14 +186,22 @@ void setup() {
digitalWrite(EXT_POWER_SW, EXT_POWER_ON);
strcat_P(features, " VEXT");
#endif
#if defined HAS_PMU || defined HAS_IP5306
#ifdef HAS_PMU
AXP192_init();
#elif defined HAS_IP5306
IP5306_init();
#endif
strcat_P(features, " PMU");
#endif
// read (and initialize on first run) runtime settings from NVRAM
loadConfig(); // includes initialize if necessary
// now that we are powered, we scan i2c bus for devices
i2c_scan();
// initialize display
#ifdef HAS_DISPLAY
strcat_P(features, " OLED");
@@ -201,9 +210,6 @@ void setup() {
dp_init(RTC_runmode == RUNMODE_POWERCYCLE ? true : false);
#endif
// scan i2c bus for devices
i2c_scan();
#ifdef BOARD_HAS_PSRAM
assert(psramFound());
ESP_LOGI(TAG, "PSRAM found and initialized");
@@ -325,6 +331,12 @@ void setup() {
assert(spi_init() == ESP_OK);
#endif
// initialize MQTT
#ifdef HAS_MQTT
strcat_P(features, " MQTT");
assert(mqtt_init() == ESP_OK);
#endif
#ifdef HAS_SDCARD
if (sdcard_init())
strcat_P(features, " SD");
+163
View File
@@ -0,0 +1,163 @@
#ifdef HAS_MQTT
#include "mqttclient.h"
static const char TAG[] = __FILE__;
QueueHandle_t MQTTSendQueue;
TaskHandle_t mqttTask;
WiFiClient EthClient;
PubSubClient mqttClient(EthClient);
void NetworkEvent(WiFiEvent_t event) {
switch (event) {
case SYSTEM_EVENT_ETH_START:
ESP_LOGI(TAG, "Ethernet link layer started");
ETH.setHostname(ETH.macAddress().c_str());
break;
case SYSTEM_EVENT_ETH_CONNECTED:
ESP_LOGI(TAG, "Network link connected");
break;
case SYSTEM_EVENT_ETH_GOT_IP:
ESP_LOGI(TAG, "ETH MAC: %s", ETH.macAddress().c_str());
ESP_LOGI(TAG, "IPv4: %s", ETH.localIP().toString().c_str());
ESP_LOGI(TAG, "Link Speed: %d Mbps %s", ETH.linkSpeed(),
ETH.fullDuplex() ? "full duplex" : "half duplex");
mqtt_connect(MQTT_SERVER, MQTT_PORT);
break;
case SYSTEM_EVENT_ETH_DISCONNECTED:
ESP_LOGI(TAG, "Network link disconnected");
break;
case SYSTEM_EVENT_ETH_STOP:
ESP_LOGI(TAG, "Ethernet link layer stopped");
break;
default:
break;
}
}
int mqtt_connect(const char *my_host, const uint16_t my_port) {
IPAddress mqtt_server_ip;
static String clientId = "paxcounter-" + ETH.macAddress();
ESP_LOGI(TAG, "MQTT name is %s", clientId.c_str());
// resolve server
if (WiFi.hostByName(my_host, mqtt_server_ip)) {
ESP_LOGI(TAG, "Attempting to connect to %s [%s]", my_host,
mqtt_server_ip.toString().c_str());
} else {
ESP_LOGI(TAG, "Could not resolve %s", my_host);
return -1;
}
// attempt to connect to MQTT server
if (EthClient.connect(mqtt_server_ip, my_port, HOMECYCLE * 2 * 1000)) {
mqttClient.setServer(mqtt_server_ip, my_port);
mqttClient.setKeepAlive(HOMECYCLE * 2);
mqttClient.setCallback(mqtt_callback);
if (mqttClient.connect(clientId.c_str())) {
ESP_LOGI(TAG, "MQTT server connected, subscribing...");
mqttClient.publish(MQTT_OUTTOPIC, clientId.c_str());
mqttClient.subscribe(MQTT_INTOPIC);
ESP_LOGI(TAG, "MQTT topic subscribed");
} else {
ESP_LOGW(TAG, "MQTT server not responding, retrying later");
return -1;
}
} else {
ESP_LOGW(TAG, "MQTT server not connected, retrying later");
return -1;
}
}
void mqtt_client_task(void *param) {
MessageBuffer_t msg;
while (1) {
// fetch next or wait for payload to send from queue
if (xQueueReceive(MQTTSendQueue, &msg, portMAX_DELAY) != pdTRUE) {
ESP_LOGE(TAG, "Premature return from xQueueReceive() with no data!");
continue;
}
// send data to mqtt server, if we are connected
if (mqttClient.connected()) {
mqttClient.beginPublish(MQTT_OUTTOPIC, msg.MessageSize + 2, false);
mqttClient.write(msg.MessagePort);
mqttClient.write('/');
mqttClient.write(msg.Message, msg.MessageSize);
if (mqttClient.endPublish()) {
ESP_LOGI(TAG, "%d byte(s) sent to MQTT", msg.MessageSize + 2);
continue; // while(1)
} else
goto reconnect;
} else {
// attempt to reconnect to MQTT server
reconnect:
mqtt_enqueuedata(&msg); // postpone the undelivered message
delay(MQTT_RETRYSEC * 1000);
mqtt_connect(MQTT_SERVER, MQTT_PORT);
}
} // while(1)
}
esp_err_t mqtt_init(void) {
assert(SEND_QUEUE_SIZE);
MQTTSendQueue = xQueueCreate(SEND_QUEUE_SIZE, sizeof(MessageBuffer_t));
if (MQTTSendQueue == 0) {
ESP_LOGE(TAG, "Could not create MQTT send queue. Aborting.");
return ESP_FAIL;
}
ESP_LOGI(TAG, "MQTT send queue created, size %d Bytes",
SEND_QUEUE_SIZE * PAYLOAD_BUFFER_SIZE);
ESP_LOGI(TAG, "Starting MQTTloop...");
xTaskCreate(mqtt_client_task, "mqttloop", 4096, (void *)NULL, 2, &mqttTask);
WiFi.onEvent(NetworkEvent);
ETH.begin();
return ESP_OK;
}
void mqtt_enqueuedata(MessageBuffer_t *message) {
// enqueue message in MQTT send queue
BaseType_t ret;
MessageBuffer_t DummyBuffer;
sendprio_t prio = message->MessagePrio;
switch (prio) {
case prio_high:
// clear space in queue if full, then fallthrough to normal
if (!uxQueueSpacesAvailable(MQTTSendQueue))
xQueueReceive(MQTTSendQueue, &DummyBuffer, (TickType_t)0);
case prio_normal:
ret = xQueueSendToFront(MQTTSendQueue, (void *)message, (TickType_t)0);
break;
case prio_low:
default:
ret = xQueueSendToBack(MQTTSendQueue, (void *)message, (TickType_t)0);
break;
}
if (ret != pdTRUE)
ESP_LOGW(TAG, "MQTT sendqueue is full");
}
void mqtt_callback(char *topic, byte *payload, unsigned int length) {
String s = "";
for (int i = 0; i < length; i++)
s += (char)payload[i];
ESP_LOGD(TAG, "MQTT: Received %u byte(s) of payload [%s]", length, s);
// rcommand(payload, length);
}
void mqtt_queuereset(void) { xQueueReset(MQTTSendQueue); }
#endif // HAS_MQTT
+27
View File
@@ -143,6 +143,13 @@ void AXP192_init(void) {
pmu.clearIRQ();
#endif // PMU_INT
// set charging parameterss according to user settings if we have (see power.h)
#ifdef PMU_CHARGE_CURRENT
pmu.setChargeControlCur(PMU_CHARGE_CURRENT);
pmu.setChargingTargetVoltage(PMU_CHARGE_CUTOFF);
pmu.enableChargeing(true);
#endif
ESP_LOGI(TAG, "AXP192 PMU initialized");
}
}
@@ -292,6 +299,20 @@ uint8_t IP5306_GetBatteryLevel(void) {
return IP5306_LEDS2PCT(state);
}
void IP5306_SetChargerEnabled(uint8_t v) {
ip5306_set_bits(IP5306_REG_SYS_0, 4, 1, v); // 0:dis,*1:en
}
void IP5306_SetChargeCutoffVoltage(uint8_t v) {
ip5306_set_bits(IP5306_REG_CHG_2, 2, 2,
v); //*0:4.2V, 1:4.3V, 2:4.35V, 3:4.4V
}
void IP5306_SetEndChargeCurrentDetection(uint8_t v) {
ip5306_set_bits(IP5306_REG_CHG_1, 6, 2,
v); // 0:200mA, 1:400mA, *2:500mA, 3:600mA
}
void printIP5306Stats(void) {
bool usb = IP5306_GetPowerSource();
bool full = IP5306_GetBatteryFull();
@@ -302,4 +323,10 @@ void printIP5306Stats(void) {
full ? "CHARGED" : (usb ? "CHARGING" : "DISCHARGING"), level);
}
void IP5306_init(void) {
IP5306_SetChargerEnabled(1);
IP5306_SetChargeCutoffVoltage(PMU_CHG_CUTOFF);
IP5306_SetEndChargeCurrentDetection(PMU_CHG_CURRENT);
}
#endif // HAS_IP5306
+31 -10
View File
@@ -1,25 +1,34 @@
// routines for writing data to an SD-card, if present
#if (HAS_SDCARD)
// Local logging tag
static const char TAG[] = __FILE__;
#include "sdcard.h"
static bool useSDCard;
#ifdef HAS_SDCARD
static void createFile(void);
static bool useSDCard;
File fileSDCard;
bool sdcard_init() {
ESP_LOGD(TAG, "looking for SD-card...");
ESP_LOGI(TAG, "looking for SD-card...");
// for usage of SD drivers on ESP32 platform see
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sdspi_host.html
// https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/sdmmc_host.html
#if HAS_SDCARD == 1 // use SD SPI host driver
useSDCard = SD.begin(SDCARD_CS, SDCARD_MOSI, SDCARD_MISO, SDCARD_SCLK);
if (useSDCard)
#elif HAS_SDCARD == 2 // use SD MMC host driver
useSDCard = SD_MMC.begin();
#endif
if (useSDCard) {
ESP_LOGI(TAG, "SD-card found");
createFile();
else
ESP_LOGD(TAG, "SD-card not found");
} else
ESP_LOGI(TAG, "SD-card not found");
return useSDCard;
}
@@ -63,11 +72,23 @@ void createFile(void) {
for (int i = 0; i < 100; i++) {
sprintf(bufferFilename, SDCARD_FILE_NAME, i);
ESP_LOGD(TAG, "SD: looking for file <%s>", bufferFilename);
// ESP_LOGD(TAG, "SD: looking for file <%s>", bufferFilename);
#if HAS_SDCARD == 1
bool fileExists = SD.exists(bufferFilename);
#elif HAS_SDCARD == 2
bool fileExists = SD_MMC.exists(bufferFilename);
#endif
if (!fileExists) {
ESP_LOGD(TAG, "SD: file does not exist: opening");
// ESP_LOGD(TAG, "SD: file does not exist: opening");
#if HAS_SDCARD == 1
fileSDCard = SD.open(bufferFilename, FILE_WRITE);
#elif HAS_SDCARD == 2
fileSDCard = SD_MMC.open(bufferFilename, FILE_WRITE);
#endif
if (fileSDCard) {
ESP_LOGD(TAG, "SD: name opened: <%s>", bufferFilename);
fileSDCard.print(SDCARD_FILE_HEADER);
+6
View File
@@ -50,6 +50,9 @@ void SendPayload(uint8_t port, sendprio_t prio) {
#ifdef HAS_SPI
spi_enqueuedata(&SendBuffer);
#endif
#ifdef HAS_MQTT
mqtt_enqueuedata(&SendBuffer);
#endif
// write data to sdcard, if present
#ifdef HAS_SDCARD
@@ -179,4 +182,7 @@ void flushQueues() {
#ifdef HAS_SPI
spi_queuereset();
#endif
#ifdef HAS_MQTT
mqtt_queuereset();
#endif
}
+2
View File
@@ -1,5 +1,6 @@
#include "timekeeper.h"
/*
#if !(HAS_LORA)
#if (TIME_SYNC_LORASERVER)
#error TIME_SYNC_LORASERVER defined, but device has no LORA configured
@@ -7,6 +8,7 @@
#error TIME_SYNC_LORAWAN defined, but device has no LORA configured
#endif
#endif
*/
// Local logging tag
static const char TAG[] = __FILE__;