Merge pull request #338 from cyberman54/development

New feature display pages & flip by button
This commit is contained in:
Verkehrsrot 2019-04-01 18:38:26 +02:00 committed by GitHub
commit fc60ade4d2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 122 additions and 21 deletions

View File

@ -46,7 +46,7 @@ Depending on board hardware following features are supported:
- LED (shows power & status) - LED (shows power & status)
- OLED Display (shows detailed status) - OLED Display (shows detailed status)
- RGB LED (shows colorized status) - RGB LED (shows colorized status)
- Button - Button (used to flip display pages if device has display, else sends alarm message)
- Silicon unique ID - Silicon unique ID
- Battery voltage monitoring - Battery voltage monitoring
- GPS (Generic serial NMEA, or Quectel L76 I2C) - GPS (Generic serial NMEA, or Quectel L76 I2C)
@ -140,6 +140,10 @@ Paxcounter generates identifiers for sniffed MAC adresses and collects them temp
- Red long blink: LoRaWAN stack error - Red long blink: LoRaWAN stack error
- White long blink: Known Beacon detected - White long blink: Known Beacon detected
# Display
If you're using a device with OLED display, or if you add such one to the I2C bus, the device shows live data on the display. You can flip between pages showing pax, time and gps data by pressing the button of the device.
# Sensors and Peripherals # Sensors and Peripherals
You can add up to 3 user defined sensors. Insert sensor's payload scheme in [*sensor.cpp*](src/sensor.cpp). Bosch BME280 / BME680 environment sensors are supported. Enable *flag lib_deps_sensors* for your board in [*platformio.ini*](src/platformio.ini) and configure BME in board's hal file before build. If you need Bosch's proprietary BSEC libraray (e.g. to get indoor air quality value from BME680) further enable *build_flags_sensors*, which comes on the price of reduced RAM and increased build size. RTC DS3231, generic serial NMEA GPS, I2C LoPy GPS are supported, and to be configured in board's hal file. See [*generic.h*](src/hal/generic.h) for all options. You can add up to 3 user defined sensors. Insert sensor's payload scheme in [*sensor.cpp*](src/sensor.cpp). Bosch BME280 / BME680 environment sensors are supported. Enable *flag lib_deps_sensors* for your board in [*platformio.ini*](src/platformio.ini) and configure BME in board's hal file before build. If you need Bosch's proprietary BSEC libraray (e.g. to get indoor air quality value from BME680) further enable *build_flags_sensors*, which comes on the price of reduced RAM and increased build size. RTC DS3231, generic serial NMEA GPS, I2C LoPy GPS are supported, and to be configured in board's hal file. See [*generic.h*](src/hal/generic.h) for all options.

View File

@ -1,6 +1,7 @@
#ifndef _BUTTON_H #ifndef _BUTTON_H
#define _BUTTON_H #define _BUTTON_H
#include "display.h"
#include "senddata.h" #include "senddata.h"
void readButton(); void readButton();

View File

@ -4,12 +4,14 @@
#include <U8x8lib.h> #include <U8x8lib.h>
#include "cyclic.h" #include "cyclic.h"
extern uint8_t DisplayState; extern uint8_t DisplayIsOn;
extern HAS_DISPLAY u8x8; extern HAS_DISPLAY u8x8;
void init_display(const char *Productname, const char *Version); void init_display(const char *Productname, const char *Version);
void refreshtheDisplay(void); void refreshtheDisplay(void);
void refreshtheDisplay(bool nextPage);
void draw_page(time_t t, uint8_t page);
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb); void DisplayKey(const uint8_t *key, uint8_t len, bool lsb);
#endif #endif

View File

@ -7,9 +7,13 @@
static const char TAG[] = __FILE__; static const char TAG[] = __FILE__;
void readButton() { void readButton() {
ESP_LOGI(TAG, "Button pressed"); ESP_LOGI(TAG, "Button pressed");
payload.reset(); #ifdef HAS_DISPLAY
payload.addButton(0x01); refreshtheDisplay(true); // switch to next display page
SendPayload(BUTTONPORT, prio_normal); #else
payload.reset();
payload.addButton(0x01);
SendPayload(BUTTONPORT, prio_normal);
#endif
} }
#endif #endif

View File

