Merge pull request #883 from cyberman54/master

sync dev to master
This commit is contained in:
Verkehrsrot 2022-07-29 20:32:31 +02:00 committed by GitHub
commit e73bd19a82
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 162 additions and 219 deletions

View File

@ -22,7 +22,7 @@ Paxcounter is an [ESP32](https://www.espressif.com/en/products/socs/esp32) MCU b
Intention of this project is to do this without intrusion in privacy: You don't need to track people owned devices, if you just want to count them. Therefore, Paxcounter does not persistenly store MAC adresses and does no kind of fingerprinting the scanned devices. Intention of this project is to do this without intrusion in privacy: You don't need to track people owned devices, if you just want to count them. Therefore, Paxcounter does not persistenly store MAC adresses and does no kind of fingerprinting the scanned devices.
Data can either be be stored on a local SD-card, transferred to cloud using LoRaWAN network or MQTT over TCP/IP, or transmitted to a local host using serial (SPI) interface. Data can either be be stored on a local SD-card, transferred to cloud using LoRaWAN network (e.g. TheThingsNetwork or Helium) or MQTT over TCP/IP, or transmitted to a local host using serial (SPI) interface.
You can build this project battery powered using ESP32 deep sleep mode and reach long uptimes with a single 18650 Li-Ion cell. You can build this project battery powered using ESP32 deep sleep mode and reach long uptimes with a single 18650 Li-Ion cell.
@ -82,7 +82,7 @@ Some <b>3D printable cases</b> can be found (and, if wanted so, ordered) on Thin
for example.<br> for example.<br>
<b>Power consumption</b> was metered at around 450 - 1000mW, depending on board and user settings in paxcounter.conf. <b>Power consumption</b> was metered at around 450 - 1000mW, depending on board and user settings in paxcounter.conf.
By default bluetooth sniffing not installed (#define *BLECOUNTER* 0 in paxcounter.conf). Installing and enabling bluetooth costs 30% more power + 30% flash storage for the software stack. 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. By default bluetooth sniffing not installed (#define *BLECOUNTER* 0 in paxcounter.conf). 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 # Preparing
@ -98,7 +98,7 @@ Edit `platformio_orig.ini` and select desired hardware target in section boards.
## paxcounter.conf ## paxcounter.conf
Edit `src/paxcounter_orig.conf` and tailor settings in this file according to your needs and use case. Please take care of the duty cycle regulations of the LoRaWAN network you're going to use. Copy or rename to `src/paxcounter.conf`. Edit `src/paxcounter_orig.conf` and tailor settings in this file according to your needs and use case. Please take care of the duty cycle regulations of the LoRaWAN network you're going to use. Copy or rename to `src/paxcounter.conf`.
If your device has a **real time clock** it can be updated bei either LoRaWAN network or GPS time, according to settings *TIME_SYNC_INTERVAL* and *TIME_SYNC_LORAWAN* in `paxcounter.conf`. If your device has a **real time clock** it can be updated by either LoRaWAN network or GPS time, according to settings *TIME_SYNC_INTERVAL* and *TIME_SYNC_LORAWAN* in `paxcounter.conf`.
## src/lmic_config.h ## src/lmic_config.h
Edit `src/lmic_config.h` and tailor settings in this file according to your country and device hardware. Please take care of national regulations when selecting the frequency band for LoRaWAN. Edit `src/lmic_config.h` and tailor settings in this file according to your country and device hardware. Please take care of national regulations when selecting the frequency band for LoRaWAN.

View File

@ -14,14 +14,17 @@
#endif #endif
#define DISPLAY_PAGES (7) // number of paxcounter display pages #define DISPLAY_PAGES (7) // number of paxcounter display pages
#define PLOTBUFFERSIZE (MY_DISPLAY_WIDTH * MY_DISPLAY_HEIGHT / 8)
// settings for OLED display library // settings for OLED display library
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
#define MY_FONT_SMALL FONT_SMALL #define MY_FONT_SMALL FONT_6x8
#define MY_FONT_NORMAL FONT_NORMAL #define MY_FONT_NORMAL FONT_8x8
#define MY_FONT_LARGE FONT_LARGE #define MY_FONT_LARGE FONT_16x32
#define MY_FONT_STRETCHED FONT_STRETCHED #define MY_FONT_STRETCHED FONT_12x16
#define USE_BACKBUFFER 1
#define MY_DISPLAY_FIRSTLINE 30
#ifdef MY_DISPLAY_ADDR #ifdef MY_DISPLAY_ADDR
#define OLED_ADDR MY_DISPLAY_ADDR #define OLED_ADDR MY_DISPLAY_ADDR
#else #else
@ -33,6 +36,12 @@
#ifndef OLED_FREQUENCY #ifndef OLED_FREQUENCY
#define OLED_FREQUENCY 400000L #define OLED_FREQUENCY 400000L
#endif #endif
#ifndef MY_DISPLAY_FGCOLOR
#define MY_DISPLAY_FGCOLOR OLED_WHITE
#endif
#ifndef MY_DISPLAY_BGCOLOR
#define MY_DISPLAY_BGCOLOR OLED_BLACK
#endif
// settings for TFT display library // settings for TFT display library
#elif (HAS_DISPLAY == 2) #elif (HAS_DISPLAY == 2)
@ -42,6 +51,8 @@
#define MY_FONT_LARGE 4 #define MY_FONT_LARGE 4
#define MY_FONT_STRETCHED 6 #define MY_FONT_STRETCHED 6
#define MY_DISPLAY_FIRSTLINE 30
#ifndef MY_DISPLAY_FGCOLOR #ifndef MY_DISPLAY_FGCOLOR
#define MY_DISPLAY_FGCOLOR TFT_WHITE #define MY_DISPLAY_FGCOLOR TFT_WHITE
#endif #endif
@ -76,7 +87,7 @@
const uint8_t QR_SCALEFACTOR = (MY_DISPLAY_HEIGHT - 4) / 29; // 4px borderlines const uint8_t QR_SCALEFACTOR = (MY_DISPLAY_HEIGHT - 4) / 29; // 4px borderlines
extern uint8_t DisplayIsOn, displaybuf[]; extern uint8_t DisplayIsOn;
extern hw_timer_t *displayIRQ; extern hw_timer_t *displayIRQ;
extern uint8_t volatile channel; // wifi channel rotation counter extern uint8_t volatile channel; // wifi channel rotation counter
@ -86,11 +97,10 @@ void dp_init(bool verbose = false);
void dp_shutdown(void); void dp_shutdown(void);
void dp_message(const char *msg, int line, bool invers); void dp_message(const char *msg, int line, bool invers);
void dp_drawPage(bool nextpage); void dp_drawPage(bool nextpage);
void dp_println(int lines = 1);
void dp_printf(const char *format, ...); void dp_printf(const char *format, ...);
void dp_setFont(int font, int inv = 0); void dp_setFont(int font, int inv = 0);
void dp_dump(uint8_t *pBuffer); void dp_dump(uint8_t *pBuffer = NULL);
void dp_setTextCursor(int col, int row); void dp_setTextCursor(int col = 0, int row = MY_DISPLAY_FIRSTLINE);
void dp_contrast(uint8_t contrast); void dp_contrast(uint8_t contrast);
void dp_clear(void); void dp_clear(void);
void dp_power(uint8_t screenon); void dp_power(uint8_t screenon);

View File

@ -21,6 +21,9 @@
#include "BintrayClient.h" #include "BintrayClient.h"
// Local logging tag
static const char TAG[] = __FILE__;
BintrayClient::BintrayClient(const String &user, const String &repository, const String &package) BintrayClient::BintrayClient(const String &user, const String &repository, const String &package)
: m_user(user), m_repo(repository), m_package(package), : m_user(user), m_repo(repository), m_package(package),
m_storage_host("pax.express"), m_storage_host("pax.express"),

View File

@ -14,10 +14,10 @@
;halfile = ttgov1.h ;halfile = ttgov1.h
;halfile = ttgov2.h ;halfile = ttgov2.h
;halfile = ttgov21old.h ;halfile = ttgov21old.h
;halfile = ttgov21new.h halfile = ttgov21new.h
;halfile = ttgofox.h ;halfile = ttgofox.h
;halfile = ttgobeam.h ;halfile = ttgobeam.h
halfile = ttgobeam10.h ;halfile = ttgobeam10.h
;halfile = ttgotdisplay.h ;halfile = ttgotdisplay.h
;halfile = ttgotwristband.h ;halfile = ttgotwristband.h
;halfile = fipy.h ;halfile = fipy.h
@ -46,7 +46,7 @@ description = Paxcounter is a device for metering passenger flows in realtime. I
[common] [common]
; for release_version use max. 10 chars total, use any decimal format like "a.b.c" ; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
release_version = 3.2.1 release_version = 3.3.0
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; 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 ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
debug_level = 3 debug_level = 3
@ -54,14 +54,15 @@ extra_scripts = pre:build.py
otakeyfile = ota.conf otakeyfile = ota.conf
lorakeyfile = loraconf.h lorakeyfile = loraconf.h
lmicconfigfile = lmic_config.h lmicconfigfile = lmic_config.h
platform_espressif32 = espressif32@4.1.0 platform_espressif32 = espressif32@5.0.0
monitor_speed = 115200 monitor_speed = 115200
upload_speed = 115200 ; set by build.py and taken from hal file upload_speed = 115200 ; set by build.py and taken from hal file
display_library = ; set by build.py and taken from hal file display_library = ; set by build.py and taken from hal file
lib_deps_lora = lib_deps_lora =
mcci-catena/MCCI LoRaWAN LMIC library @ ^4.1.1 mcci-catena/MCCI LoRaWAN LMIC library @ ^4.1.1
lib_deps_display = lib_deps_display =
bitbank2/OneBitDisplay @ ^1.11.0 https://github.com/bitbank2/OneBitDisplay#8d4ab34
;bitbank2/OneBitDisplay @ ^2.1.0
ricmoo/QRCode @ ^0.0.1 ricmoo/QRCode @ ^0.0.1
bodmer/TFT_eSPI @ ^2.3.84 bodmer/TFT_eSPI @ ^2.3.84
lib_deps_ledmatrix = lib_deps_ledmatrix =

View File

@ -8,11 +8,11 @@ Display-Mask (128 x 64 pixel):
| 11111111112 | 11111111112
|012345678901234567890 Font |012345678901234567890 Font
----------------------- --------- ----------------------- ---------
0|PAX:aabbccdd STRETCHED 0|PAX:aabbccdd LARGE
1|PAX:aabbccdd STRETCHED 1|PAX:aabbccdd LARGE
2| 2|
3|WIFI:abcde BLTH:abcde SMALL 3|WIFI:abcde BLTH:abcde SMALL
4|B:a.bcV Sats:ab ch:ab SMALL 4|Batt:abc% chan:ab SMALL
5|RLIM:abcd Mem:abcdKB SMALL 5|RLIM:abcd Mem:abcdKB SMALL
6|27.Feb 2019 20:27:00* SMALL 6|27.Feb 2019 20:27:00* SMALL
7|yyyyyyyyyyyyy xx SFab SMALL 7|yyyyyyyyyyyyy xx SFab SMALL
@ -25,9 +25,10 @@ y = LMIC event message
xx = payload sendqueue length xx = payload sendqueue length
ab = LMIC spread factor ab = LMIC spread factor
MY_FONT_SMALL: 6x8px = 21 chars / line MY_FONT_SMALL: 6x8px = 21 chars / line @ 8 lines
MY_FONT_NORMAL: 8x8px = 16 chars / line MY_FONT_NORMAL: 8x8px = 16 chars / line @ 8 lines
MY_FONT_STRETCHED: 16x32px = 8 chars / line MY_FONT_STRETCHED: 12x16px = 10 chars / line @ 4 lines
MY_FONT_LARGE: 16x32px = 8 chars / line @ 2 lines
*/ */
@ -39,18 +40,14 @@ MY_FONT_STRETCHED: 16x32px = 8 chars / line
// local Tag for logging // local Tag for logging
static const char TAG[] = __FILE__; static const char TAG[] = __FILE__;
static uint8_t plotbuf[PLOTBUFFERSIZE] = {0};
uint8_t DisplayIsOn = 0; uint8_t DisplayIsOn = 0;
uint8_t displaybuf[MY_DISPLAY_WIDTH * MY_DISPLAY_HEIGHT / 8] = {0};
static uint8_t plotbuf[MY_DISPLAY_WIDTH * MY_DISPLAY_HEIGHT / 8] = {0};
static int dp_row = 0, dp_col = 0, dp_font = 0;
hw_timer_t *displayIRQ = NULL; hw_timer_t *displayIRQ = NULL;
QRCode qrcode; QRCode qrcode;
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
OBDISP ssoled; ONE_BIT_DISPLAY oled;
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
TFT_eSPI tft = TFT_eSPI(MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT); TFT_eSPI tft = TFT_eSPI(MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT);
#else #else
@ -62,16 +59,11 @@ void dp_setup(int contrast) {
#if (HAS_DISPLAY) == 1 // I2C OLED #if (HAS_DISPLAY) == 1 // I2C OLED
int rc = obdI2CInit(&ssoled, OLED_TYPE, OLED_ADDR, MY_DISPLAY_FLIP, oled.I2Cbegin(OLED_TYPE, OLED_ADDR, OLED_FREQUENCY);
MY_DISPLAY_INVERT, USE_HW_I2C, MY_DISPLAY_SDA, assert(oled.allocBuffer()); // render all outputs to lib internal backbuffer
MY_DISPLAY_SCL, MY_DISPLAY_RST, oled.setTextWrap(false);
OLED_FREQUENCY); // use standard I2C bus at 400Khz oled.setRotation(
_ASSERT(rc != OLED_NOT_FOUND); MY_DISPLAY_FLIP ? 2 : 0); // 0 = no rotation, 1 = 90°, 2 = 180°, 3 = 280°
// set display buffer
obdSetBackBuffer(&ssoled, displaybuf);
obdSetTextWrap(&ssoled, true);
dp_font = MY_FONT_NORMAL;
#elif (HAS_DISPLAY) == 2 // SPI TFT #elif (HAS_DISPLAY) == 2 // SPI TFT
@ -103,22 +95,17 @@ void dp_init(bool verbose) {
esp_chip_info(&chip_info); esp_chip_info(&chip_info);
dp_setFont(MY_FONT_NORMAL); dp_setFont(MY_FONT_NORMAL);
dp_printf("** PAXCOUNTER **"); dp_printf("** PAXCOUNTER **\r\n");
dp_println(); dp_printf("Software v%s\r\n", PROGVERSION);
dp_printf("Software v%s", PROGVERSION); dp_printf("ESP32 %d cores\r\n", chip_info.cores);
dp_println(); dp_printf("Chip Rev.%d\r\n", chip_info.revision);
dp_printf("ESP32 %d cores", chip_info.cores); dp_printf("WiFi%s%s\r\n", (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
dp_println();
dp_printf("Chip Rev.%d", chip_info.revision);
dp_println();
dp_printf("WiFi%s%s", (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : ""); (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
dp_println();
dp_printf("%dMB %s Flash", spi_flash_get_chip_size() / (1024 * 1024), dp_printf("%dMB %s Flash", spi_flash_get_chip_size() / (1024 * 1024),
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." : "ext."); (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int." : "ext.");
// give user some time to read or take picture // give user some time to read or take picture
dp_dump(displaybuf); dp_dump();
delay(2000); delay(2000);
dp_clear(); dp_clear();
#endif // VERBOSE #endif // VERBOSE
@ -136,17 +123,16 @@ void dp_init(bool verbose) {
// display DEVEUI as plain text on the right // display DEVEUI as plain text on the right
const int x_offset = QR_SCALEFACTOR * 29 + 14; const int x_offset = QR_SCALEFACTOR * 29 + 14;
dp_setTextCursor(x_offset, 0);
dp_setFont(MY_FONT_NORMAL); dp_setFont(MY_FONT_NORMAL);
dp_printf("DEVEUI"); dp_setTextCursor(x_offset, 0);
dp_println(); dp_printf("DEVEUI:\r\n");
for (uint8_t i = 0; i <= 3; i++) { for (uint8_t i = 0; i <= 3; i++) {
dp_setTextCursor(x_offset, i + 3); dp_setTextCursor(x_offset, i * 8 + 20);
dp_printf("%4.4s", deveui + i * 4); dp_printf("%4.4s", deveui + i * 4);
} }
// give user some time to read or take picture // give user some time to read or take picture
dp_dump(displaybuf); dp_dump();
#if !(BOOTMENU) #if !(BOOTMENU)
delay(8000); delay(8000);
#endif #endif
@ -198,10 +184,6 @@ void dp_drawPage(bool nextpage) {
time_t now; time_t now;
struct tm timeinfo = {0}; struct tm timeinfo = {0};
#if (HAS_GPS)
static bool wasnofix = true;
#endif
if (nextpage) { if (nextpage) {
DisplayPage = (DisplayPage >= DISPLAY_PAGES - 1) ? 0 : (DisplayPage + 1); DisplayPage = (DisplayPage >= DISPLAY_PAGES - 1) ? 0 : (DisplayPage + 1);
dp_clear(); dp_clear();
@ -215,9 +197,9 @@ void dp_drawPage(bool nextpage) {
// line 1/2: pax counter // line 1/2: pax counter
// display number of unique macs total Wifi + BLE // display number of unique macs total Wifi + BLE
if (DisplayPage < 5) { if (DisplayPage < 3) {
dp_setFont(MY_FONT_STRETCHED); dp_setFont(MY_FONT_LARGE);
dp_printf("%-5d", count.pax); dp_printf("%-8d", count.pax);
} }
switch (DisplayPage) { switch (DisplayPage) {
@ -233,8 +215,8 @@ void dp_drawPage(bool nextpage) {
// ---------- page 0: parameters overview ---------- // ---------- page 0: parameters overview ----------
case 0: case 0:
dp_setTextCursor(0, 3);
dp_setFont(MY_FONT_SMALL); dp_setFont(MY_FONT_SMALL);
dp_setTextCursor();
// line 3: wifi + bluetooth counters // line 3: wifi + bluetooth counters
// WIFI:abcde BLTH:abcde // WIFI:abcde BLTH:abcde
@ -260,34 +242,24 @@ void dp_drawPage(bool nextpage) {
#else #else
dp_printf("Sniffer disabled"); dp_printf("Sniffer disabled");
#endif #endif
dp_println(); dp_printf("\r\n");
// line 4: Battery + GPS status + Wifi channel // line 4: Battery + GPS status + Wifi channel
// B:a.bcV Sats:ab ch:ab // B:a.bcV Sats:ab ch:ab
#if (defined BAT_MEASURE_ADC || defined HAS_PMU || defined HAS_IP5306) #if (defined BAT_MEASURE_ADC || defined HAS_PMU || defined HAS_IP5306)
if (batt_level == 0) if (batt_level == 0)
dp_printf("No batt "); dp_printf("No batt ");
else else
dp_printf("B:%3d%% ", batt_level); dp_printf("Batt:%3u%% ", batt_level);
#else #else
dp_printf(" "); dp_printf(" ");
#endif #endif
dp_printf("chan:%02u\r\n", channel);
#if (HAS_GPS)
dp_setFont(MY_FONT_SMALL, !gps_hasfix());
dp_printf("Sats:%.2d", gps.satellites.value());
dp_setFont(MY_FONT_SMALL);
#else
dp_printf(" ");
#endif
dp_printf(" ch:%02d", channel);
dp_println();
// line 5: RSSI limiter + free memory // line 5: RSSI limiter + free memory
// RLIM:abcd Mem:abcdKB // RLIM:abcd Mem:abcdKB
dp_printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit); dp_printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit);
dp_printf(" Mem:%4dKB", getFreeRAM() / 1024); dp_printf(" Mem:%4dKB\r\n", getFreeRAM() / 1024);
dp_println();
// line 6: time + date // line 6: time + date
// Wed Jan 12 21:49:08 * // Wed Jan 12 21:49:08 *
@ -302,12 +274,11 @@ void dp_drawPage(bool nextpage) {
// display inverse timeState if clock controller is enabled // display inverse timeState if clock controller is enabled
#if (defined HAS_DCF77) || (defined HAS_IF482) #if (defined HAS_DCF77) || (defined HAS_IF482)
dp_setFont(MY_FONT_SMALL, 1); dp_setFont(MY_FONT_SMALL, 1);
dp_printf("%c", timeState); dp_printf("%c\r\n", timeState);
dp_setFont(MY_FONT_SMALL, 0); dp_setFont(MY_FONT_SMALL, 0);
#else #else
dp_printf("%c", timeState); dp_printf("%c\r\n", timeState);
#endif #endif
dp_println();
#endif // TIME_SYNC_INTERVAL #endif // TIME_SYNC_INTERVAL
// line 7: LMIC status // line 7: LMIC status
@ -322,7 +293,7 @@ void dp_drawPage(bool nextpage) {
dp_setFont(MY_FONT_SMALL, 0); dp_setFont(MY_FONT_SMALL, 0);
#endif // HAS_LORA #endif // HAS_LORA
dp_dump(displaybuf); dp_dump();
break; break;
// ---------- page 1: lorawan parameters ---------- // ---------- page 1: lorawan parameters ----------
@ -337,19 +308,15 @@ void dp_drawPage(bool nextpage) {
// 7|SNR:-0000 RSSI:-0000 // 7|SNR:-0000 RSSI:-0000
dp_setFont(MY_FONT_SMALL); dp_setFont(MY_FONT_SMALL);
dp_setTextCursor(0, 3); dp_setTextCursor();
dp_printf("Net:%06X Pwr:%-2d", LMIC.netid & 0x001FFFFF, LMIC.radio_txpow); dp_printf("Net:%06X Pwr:%-2d\r\n", LMIC.netid & 0x001FFFFF, LMIC.radio_txpow);
dp_println(); dp_printf("Dev:%08X DR:%1d\r\n", LMIC.devaddr, LMIC.datarate);
dp_printf("Dev:%08X DR:%1d", LMIC.devaddr, LMIC.datarate); dp_printf("ChMsk:%04X Nonce:%04X\r\n", LMIC.channelMap, LMIC.devNonce);
dp_println(); dp_printf("fUp:%-6d fDn:%-6d\r\n", LMIC.seqnoUp ? LMIC.seqnoUp - 1 : 0,
dp_printf("ChMsk:%04X Nonce:%04X", LMIC.channelMap, LMIC.devNonce);
dp_println();
dp_printf("fUp:%-6d fDn:%-6d", LMIC.seqnoUp ? LMIC.seqnoUp - 1 : 0,
LMIC.seqnoDn ? LMIC.seqnoDn - 1 : 0); LMIC.seqnoDn ? LMIC.seqnoDn - 1 : 0);
dp_println();
dp_printf("SNR:%-5d RSSI:%-5d", (LMIC.snr + 2) / 4, LMIC.rssi); dp_printf("SNR:%-5d RSSI:%-5d", (LMIC.snr + 2) / 4, LMIC.rssi);
dp_dump(displaybuf); dp_dump();
break; break;
#else // flip page if we are unattended #else // flip page if we are unattended
DisplayPage++; DisplayPage++;
@ -359,31 +326,21 @@ void dp_drawPage(bool nextpage) {
case 2: case 2:
#if (HAS_GPS) #if (HAS_GPS)
// show satellite status at bottom line
dp_setFont(MY_FONT_SMALL);
dp_setTextCursor(0, 56);
dp_printf("%u Sats", gps.satellites.value());
dp_printf(gps_hasfix() ? " " : " - No fix");
// show latitude and longitude
dp_setFont(MY_FONT_STRETCHED); dp_setFont(MY_FONT_STRETCHED);
dp_setTextCursor(0, 3); dp_setTextCursor();
if (gps_hasfix()) { dp_printf("%c%09.6f\r\n", gps.location.rawLat().negative ? 'S' : 'N',
// line 5: clear "No fix" gps.location.lat());
if (wasnofix) { dp_printf("%c%09.6f", gps.location.rawLng().negative ? 'W' : 'E',
dp_setTextCursor(2, 4); gps.location.lng());
dp_printf(" "); dp_dump();
wasnofix = false;
}
// line 3-4: GPS latitude
dp_printf("%c%07.4f", gps.location.rawLat().negative ? 'S' : 'N',
gps.location.lat());
// line 6-7: GPS longitude
dp_printf("%c%07.4f", gps.location.rawLng().negative ? 'W' : 'E',
gps.location.lng());
} else {
dp_setTextCursor(2, 4);
dp_setFont(MY_FONT_STRETCHED, 1);
dp_printf("No fix");
wasnofix = true;
}
dp_dump(displaybuf);
break; break;
#else // flip page if we are unattended #else // flip page if we are unattended
DisplayPage++; DisplayPage++;
@ -394,25 +351,14 @@ void dp_drawPage(bool nextpage) {
#if (HAS_BME) #if (HAS_BME)
dp_setFont(MY_FONT_STRETCHED); dp_setFont(MY_FONT_STRETCHED);
dp_setTextCursor(0, 2); dp_setTextCursor(0, 0);
dp_printf("TMP: %-6.1f\r\n", bme_status.temperature);
// line 2-3: Temp dp_printf("HUM: %-6.1f\r\n", bme_status.humidity);
dp_printf("TMP:%-2.1f", bme_status.temperature); dp_printf("PRE: %-6.1f\r\n", bme_status.pressure);
dp_println(2);
// line 4-5: Hum
dp_printf("HUM:%-2.1f", bme_status.humidity);
dp_println(2);
#ifdef HAS_BME680 #ifdef HAS_BME680
// line 6-7: IAQ dp_printf("IAQ: %-6.0f", bme_status.iaq);
dp_printf("IAQ:%-3.0f", bme_status.iaq); #endif
#else // is BME280 or BMP180 dp_dump();
// line 6-7: Pre
dp_printf("PRE:%-2.1f", bme_status.pressure);
#endif // HAS_BME680
dp_dump(displaybuf);
break; // page 3 break; // page 3
#else // flip page if we are unattended #else // flip page if we are unattended
DisplayPage++; DisplayPage++;
@ -421,20 +367,25 @@ void dp_drawPage(bool nextpage) {
// ---------- page 4: time ---------- // ---------- page 4: time ----------
case 4: case 4:
dp_setFont(MY_FONT_LARGE);
dp_setTextCursor(0, 4);
time(&now); time(&now);
localtime_r(&now, &timeinfo); localtime_r(&now, &timeinfo);
strftime(strftime_buf, sizeof(strftime_buf), "%T", &timeinfo); strftime(strftime_buf, sizeof(strftime_buf), "%T", &timeinfo);
dp_printf("%.8s", strftime_buf);
dp_dump(displaybuf); dp_setFont(MY_FONT_STRETCHED);
dp_setTextCursor(0, 0);
dp_printf("Timeofday:");
dp_setTextCursor(0, 26);
dp_setFont(MY_FONT_LARGE);
dp_printf("%.8s\r\n", strftime_buf);
dp_setFont(MY_FONT_SMALL);
dp_printf("%21.1f", uptime() / 1000.0);
dp_dump();
break; break;
// ---------- page 5: pax graph ---------- // ---------- page 5: pax graph ----------
case 5: case 5:
// update histogram // update and show histogram
dp_plotCurve(count.pax, false); dp_plotCurve(count.pax, false);
dp_dump(plotbuf); dp_dump(plotbuf);
break; break;
@ -455,35 +406,33 @@ void dp_drawPage(bool nextpage) {
// ------------- display helper functions ----------------- // ------------- display helper functions -----------------
void dp_setTextCursor(int x, int y) { void dp_setTextCursor(int x, int y) {
// x represents the pixel column
// y represents the text row
dp_col = x;
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
dp_row = y; oled.setCursor(x, y);
obdSetCursor(&ssoled, dp_col, dp_row);
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
switch (dp_font >> 1) { tft.setCursor(x, y);
case MY_FONT_STRETCHED:
case MY_FONT_LARGE:
dp_row = y * 26;
break;
case MY_FONT_SMALL:
case MY_FONT_NORMAL:
default:
dp_row = y * 16;
break;
}
tft.setCursor(dp_col, dp_row);
#endif #endif
} }
void dp_setFont(int font, int inv) { void dp_setFont(int font, int inv) {
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
dp_font = (font << 1) | (inv & 0x01); // handle invers printing
if (inv)
oled.setTextColor(MY_DISPLAY_BGCOLOR, MY_DISPLAY_FGCOLOR);
else
oled.setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR);
// set desired font
oled.setFont(font);
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
// map font oled -> tft // handle invers printing
if (inv)
tft.setTextColor(MY_DISPLAY_BGCOLOR, MY_DISPLAY_FGCOLOR);
else
tft.setTextColor(MY_DISPLAY_FGCOLOR, MY_DISPLAY_BGCOLOR);
// map desired oled font to tft font
switch (font) { switch (font) {
case MY_FONT_STRETCHED: // 16x16 on OLED case MY_FONT_STRETCHED: // 16x16 on OLED
case MY_FONT_LARGE: // 16x32 on OLED case MY_FONT_LARGE: // 16x32 on OLED
@ -495,21 +444,10 @@ void dp_setFont(int font, int inv) {
tft.setTextFont(2); // 16px tft.setTextFont(2); // 16px
break; break;
} }
// to do: invers printing
#endif #endif
} }
void dp_println(int lines) {
dp_col = 0;
dp_row += lines;
#if (HAS_DISPLAY) == 1
dp_setTextCursor(dp_col, dp_row);
#elif (HAS_DISPLAY) == 2
for (int i = 1; i <= lines; i++)
tft.println();
#endif
};
void dp_printf(const char *format, ...) { void dp_printf(const char *format, ...) {
char loc_buf[64]; char loc_buf[64];
char *temp = loc_buf; char *temp = loc_buf;
@ -533,8 +471,7 @@ void dp_printf(const char *format, ...) {
} }
va_end(arg); va_end(arg);
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
obdWriteString(&ssoled, 0, -1, dp_row, temp, dp_font >> 1, dp_font & 0x01, oled.write(temp);
false);
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
tft.printf(temp); tft.printf(temp);
#endif #endif
@ -545,26 +482,29 @@ void dp_printf(const char *format, ...) {
void dp_dump(uint8_t *pBuffer) { void dp_dump(uint8_t *pBuffer) {
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
obdDumpBuffer(&ssoled, pBuffer); if (pBuffer)
memcpy(oled.getBuffer(), pBuffer, PLOTBUFFERSIZE);
oled.display();
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
// probably oled buffer stucture is not suitable for tft -> to be checked if (pBuffer)
tft.drawBitmap(0, 0, pBuffer, MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT, tft.drawBitmap(0, 0, pBuffer, MY_DISPLAY_WIDTH, MY_DISPLAY_HEIGHT,
MY_DISPLAY_FGCOLOR); MY_DISPLAY_FGCOLOR);
#endif #endif
} }
void dp_clear(void) { void dp_clear(void) {
dp_setTextCursor(0, 0);
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
obdFill(&ssoled, 0, 1); oled.fillScreen(MY_DISPLAY_BGCOLOR);
oled.display();
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
tft.fillScreen(MY_DISPLAY_BGCOLOR); tft.fillScreen(MY_DISPLAY_BGCOLOR);
#endif #endif
dp_setTextCursor(0, 0);
} }
void dp_contrast(uint8_t contrast) { void dp_contrast(uint8_t contrast) {
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
obdSetContrast(&ssoled, contrast); oled.setContrast(contrast);
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
// to do: gamma correction for TFT // to do: gamma correction for TFT
#endif #endif
@ -572,7 +512,7 @@ void dp_contrast(uint8_t contrast) {
void dp_power(uint8_t screenon) { void dp_power(uint8_t screenon) {
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
obdPower(&ssoled, screenon); oled.setPower(screenon);
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
// to come // to come
#endif #endif
@ -580,7 +520,7 @@ void dp_power(uint8_t screenon) {
void dp_shutdown(void) { void dp_shutdown(void) {
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
obdPower(&ssoled, false); oled.setPower(false);
delay(DISPLAYREFRESH_MS / 1000 * 1.1); delay(DISPLAYREFRESH_MS / 1000 * 1.1);
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
// to come // to come
@ -589,10 +529,10 @@ void dp_shutdown(void) {
// print static message on display // print static message on display
void dp_message(const char *msg, int line, bool invers) { void dp_message(const char *msg, int line, bool invers) {
dp_setTextCursor(0, line); dp_setFont(MY_FONT_SMALL, invers ? 1 : 0);
dp_setFont(MY_FONT_NORMAL, invers ? 1 : 0); dp_setTextCursor(0, line * 8);
dp_printf("%-16s", msg); dp_printf("%-16s", msg);
dp_dump(displaybuf); dp_dump();
} // dp_message } // dp_message
// ------------- QR code plotter ----------------- // ------------- QR code plotter -----------------
@ -625,8 +565,7 @@ void dp_printqr(uint16_t offset_x, uint16_t offset_y, const char *Message) {
void dp_fillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height, void dp_fillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
uint8_t bRender) { uint8_t bRender) {
#if (HAS_DISPLAY) == 1 #if (HAS_DISPLAY) == 1
for (uint16_t xi = x; xi < x + width; xi++) oled.fillRect(x, y, width, height, MY_DISPLAY_FGCOLOR);
obdDrawLine(&ssoled, xi, y, xi, y + height - 1, 1, bRender);
#elif (HAS_DISPLAY) == 2 #elif (HAS_DISPLAY) == 2
tft.fillRect(x, y, width, height, MY_DISPLAY_FGCOLOR); tft.fillRect(x, y, width, height, MY_DISPLAY_FGCOLOR);
#endif #endif

View File

@ -29,7 +29,6 @@
#define SDCARD_SCLK SCK #define SDCARD_SCLK SCK
#define CFG_sx1276_radio 1 // select LoRa chip #define CFG_sx1276_radio 1 // select LoRa chip
#define BOARD_HAS_PSRAM // use if board has external PSRAM
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature #define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
#define HAS_DISPLAY 2 // TFT-LCD, support work in progess, not ready yet #define HAS_DISPLAY 2 // TFT-LCD, support work in progess, not ready yet

View File

@ -38,14 +38,6 @@ void i2c_scan(void) {
BBI2C bbi2c; BBI2C bbi2c;
const char *szNames[] = {
"Unknown", "SSD1306", "SH1106", "VL53L0X", "BMP180", "BMP280",
"BME280", "MPU-60x0", "MPU-9250", "MCP9808", "LSM6DS3", "ADXL345",
"ADS1115", "MAX44009", "MAG3110", "CCS811", "HTS221", "LPS25H",
"LSM9DS1", "LM8330", "DS3231", "LIS3DH", "LIS3DSH", "INA219",
"SHT3X", "HDC1080", "MPU6886", "BME680", "AXP202", "AXP192",
"24AA02XEXX", "DS1307"};
ESP_LOGI(TAG, "Starting I2C bus scan..."); ESP_LOGI(TAG, "Starting I2C bus scan...");
memset(&bbi2c, 0, sizeof(bbi2c)); memset(&bbi2c, 0, sizeof(bbi2c));
@ -58,6 +50,8 @@ void i2c_scan(void) {
uint8_t map[16]; uint8_t map[16];
uint8_t i; uint8_t i;
int iDevice, iCount; int iDevice, iCount;
uint32_t iDevCapab;
char szName[15];
I2CScan(&bbi2c, map); // get bitmap of connected I2C devices I2CScan(&bbi2c, map); // get bitmap of connected I2C devices
if (map[0] == 0xfe) // something is wrong with the I2C bus if (map[0] == 0xfe) // something is wrong with the I2C bus
@ -72,9 +66,10 @@ void i2c_scan(void) {
if (map[i >> 3] & (1 << (i & 7))) // device found if (map[i >> 3] & (1 << (i & 7))) // device found
{ {
iCount++; iCount++;
iDevice = I2CDiscoverDevice(&bbi2c, i); iDevice = I2CDiscoverDevice(&bbi2c, i, &iDevCapab);
I2CGetDeviceName(iDevice, szName);
ESP_LOGI(TAG, "Device found at 0x%X, type = %s", i, ESP_LOGI(TAG, "Device found at 0x%X, type = %s", i,
szNames[iDevice]); // show the device name as a string szName); // show the device name as a string
} }
} // for i } // for i
ESP_LOGI(TAG, "%u I2C device(s) found", iCount); ESP_LOGI(TAG, "%u I2C device(s) found", iCount);

View File

@ -50,19 +50,14 @@ void start_ota_update() {
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
dp_setup(); dp_setup();
dp_setFont(MY_FONT_NORMAL);
dp_printf("SOFTWARE UPDATE"); dp_printf("SOFTWARE UPDATE\r\n");
dp_println(); dp_printf("WiFi connect ..\r\n");
dp_printf("WiFi connect .."); dp_printf("Has Update? ..\r\n");
dp_println(); dp_printf("Fetching ..\r\n");
dp_printf("Has Update? .."); dp_printf("Downloading ..\r\n");
dp_println(); dp_printf("Rebooting ..\r\n");
dp_printf("Fetching .."); dp_dump();
dp_println();
dp_printf("Downloading ..");
dp_println();
dp_printf("Rebooting ..");
dp_dump(displaybuf);
#endif #endif
ESP_LOGI(TAG, "Starting Wifi OTA update"); ESP_LOGI(TAG, "Starting Wifi OTA update");
@ -330,15 +325,14 @@ retry:
void ota_display(const uint8_t row, const std::string status, void ota_display(const uint8_t row, const std::string status,
const std::string msg) { const std::string msg) {
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
dp_setFont(MY_FONT_SMALL); dp_setTextCursor(14 * 8, row * 8);
dp_setTextCursor(14, row);
dp_printf(status.substr(0, 2).c_str()); dp_printf(status.substr(0, 2).c_str());
if (!msg.empty()) { if (!msg.empty()) {
dp_printf(" "); dp_printf(" ");
dp_printf(msg.substr(0, 16).c_str()); dp_printf(msg.substr(0, 16).c_str());
dp_println(); // dp_printf("\r\n");
} }
dp_dump(displaybuf); dp_dump();
#endif #endif
} }

View File

@ -64,10 +64,12 @@ void AXP192_powerevent_IRQ(void) {
pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ); pmu.setChgLEDMode(AXP20X_LED_BLINK_1HZ);
} }
#ifdef HAS_BUTTON
// short press -> esp32 deep sleep mode, can be exited by pressing user button // short press -> esp32 deep sleep mode, can be exited by pressing user button
if (pmu.isPEKShortPressIRQ()) { if (pmu.isPEKShortPressIRQ()) {
enter_deepsleep(0, HAS_BUTTON); enter_deepsleep(0, HAS_BUTTON);
} }
#endif
// long press -> shutdown power, can be exited by another longpress // long press -> shutdown power, can be exited by another longpress
if (pmu.isPEKLongtPressIRQ()) { if (pmu.isPEKLongtPressIRQ()) {

View File

@ -200,9 +200,9 @@ void enter_deepsleep(const uint64_t wakeup_sec, gpio_num_t wakeup_gpio) {
// time stamp sleep start time and save system monotonic time. Deep sleep. // time stamp sleep start time and save system monotonic time. Deep sleep.
gettimeofday(&RTC_sleep_start_time, NULL); gettimeofday(&RTC_sleep_start_time, NULL);
RTC_millis += millis(); RTC_millis += esp_timer_get_time() / 1000;
ESP_LOGI(TAG, "Going to sleep, good bye."); ESP_LOGI(TAG, "Going to sleep, good bye.");
esp_deep_sleep_start(); esp_deep_sleep_start();
} }
unsigned long long uptime() { return (RTC_millis + millis()); } unsigned long long uptime() { return (RTC_millis + esp_timer_get_time() / 1000); }