From 1195148b2498fa262f8311a48127eae79b5314d5 Mon Sep 17 00:00:00 2001 From: rbsexton Date: Sat, 2 Apr 2022 11:46:45 -0500 Subject: [PATCH 1/5] Factor out the SI-adjustment code from LcdTask::displayScaledNumberValue() so that it can be re-used in other methods. --- src/lcd.cpp | 42 ++++++++++++++++++++++++++---------------- src/lcd.h | 1 + 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/lcd.cpp b/src/lcd.cpp index 5b8ff114..9cd8a728 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -619,26 +619,36 @@ void LcdTask::displayInfoLine(LcdInfoLine line, unsigned long &nextUpdate) } } -void LcdTask::displayScaledNumberValue(int line, const char *name, double value, int precision, const char *unit) -{ - static const char *mod[] = { - "", - "k", - "m", - "g", - "t", - "p" - }; - - int index = 0; - while (value > 1000 && index < ARRAY_ITEMS(mod)) +// Adjust the value down until its in the range 0-1000, +// and return the SI prefix for the scaled number. +const char *LcdTask::ScaleNumberSI(double *value) { { - value /= 1000; - index++; + static const char *mod[] = { + "", + "k", + "m", + "g", + "t", + "p" + }; + + int index = 0; + while (*value > 1000 && index < ARRAY_ITEMS(mod)) + { + *value /= 1000; + index++; + } + + return(mod[index]); } +} + +void LcdTask::displayScaledNumberValue(int line, const char *name, double value, int precision, const char *unit) +{ + char newUnit[20]; - sprintf(newUnit, "%s%s", mod[index], unit); + sprintf(newUnit, "%s%s", ScaleNumberSI(&value), unit); displayNumberValue(line, name, value, precision, newUnit); } diff --git a/src/lcd.h b/src/lcd.h index 9808fd97..d0dde339 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -133,6 +133,7 @@ class LcdTask : public MicroTasks::Task void displayStateLine(uint8_t EvseState, unsigned long &nextUpdate); void displayInfoLine(LcdInfoLine info, unsigned long &nextUpdate); void displayNumberValue(int line, const char *name, double value, int precision, const char *unit); + const char *ScaleNumberSI(double *value); void displayScaledNumberValue(int line, const char *name, double value, int precision, const char *unit); void displayInfoEventTime(const char *name, Scheduler::EventInstance &event); void displayNameValue(int line, const char *name, const char *value); From d06bae56e35c9e954ceb078a681e6fafe72aebda Mon Sep 17 00:00:00 2001 From: rbsexton Date: Mon, 4 Apr 2022 09:13:36 -0500 Subject: [PATCH 2/5] Add a method to format a double to a specfic numner of significant figures. --- src/lcd.cpp | 22 ++++++++++++++++++++++ src/lcd.h | 1 + 2 files changed, 23 insertions(+) diff --git a/src/lcd.cpp b/src/lcd.cpp index 9cd8a728..8b7b6935 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -643,6 +643,28 @@ const char *LcdTask::ScaleNumberSI(double *value) { } } +// Format a number to a specif number of signficant figures. +// Requires a a number that that has already been adjusted for SI notation. +// +// Arguments: buffer, buffer length, +// value in question, number of significant figures. +// returns a pointer to the formatted buffer. +char *LcdTask::formatDoubleSigFigures(char *buffer, int buflen, double value, int figures) +{ + + // There is no way to get less than three. + int integer_figures; + if ( value >= 100.0 ) integer_figures = 3; + else if ( value >= 10.0 ) integer_figures = 2; + else if ( value >= 1.0 ) integer_figures = 1; + else integer_figures = 0; + + int precision = figures - integer_figures; + + snprintf(buffer, buflen, "%.*f", precision, value); + return(buffer); +} + void LcdTask::displayScaledNumberValue(int line, const char *name, double value, int precision, const char *unit) { diff --git a/src/lcd.h b/src/lcd.h index d0dde339..1c8d370b 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -134,6 +134,7 @@ class LcdTask : public MicroTasks::Task void displayInfoLine(LcdInfoLine info, unsigned long &nextUpdate); void displayNumberValue(int line, const char *name, double value, int precision, const char *unit); const char *ScaleNumberSI(double *value); + char *formatDoubleSigFigures(char *buffer, int buflen, double value, int figures); void displayScaledNumberValue(int line, const char *name, double value, int precision, const char *unit); void displayInfoEventTime(const char *name, Scheduler::EventInstance &event); void displayNameValue(int line, const char *name, const char *value); From 32b0927b893943df9b1e778fbcb8d2d9615b2ff8 Mon Sep 17 00:00:00 2001 From: rbsexton Date: Mon, 4 Apr 2022 09:18:00 -0500 Subject: [PATCH 3/5] New method, LcdTask::displayNumberValueSigFigures that uses signicant figures rather than decimals after the decima point. --- src/lcd.cpp | 16 ++++++++++++++++ src/lcd.h | 1 + 2 files changed, 17 insertions(+) diff --git a/src/lcd.cpp b/src/lcd.cpp index 8b7b6935..581345e7 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -683,6 +683,22 @@ void LcdTask::displayNumberValue(int line, const char *name, double value, int p displayNameValue(line, name, number); } + +// Display a numeric value that has already been SI adjusted, +// adjusted to a specifed number of significant figures, and appended with units +void LcdTask::displayNumberValueSigFigures(int line, const char *name, double value, int figures, const char *unit) +{ + + char number[20]; + + formatDoubleSigFigures(number, sizeof(number), value, figures); + + char with_unit[20]; + sprintf(with_unit,"%s%s",number,unit); + + displayNameValue(line, name, with_unit); +} + void LcdTask::displayInfoEventTime(const char *name, Scheduler::EventInstance &event) { char temp[20]; diff --git a/src/lcd.h b/src/lcd.h index 1c8d370b..b17e8cda 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -133,6 +133,7 @@ class LcdTask : public MicroTasks::Task void displayStateLine(uint8_t EvseState, unsigned long &nextUpdate); void displayInfoLine(LcdInfoLine info, unsigned long &nextUpdate); void displayNumberValue(int line, const char *name, double value, int precision, const char *unit); + void displayNumberValueSigFigures(int line, const char *name, double value, int figures, const char *unit); const char *ScaleNumberSI(double *value); char *formatDoubleSigFigures(char *buffer, int buflen, double value, int figures); void displayScaledNumberValue(int line, const char *name, double value, int precision, const char *unit); From 422cf2827ffa1fc15a20e2bdd4abefce97cd0c2a Mon Sep 17 00:00:00 2001 From: rbsexton Date: Mon, 4 Apr 2022 09:19:27 -0500 Subject: [PATCH 4/5] Overload displayScaledNumberValue to use significant figures instead of digits after the decimal point. --- src/lcd.cpp | 14 ++++++++++++++ src/lcd.h | 1 + 2 files changed, 15 insertions(+) diff --git a/src/lcd.cpp b/src/lcd.cpp index 581345e7..2ff0c73a 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -675,6 +675,20 @@ void LcdTask::displayScaledNumberValue(int line, const char *name, double value, displayNumberValue(line, name, value, precision, newUnit); } +// Display a scaled number and adjust output such that the user gets some number +// of significant figures eg, for 4: 1.00598kWh appears as 1.005 rather than 1.0 +// Overloaded on displayScaledNumberValue +void LcdTask::displayScaledNumberValue(int line, const char *name, double value, const char *unit) +{ + + char newUnit[20]; + sprintf(newUnit, "%s%s", ScaleNumberSI(&value), unit); + + displayNumberValueSigFigures(line, name, value, 4, newUnit); +} + +// Display a numeric value preceded by the quantity name, scaled for SI notation, +// and with a specific number of digits after the decimal point. void LcdTask::displayNumberValue(int line, const char *name, double value, int precision, const char *unit) { char number[20]; diff --git a/src/lcd.h b/src/lcd.h index b17e8cda..807221eb 100644 --- a/src/lcd.h +++ b/src/lcd.h @@ -137,6 +137,7 @@ class LcdTask : public MicroTasks::Task const char *ScaleNumberSI(double *value); char *formatDoubleSigFigures(char *buffer, int buflen, double value, int figures); void displayScaledNumberValue(int line, const char *name, double value, int precision, const char *unit); + void displayScaledNumberValue(int line, const char *name, double value, const char *unit); void displayInfoEventTime(const char *name, Scheduler::EventInstance &event); void displayNameValue(int line, const char *name, const char *value); void displayStopWatchTime(const char *name, uint32_t time); From 4cc10f96614f7703da580ef4c9973e0ec57aeb5c Mon Sep 17 00:00:00 2001 From: rbsexton Date: Mon, 4 Apr 2022 09:21:13 -0500 Subject: [PATCH 5/5] Put the new formatting method to use, and add a comment. --- src/lcd.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/lcd.cpp b/src/lcd.cpp index 2ff0c73a..3c3f55d1 100644 --- a/src/lcd.cpp +++ b/src/lcd.cpp @@ -509,7 +509,7 @@ void LcdTask::displayInfoLine(LcdInfoLine line, unsigned long &nextUpdate) { case LcdInfoLine::EnergySession: // Energy 1,018Wh - displayScaledNumberValue(1, "Energy", _evse->getSessionEnergy(), 1, "Wh"); + displayScaledNumberValue(1, "Energy", _evse->getSessionEnergy(), "Wh"); _updateInfoLine = false; break; @@ -666,6 +666,7 @@ char *LcdTask::formatDoubleSigFigures(char *buffer, int buflen, double value, in } +// Display a scaled number with a specific number of digits after the decimal point. void LcdTask::displayScaledNumberValue(int line, const char *name, double value, int precision, const char *unit) {