commit
a518c1a5e5
12
README.md
12
README.md
@ -150,7 +150,13 @@ Paxcounter generates identifiers for sniffed MAC adresses and collects them temp
|
||||
|
||||
# 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, GPS and BME sensor data by pressing the button of the device.
|
||||
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 display pages showing
|
||||
- recent count of pax
|
||||
- histogram
|
||||
- GPS data
|
||||
- BME sensor data
|
||||
- Time of day
|
||||
by pressing the button of the device.
|
||||
|
||||
# Sensors and Peripherals
|
||||
|
||||
@ -312,8 +318,8 @@ Note: all settings are stored in NVRAM and will be reloaded when device starts.
|
||||
Example for EU868:
|
||||
|
||||
DataRate Configuration Bit/s
|
||||
0 LoRa: SF12 / 125 kHz 250
|
||||
1 LoRa: SF11 / 125 kHz 440
|
||||
0 LoRa: SF12 / 125 kHz 250
|
||||
1 LoRa: SF11 / 125 kHz 440
|
||||
2 LoRa: SF10 / 125 kHz 980
|
||||
3 LoRa: SF9 / 125 kHz 1760
|
||||
4 LoRa: SF8 / 125 kHz 3125
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include "senddata.h"
|
||||
#include "rcommand.h"
|
||||
#include "spislave.h"
|
||||
|
||||
#if(HAS_LORA)
|
||||
#include <lmic.h>
|
||||
#endif
|
||||
@ -13,6 +14,10 @@
|
||||
#include "bmesensor.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAS_DISPLAY
|
||||
#include "display.h"
|
||||
#endif
|
||||
|
||||
extern Ticker housekeeper;
|
||||
|
||||
void housekeeping(void);
|
||||
|
@ -1,16 +1,24 @@
|
||||
#ifndef _DISPLAY_H
|
||||
#define _DISPLAY_H
|
||||
|
||||
#include <U8x8lib.h>
|
||||
#include "cyclic.h"
|
||||
#include "qrcode.h"
|
||||
|
||||
extern uint8_t DisplayIsOn;
|
||||
|
||||
extern HAS_DISPLAY u8x8;
|
||||
|
||||
void init_display(const char *Productname, const char *Version);
|
||||
void refreshTheDisplay(bool nextPage = false);
|
||||
void init_display(uint8_t verbose = 0);
|
||||
void draw_page(time_t t, uint8_t page);
|
||||
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb);
|
||||
void dp_printf(uint16_t x, uint16_t y, uint8_t font, uint8_t inv,
|
||||
const char *format, ...);
|
||||
void dp_printqr(uint16_t offset_x, uint16_t offset_y, const char *Message);
|
||||
void oledfillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
|
||||
uint8_t bRender);
|
||||
void oledScrollBufferLeft(uint8_t *buf, const uint16_t width,
|
||||
const uint16_t height);
|
||||
int oledDrawPixel(uint8_t *buf, const uint16_t x, const uint16_t y,
|
||||
const uint8_t dot);
|
||||
void oledPlotCurve(uint16_t count, bool reset);
|
||||
void oledRescaleBuffer(uint8_t *buf, const int factor);
|
||||
|
||||
#endif
|
@ -13,6 +13,6 @@ void refreshTheMatrixDisplay(bool nextPage = false);
|
||||
void DrawNumber(String strNum, uint8_t iDotPos = 0);
|
||||
uint8_t GetCharFromFont(char cChar);
|
||||
uint8_t GetCharWidth(char cChar);
|
||||
void ScrollLeft(uint8_t *buf, const uint16_t cols, const uint16_t rows);
|
||||
void ScrollMatrixLeft(uint8_t *buf, const uint16_t cols, const uint16_t rows);
|
||||
|
||||
#endif
|
@ -4,6 +4,7 @@
|
||||
#ifdef USE_OTA
|
||||
|
||||
#include "globals.h"
|
||||
#include <ss_oled.h>
|
||||
#include <Update.h>
|
||||
#include <WiFi.h>
|
||||
#include <WiFiClientSecure.h>
|
||||
@ -14,11 +15,9 @@
|
||||
int do_ota_update();
|
||||
void start_ota_update();
|
||||
int version_compare(const String v1, const String v2);
|
||||
void display(const uint8_t row, const std::string status,
|
||||
const std::string msg);
|
||||
#ifdef HAS_DISPLAY
|
||||
void ota_display(const uint8_t row, const std::string status,
|
||||
const std::string msg);
|
||||
void show_progress(unsigned long current, unsigned long size);
|
||||
#endif
|
||||
|
||||
#endif // USE_OTA
|
||||
|
||||
|
@ -19,6 +19,8 @@ void power_event_IRQ(void);
|
||||
void AXP192_power(bool on);
|
||||
void AXP192_init(void);
|
||||
void AXP192_showstatus(void);
|
||||
uint8_t i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len);
|
||||
uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len);
|
||||
#endif // HAS_PMU
|
||||
|
||||
#endif
|
@ -2,10 +2,15 @@
|
||||
#define _SENDDATA_H
|
||||
|
||||
#include "spislave.h"
|
||||
#include "cyclic.h"
|
||||
|
||||
#if(HAS_LORA)
|
||||
#include "lorawan.h"
|
||||
#endif
|
||||
#include "cyclic.h"
|
||||
|
||||
#ifdef HAS_DISPLAY
|
||||
#include "display.h"
|
||||
#endif
|
||||
|
||||
extern Ticker sendcycler;
|
||||
|
||||
|
@ -34,16 +34,16 @@ halfile = generic.h
|
||||
|
||||
[platformio]
|
||||
; upload firmware to board with usb cable
|
||||
default_envs = usb
|
||||
;default_envs = usb
|
||||
; upload firmware to a jfrog bintray repository
|
||||
;default_envs = ota
|
||||
; use latest versions of libraries
|
||||
;default_envs = dev
|
||||
default_envs = usb
|
||||
description = Paxcounter is a device for metering passenger flows in realtime. It counts how many mobile devices are around.
|
||||
|
||||
[common]
|
||||
; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
|
||||
release_version = 1.8.34
|
||||
release_version = 1.8.52
|
||||
; 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
|
||||
debug_level = 3
|
||||
@ -57,7 +57,9 @@ upload_speed = 115200
|
||||
lib_deps_lora =
|
||||
MCCI LoRaWAN LMIC library@>=3.0.99
|
||||
lib_deps_display =
|
||||
U8g2@>=2.26.13
|
||||
ss_oled@>=3.0.0
|
||||
BitBang_I2C@>=1.2.0
|
||||
QRCode@>=0.0.1
|
||||
lib_deps_matrix_display =
|
||||
https://github.com/Seeed-Studio/Ultrathin_LED_Matrix.git
|
||||
lib_deps_rgbled =
|
||||
@ -66,14 +68,13 @@ lib_deps_gps =
|
||||
1655@>=1.0.2 ;TinyGPSPlus by Mikal Hart
|
||||
lib_deps_sensors =
|
||||
Adafruit Unified Sensor@>=1.0.3
|
||||
Adafruit BME280 Library@>=1.0.9
|
||||
Adafruit BME280 Library@>=1.0.10
|
||||
lib_deps_basic =
|
||||
ArduinoJson@^5.13.1
|
||||
76@>=1.2.2 ;Timezone by Jack Christensen
|
||||
274@>=2.3.3 ;RTC by Michael Miller
|
||||
SimpleButton
|
||||
;AXP202X_Library@^1.0.1
|
||||
https://github.com/lewisxhe/AXP202X_Library.git#8045ddf
|
||||
AXP202X_Library@>=1.0.1
|
||||
lib_deps_all =
|
||||
${common.lib_deps_basic}
|
||||
${common.lib_deps_lora}
|
||||
|
@ -20,7 +20,7 @@ void defaultConfig() {
|
||||
cfg.adrmode = 1; // 0=disabled, 1=enabled
|
||||
cfg.screensaver = 0; // 0=disabled, 1=enabled
|
||||
cfg.screenon = 1; // 0=disabled, 1=enabled
|
||||
cfg.countermode = 0; // 0=cyclic, 1=cumulative, 2=cyclic confirmed
|
||||
cfg.countermode = COUNTERMODE; // 0=cyclic, 1=cumulative, 2=cyclic confirmed
|
||||
cfg.rssilimit = 0; // threshold for rssilimiter, negative value!
|
||||
cfg.sendcycle = SENDCYCLE; // payload send cycle [seconds/2]
|
||||
cfg.wifichancycle =
|
||||
|
@ -128,5 +128,9 @@ void reset_counters() {
|
||||
macs_total = 0; // reset all counters
|
||||
macs_wifi = 0;
|
||||
macs_ble = 0;
|
||||
#ifdef HAS_DISPLAY
|
||||
oledPlotCurve(0, true);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
}
|
510
src/display.cpp
510
src/display.cpp
@ -4,116 +4,134 @@
|
||||
|
||||
Display-Mask (128 x 64 pixel):
|
||||
|
||||
| 111111
|
||||
|0123456789012345
|
||||
------------------
|
||||
0|PAX:aabbccddee
|
||||
1|PAX:aabbccddee
|
||||
2|B:a.bcV Sats:ab
|
||||
3|BLTH:abcde SFab
|
||||
4|WIFI:abcde ch:ab
|
||||
5|RLIM:abcd abcdKB
|
||||
6|20:27:00* 27.Feb
|
||||
7|yyyyyyyyyyyyyyab
|
||||
| | |
|
||||
| 11111111112
|
||||
|012345678901234567890 Font
|
||||
----------------------- ---------
|
||||
0|PAX:aabbccdd STRETCHED
|
||||
1|PAX:aabbccdd STRETCHED
|
||||
2|
|
||||
3|B:a.bcV Sats:ab ch:ab SMALL
|
||||
4|WIFI:abcde BLTH:abcde SMALL
|
||||
5|RLIM:abcd Mem:abcdKB SMALL
|
||||
6|27.Feb 2019 20:27:00* SMALL
|
||||
7|yyyyyyyyyyyyyyyy SFab SMALL
|
||||
|
||||
line 6: * = char {L|G|R|?} indicates time source,
|
||||
inverse = clock controller is active,
|
||||
pulsed = pps input signal is active
|
||||
* = char {L|G|R|?} indicates time source,
|
||||
inverse = clock controller is active,
|
||||
pulsed = pps input signal is active
|
||||
|
||||
line 7: y = LMIC event message; ab = payload queue length
|
||||
y = LMIC event message; ab = payload queue length
|
||||
|
||||
FONT_SMALL: 6x8px = 21 chars / line
|
||||
FONT_NORMAL: 8x8px = 16 chars / line
|
||||
FONT_STRETCHED: 16x32px = 8 chars / line
|
||||
|
||||
*/
|
||||
|
||||
// Basic Config
|
||||
#include "globals.h"
|
||||
#include <ss_oled.h>
|
||||
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
|
||||
|
||||
#define DISPLAY_PAGES (4) // number of display pages
|
||||
// local Tag for logging
|
||||
static const char TAG[] = __FILE__;
|
||||
|
||||
HAS_DISPLAY u8x8(MY_OLED_RST, MY_OLED_SCL, MY_OLED_SDA);
|
||||
#define DISPLAY_PAGES (5) // number of paxcounter display pages
|
||||
|
||||
// helper arry for converting month values to text
|
||||
// settings for oled display library
|
||||
#define USE_BACKBUFFER
|
||||
|
||||
// settings for qr code generator
|
||||
#define QR_VERSION 3 // 29 x 29px
|
||||
#define QR_SCALEFACTOR 2 // 29 -> 58x < 64px
|
||||
|
||||
// settings for curve plotter
|
||||
#define DISPLAY_WIDTH 128 // Width in pixels of OLED-display, must be 32X
|
||||
#define DISPLAY_HEIGHT 64 // Height in pixels of OLED-display, must be 64X
|
||||
|
||||
// helper array for converting month values to text
|
||||
const char *printmonth[] = {"xxx", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
|
||||
|
||||
uint8_t DisplayIsOn = 0;
|
||||
uint8_t displaybuf[DISPLAY_WIDTH * DISPLAY_HEIGHT / 8] = {0};
|
||||
|
||||
// helper function, prints a hex key on display
|
||||
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb) {
|
||||
const uint8_t *p;
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
p = lsb ? key + len - i - 1 : key + i;
|
||||
u8x8.printf("%02X", *p);
|
||||
}
|
||||
u8x8.printf("\n");
|
||||
}
|
||||
QRCode qrcode;
|
||||
|
||||
void init_display(const char *Productname, const char *Version) {
|
||||
void init_display(uint8_t verbose) {
|
||||
|
||||
// block i2c bus access
|
||||
if (!I2C_MUTEX_LOCK())
|
||||
ESP_LOGV(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
|
||||
else {
|
||||
// show startup screen
|
||||
uint8_t buf[32];
|
||||
u8x8.begin();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.clear();
|
||||
u8x8.setFlipMode(0);
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.draw2x2String(0, 0, Productname);
|
||||
u8x8.setInverseFont(0);
|
||||
u8x8.draw2x2String(2, 2, Productname);
|
||||
delay(500);
|
||||
u8x8.clear();
|
||||
u8x8.setFlipMode(1);
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.draw2x2String(0, 0, Productname);
|
||||
u8x8.setInverseFont(0);
|
||||
u8x8.draw2x2String(2, 2, Productname);
|
||||
delay(500);
|
||||
|
||||
u8x8.setFlipMode(0);
|
||||
u8x8.clear();
|
||||
|
||||
#ifdef DISPLAY_FLIP
|
||||
u8x8.setFlipMode(1);
|
||||
// init display
|
||||
#ifndef DISPLAY_FLIP
|
||||
oledInit(OLED_128x64, ANGLE_0, false, -1, -1, 400000L);
|
||||
#else
|
||||
oledInit(OLED_128x64, ANGLE_FLIPY, false, -1, -1, 400000L);
|
||||
#endif
|
||||
|
||||
// Display chip information
|
||||
// clear display
|
||||
oledSetContrast(DISPLAYCONTRAST);
|
||||
oledFill(0, 1);
|
||||
|
||||
if (verbose) {
|
||||
|
||||
// show startup screen
|
||||
// to come -> display .bmp file with logo
|
||||
|
||||
// show chip information
|
||||
#if (VERBOSE)
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
u8x8.printf("ESP32 %d cores\nWiFi%s%s\n", chip_info.cores,
|
||||
esp_chip_info_t chip_info;
|
||||
esp_chip_info(&chip_info);
|
||||
dp_printf(0, 0, 0, 0, "** PAXCOUNTER **");
|
||||
dp_printf(0, 1, 0, 0, "Software v%s", PROGVERSION);
|
||||
dp_printf(0, 3, 0, 0, "ESP32 %d cores", chip_info.cores);
|
||||
dp_printf(0, 4, 0, 0, "Chip Rev.%d", chip_info.revision);
|
||||
dp_printf(0, 5, 0, 0, "WiFi%s%s",
|
||||
(chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
|
||||
(chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");
|
||||
u8x8.printf("ESP Rev.%d\n", chip_info.revision);
|
||||
u8x8.printf("%dMB %s Flash\n", spi_flash_get_chip_size() / (1024 * 1024),
|
||||
dp_printf(0, 6, 0, 0, "%dMB %s Flash",
|
||||
spi_flash_get_chip_size() / (1024 * 1024),
|
||||
(chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "int."
|
||||
: "ext.");
|
||||
|
||||
// give user some time to read or take picture
|
||||
oledDumpBuffer(NULL);
|
||||
delay(2000);
|
||||
oledFill(0x00, 1);
|
||||
#endif // VERBOSE
|
||||
|
||||
u8x8.print(Productname);
|
||||
u8x8.print(" v");
|
||||
u8x8.println(PROGVERSION);
|
||||
|
||||
#if (HAS_LORA)
|
||||
u8x8.println("DEVEUI:");
|
||||
os_getDevEui((u1_t *)buf);
|
||||
DisplayKey(buf, 8, true);
|
||||
delay(3000);
|
||||
// generate DEVEUI as QR code and text
|
||||
uint8_t buf[8];
|
||||
char deveui[17];
|
||||
os_getDevEui((u1_t *)buf);
|
||||
sprintf(deveui, "%016llX", *((uint64_t *)&buf));
|
||||
|
||||
// display DEVEUI as QR code on the left
|
||||
oledSetContrast(30);
|
||||
dp_printqr(3, 3, deveui);
|
||||
|
||||
// display DEVEUI as plain text on the right
|
||||
dp_printf(72, 0, FONT_NORMAL, 0, "LORAWAN");
|
||||
dp_printf(72, 1, FONT_NORMAL, 0, "DEVEUI:");
|
||||
dp_printf(80, 3, FONT_NORMAL, 0, "%4.4s", deveui);
|
||||
dp_printf(80, 4, FONT_NORMAL, 0, "%4.4s", deveui + 4);
|
||||
dp_printf(80, 5, FONT_NORMAL, 0, "%4.4s", deveui + 8);
|
||||
dp_printf(80, 6, FONT_NORMAL, 0, "%4.4s", deveui + 12);
|
||||
|
||||
// give user some time to read or take picture
|
||||
oledDumpBuffer(NULL);
|
||||
delay(8000);
|
||||
oledSetContrast(DISPLAYCONTRAST);
|
||||
oledFill(0x00, 1);
|
||||
#endif // HAS_LORA
|
||||
u8x8.clear();
|
||||
u8x8.setPowerSave(!cfg.screenon); // set display off if disabled
|
||||
u8x8.draw2x2String(0, 0, "PAX:0");
|
||||
#if (BLECOUNTER)
|
||||
u8x8.setCursor(0, 3);
|
||||
u8x8.printf("BLTH:0");
|
||||
#endif
|
||||
u8x8.setCursor(0, 4);
|
||||
u8x8.printf("WIFI:0");
|
||||
u8x8.setCursor(0, 5);
|
||||
u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%d", cfg.rssilimit);
|
||||
|
||||
} // verbose
|
||||
|
||||
oledPower(cfg.screenon); // set display off if disabled
|
||||
|
||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
||||
} // mutex
|
||||
@ -137,15 +155,16 @@ void refreshTheDisplay(bool nextPage) {
|
||||
// set display on/off according to current device configuration
|
||||
if (DisplayIsOn != cfg.screenon) {
|
||||
DisplayIsOn = cfg.screenon;
|
||||
u8x8.setPowerSave(!cfg.screenon);
|
||||
oledPower(cfg.screenon);
|
||||
}
|
||||
|
||||
if (nextPage) {
|
||||
DisplayPage = (DisplayPage >= DISPLAY_PAGES - 1) ? 0 : (DisplayPage + 1);
|
||||
u8x8.clear();
|
||||
oledFill(0, 1);
|
||||
}
|
||||
|
||||
draw_page(t, DisplayPage);
|
||||
oledDumpBuffer(NULL);
|
||||
|
||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
||||
|
||||
@ -154,191 +173,160 @@ void refreshTheDisplay(bool nextPage) {
|
||||
|
||||
void draw_page(time_t t, uint8_t page) {
|
||||
|
||||
char timeState, buff[16];
|
||||
char timeState;
|
||||
uint8_t msgWaiting;
|
||||
#if (HAS_GPS)
|
||||
static bool wasnofix = true;
|
||||
#endif
|
||||
|
||||
// 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 1/2: pax counter
|
||||
dp_printf(0, 0, FONT_STRETCHED, 0, "PAX:%-4d",
|
||||
macs.size()); // display number of unique macs total Wifi + BLE
|
||||
|
||||
// update histogram if we have a display
|
||||
oledPlotCurve(macs.size(), false);
|
||||
|
||||
switch (page % DISPLAY_PAGES) {
|
||||
|
||||
// page 0: parameters overview
|
||||
// page 1: time
|
||||
// page 1: pax graph
|
||||
// page 2: GPS
|
||||
// page 3: BME280/680
|
||||
// page 4: time
|
||||
|
||||
// page 0: parameters overview
|
||||
case 0:
|
||||
|
||||
// update Battery status (line 2)
|
||||
#if (defined BAT_MEASURE_ADC || defined HAS_PMU)
|
||||
u8x8.setCursor(0, 2);
|
||||
if (batt_voltage == 0xffff)
|
||||
u8x8.printf("B:USB ");
|
||||
else
|
||||
u8x8.printf("B:%.2fV", batt_voltage / 1000.0);
|
||||
#endif
|
||||
|
||||
// update GPS status (line 2)
|
||||
#if (HAS_GPS)
|
||||
u8x8.setCursor(9, 2);
|
||||
if (gps.location.age() < 1500) // if no fix then display Sats value inverse
|
||||
u8x8.printf("Sats:%.2d", gps.satellites.value());
|
||||
else {
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.printf("Sats:%.2d", gps.satellites.value());
|
||||
u8x8.setInverseFont(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
// update bluetooth counter + LoRa SF (line 3)
|
||||
// line 3: wifi + bluetooth counters
|
||||
dp_printf(0, 3, FONT_SMALL, 0, "WIFI:%-5d", macs_wifi);
|
||||
#if (BLECOUNTER)
|
||||
u8x8.setCursor(0, 3);
|
||||
if (cfg.blescan)
|
||||
u8x8.printf("BLTH:%-5d", macs_ble);
|
||||
dp_printf(66, 3, FONT_SMALL, 0, "BLTH:%-5d", macs_ble);
|
||||
else
|
||||
u8x8.printf("%s", "BLTH:off");
|
||||
dp_printf(66, 3, FONT_SMALL, 0, "%s", "BLTH:off");
|
||||
#endif
|
||||
|
||||
#if (HAS_LORA)
|
||||
u8x8.setCursor(12, 3);
|
||||
if (!cfg.adrmode) // if ADR=off then display SF value inverse
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.printf("%-4s", getSfName(updr2rps(LMIC.datarate)));
|
||||
if (!cfg.adrmode) // switch off inverse if it was turned on
|
||||
u8x8.setInverseFont(0);
|
||||
#endif // HAS_LORA
|
||||
// line 4: Battery + GPS status + Wifi channel
|
||||
#if (defined BAT_MEASURE_ADC || defined HAS_PMU)
|
||||
if (batt_voltage == 0xffff)
|
||||
dp_printf(0, 4, FONT_SMALL, 0, "%s", "USB ");
|
||||
else if (batt_voltage == 0)
|
||||
dp_printf(0, 4, FONT_SMALL, 0, "%s", "No batt");
|
||||
else
|
||||
dp_printf(0, 4, FONT_SMALL, 0, "B:%.2fV", batt_voltage / 1000.0);
|
||||
#endif
|
||||
#if (HAS_GPS)
|
||||
if (gps.location.age() < 1500) // if no fix then display Sats value inverse
|
||||
dp_printf(48, 4, FONT_SMALL, 0, "Sats:%.2d", gps.satellites.value());
|
||||
else
|
||||
dp_printf(48, 4, FONT_SMALL, 1, "Sats:%.2d", gps.satellites.value());
|
||||
#endif
|
||||
dp_printf(96, 4, FONT_SMALL, 0, "ch:%02d", channel);
|
||||
|
||||
// line 4: update wifi counter + channel display
|
||||
u8x8.setCursor(0, 4);
|
||||
u8x8.printf("WIFI:%-5d", macs_wifi);
|
||||
u8x8.setCursor(11, 4);
|
||||
u8x8.printf("ch:%02d", channel);
|
||||
// line 5: RSSI limiter + free memory
|
||||
dp_printf(0, 5, FONT_SMALL, 0, !cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d",
|
||||
cfg.rssilimit);
|
||||
dp_printf(66, 5, FONT_SMALL, 0, "Mem:%4dKB", getFreeRAM() / 1024);
|
||||
|
||||
// line 5: update RSSI limiter status & free memory display
|
||||
u8x8.setCursor(0, 5);
|
||||
u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit);
|
||||
u8x8.setCursor(10, 5);
|
||||
u8x8.printf("%4dKB", getFreeRAM() / 1024);
|
||||
|
||||
// line 6: update time-of-day or LoRa status display
|
||||
u8x8.setCursor(0, 6);
|
||||
// line 6: time + date
|
||||
#if (TIME_SYNC_INTERVAL)
|
||||
// we want a systime display instead LoRa status
|
||||
timeState = TimePulseTick ? ' ' : timeSetSymbols[timeSource];
|
||||
TimePulseTick = false;
|
||||
|
||||
dp_printf(0, 6, FONT_SMALL, 0, "%02d.%3s %4d", day(t), printmonth[month(t)],
|
||||
year(t));
|
||||
dp_printf(72, 6, FONT_SMALL, 0, "%02d:%02d:%02d", hour(t), minute(t),
|
||||
second(t));
|
||||
|
||||
// display inverse timeState if clock controller is enabled
|
||||
#if (defined HAS_DCF77) || (defined HAS_IF482)
|
||||
u8x8.printf("%02d:%02d:%02d", hour(t), minute(t), second(t));
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.printf("%c", timeState);
|
||||
u8x8.setInverseFont(0);
|
||||
dp_printf(120, 6, FONT_SMALL, 1, "%c", timeState);
|
||||
#else
|
||||
u8x8.printf("%02d:%02d:%02d%c", hour(t), minute(t), second(t), timeState);
|
||||
#endif // HAS_DCF77 || HAS_IF482
|
||||
if (timeSource != _unsynced)
|
||||
u8x8.printf(" %2d.%3s", day(t), printmonth[month(t)]);
|
||||
dp_printf(120, 6, FONT_SMALL, 0, "%c", timeState);
|
||||
#endif
|
||||
|
||||
#endif // TIME_SYNC_INTERVAL
|
||||
|
||||
// line 7: LORA network status
|
||||
#if (HAS_LORA)
|
||||
// line 7: update LMiC event display
|
||||
u8x8.setCursor(0, 7);
|
||||
u8x8.printf("%-14s", lmic_event_msg);
|
||||
|
||||
// update LoRa send queue display
|
||||
// LMiC event display, display inverse if sendqueue not empty
|
||||
msgWaiting = uxQueueMessagesWaiting(LoraSendQueue);
|
||||
if (msgWaiting) {
|
||||
sprintf(buff, "%2d", msgWaiting);
|
||||
u8x8.setCursor(14, 7);
|
||||
u8x8.printf("%-2s", msgWaiting == SEND_QUEUE_SIZE ? "<>" : buff);
|
||||
} else
|
||||
u8x8.printf(" ");
|
||||
if (msgWaiting)
|
||||
dp_printf(0, 7, FONT_SMALL, 1, "%-16s", lmic_event_msg);
|
||||
else
|
||||
dp_printf(0, 7, FONT_SMALL, 0, "%-16s", lmic_event_msg);
|
||||
// LORA datarate, display inverse if ADR disabled
|
||||
if (cfg.adrmode)
|
||||
dp_printf(100, 7, FONT_SMALL, 0, "%-4s",
|
||||
getSfName(updr2rps(LMIC.datarate)));
|
||||
else
|
||||
dp_printf(100, 7, FONT_SMALL, 1, "%-4s",
|
||||
getSfName(updr2rps(LMIC.datarate)));
|
||||
#endif // HAS_LORA
|
||||
|
||||
break; // page0
|
||||
|
||||
// page 1: pax graph
|
||||
case 1:
|
||||
|
||||
// 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);
|
||||
|
||||
oledDumpBuffer(displaybuf);
|
||||
break; // page1
|
||||
|
||||
// page 2: GPS
|
||||
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);
|
||||
dp_printf(16, 5, FONT_STRETCHED, 0, " ");
|
||||
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);
|
||||
dp_printf(0, 3, FONT_STRETCHED, 0, "%c%07.4f",
|
||||
gps.location.rawLat().negative ? 'S' : 'N', gps.location.lat());
|
||||
|
||||
// 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);
|
||||
dp_printf(0, 6, FONT_STRETCHED, 0, "%c%07.4f",
|
||||
gps.location.rawLat().negative ? 'W' : 'E', gps.location.lng());
|
||||
|
||||
} else {
|
||||
snprintf(buff, sizeof(buff), "No fix");
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.draw2x2String(2, 5, buff);
|
||||
u8x8.setInverseFont(0);
|
||||
dp_printf(16, 5, FONT_STRETCHED, 1, "No fix");
|
||||
wasnofix = true;
|
||||
}
|
||||
|
||||
#else
|
||||
snprintf(buff, sizeof(buff), "No GPS");
|
||||
u8x8.draw2x2String(2, 5, buff);
|
||||
dp_printf(16, 5, FONT_STRETCHED, 1, "No GPS");
|
||||
#endif
|
||||
|
||||
break; // page2
|
||||
|
||||
// page 3: BME280/680
|
||||
case 3:
|
||||
|
||||
#if (HAS_BME)
|
||||
// line 2-3: Temp
|
||||
snprintf(buff, sizeof(buff), "TMP:%-2.1f", bme_status.temperature);
|
||||
u8x8.draw2x2String(0, 2, buff);
|
||||
dp_printf(0, 2, FONT_STRETCHED, 0, "TMP:%-2.1f", bme_status.temperature);
|
||||
|
||||
// line 4-5: Hum
|
||||
snprintf(buff, sizeof(buff), "HUM:%-2.1f", bme_status.humidity);
|
||||
u8x8.draw2x2String(0, 4, buff);
|
||||
dp_printf(0, 4, FONT_STRETCHED, 0, "HUM:%-2.1f", bme_status.humidity);
|
||||
|
||||
#ifdef HAS_BME680
|
||||
// line 6-7: IAQ
|
||||
snprintf(buff, sizeof(buff), "IAQ:%-3.0f", bme_status.iaq);
|
||||
u8x8.draw2x2String(0, 6, buff);
|
||||
dp_printf(0, 6, FONT_STRETCHED, 0, "IAQ:%-3.0f", bme_status.iaq);
|
||||
#endif
|
||||
|
||||
#else
|
||||
snprintf(buff, sizeof(buff), "No BME");
|
||||
u8x8.draw2x2String(2, 5, buff);
|
||||
dp_printf(16, 5, FONT_STRETCHED, 1, "No BME");
|
||||
#endif
|
||||
|
||||
break; // page3
|
||||
|
||||
// page 4: time
|
||||
case 4:
|
||||
|
||||
dp_printf(0, 4, FONT_LARGE, 0, "%02d:%02d:%02d", hour(t), minute(t),
|
||||
second(t));
|
||||
break;
|
||||
|
||||
default:
|
||||
break; // default
|
||||
|
||||
@ -346,4 +334,148 @@ void draw_page(time_t t, uint8_t page) {
|
||||
|
||||
} // draw_page
|
||||
|
||||
// display helper functions
|
||||
void dp_printf(uint16_t x, uint16_t y, uint8_t font, uint8_t inv,
|
||||
const char *format, ...) {
|
||||
char loc_buf[64];
|
||||
char *temp = loc_buf;
|
||||
va_list arg;
|
||||
va_list copy;
|
||||
va_start(arg, format);
|
||||
va_copy(copy, arg);
|
||||
int len = vsnprintf(temp, sizeof(loc_buf), format, copy);
|
||||
va_end(copy);
|
||||
if (len < 0) {
|
||||
va_end(arg);
|
||||
return;
|
||||
};
|
||||
if (len >= sizeof(loc_buf)) {
|
||||
temp = (char *)malloc(len + 1);
|
||||
if (temp == NULL) {
|
||||
va_end(arg);
|
||||
return;
|
||||
}
|
||||
len = vsnprintf(temp, len + 1, format, arg);
|
||||
}
|
||||
va_end(arg);
|
||||
oledWriteString(0, x, y, temp, font, inv, false);
|
||||
if (temp != loc_buf) {
|
||||
free(temp);
|
||||
}
|
||||
}
|
||||
|
||||
void dp_printqr(uint16_t offset_x, uint16_t offset_y, const char *Message) {
|
||||
uint8_t qrcodeData[qrcode_getBufferSize(QR_VERSION)];
|
||||
qrcode_initText(&qrcode, qrcodeData, QR_VERSION, ECC_HIGH, Message);
|
||||
|
||||
// draw QR code
|
||||
for (uint16_t y = 0; y < qrcode.size; y++)
|
||||
for (uint16_t x = 0; x < qrcode.size; x++)
|
||||
if (!qrcode_getModule(&qrcode, x, y)) // "black"
|
||||
oledfillRect(x * QR_SCALEFACTOR + offset_x,
|
||||
y * QR_SCALEFACTOR + offset_y, QR_SCALEFACTOR,
|
||||
QR_SCALEFACTOR, false);
|
||||
// draw horizontal frame lines
|
||||
oledfillRect(0, 0, qrcode.size * QR_SCALEFACTOR + 2 * offset_x, offset_y,
|
||||
false);
|
||||
oledfillRect(0, qrcode.size * QR_SCALEFACTOR + offset_y,
|
||||
qrcode.size * QR_SCALEFACTOR + 2 * offset_x, offset_y, false);
|
||||
// draw vertical frame lines
|
||||
oledfillRect(0, 0, offset_x, qrcode.size * QR_SCALEFACTOR + 2 * offset_y,
|
||||
false);
|
||||
oledfillRect(qrcode.size * QR_SCALEFACTOR + offset_x, 0, offset_x,
|
||||
qrcode.size * QR_SCALEFACTOR + 2 * offset_y, false);
|
||||
}
|
||||
|
||||
void oledfillRect(uint16_t x, uint16_t y, uint16_t width, uint16_t height,
|
||||
uint8_t bRender) {
|
||||
for (uint16_t xi = x; xi < x + width; xi++)
|
||||
oledDrawLine(xi, y, xi, y + height - 1, bRender);
|
||||
}
|
||||
|
||||
int oledDrawPixel(uint8_t *buf, const uint16_t x, const uint16_t y,
|
||||
const uint8_t dot) {
|
||||
|
||||
if (x > DISPLAY_WIDTH || y > DISPLAY_HEIGHT)
|
||||
return -1;
|
||||
|
||||
uint8_t bit = y & 7;
|
||||
uint16_t idx = y / 8 * DISPLAY_WIDTH + x;
|
||||
|
||||
buf[idx] &= ~(1 << bit); // clear pixel
|
||||
if (dot)
|
||||
buf[idx] |= (1 << bit); // set pixel
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void oledScrollBufferLeft(uint8_t *buf, const uint16_t width,
|
||||
const uint16_t height) {
|
||||
|
||||
uint16_t col, page, idx;
|
||||
|
||||
for (page = 0; page < height / 8; page++) {
|
||||
for (col = 0; col < width - 1; col++) {
|
||||
idx = page * width + col;
|
||||
buf[idx] = buf[idx + 1];
|
||||
}
|
||||
buf[idx + 1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void oledPlotCurve(uint16_t count, bool reset) {
|
||||
|
||||
static uint16_t last_count = 0, col = 0, row = 0;
|
||||
static int scalefactor = 1, oldsf = 1;
|
||||
|
||||
if ((last_count == count) && !reset)
|
||||
return;
|
||||
|
||||
if (reset) { // next count cycle?
|
||||
if (col < DISPLAY_WIDTH - 1) // matrix not full -> increment column
|
||||
col++;
|
||||
else // matrix full -> scroll left 1 dot
|
||||
oledScrollBufferLeft(displaybuf, DISPLAY_WIDTH, DISPLAY_HEIGHT);
|
||||
|
||||
} else // clear current dot
|
||||
oledDrawPixel(displaybuf, col, row, 0);
|
||||
|
||||
// re-scale, if necessary
|
||||
oldsf = scalefactor;
|
||||
while (((count / scalefactor) <= DISPLAY_HEIGHT) && (scalefactor > 1))
|
||||
scalefactor--;
|
||||
while ((count / scalefactor) > DISPLAY_HEIGHT)
|
||||
scalefactor++;
|
||||
if (scalefactor != oldsf)
|
||||
oledRescaleBuffer(displaybuf, scalefactor);
|
||||
|
||||
// set new dot
|
||||
row = DISPLAY_HEIGHT - 1 - (count / scalefactor) % DISPLAY_HEIGHT;
|
||||
last_count = count;
|
||||
oledDrawPixel(displaybuf, col, row, 1);
|
||||
}
|
||||
|
||||
void oledRescaleBuffer(uint8_t *buf, const int factor) {
|
||||
|
||||
if (!factor)
|
||||
return;
|
||||
|
||||
uint64_t buf_col;
|
||||
|
||||
for (uint16_t col = 0; col < DISPLAY_WIDTH; col++) {
|
||||
// convert column bytes from display buffer to uint64_t
|
||||
buf_col = *(uint64_t *)&buf[col * DISPLAY_HEIGHT / 8];
|
||||
|
||||
if (factor < 0)
|
||||
// shift left: scroll up = scale down
|
||||
buf_col <= abs(factor);
|
||||
else
|
||||
// shift right: scroll down = scale up
|
||||
buf_col >= abs(factor);
|
||||
|
||||
// write back uint64_t to uint8_t display buffer
|
||||
*(uint64_t *)&buf[col * DISPLAY_HEIGHT / 8] = buf_col;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAS_DISPLAY
|
@ -1,5 +1,5 @@
|
||||
// clang-format off
|
||||
// upload_speed 115200
|
||||
// upload_speed 921600
|
||||
// board esp32dev
|
||||
|
||||
#ifndef _EBOX_H
|
||||
|
@ -1,5 +1,5 @@
|
||||
// clang-format off
|
||||
// upload_speed 115200
|
||||
// upload_speed 921600
|
||||
// board esp32dev
|
||||
|
||||
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
//#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define HAS_DISPLAY 1
|
||||
//#define DISPLAY_FLIP 1 // use if display is rotated
|
||||
#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
|
||||
#define BAT_VOLTAGE_DIVIDER ((82.0+220.0)/82.0) // 82k + 220k 1%
|
||||
@ -29,7 +29,7 @@
|
||||
// Pins for I2C interface of OLED Display
|
||||
#define MY_OLED_SDA SDA
|
||||
#define MY_OLED_SCL SCL
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
#define MY_OLED_RST NOT_A_PIN
|
||||
|
||||
// Settings for on board DS3231 RTC chip
|
||||
// note: to use RTC_INT, capacitor 100nF next to red LED must be removed to sharpen interrupt signal slope
|
||||
|
@ -44,7 +44,7 @@
|
||||
#define BOARD_HAS_PSRAM // use if board has external PSRAM
|
||||
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define HAS_DISPLAY 1
|
||||
//#define DISPLAY_FLIP 1 // use if display is rotated
|
||||
#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
|
||||
#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 100k/100k on board
|
||||
|
@ -16,7 +16,7 @@
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define CFG_sx1276_radio 1
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
|
||||
#define HAS_DISPLAY 1 // OLED-Display on board
|
||||
#define HAS_LED LED_BUILTIN // white LED on board
|
||||
#define HAS_BUTTON KEY_BUILTIN // button "PROG" on board
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define CFG_sx1276_radio 1
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
|
||||
#define HAS_DISPLAY 1 // OLED-Display on board
|
||||
#define HAS_LED LED_BUILTIN // white LED on board
|
||||
#define HAS_BUTTON KEY_BUILTIN // button "PROG" on board
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
||||
// disable brownout detection (avoid unexpected reset on some boards)
|
||||
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
|
||||
#define HAS_DISPLAY 1 // OLED-Display on board
|
||||
//#define DISPLAY_FLIP 1 // uncomment this for rotated display
|
||||
#define HAS_LED 22 // ESP32 GPIO12 (pin22) On Board LED
|
||||
#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW
|
||||
@ -37,7 +37,7 @@
|
||||
// Pins for I2C interface of OLED Display
|
||||
#define MY_OLED_SDA (14)
|
||||
#define MY_OLED_SCL (12)
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
#define MY_OLED_RST NOT_A_PIN
|
||||
|
||||
// I2C config for Microchip 24AA02E64 DEVEUI unique address
|
||||
#define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64
|
||||
|
@ -13,7 +13,7 @@
|
||||
// disable brownout detection (avoid unexpected reset on some boards)
|
||||
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
|
||||
#define HAS_DISPLAY 1 // OLED-Display on board
|
||||
//#define DISPLAY_FLIP 1 // uncomment this for rotated display
|
||||
#define HAS_LED NOT_A_PIN // Led os on same pin as Lora SS pin, to avoid problems, we don't use it
|
||||
#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW
|
||||
@ -39,7 +39,7 @@
|
||||
// Pins for I2C interface of OLED Display
|
||||
#define MY_OLED_SDA (21)
|
||||
#define MY_OLED_SCL (22)
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
#define MY_OLED_RST NOT_A_PIN
|
||||
|
||||
// I2C config for Microchip 24AA02E64 DEVEUI unique address
|
||||
#define MCP_24AA02E64_I2C_ADDRESS 0x50 // I2C address for the 24AA02E64
|
||||
|
@ -41,10 +41,10 @@
|
||||
#define LORA_IO2 LMIC_UNUSED_PIN
|
||||
|
||||
// Pins for I2C interface of OLED Display
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // U8X8_SSD1306_128X32_UNIVISION_SW_I2C //
|
||||
#define HAS_DISPLAY 1
|
||||
//#define DISPLAY_FLIP 1 // uncomment this for rotated display
|
||||
#define MY_OLED_SDA (23)
|
||||
#define MY_OLED_SCL (22)
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
#define MY_OLED_RST NOT_A_PIN
|
||||
|
||||
#endif
|
||||
|
@ -33,10 +33,10 @@
|
||||
#define BME680_ADDR BME680_I2C_ADDR_PRIMARY // !! connect SDIO of BME680 to GND !!
|
||||
|
||||
// display (if connected)
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define HAS_DISPLAY 1
|
||||
#define MY_OLED_SDA SDA
|
||||
#define MY_OLED_SCL SCL
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
#define MY_OLED_RST NOT_A_PIN
|
||||
//#define DISPLAY_FLIP 1 // use if display is rotated
|
||||
|
||||
// user defined sensors (if connected)
|
||||
|
@ -20,10 +20,10 @@ User, long press -> send LORA message
|
||||
Reset -> reset device
|
||||
*/
|
||||
|
||||
//#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define HAS_DISPLAY 1
|
||||
#define MY_OLED_SDA SDA
|
||||
#define MY_OLED_SCL SCL
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
#define MY_OLED_RST NOT_A_PIN
|
||||
//#define DISPLAY_FLIP 1 // use if display is rotated
|
||||
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
|
@ -10,7 +10,7 @@
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define HAS_DISPLAY 1
|
||||
#define HAS_LED NOT_A_PIN // green on board LED is useless, is GPIO25, which switches power for Lora+Display
|
||||
|
||||
#define EXT_POWER_SW GPIO_NUM_25 // switches power for LoRa chip
|
||||
@ -23,7 +23,7 @@
|
||||
// Pins for I2C interface of OLED Display
|
||||
#define MY_OLED_SDA (21)
|
||||
#define MY_OLED_SCL (22)
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
#define MY_OLED_RST NOT_A_PIN
|
||||
|
||||
// Settings for on board DS3231 RTC chip
|
||||
#define HAS_RTC MY_OLED_SDA, MY_OLED_SCL // SDA, SCL
|
||||
|
@ -12,7 +12,7 @@
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define CFG_sx1276_radio 1
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C // OLED-Display on board
|
||||
#define HAS_DISPLAY 1 // OLED-Display on board
|
||||
//#define DISPLAY_FLIP 1 // uncomment this for rotated display
|
||||
#define HAS_LED LED_BUILTIN
|
||||
#define LED_ACTIVE_LOW 1 // Onboard LED is active when pin is LOW
|
||||
|
@ -12,7 +12,7 @@
|
||||
#define HAS_LORA 1 // comment out if device shall not send data via LoRa
|
||||
#define CFG_sx1276_radio 1 // HPD13A LoRa SoC
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define HAS_DISPLAY 1
|
||||
//#define DISPLAY_FLIP 1 // uncomment this for rotated display
|
||||
#define HAS_LED NOT_A_PIN // on-board LED is wired to SCL (used by display) therefore totally useless
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
// Pins for I2C interface of OLED Display
|
||||
#define MY_OLED_SDA (21)
|
||||
#define MY_OLED_SCL (22)
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
#define MY_OLED_RST NOT_A_PIN
|
||||
|
||||
// Pins for LORA chip SPI interface come from board file, we need some
|
||||
// additional definitions for LMIC
|
||||
|
@ -20,7 +20,7 @@
|
||||
//#define HAS_BME 1 // Enable BME sensors in general
|
||||
//#define HAS_BME280 GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define HAS_DISPLAY 1
|
||||
#define HAS_LED (25) // green on board LED
|
||||
#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
|
||||
#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 100k/100k on board
|
||||
@ -28,7 +28,7 @@
|
||||
// Pins for I2C interface of OLED Display
|
||||
#define MY_OLED_SDA (21)
|
||||
#define MY_OLED_SCL (22)
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
#define MY_OLED_RST NOT_A_PIN
|
||||
|
||||
// Pins for LORA chip SPI interface, reset line and interrupt lines
|
||||
#define LORA_SCK (5)
|
||||
|
@ -19,7 +19,7 @@
|
||||
#define HAS_LED NOT_A_PIN // no usable LED on board
|
||||
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define HAS_DISPLAY 1
|
||||
//#define DISPLAY_FLIP 1 // rotated display
|
||||
//#define BAT_MEASURE_ADC ADC1_GPIO35_CHANNEL // battery probe GPIO pin -> ADC1_CHANNEL_7
|
||||
//#define BAT_VOLTAGE_DIVIDER 2 // voltage divider 100k/100k on board
|
||||
@ -27,7 +27,7 @@
|
||||
// Pins for I2C interface of OLED Display
|
||||
#define MY_OLED_SDA (21)
|
||||
#define MY_OLED_SCL (22)
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
#define MY_OLED_RST NOT_A_PIN
|
||||
|
||||
// Pins for LORA chip SPI interface, reset line and interrupt lines
|
||||
#define LORA_SCK (5)
|
||||
|
@ -9,10 +9,10 @@
|
||||
|
||||
#define HAS_LED NOT_A_PIN // no LED
|
||||
|
||||
#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C
|
||||
#define HAS_DISPLAY 1
|
||||
#define MY_OLED_SDA (5)
|
||||
#define MY_OLED_SCL (4)
|
||||
#define MY_OLED_RST U8X8_PIN_NONE
|
||||
#define MY_OLED_RST NOT_A_PIN
|
||||
#define DISPLAY_FLIP 1 // use if display is rotated
|
||||
|
||||
#define DISABLE_BROWNOUT 1 // comment out if you want to keep brownout feature
|
||||
|
@ -94,7 +94,7 @@ void refreshTheMatrixDisplay(bool nextPage) {
|
||||
if (col < (LED_MATRIX_WIDTH - 1))
|
||||
col++;
|
||||
else
|
||||
ScrollLeft(displaybuf, LED_MATRIX_WIDTH, LED_MATRIX_HEIGHT);
|
||||
ScrollMatrixLeft(displaybuf, LED_MATRIX_WIDTH, LED_MATRIX_HEIGHT);
|
||||
|
||||
} else
|
||||
matrix.drawPoint(col, row, 0); // clear current dot
|
||||
@ -204,7 +204,7 @@ uint8_t GetCharWidth(char cChar) {
|
||||
return CharDescriptor.width;
|
||||
}
|
||||
|
||||
void ScrollLeft(uint8_t *buf, const uint16_t cols, const uint16_t rows) {
|
||||
void ScrollMatrixLeft(uint8_t *buf, const uint16_t cols, const uint16_t rows) {
|
||||
uint32_t i, k, idx;
|
||||
const uint32_t x = cols / 8;
|
||||
|
||||
|
@ -129,7 +129,7 @@ void setup() {
|
||||
esp_log_level_set("*", ESP_LOG_NONE);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Starting %s v%s", PRODUCTNAME, PROGVERSION);
|
||||
ESP_LOGI(TAG, "Starting Software v%s", PROGVERSION);
|
||||
|
||||
// print chip information on startup if in verbose mode
|
||||
#if (VERBOSE)
|
||||
@ -172,9 +172,9 @@ void setup() {
|
||||
|
||||
// open i2c bus
|
||||
#ifdef HAS_DISPLAY
|
||||
Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 100000);
|
||||
Wire.begin(MY_OLED_SDA, MY_OLED_SCL, 400000);
|
||||
#else
|
||||
Wire.begin(SDA, SCL, 100000);
|
||||
Wire.begin(SDA, SCL, 400000);
|
||||
#endif
|
||||
|
||||
// setup power on boards with power management logic
|
||||
@ -200,7 +200,7 @@ void setup() {
|
||||
#ifdef HAS_DISPLAY
|
||||
strcat_P(features, " OLED");
|
||||
DisplayIsOn = cfg.screenon;
|
||||
init_display(PRODUCTNAME, PROGVERSION); // note: blocking call
|
||||
init_display(!cfg.runmode); // note: blocking call
|
||||
#endif
|
||||
|
||||
#ifdef BOARD_HAS_PSRAM
|
||||
|
83
src/ota.cpp
83
src/ota.cpp
@ -48,25 +48,25 @@ void start_ota_update() {
|
||||
|
||||
switch_LED(LED_ON);
|
||||
|
||||
// init display
|
||||
#ifdef HAS_DISPLAY
|
||||
u8x8.begin();
|
||||
u8x8.setFont(u8x8_font_chroma48medium8_r);
|
||||
u8x8.clear();
|
||||
#ifdef DISPLAY_FLIP
|
||||
u8x8.setFlipMode(1);
|
||||
#ifndef DISPLAY_FLIP
|
||||
oledInit(OLED_128x64, ANGLE_0, false, -1, -1, 400000L);
|
||||
#else
|
||||
oledInit(OLED_128x64, ANGLE_FLIPY, false, -1, -1, 400000L);
|
||||
#endif
|
||||
u8x8.setInverseFont(1);
|
||||
u8x8.print("SOFTWARE UPDATE \n");
|
||||
u8x8.setInverseFont(0);
|
||||
u8x8.print("WiFi connect ..\n");
|
||||
u8x8.print("Has Update? ..\n");
|
||||
u8x8.print("Fetching ..\n");
|
||||
u8x8.print("Downloading ..\n");
|
||||
u8x8.print("Rebooting ..");
|
||||
oledFill(0, 1);
|
||||
dp_printf(0, 0, 0, 1, "SOFTWARE UPDATE");
|
||||
dp_printf(0, 1, 0, 0, "WiFi connect ..");
|
||||
dp_printf(0, 2, 0, 0, "Has Update? ..");
|
||||
dp_printf(0, 3, 0, 0, "Fetching ..");
|
||||
dp_printf(0, 4, 0, 0, "Downloading ..");
|
||||
dp_printf(0, 5, 0, 0, "Rebooting ..");
|
||||
oledDumpBuffer(NULL);
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "Starting Wifi OTA update");
|
||||
display(1, "**", WIFI_SSID);
|
||||
ota_display(1, "**", WIFI_SSID);
|
||||
|
||||
WiFi.mode(WIFI_STA);
|
||||
WiFi.begin(WIFI_SSID, WIFI_PASS);
|
||||
@ -81,7 +81,7 @@ void start_ota_update() {
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
// we now have wifi connection and try to do an OTA over wifi update
|
||||
ESP_LOGI(TAG, "Connected to %s", WIFI_SSID);
|
||||
display(1, "OK", "WiFi connected");
|
||||
ota_display(1, "OK", "WiFi connected");
|
||||
// do a number of tries to update firmware limited by OTA_MAX_TRY
|
||||
uint8_t j = OTA_MAX_TRY;
|
||||
while ((j--) && (ret > 0)) {
|
||||
@ -97,13 +97,13 @@ void start_ota_update() {
|
||||
|
||||
// wifi did not connect
|
||||
ESP_LOGI(TAG, "Could not connect to %s", WIFI_SSID);
|
||||
display(1, " E", "no WiFi connect");
|
||||
ota_display(1, " E", "no WiFi connect");
|
||||
delay(5000);
|
||||
|
||||
end:
|
||||
switch_LED(LED_OFF);
|
||||
ESP_LOGI(TAG, "Rebooting to %s firmware", (ret == 0) ? "new" : "current");
|
||||
display(5, "**", ""); // mark line rebooting
|
||||
ota_display(5, "**", ""); // mark line rebooting
|
||||
delay(5000);
|
||||
ESP.restart();
|
||||
|
||||
@ -119,7 +119,7 @@ int do_ota_update() {
|
||||
|
||||
// Fetch the latest firmware version
|
||||
ESP_LOGI(TAG, "Checking latest firmware version on server");
|
||||
display(2, "**", "checking version");
|
||||
ota_display(2, "**", "checking version");
|
||||
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
return 1;
|
||||
@ -128,23 +128,23 @@ int do_ota_update() {
|
||||
|
||||
if (latest.length() == 0) {
|
||||
ESP_LOGI(TAG, "Could not fetch info on latest firmware");
|
||||
display(2, " E", "file not found");
|
||||
ota_display(2, " E", "file not found");
|
||||
return -1;
|
||||
} else if (version_compare(latest, cfg.version) <= 0) {
|
||||
ESP_LOGI(TAG, "Current firmware is up to date");
|
||||
display(2, "NO", "no update found");
|
||||
ota_display(2, "NO", "no update found");
|
||||
return -1;
|
||||
}
|
||||
ESP_LOGI(TAG, "New firmware version v%s available", latest.c_str());
|
||||
display(2, "OK", latest.c_str());
|
||||
ota_display(2, "OK", latest.c_str());
|
||||
|
||||
display(3, "**", "");
|
||||
ota_display(3, "**", "");
|
||||
if (WiFi.status() != WL_CONNECTED)
|
||||
return 1;
|
||||
String firmwarePath = bintray.getBinaryPath(latest);
|
||||
if (!firmwarePath.endsWith(".bin")) {
|
||||
ESP_LOGI(TAG, "Unsupported binary format");
|
||||
display(3, " E", "file type error");
|
||||
ota_display(3, " E", "file type error");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ int do_ota_update() {
|
||||
|
||||
if (!client.connect(currentHost.c_str(), port)) {
|
||||
ESP_LOGI(TAG, "Cannot connect to %s", currentHost.c_str());
|
||||
display(3, " E", "connection lost");
|
||||
ota_display(3, " E", "connection lost");
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@ -169,7 +169,7 @@ int do_ota_update() {
|
||||
if (!client.connect(currentHost.c_str(), port)) {
|
||||
ESP_LOGI(TAG, "Redirect detected, but cannot connect to %s",
|
||||
currentHost.c_str());
|
||||
display(3, " E", "server error");
|
||||
ota_display(3, " E", "server error");
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
@ -185,7 +185,7 @@ int do_ota_update() {
|
||||
while (client.available() == 0) {
|
||||
if ((millis() - timeout) > (RESPONSE_TIMEOUT_MS)) {
|
||||
ESP_LOGI(TAG, "Client timeout");
|
||||
display(3, " E", "client timeout");
|
||||
ota_display(3, " E", "client timeout");
|
||||
goto abort;
|
||||
}
|
||||
}
|
||||
@ -243,12 +243,12 @@ int do_ota_update() {
|
||||
} // while (client.available())
|
||||
} // while (redirect)
|
||||
|
||||
display(3, "OK", ""); // line download
|
||||
ota_display(3, "OK", ""); // line download
|
||||
|
||||
// check whether we have everything for OTA update
|
||||
if (!(contentLength && isValidContentType)) {
|
||||
ESP_LOGI(TAG, "Invalid OTA server response");
|
||||
display(4, " E", "response error");
|
||||
ota_display(4, " E", "response error");
|
||||
goto retry;
|
||||
}
|
||||
|
||||
@ -262,7 +262,7 @@ int do_ota_update() {
|
||||
if (!Update.begin(contentLength)) {
|
||||
#endif
|
||||
ESP_LOGI(TAG, "Not enough space to start OTA update");
|
||||
display(4, " E", "disk full");
|
||||
ota_display(4, " E", "disk full");
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@ -271,13 +271,13 @@ int do_ota_update() {
|
||||
Update.onProgress(&show_progress);
|
||||
#endif
|
||||
|
||||
display(4, "**", "writing...");
|
||||
ota_display(4, "**", "writing...");
|
||||
written = Update.writeStream(client); // this is a blocking call
|
||||
|
||||
if (written == contentLength) {
|
||||
ESP_LOGI(TAG, "Written %u bytes successfully", written);
|
||||
snprintf(buf, 17, "%ukB Done!", (uint16_t)(written / 1024));
|
||||
display(4, "OK", buf);
|
||||
ota_display(4, "OK", buf);
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Written only %u of %u bytes, OTA update attempt cancelled",
|
||||
written, contentLength);
|
||||
@ -288,7 +288,7 @@ int do_ota_update() {
|
||||
} else {
|
||||
ESP_LOGI(TAG, "An error occurred. Error#: %d", Update.getError());
|
||||
snprintf(buf, 17, "Error#: %d", Update.getError());
|
||||
display(4, " E", buf);
|
||||
ota_display(4, " E", buf);
|
||||
goto retry;
|
||||
}
|
||||
|
||||
@ -307,27 +307,26 @@ retry:
|
||||
|
||||
} // do_ota_update
|
||||
|
||||
void display(const uint8_t row, const std::string status,
|
||||
const std::string msg) {
|
||||
void ota_display(const uint8_t row, const std::string status,
|
||||
const std::string msg) {
|
||||
#ifdef HAS_DISPLAY
|
||||
u8x8.setCursor(14, row);
|
||||
u8x8.print((status.substr(0, 2)).c_str());
|
||||
dp_printf(112, row, 0, 0, status.substr(0, 2).c_str());
|
||||
if (!msg.empty()) {
|
||||
u8x8.clearLine(7);
|
||||
u8x8.setCursor(0, 7);
|
||||
u8x8.print(msg.substr(0, 16).c_str());
|
||||
dp_printf(0, 7, 0, 0, " ");
|
||||
dp_printf(0, 7, 0, 0, msg.substr(0, 16).c_str());
|
||||
}
|
||||
oledDumpBuffer(NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef HAS_DISPLAY
|
||||
// callback function to show download progress while streaming data
|
||||
void show_progress(unsigned long current, unsigned long size) {
|
||||
#ifdef HAS_DISPLAY
|
||||
char buf[17];
|
||||
snprintf(buf, 17, "%-9lu (%3lu%%)", current, current * 100 / size);
|
||||
display(4, "**", buf);
|
||||
}
|
||||
ota_display(4, "**", buf);
|
||||
#endif
|
||||
}
|
||||
|
||||
// helper function to convert strings into lower case
|
||||
bool comp(char s1, char s2) { return tolower(s1) < tolower(s2); }
|
||||
|
@ -6,18 +6,17 @@
|
||||
//
|
||||
// Note: After editing, before "build", use "clean" button in PlatformIO!
|
||||
|
||||
#define PRODUCTNAME "PAXCNT"
|
||||
|
||||
// Verbose enables serial output
|
||||
#define VERBOSE 1 // set to 0 to silence the device, for mute use build option
|
||||
|
||||
// Payload send cycle and encoding
|
||||
#define SENDCYCLE 30 // payload send cycle [seconds/2], 0 .. 255
|
||||
#define PAYLOAD_ENCODER 2 // payload encoder: 1=Plain, 2=Packed, 3=Cayenne LPP dynamic, 4=Cayenne LPP packed
|
||||
#define COUNTERMODE 0 // 0=cyclic, 1=cumulative, 2=cyclic confirmed
|
||||
|
||||
// Set this to include BLE counting and vendor filter functions, or to switch off WIFI counting
|
||||
#define VENDORFILTER 1 // set to 0 if you want to count things, not people
|
||||
#define BLECOUNTER 0 // set it to 1 if you want to use BLE count, at expense of power & memory
|
||||
#define BLECOUNTER 1 // set it to 1 if you want to use BLE count, at expense of power & memory
|
||||
#define WIFICOUNTER 1 // set it to 0 if you want to switch off WIFI count
|
||||
|
||||
// BLE scan parameters
|
||||
@ -56,6 +55,7 @@
|
||||
// Hardware settings
|
||||
#define RGBLUMINOSITY 30 // RGB LED luminosity [default = 30%]
|
||||
#define DISPLAYREFRESH_MS 40 // OLED refresh cycle in ms [default = 40] -> 1000/40 = 25 frames per second
|
||||
#define DISPLAYCONTRAST 80 // 0 .. 255, OLED display contrast [default = 80]
|
||||
#define HOMECYCLE 30 // house keeping cycle in seconds [default = 30 secs]
|
||||
|
||||
// Settings for BME680 environmental sensor
|
||||
@ -75,7 +75,7 @@
|
||||
#define TIME_SYNC_INTERVAL_RETRY 10 // retry time sync after lost sync each .. minutes [default = 10], 0 means off
|
||||
#define TIME_SYNC_COMPILEDATE 0 // set to 1 to use compile date to initialize RTC after power outage [default = 0]
|
||||
#define TIME_SYNC_LORAWAN 0 // set to 1 to use LORA network as time source, 0 means off [default = 0]
|
||||
#define TIME_SYNC_LORASERVER 0 // set to 1 to use LORA timeserver as time source, 0 means off [default = 0]
|
||||
#define TIME_SYNC_LORASERVER 0 // set to 1 to use LORA timeserver as time source, 0 means off [default = 0]
|
||||
|
||||
// settings for syncing time with timeserver applications
|
||||
#define TIME_SYNC_SAMPLES 1 // number of time requests for averaging
|
||||
|
222
src/power.cpp
222
src/power.cpp
@ -11,48 +11,41 @@ AXP20X_Class pmu;
|
||||
|
||||
void power_event_IRQ(void) {
|
||||
|
||||
if (!I2C_MUTEX_LOCK())
|
||||
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
|
||||
else {
|
||||
pmu.readIRQ();
|
||||
|
||||
pmu.readIRQ();
|
||||
// put your power event handler code here
|
||||
if (pmu.isVbusOverVoltageIRQ())
|
||||
ESP_LOGI(TAG, "USB voltage %.2fV too high.", pmu.getVbusVoltage() / 1000);
|
||||
if (pmu.isVbusPlugInIRQ())
|
||||
ESP_LOGI(TAG, "USB plugged, %.2fV @ %.0mA", pmu.getVbusVoltage() / 1000,
|
||||
pmu.getVbusCurrent());
|
||||
if (pmu.isVbusRemoveIRQ())
|
||||
ESP_LOGI(TAG, "USB unplugged.");
|
||||
|
||||
if (pmu.isVbusOverVoltageIRQ())
|
||||
ESP_LOGI(TAG, "USB voltage %.2fV too high.", pmu.getVbusVoltage() / 1000);
|
||||
if (pmu.isVbusPlugInIRQ())
|
||||
ESP_LOGI(TAG, "USB plugged, %.2fV @ %.0mA", pmu.getVbusVoltage() / 1000,
|
||||
pmu.getVbusCurrent());
|
||||
if (pmu.isVbusRemoveIRQ())
|
||||
ESP_LOGI(TAG, "USB unplugged.");
|
||||
if (pmu.isBattPlugInIRQ())
|
||||
ESP_LOGI(TAG, "Battery is connected.");
|
||||
if (pmu.isBattRemoveIRQ())
|
||||
ESP_LOGI(TAG, "Battery was removed.");
|
||||
if (pmu.isChargingIRQ())
|
||||
ESP_LOGI(TAG, "Battery charging.");
|
||||
if (pmu.isChargingDoneIRQ())
|
||||
ESP_LOGI(TAG, "Battery charging done.");
|
||||
if (pmu.isBattTempLowIRQ())
|
||||
ESP_LOGI(TAG, "Battery high temperature.");
|
||||
if (pmu.isBattTempHighIRQ())
|
||||
ESP_LOGI(TAG, "Battery low temperature.");
|
||||
|
||||
if (pmu.isBattPlugInIRQ())
|
||||
ESP_LOGI(TAG, "Battery is connected.");
|
||||
if (pmu.isBattRemoveIRQ())
|
||||
ESP_LOGI(TAG, "Battery was removed.");
|
||||
if (pmu.isChargingIRQ())
|
||||
ESP_LOGI(TAG, "Battery charging.");
|
||||
if (pmu.isChargingDoneIRQ())
|
||||
ESP_LOGI(TAG, "Battery charging done.");
|
||||
if (pmu.isBattTempLowIRQ())
|
||||
ESP_LOGI(TAG, "Battery high temperature.");
|
||||
if (pmu.isBattTempHighIRQ())
|
||||
ESP_LOGI(TAG, "Battery low temperature.");
|
||||
// display on/off
|
||||
if (pmu.isPEKShortPressIRQ()) {
|
||||
cfg.screenon = !cfg.screenon;
|
||||
}
|
||||
|
||||
// display on/off
|
||||
if (pmu.isPEKShortPressIRQ()) {
|
||||
cfg.screenon = !cfg.screenon;
|
||||
}
|
||||
// shutdown power
|
||||
if (pmu.isPEKLongtPressIRQ()) {
|
||||
AXP192_power(false); // switch off Lora, GPS, display
|
||||
pmu.shutdown();
|
||||
}
|
||||
|
||||
// shutdown power
|
||||
if (pmu.isPEKLongtPressIRQ()) {
|
||||
AXP192_power(false); // switch off Lora, GPS, display
|
||||
pmu.shutdown();
|
||||
}
|
||||
|
||||
pmu.clearIRQ();
|
||||
I2C_MUTEX_UNLOCK();
|
||||
} // mutex
|
||||
pmu.clearIRQ();
|
||||
|
||||
// refresh stored voltage value
|
||||
read_voltage();
|
||||
@ -75,70 +68,103 @@ void AXP192_power(bool on) {
|
||||
|
||||
void AXP192_showstatus(void) {
|
||||
|
||||
if (!I2C_MUTEX_LOCK())
|
||||
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
|
||||
else {
|
||||
|
||||
if (pmu.isBatteryConnect())
|
||||
if (pmu.isChargeing())
|
||||
ESP_LOGI(TAG, "Battery charging, %.2fV @ %.0fmAh",
|
||||
pmu.getBattVoltage() / 1000, pmu.getBattChargeCurrent());
|
||||
else
|
||||
ESP_LOGI(TAG, "Battery not charging");
|
||||
if (pmu.isBatteryConnect())
|
||||
if (pmu.isChargeing())
|
||||
ESP_LOGI(TAG, "Battery charging, %.2fV @ %.0fmAh",
|
||||
pmu.getBattVoltage() / 1000, pmu.getBattChargeCurrent());
|
||||
else
|
||||
ESP_LOGI(TAG, "No Battery");
|
||||
ESP_LOGI(TAG, "Battery not charging");
|
||||
else
|
||||
ESP_LOGI(TAG, "No Battery");
|
||||
|
||||
if (pmu.isVBUSPlug())
|
||||
ESP_LOGI(TAG, "USB powered, %.0fmW",
|
||||
pmu.getVbusVoltage() / 1000 * pmu.getVbusCurrent());
|
||||
else
|
||||
ESP_LOGI(TAG, "USB not present");
|
||||
|
||||
I2C_MUTEX_UNLOCK();
|
||||
} // mutex
|
||||
if (pmu.isVBUSPlug())
|
||||
ESP_LOGI(TAG, "USB powered, %.0fmW",
|
||||
pmu.getVbusVoltage() / 1000 * pmu.getVbusCurrent());
|
||||
else
|
||||
ESP_LOGI(TAG, "USB not present");
|
||||
}
|
||||
|
||||
void AXP192_init(void) {
|
||||
|
||||
// block i2c bus access
|
||||
if (I2C_MUTEX_LOCK()) {
|
||||
if (pmu.begin(i2c_readBytes, i2c_writeBytes, AXP192_PRIMARY_ADDRESS) == AXP_FAIL)
|
||||
ESP_LOGI(TAG, "AXP192 PMU initialization failed");
|
||||
else {
|
||||
|
||||
if (pmu.begin(Wire, AXP192_PRIMARY_ADDRESS))
|
||||
ESP_LOGI(TAG, "AXP192 PMU initialization failed");
|
||||
else {
|
||||
// configure AXP192
|
||||
pmu.setDCDC1Voltage(3300); // for external OLED display
|
||||
pmu.setTimeOutShutdown(false); // no automatic shutdown
|
||||
pmu.setTSmode(AXP_TS_PIN_MODE_DISABLE); // TS pin mode off to save power
|
||||
|
||||
// configure AXP192
|
||||
pmu.setDCDC1Voltage(3300); // for external OLED display
|
||||
pmu.setTimeOutShutdown(false); // no automatic shutdown
|
||||
pmu.setTSmode(AXP_TS_PIN_MODE_DISABLE); // TS pin mode off to save power
|
||||
// switch ADCs on
|
||||
pmu.adc1Enable(AXP202_BATT_VOL_ADC1, true);
|
||||
pmu.adc1Enable(AXP202_BATT_CUR_ADC1, true);
|
||||
pmu.adc1Enable(AXP202_VBUS_VOL_ADC1, true);
|
||||
pmu.adc1Enable(AXP202_VBUS_CUR_ADC1, true);
|
||||
|
||||
// switch ADCs on
|
||||
pmu.adc1Enable(AXP202_BATT_VOL_ADC1, true);
|
||||
pmu.adc1Enable(AXP202_BATT_CUR_ADC1, true);
|
||||
pmu.adc1Enable(AXP202_VBUS_VOL_ADC1, true);
|
||||
pmu.adc1Enable(AXP202_VBUS_CUR_ADC1, true);
|
||||
// switch power rails on
|
||||
AXP192_power(true);
|
||||
|
||||
// switch power rails on
|
||||
AXP192_power(true);
|
||||
|
||||
// I2C access of AXP202X library currently is not mutexable
|
||||
// so we better should disable AXP interrupts... ?
|
||||
#ifdef PMU_INT
|
||||
pinMode(PMU_INT, INPUT_PULLUP);
|
||||
attachInterrupt(digitalPinToInterrupt(PMU_INT), PMUIRQ, FALLING);
|
||||
pmu.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ |
|
||||
AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ |
|
||||
AXP202_CHARGING_FINISHED_IRQ,
|
||||
1);
|
||||
pmu.clearIRQ();
|
||||
pinMode(PMU_INT, INPUT_PULLUP);
|
||||
attachInterrupt(digitalPinToInterrupt(PMU_INT), PMUIRQ, FALLING);
|
||||
pmu.enableIRQ(AXP202_VBUS_REMOVED_IRQ | AXP202_VBUS_CONNECT_IRQ |
|
||||
AXP202_BATT_REMOVED_IRQ | AXP202_BATT_CONNECT_IRQ |
|
||||
AXP202_CHARGING_FINISHED_IRQ,
|
||||
1);
|
||||
pmu.clearIRQ();
|
||||
#endif // PMU_INT
|
||||
|
||||
ESP_LOGI(TAG, "AXP192 PMU initialized");
|
||||
}
|
||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
||||
} else
|
||||
ESP_LOGE(TAG, "I2c bus busy - PMU initialization error");
|
||||
ESP_LOGI(TAG, "AXP192 PMU initialized");
|
||||
}
|
||||
}
|
||||
|
||||
// helper functions for mutexing i2c access
|
||||
uint8_t i2c_readBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||
if (I2C_MUTEX_LOCK()) {
|
||||
|
||||
uint8_t ret = 0;
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(reg);
|
||||
Wire.endTransmission(false);
|
||||
uint8_t cnt = Wire.requestFrom(addr, (uint8_t)len, (uint8_t)1);
|
||||
if (!cnt) {
|
||||
ret = 0xFF;
|
||||
}
|
||||
uint16_t index = 0;
|
||||
while (Wire.available()) {
|
||||
if (index > len)
|
||||
return 0xFF;
|
||||
data[index++] = Wire.read();
|
||||
}
|
||||
|
||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
||||
return ret;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t i2c_writeBytes(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t len) {
|
||||
if (I2C_MUTEX_LOCK()) {
|
||||
|
||||
uint8_t ret = 0;
|
||||
Wire.beginTransmission(addr);
|
||||
Wire.write(reg);
|
||||
for (uint16_t i = 0; i < len; i++) {
|
||||
Wire.write(data[i]);
|
||||
}
|
||||
ret = Wire.endTransmission();
|
||||
|
||||
I2C_MUTEX_UNLOCK(); // release i2c bus access
|
||||
return ret ? 0xFF : ret;
|
||||
//return ret ? ret : 0xFF;
|
||||
} else {
|
||||
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
|
||||
return 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAS_PMU
|
||||
|
||||
#ifdef BAT_MEASURE_ADC
|
||||
@ -196,26 +222,28 @@ uint16_t read_voltage() {
|
||||
uint16_t voltage = 0;
|
||||
|
||||
#ifdef HAS_PMU
|
||||
if (!I2C_MUTEX_LOCK())
|
||||
ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
|
||||
else {
|
||||
voltage = pmu.isVBUSPlug() ? 0xffff : pmu.getBattVoltage();
|
||||
I2C_MUTEX_UNLOCK();
|
||||
}
|
||||
// if (!I2C_MUTEX_LOCK())
|
||||
// ESP_LOGW(TAG, "[%0.3f] i2c mutex lock failed", millis() / 1000.0);
|
||||
// else {
|
||||
voltage = pmu.isVBUSPlug() ? 0xffff : pmu.getBattVoltage();
|
||||
// I2C_MUTEX_UNLOCK();
|
||||
// }
|
||||
#else
|
||||
|
||||
#ifdef BAT_MEASURE_ADC
|
||||
// multisample ADC
|
||||
uint32_t adc_reading = 0;
|
||||
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
|
||||
for (int i = 0; i < NO_OF_SAMPLES; i++) {
|
||||
adc_reading += adc1_get_raw(adc_channel);
|
||||
}
|
||||
#else // ADC2
|
||||
int adc_buf = 0;
|
||||
for (int i = 0; i < NO_OF_SAMPLES; i++) {
|
||||
#ifndef BAT_MEASURE_ADC_UNIT // ADC1
|
||||
adc_reading += adc1_get_raw(adc_channel);
|
||||
#else // ADC2
|
||||
ESP_ERROR_CHECK(adc2_get_raw(adc_channel, ADC_WIDTH_BIT_12, &adc_buf));
|
||||
adc_reading += adc_buf;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
adc_reading /= NO_OF_SAMPLES;
|
||||
// Convert ADC reading to voltage in mV
|
||||
voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_characs);
|
||||
|
@ -75,6 +75,10 @@ void sendData() {
|
||||
get_salt(); // get new salt for salting hashes
|
||||
ESP_LOGI(TAG, "Counter cleared");
|
||||
}
|
||||
#ifdef HAS_DISPLAY
|
||||
else
|
||||
oledPlotCurve(macs.size(), true);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user