Added analog voltage display
This commit is contained in:
parent
df5ff1c91a
commit
0274b5d755
|
@ -180,6 +180,48 @@ String xdrDelete(String input){
|
|||
return input;
|
||||
}
|
||||
|
||||
Point rotatePoint(const Point& origin, const Point& p, double angle) {
|
||||
// rotate poind around origin by degrees
|
||||
Point rotated;
|
||||
double phi = angle * M_PI / 180.0;
|
||||
double dx = p.x - origin.x;
|
||||
double dy = p.y - origin.y;
|
||||
rotated.x = origin.x + cos(phi) * dx - sin(phi) * dy;
|
||||
rotated.y = origin.y + sin(phi) * dx + cos(phi) * dy;
|
||||
return rotated;
|
||||
}
|
||||
|
||||
std::vector<Point> rotatePoints(const Point& origin, const std::vector<Point>& pts, double angle) {
|
||||
std::vector<Point> rotatedPoints;
|
||||
for (const auto& p : pts) {
|
||||
rotatedPoints.push_back(rotatePoint(origin, p, angle));
|
||||
}
|
||||
return rotatedPoints;
|
||||
}
|
||||
|
||||
void fillPoly4(const std::vector<Point>& p4, uint16_t color) {
|
||||
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[1].x, p4[1].y, p4[2].x, p4[2].y, color);
|
||||
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[2].x, p4[2].y, p4[3].x, p4[3].y, color);
|
||||
}
|
||||
|
||||
// Draw centered text
|
||||
void drawTextCenter(int16_t cx, int16_t cy, String text) {
|
||||
int16_t x1, y1;
|
||||
uint16_t w, h;
|
||||
getdisplay().getTextBounds(text, 0, 150, &x1, &y1, &w, &h);
|
||||
getdisplay().setCursor(cx - w / 2, cy + h / 2);
|
||||
getdisplay().print(text);
|
||||
}
|
||||
|
||||
// Draw right aligned text
|
||||
void drawTextRalign(int16_t x, int16_t y, String text) {
|
||||
int16_t x1, y1;
|
||||
uint16_t w, h;
|
||||
getdisplay().getTextBounds(text, 0, 150, &x1, &y1, &w, &h);
|
||||
getdisplay().setCursor(x - w, y);
|
||||
getdisplay().print(text);
|
||||
}
|
||||
|
||||
// Show a triangle for trend direction high (x, y is the left edge)
|
||||
void displayTrendHigh(int16_t x, int16_t y, uint16_t size, uint16_t color){
|
||||
getdisplay().fillTriangle(x, y, x+size*2, y, x+size, y-size*2, color);
|
||||
|
|
|
@ -39,6 +39,14 @@ GxEPD2_BW<GxEPD2_420_GYE042A87, GxEPD2_420_GYE042A87::HEIGHT> & getdisplay();
|
|||
GxEPD2_BW<GxEPD2_420_SE0420NQ04, GxEPD2_420_SE0420NQ04::HEIGHT> & getdisplay();
|
||||
#endif
|
||||
|
||||
struct Point {
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
Point rotatePoint(const Point& origin, const Point& p, double angle);
|
||||
std::vector<Point> rotatePoints(const Point& origin, const std::vector<Point>& pts, double angle);
|
||||
void fillPoly4(const std::vector<Point>& p4, uint16_t color);
|
||||
|
||||
void hardwareInit();
|
||||
|
||||
void setPortPin(uint pin, bool value); // Set port pin for extension port
|
||||
|
@ -58,6 +66,9 @@ void setBuzzerPower(uint power); // Set buzzer power
|
|||
|
||||
String xdrDelete(String input); // Delete xdr prefix from string
|
||||
|
||||
void drawTextCenter(int16_t cx, int16_t cy, String text);
|
||||
void drawTextRalign(int16_t x, int16_t y, String text);
|
||||
|
||||
void displayTrendHigh(int16_t x, int16_t y, uint16_t size, uint16_t color);
|
||||
void displayTrendLow(int16_t x, int16_t y, uint16_t size, uint16_t color);
|
||||
|
||||
|
|
|
@ -22,43 +22,6 @@ TODO
|
|||
|
||||
*/
|
||||
|
||||
struct Point {
|
||||
double x;
|
||||
double y;
|
||||
};
|
||||
|
||||
Point rotatePoint(const Point& origin, const Point& p, double angle) {
|
||||
// rotate poind around origin by degrees
|
||||
Point rotated;
|
||||
double phi = angle * M_PI / 180.0;
|
||||
double dx = p.x - origin.x;
|
||||
double dy = p.y - origin.y;
|
||||
rotated.x = origin.x + cos(phi) * dx - sin(phi) * dy;
|
||||
rotated.y = origin.y + sin(phi) * dx + cos(phi) * dy;
|
||||
return rotated;
|
||||
}
|
||||
|
||||
std::vector<Point> rotatePoints(const Point& origin, const std::vector<Point>& pts, double angle) {
|
||||
std::vector<Point> rotatedPoints;
|
||||
for (const auto& p : pts) {
|
||||
rotatedPoints.push_back(rotatePoint(origin, p, angle));
|
||||
}
|
||||
return rotatedPoints;
|
||||
}
|
||||
|
||||
void fillPoly4(const std::vector<Point>& p4, uint16_t color) {
|
||||
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[1].x, p4[1].y, p4[2].x, p4[2].y, color);
|
||||
getdisplay().fillTriangle(p4[0].x, p4[0].y, p4[2].x, p4[2].y, p4[3].x, p4[3].y, color);
|
||||
}
|
||||
|
||||
void drawTextCentered(int16_t tx, int16_t ty, String text) {
|
||||
int16_t x, y;
|
||||
uint16_t w, h;
|
||||
getdisplay().getTextBounds(text, 0, 0, &x, &y, &w, &h);
|
||||
getdisplay().setCursor(tx - w / 2, ty + h / 2);
|
||||
getdisplay().print(text);
|
||||
}
|
||||
|
||||
#define fuel_width 16
|
||||
#define fuel_height 16
|
||||
static unsigned char fuel_bits[] = {
|
||||
|
@ -171,7 +134,7 @@ class PageFluid : public Page{
|
|||
} else {
|
||||
strcpy(buffer, "---");
|
||||
}
|
||||
drawTextCentered(c.x, c.y + r - 20, String(buffer));
|
||||
drawTextCenter(c.x, c.y + r - 20, String(buffer));
|
||||
|
||||
// draw symbol (as bitmap)
|
||||
switch (fluidtype) {
|
||||
|
@ -197,18 +160,18 @@ class PageFluid : public Page{
|
|||
// scale texts
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||
p = {c.x, c.y - r + 30};
|
||||
drawTextCentered(p.x, p.y, "1/2");
|
||||
drawTextCenter(p.x, p.y, "1/2");
|
||||
pr = rotatePoint(c, p, -60);
|
||||
drawTextCentered(pr.x, pr.y, "1/4");
|
||||
drawTextCenter(pr.x, pr.y, "1/4");
|
||||
pr = rotatePoint(c, p, 60);
|
||||
drawTextCentered(pr.x, pr.y, "3/4");
|
||||
drawTextCenter(pr.x, pr.y, "3/4");
|
||||
|
||||
// empty and full
|
||||
getdisplay().setFont(&Ubuntu_Bold12pt7b);
|
||||
p = rotatePoint(c, {c.x, c.y - r + 30}, -130);
|
||||
drawTextCentered(p.x, p.y, "E");
|
||||
drawTextCenter(p.x, p.y, "E");
|
||||
p = rotatePoint(c, {c.x, c.y - r + 30}, 130);
|
||||
drawTextCentered(p.x, p.y, "F");
|
||||
drawTextCenter(p.x, p.y, "F");
|
||||
|
||||
// lines
|
||||
std::vector<Point> pts = {
|
||||
|
|
|
@ -11,6 +11,7 @@ bool keylock = false; // Keylock
|
|||
int average = 0; // Average type [0...3], 0=off, 1=10s, 2=60s, 3=300s
|
||||
bool trend = true; // Trend indicator [0|1], 0=off, 1=on
|
||||
double raw = 0;
|
||||
char mode = 'D'; // display mode (A)nalog | (D)igital
|
||||
|
||||
public:
|
||||
PageVoltage(CommonData &common){
|
||||
|
@ -24,6 +25,16 @@ public:
|
|||
return 0; // Commit the key
|
||||
}
|
||||
|
||||
// Switch display mode
|
||||
if (key == 2) {
|
||||
if (mode == 'A') {
|
||||
mode = 'D';
|
||||
} else {
|
||||
mode = 'A';
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Trend indicator
|
||||
if(key == 5){
|
||||
trend = !trend;
|
||||
|
@ -38,6 +49,41 @@ public:
|
|||
return key;
|
||||
}
|
||||
|
||||
void printAvg(int avg, uint16_t x, uint16_t y, bool prefix) {
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||
getdisplay().setCursor(x, y);
|
||||
if (prefix) {
|
||||
getdisplay().print("Avg: ");
|
||||
}
|
||||
switch (average) {
|
||||
case 0:
|
||||
getdisplay().print("1s");
|
||||
break;
|
||||
case 1:
|
||||
getdisplay().print("10s");
|
||||
break;
|
||||
case 2:
|
||||
getdisplay().print("60s");
|
||||
break;
|
||||
case 3:
|
||||
getdisplay().print("300s");
|
||||
break;
|
||||
default:
|
||||
getdisplay().print("1s");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void printVoltageSymbol(uint16_t x, uint16_t y, uint16_t color) {
|
||||
getdisplay().setFont(&Ubuntu_Bold16pt7b);
|
||||
getdisplay().setCursor(x, y);
|
||||
getdisplay().print("V");
|
||||
getdisplay().fillRect(x, y + 6, 22, 3, color);
|
||||
getdisplay().fillRect(x, y + 11, 6, 3, color);
|
||||
getdisplay().fillRect(x + 8, y + 11, 6, 3, color);
|
||||
getdisplay().fillRect(x + 16, y + 11, 6, 3, color);
|
||||
}
|
||||
|
||||
virtual void displayPage(CommonData &commonData, PageData &pageData)
|
||||
{
|
||||
GwConfigHandler *config = commonData.config;
|
||||
|
@ -135,92 +181,177 @@ public:
|
|||
// Set display in partial refresh mode
|
||||
getdisplay().setPartialWindow(0, 0, getdisplay().width(), getdisplay().height()); // Set partial update
|
||||
|
||||
// Show name
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold32pt7b);
|
||||
getdisplay().setCursor(20, 100);
|
||||
getdisplay().print(name1); // Value name
|
||||
if (mode == 'D') {
|
||||
// Display mode digital
|
||||
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt7b);
|
||||
getdisplay().setCursor(270, 100);
|
||||
getdisplay().print("V");
|
||||
// Show name
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
getdisplay().setFont(&Ubuntu_Bold32pt7b);
|
||||
getdisplay().setCursor(20, 100);
|
||||
getdisplay().print(name1); // Value name
|
||||
|
||||
// Show battery type
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||
getdisplay().setCursor(295, 100);
|
||||
getdisplay().print(batType);
|
||||
// Show unit
|
||||
getdisplay().setFont(&Ubuntu_Bold20pt7b);
|
||||
getdisplay().setCursor(270, 100);
|
||||
getdisplay().print("V");
|
||||
|
||||
// Show average settings
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||
getdisplay().setCursor(320, 84);
|
||||
switch (average) {
|
||||
case 0:
|
||||
getdisplay().print("Avg: 1s");
|
||||
break;
|
||||
case 1:
|
||||
getdisplay().print("Avg: 10s");
|
||||
break;
|
||||
case 2:
|
||||
getdisplay().print("Avg: 60s");
|
||||
break;
|
||||
case 3:
|
||||
getdisplay().print("Avg: 300s");
|
||||
break;
|
||||
default:
|
||||
getdisplay().print("Avg: 1s");
|
||||
break;
|
||||
}
|
||||
// Show battery type
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||
getdisplay().setCursor(295, 100);
|
||||
getdisplay().print(batType);
|
||||
|
||||
// Reading bus data or using simulation data
|
||||
getdisplay().setFont(&DSEG7Classic_BoldItalic60pt7b);
|
||||
getdisplay().setCursor(20, 240);
|
||||
if(simulation == true){
|
||||
if(batVoltage == "12V"){
|
||||
value1 = 12.0;
|
||||
}
|
||||
if(batVoltage == "24V"){
|
||||
value1 = 24.0;
|
||||
}
|
||||
value1 += float(random(0, 5)) / 10; // Simulation data
|
||||
getdisplay().print(value1,1);
|
||||
}
|
||||
else{
|
||||
// Check for valid real data, display also if hold values activated
|
||||
if(valid1 == true || holdvalues == true){
|
||||
// Resolution switching
|
||||
if(value1 < 10){
|
||||
getdisplay().print(value1,2);
|
||||
// Show average settings
|
||||
printAvg(average, 320, 84, true);
|
||||
|
||||
// Reading bus data or using simulation data
|
||||
getdisplay().setFont(&DSEG7Classic_BoldItalic60pt7b);
|
||||
getdisplay().setCursor(20, 240);
|
||||
if(simulation == true){
|
||||
if(batVoltage == "12V"){
|
||||
value1 = 12.0;
|
||||
}
|
||||
if(value1 >= 10 && value1 < 100){
|
||||
getdisplay().print(value1,1);
|
||||
}
|
||||
if(value1 >= 100){
|
||||
getdisplay().print(value1,0);
|
||||
if(batVoltage == "24V"){
|
||||
value1 = 24.0;
|
||||
}
|
||||
value1 += float(random(0, 5)) / 10; // Simulation data
|
||||
getdisplay().print(value1,1);
|
||||
}
|
||||
else{
|
||||
getdisplay().print("---"); // Missing bus data
|
||||
}
|
||||
}
|
||||
|
||||
// Trend indicator
|
||||
// Show trend indicator
|
||||
if(trend == true){
|
||||
getdisplay().fillRect(310, 240, 40, 120, commonData.bgcolor); // Clear area
|
||||
getdisplay().fillRect(315, 183, 35, 4, commonData.fgcolor); // Draw separator
|
||||
if(int(raw * 10) > int(valueTrend * 10)){
|
||||
displayTrendHigh(320, 174, 11, commonData.fgcolor); // Show high indicator
|
||||
// Check for valid real data, display also if hold values activated
|
||||
if(valid1 == true || holdvalues == true){
|
||||
// Resolution switching
|
||||
if(value1 < 10){
|
||||
getdisplay().print(value1,2);
|
||||
}
|
||||
if(value1 >= 10 && value1 < 100){
|
||||
getdisplay().print(value1,1);
|
||||
}
|
||||
if(value1 >= 100){
|
||||
getdisplay().print(value1,0);
|
||||
}
|
||||
}
|
||||
else{
|
||||
getdisplay().print("---"); // Missing bus data
|
||||
}
|
||||
}
|
||||
if(int(raw * 10) < int(valueTrend * 10)){
|
||||
displayTrendLow(320, 195, 11, commonData.fgcolor); // Show low indicator
|
||||
}
|
||||
}
|
||||
// No trend indicator
|
||||
else{
|
||||
getdisplay().fillRect(310, 240, 40, 120, commonData.bgcolor); // Clear area
|
||||
}
|
||||
|
||||
// Trend indicator
|
||||
// Show trend indicator
|
||||
if(trend == true){
|
||||
getdisplay().fillRect(310, 240, 40, 120, commonData.bgcolor); // Clear area
|
||||
getdisplay().fillRect(315, 183, 35, 4, commonData.fgcolor); // Draw separator
|
||||
if(int(raw * 10) > int(valueTrend * 10)){
|
||||
displayTrendHigh(320, 174, 11, commonData.fgcolor); // Show high indicator
|
||||
}
|
||||
if(int(raw * 10) < int(valueTrend * 10)){
|
||||
displayTrendLow(320, 195, 11, commonData.fgcolor); // Show low indicator
|
||||
}
|
||||
}
|
||||
// No trend indicator
|
||||
else{
|
||||
getdisplay().fillRect(310, 240, 40, 120, commonData.bgcolor); // Clear area
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// Display mode analog
|
||||
|
||||
// center
|
||||
Point c = {260, 270};
|
||||
uint8_t r = 240;
|
||||
|
||||
Point p1, p2;
|
||||
std::vector<Point> pts;
|
||||
|
||||
// Instrument
|
||||
getdisplay().drawCircleHelper(c.x, c.y, r + 2, 0x01, commonData.fgcolor);
|
||||
getdisplay().drawCircleHelper(c.x, c.y, r + 1, 0x01, commonData.fgcolor);
|
||||
getdisplay().drawCircleHelper(c.x, c.y, r , 0x01, commonData.fgcolor);
|
||||
|
||||
// Scale
|
||||
// angle to voltage scale mapping
|
||||
std::map<int, String> mapping = {
|
||||
{15, "10"}, {30, "11"}, {45, "12"}, {60, "13"}, {75, "14"}
|
||||
};
|
||||
pts = {
|
||||
{c.x - r, c.y - 1},
|
||||
{c.x - r + 12, c.y - 1},
|
||||
{c.x - r + 12, c.y + 1},
|
||||
{c.x - r, c.y + 1}
|
||||
};
|
||||
getdisplay().setFont(&Ubuntu_Bold10pt7b);
|
||||
for (int angle = 3; angle < 90; angle += 3) {
|
||||
if (angle % 15 == 0) {
|
||||
fillPoly4(rotatePoints(c, pts, angle), commonData.fgcolor);
|
||||
p1 = rotatePoint(c, {c.x - r + 30, c.y}, angle);
|
||||
drawTextCenter(p1.x, p1.y, mapping[angle]);
|
||||
}
|
||||
else {
|
||||
p1 = rotatePoint(c, {c.x - r, c.y}, angle);
|
||||
p2 = rotatePoint(c, {c.x - r + 6, c.y}, angle);
|
||||
getdisplay().drawLine(p1.x, p1.y, p2.x, p2.y, commonData.fgcolor);
|
||||
}
|
||||
}
|
||||
|
||||
// Pointer rotation and limits
|
||||
double angle;
|
||||
if (not valid1) {
|
||||
angle = -0.5;
|
||||
}
|
||||
else {
|
||||
if (value1 > 15.0) {
|
||||
angle = 91;
|
||||
}
|
||||
else if (value1 <= 9) {
|
||||
angle = -0.5;
|
||||
}
|
||||
else {
|
||||
angle = (value1 - 9) * 15;
|
||||
}
|
||||
}
|
||||
|
||||
// Pointer
|
||||
// thick part
|
||||
pts = {
|
||||
{c.x - 2, c.y + 3},
|
||||
{c.x - r + 38, c.y + 2},
|
||||
{c.x - r + 38, c.y - 2},
|
||||
{c.x - 2, c.y - 3}
|
||||
};
|
||||
fillPoly4(rotatePoints(c, pts, angle), commonData.fgcolor);
|
||||
// thin part
|
||||
pts = {
|
||||
{c.x - r + 40, c.y + 1},
|
||||
{c.x - r + 5, c.y + 1},
|
||||
{c.x - r + 5, c.y -1},
|
||||
{c.x - r + 40, c.y - 1},
|
||||
};
|
||||
fillPoly4(rotatePoints(c, pts, angle), commonData.fgcolor);
|
||||
|
||||
// base
|
||||
getdisplay().fillCircle(c.x, c.y, 8, commonData.fgcolor);
|
||||
getdisplay().fillCircle(c.x, c.y, 6, commonData.bgcolor);
|
||||
|
||||
// Symbol
|
||||
printVoltageSymbol(40, 60, commonData.fgcolor);
|
||||
|
||||
// Additional informatio at right side
|
||||
getdisplay().setFont(&Ubuntu_Bold8pt7b);
|
||||
getdisplay().setCursor(300, 60);
|
||||
getdisplay().print("Source:");
|
||||
getdisplay().setCursor(300, 80);
|
||||
getdisplay().print(name1);
|
||||
|
||||
getdisplay().setCursor(300, 110);
|
||||
getdisplay().print("Type:");
|
||||
getdisplay().setCursor(300, 130);
|
||||
getdisplay().print(batType);
|
||||
|
||||
getdisplay().setCursor(300, 160);
|
||||
getdisplay().print("Avg:");
|
||||
printAvg(average, 300, 180, false);
|
||||
|
||||
}
|
||||
|
||||
// Key Layout
|
||||
getdisplay().setTextColor(commonData.fgcolor);
|
||||
|
@ -228,6 +359,8 @@ public:
|
|||
if(keylock == false){
|
||||
getdisplay().setCursor(10, 290);
|
||||
getdisplay().print("[AVG]");
|
||||
getdisplay().setCursor(62, 290);
|
||||
getdisplay().print("[MODE]");
|
||||
getdisplay().setCursor(130, 290);
|
||||
getdisplay().print("[ <<<< " + String(commonData.data.actpage) + "/" + String(commonData.data.maxpage) + " >>>> ]");
|
||||
getdisplay().setCursor(293, 290);
|
||||
|
|
Loading…
Reference in New Issue