@ -26,6 +26,8 @@ line 7: y = Text for LMIC status; ab = payload queue
#include "globals.h" #include "globals.h"
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes #include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
#define DISPLAY_PAGES (3) // number of display pages
HAS_DISPLAY u8x8(MY_OLED_RST, MY_OLED_SCL, MY_OLED_SDA); HAS_DISPLAY u8x8(MY_OLED_RST, MY_OLED_SCL, MY_OLED_SDA);
// helper string for converting LoRa spread factor values // helper string for converting LoRa spread factor values
@ -45,7 +47,7 @@ const char lora_datarate[] = {"121110090807FSNA"};
const char *printmonth[] = {"xxx", "Jan", "Feb", "Mar", "Apr", "May", "Jun", const char *printmonth[] = {"xxx", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
uint8_t DisplayState = 0; uint8_t DisplayIsOn = 0;
// helper function, prints a hex key on display // helper function, prints a hex key on display
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb) { void DisplayKey(const uint8_t *key, uint8_t len, bool lsb) {
@ -127,28 +129,53 @@ void init_display(const char *Productname, const char *Version) {
} // mutex } // mutex
} // init_display } // init_display
void refreshtheDisplay() { void refreshtheDisplay(bool nextPage) {
uint8_t msgWaiting; static uint8_t DisplayPage = 0;
char timeState, buff[16];
const time_t t = const time_t t =
myTZ.toLocal(now()); // note: call now() here *before* locking mutex! myTZ.toLocal(now()); // note: call now() here *before* locking mutex!
// if display is switched off we don't refresh it to relax cpu
if (!DisplayIsOn && (DisplayIsOn == cfg.screenon))
return;
// block i2c bus access // block i2c bus access
if (I2C_MUTEX_LOCK()) { if (I2C_MUTEX_LOCK()) {
// set display on/off according to current device configuration // set display on/off according to current device configuration
if (DisplayState != cfg.screenon) { if (DisplayIsOn != cfg.screenon) {
DisplayState = cfg.screenon; DisplayIsOn = cfg.screenon;
u8x8.setPowerSave(!cfg.screenon); u8x8.setPowerSave(!cfg.screenon);
} }
// if display is switched off we don't refresh it to relax cpu if (nextPage) {
if (!DisplayState) { DisplayPage = (DisplayPage >= DISPLAY_PAGES - 1) ? 0 : (DisplayPage + 1);
I2C_MUTEX_UNLOCK(); // release i2c bus access u8x8.clear();
return;
} }
draw_page(t, DisplayPage);
I2C_MUTEX_UNLOCK(); // release i2c bus access
} // mutex
} // refreshDisplay()
void refreshtheDisplay() { refreshtheDisplay(false); }
void draw_page(time_t t, uint8_t page) {
char timeState, buff[16];
uint8_t msgWaiting;
static bool wasnofix = true;
switch (page % DISPLAY_PAGES) {
// page 0: parameters overview
// page 1: time
// page 2: GPS
// page 3: BME280/680
case 0:
// update counter (lines 0-1) // update counter (lines 0-1)
snprintf( snprintf(
buff, sizeof(buff), "PAX:%-4d", buff, sizeof(buff), "PAX:%-4d",
@ -218,7 +245,7 @@ void refreshtheDisplay() {
TimePulseTick = false; TimePulseTick = false;
// 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)
u8x8.printf("%02d:%02d:%02d", hour(t), minute(t), second(t), timeState); u8x8.printf("%02d:%02d:%02d", hour(t), minute(t), second(t));
u8x8.setInverseFont(1); u8x8.setInverseFont(1);
u8x8.printf("%c", timeState); u8x8.printf("%c", timeState);
u8x8.setInverseFont(0); u8x8.setInverseFont(0);
@ -251,8 +278,71 @@ void refreshtheDisplay() {
#endif // HAS_LORA #endif // HAS_LORA
I2C_MUTEX_UNLOCK(); // release i2c bus access break; // page0
} // mutex
} // refreshDisplay() case 1:
// 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
// line 4-5: update time-of-day
snprintf(buff, sizeof(buff), "%02d:%02d:%02d", hour(t), minute(t),
second(t));
u8x8.draw2x2String(0, 4, buff);
break; // page1
case 2:
// 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
#if (HAS_GPS)
if (gps.location.age() < 1500) {
// line 5: clear "No fix"
if (wasnofix) {
snprintf(buff, sizeof(buff), " ");
u8x8.draw2x2String(2, 5, buff);
wasnofix = false;
}
// line 3-4: GPS latitude
snprintf(buff, sizeof(buff), "%c%-07.4f",
gps.location.rawLat().negative ? 'S' : 'N', gps.location.lat());
u8x8.draw2x2String(0, 3, buff);
// line 6-7: GPS longitude
snprintf(buff, sizeof(buff), "%c%-07.4f",
gps.location.rawLat().negative ? 'W' : 'E', gps.location.lng());
u8x8.draw2x2String(0, 6, buff);
} else {
snprintf(buff, sizeof(buff), "No fix");
u8x8.setInverseFont(1);
u8x8.draw2x2String(2, 5, buff);
u8x8.setInverseFont(0);
wasnofix = true;
}
#else
snprintf(buff, sizeof(buff), "No GPS");
u8x8.draw2x2String(2, 5, buff);
#endif
break; // page2
default:
break; // default
} // switch
} // draw_page
#endif // HAS_DISPLAY #endif // HAS_DISPLAY

View File

@ -314,7 +314,7 @@ void setup() {
// initialize display // initialize display
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
strcat_P(features, " OLED"); strcat_P(features, " OLED");
DisplayState = cfg.screenon; DisplayIsOn = cfg.screenon;
init_display(PRODUCTNAME, PROGVERSION); // note: blocking call init_display(PRODUCTNAME, PROGVERSION); // note: blocking call
#endif #endif