Compare commits
3 Commits
2749f25d15
...
c6df6eac56
Author | SHA1 | Date |
---|---|---|
|
c6df6eac56 | |
|
4513f9d7b0 | |
|
c5e346f4eb |
|
@ -0,0 +1,238 @@
|
|||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#if defined BOARD_OBP60S3 || defined BOARD_OBP40S3
|
||||
|
||||
/*
|
||||
* Barograph WIP
|
||||
* - Zoom feature
|
||||
* - Saves data in FRAM if available
|
||||
*/
|
||||
|
||||
#include "Pagedata.h"
|
||||
#include "OBP60Extensions.h"
|
||||
|
||||
class PageBarograph : public Page
|
||||
{
|
||||
private:
|
||||
bool keylock = false;
|
||||
bool has_fram = false;
|
||||
String flashLED;
|
||||
String useenvsensor;
|
||||
|
||||
char source = 'I'; // (I)nternal, e(X)ternal
|
||||
const int series[5] = {75, 150, 300, 600, 900};
|
||||
const int zoom[5] = {1, 2, 3, 6, 12};
|
||||
int zoomindex = 4;
|
||||
uint16_t data[336] = {0}; // current data to display
|
||||
|
||||
// y-axis
|
||||
uint16_t vmin;
|
||||
uint16_t vmax;
|
||||
uint16_t scalemin = 1000;
|
||||
uint16_t scalemax = 1020;
|
||||
uint16_t scalestep = 5;
|
||||
int hist1 = 0; // one hour trend
|
||||
int hist3 = 0; // three hours trend
|
||||
|
||||
long refresh = 0; // millis
|
||||
|
||||
void loadData() {
|
||||
// Transfer data from history to page buffer,
|
||||
// set y-axis according to data
|
||||
int i = zoom[zoomindex];
|
||||
|
||||
// get min and max values of measured data
|
||||
vmin = data[0];
|
||||
vmax = data[0];
|
||||
for (int x = 0; x < 336; x++) {
|
||||
if (data[x] != 0) {
|
||||
if (data[x] < vmin) {
|
||||
vmin = data[x];
|
||||
} else if (data[x] > vmax) {
|
||||
vmax = data[x];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// calculate y-axis scale
|
||||
uint16_t diff = vmax - vmin;
|
||||
if (diff < 20) {
|
||||
scalestep = 5;
|
||||
} else if (diff < 40) {
|
||||
scalestep = 10;
|
||||
} else {
|
||||
scalestep = 15;
|
||||
}
|
||||
scalemin = vmin - (vmin % scalestep);
|
||||
scalemax = vmax + scalestep - (vmax % scalestep);
|
||||
|
||||
// TODO implement history buffer
|
||||
};
|
||||
|
||||
public:
|
||||
PageBarograph(CommonData &common): Page(common)
|
||||
{
|
||||
logger->logDebug(GwLog::LOG, "Instantiate PageBarograph");
|
||||
|
||||
// Get config data
|
||||
useenvsensor = config->getString(common.config->useEnvSensor);
|
||||
// possible values for internal sensor
|
||||
static std::vector<String> sensorList = {
|
||||
"BME280", "BMP280", "BMP180", "BMP085", "HTU21", "SHT21"
|
||||
};
|
||||
if (std::find(sensorList.begin(), sensorList.end(), useenvsensor) != sensorList.end()) {
|
||||
source = 'I';
|
||||
} else {
|
||||
// "off" means user external data if available
|
||||
source = 'X';
|
||||
}
|
||||
//common.logger->logDebug(GwLog::LOG,"Source=%s (%s)", source, useenvsensor);
|
||||
loadData(); // initial load
|
||||
}
|
||||
|
||||
int handleKey(int key) {
|
||||
if (key == 1) {
|
||||
// zoom in
|
||||
if (zoomindex > 0) {
|
||||
zoomindex -= 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 2) {
|
||||
// zoom out
|
||||
if (zoomindex < sizeof(zoom)) {
|
||||
zoomindex += 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
if (key == 11) {
|
||||
keylock = !keylock;
|
||||
return 0;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
void displayNew(PageData &pageData) {
|
||||
#ifdef BOARD_OBP60S3
|
||||
// Clear optical warning
|
||||
if (flashLED == "Limit Violation") {
|
||||
setBlinkingLED(false);
|
||||
setFlashLED(false);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
int displayPage(PageData &pageData) {
|
||||
|
||||
// Logging boat values
|
||||
logger->logDebug(GwLog::LOG, "Drawing at PageBarograph");
|
||||
|
||||
// Draw page
|
||||
//***********************************************************
|
||||
|
||||
// Set display in partial refresh mode
|
||||
epd->setPartialWindow(0, 0, epd->width(), epd->height()); // Set partial update
|
||||
|
||||
// Frames
|
||||
epd->fillRect(0, 75, 400, 2, commonData->fgcolor); // fillRect: x, y, w, h
|
||||
epd->fillRect(130, 20, 2, 55, commonData->fgcolor);
|
||||
epd->fillRect(270, 20, 2, 55, commonData->fgcolor);
|
||||
epd->fillRect(325, 20, 2, 55, commonData->fgcolor);
|
||||
|
||||
epd->setTextColor(commonData->fgcolor);
|
||||
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
if (source == 'I') {
|
||||
drawTextCenter(360, 40, useenvsensor);
|
||||
} else {
|
||||
drawTextCenter(360, 40, "ext.");
|
||||
}
|
||||
|
||||
// Trend
|
||||
drawTextCenter(295, 62, "0.0");
|
||||
|
||||
// Alarm placeholder
|
||||
drawTextCenter(70, 62, "Alarm Off");
|
||||
|
||||
// Zoom
|
||||
int datastep = series[zoomindex];
|
||||
String fmt;
|
||||
if (datastep > 120) {
|
||||
if (datastep % 60 == 0) {
|
||||
fmt = String(datastep / 60.0, 0) + " min";
|
||||
} else {
|
||||
fmt = String(datastep / 60.0, 1) + " min";
|
||||
}
|
||||
} else {
|
||||
fmt = String(datastep) + " s";
|
||||
}
|
||||
drawTextCenter(360, 62, fmt);
|
||||
|
||||
// Current measurement
|
||||
epd->setFont(&Ubuntu_Bold16pt8b);
|
||||
drawTextCenter(200, 40, String(commonData->data.airPressure / 100, 1));
|
||||
epd->setFont(&Ubuntu_Bold8pt8b);
|
||||
drawTextCenter(200, 62, "hPa"); // Unit
|
||||
|
||||
// Diagram
|
||||
const int xstep = 48; // x-axis-grid
|
||||
const int x0 = 350; // origin
|
||||
const int y0 = 270;
|
||||
const int w = 7 * 48;
|
||||
const int h = 180;
|
||||
|
||||
// epd->drawRect(x0 - w, y0 - h, w, h, commonData->fgcolor);
|
||||
|
||||
// x-axis are hours
|
||||
for (int i = 1; i <= 6; i++) {
|
||||
String label = String(-1 * zoom[zoomindex] * i);
|
||||
epd->drawLine(x0 - i * xstep, y0, x0 - i * xstep, y0 - h, commonData->fgcolor);
|
||||
drawTextCenter(x0 - i * xstep, y0 - 10, label);
|
||||
}
|
||||
|
||||
// y-axis
|
||||
epd->drawLine(x0 + 5, y0, x0 + 5, y0 - h, commonData->fgcolor); // drawLine: x1, y1, x2, y2
|
||||
epd->drawLine(x0 - w, y0, x0 - w, y0 - h, commonData->fgcolor);
|
||||
epd->drawLine(x0 - w - 5, y0, x0 - w - 5, y0 - h, commonData->fgcolor);
|
||||
epd->drawLine(x0, y0, x0, y0 - h, commonData->fgcolor);
|
||||
|
||||
int16_t dy = 9; // px for one hPa
|
||||
int16_t y = y0;
|
||||
int16_t ys = scalemin;
|
||||
while (y >= y0 - h) {
|
||||
if (y % scalestep == 0) {
|
||||
// big step, show label and long line
|
||||
epd->setCursor(x0 + 10, y + 5);
|
||||
epd->print(String(ys));
|
||||
epd->drawLine(x0 + 5, y, x0 - w - 5, y, commonData->fgcolor);
|
||||
} else {
|
||||
// small step, only short lines left and right
|
||||
epd->drawLine(x0 + 5, y, x0, y, commonData->fgcolor);
|
||||
epd->drawLine(x0 - w - 5, y, x0 - w, y, commonData->fgcolor);
|
||||
}
|
||||
y -= dy;
|
||||
ys += 1;
|
||||
}
|
||||
|
||||
return PAGE_UPDATE;
|
||||
};
|
||||
};
|
||||
|
||||
static Page* createPage(CommonData &common){
|
||||
return new PageBarograph(common);
|
||||
}
|
||||
|
||||
/**
|
||||
* with the code below we make this page known to the PageTask
|
||||
* we give it a type (name) that can be selected in the config
|
||||
* we define which function is to be called
|
||||
* and we provide the number of user parameters we expect
|
||||
* this will be number of BoatValue pointers in pageData.values
|
||||
*/
|
||||
PageDescription registerPageBarograph(
|
||||
"Barograph", // Page name
|
||||
createPage, // Action
|
||||
0, // No bus values needed
|
||||
true // Show display header on/off
|
||||
);
|
||||
|
||||
#endif
|
|
@ -82,6 +82,10 @@ Compile result for OBP40 (CrowPanel 4.2):
|
|||
|
||||
/workspace/esp32-nmea2000-obp60/.pio/build/obp40_s3/obp40_s3-all.bin, ready to flash to offset 0x0000
|
||||
|
||||
Compilation issues
|
||||
------------------
|
||||
? Error while linking: "undefined reference to `registerPageXXX'"
|
||||
: Check if the required page is enabled for current board/environment: #if defined ...
|
||||
|
||||
Debugging tool
|
||||
--------------
|
||||
|
|
|
@ -1349,6 +1349,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -1659,6 +1660,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -1960,6 +1962,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -2252,6 +2255,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -2535,6 +2539,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -2809,6 +2814,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -3074,6 +3080,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -3330,6 +3337,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -3577,6 +3585,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -3815,6 +3824,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
|
|
@ -1372,6 +1372,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -1682,6 +1683,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -1983,6 +1985,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -2275,6 +2278,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -2558,6 +2562,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -2832,6 +2837,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -3097,6 +3103,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -3353,6 +3360,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -3600,6 +3608,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
@ -3838,6 +3847,7 @@
|
|||
"list": [
|
||||
"AIS",
|
||||
"Anchor",
|
||||
"Barograph",
|
||||
"BME280",
|
||||
"Battery",
|
||||
"Battery2",
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/* History Buffer
|
||||
*
|
||||
* Storage backed buffer for sensordata
|
||||
* Permanent storage only supported type: FRAM on I2C-Bus
|
||||
*
|
||||
* Values can be 1 to 4 bytes in length
|
||||
*
|
||||
* Header: 32 bytes of size
|
||||
* 0 0x00 HB00 4 magic number
|
||||
* 4 0x04 xxxxxxxxxxxxxxxx 16 name, space padded
|
||||
* 20 0x14 n 1 byte size of values in buffer
|
||||
* 21 0x15 mm 2 buffer size in count of values
|
||||
* 23 0x17 dd 2 time step in seconds between values
|
||||
* 25 0x19 tttt 4 unix timestamp of head
|
||||
* 29 0x1d hh 2 head pointer
|
||||
* 31 0x1f 0xff 1 header end sign
|
||||
*
|
||||
* 32 0x20 ... start of buffer data
|
||||
*
|
||||
* Usage example: 7 hours of data collected every 75 seconds
|
||||
* TODO
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
class HistoryBuffer {
|
||||
|
||||
private:
|
||||
// Header prototype for permanent storage
|
||||
uint8_t header[32] = {
|
||||
0x41, 0x48, 0x30, 0x30, // magic: HB00
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, // empty name
|
||||
0x01, // byte size
|
||||
0x50, 0x01, // value count
|
||||
0x4b, 0x00, // time step
|
||||
0x00, 0x00, 0x00, 0x00, // unix time stamp
|
||||
0x00, 0x00, // head pointer
|
||||
0xff // end sign
|
||||
};
|
||||
uint16_t head = 0; // head pointer to next new value position
|
||||
time_t timestamp; // last modification time of head
|
||||
uint16_t delta_t; // time step in seconds
|
||||
|
||||
public:
|
||||
HistoryBuffer(uint16_t size) {
|
||||
}
|
||||
~HistoryBuffer() {
|
||||
// free memory
|
||||
}
|
||||
void begin() {
|
||||
//
|
||||
}
|
||||
void finish() {
|
||||
}
|
||||
uint16_t add() {
|
||||
// returns new head value pointer
|
||||
}
|
||||
uint8_t* get() {
|
||||
// returns complete buffer in order new to old
|
||||
}
|
||||
uint8_t getvalue(uint16_t dt) {
|
||||
// Return a single value delta seconds ago
|
||||
uint16_t index = head - abs(dt) / delta_t;
|
||||
return 0;
|
||||
}
|
||||
uint8_t getvalue3() {
|
||||
}
|
||||
bool clear() {
|
||||
// clears buffer and permanent storage
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
class History {
|
||||
public:
|
||||
History() {
|
||||
}
|
||||
~History() {
|
||||
}
|
||||
void *addSeries() {
|
||||
}
|
||||
};
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef __HBUFFER_H__
|
||||
#define __HBUFFER_H__
|
||||
|
||||
class HistoryBuffer {
|
||||
public:
|
||||
HistoryBuffer(uint16_t size);
|
||||
void begin();
|
||||
void finish();
|
||||
uint16_t add();
|
||||
uint8_t* get() ;
|
||||
uint8_t getvalue(uint16_t dt);
|
||||
uint8_t getvalue3();
|
||||
void clear();
|
||||
};
|
||||
class History {
|
||||
public:
|
||||
History();
|
||||
void *addSeries();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -273,6 +273,8 @@ void registerAllPages(GwLog *logger, PageList &list){
|
|||
list.add(®isterPageAnchor);
|
||||
extern PageDescription registerPageAIS;
|
||||
list.add(®isterPageAIS);
|
||||
extern PageDescription registerPageBarograph;
|
||||
list.add(®isterPageBarograph);
|
||||
logger->logDebug(GwLog::LOG,"Memory after registering pages: stack=%d, heap=%d", uxTaskGetStackHighWaterMark(NULL), ESP.getFreeHeap());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue