Skip to content

Commit

Permalink
Fahrenheit, inverted Display & 4.2" bugfix
Browse files Browse the repository at this point in the history
Option to invert the Display and to use Fahrenheit via the Menu.
Update for 4.2" eink display with bugfixes.
airgradient/MQTT compiler warning.
  • Loading branch information
davidkreidler committed Mar 12, 2024
1 parent 0d37108 commit 63c6faa
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 41 deletions.
100 changes: 88 additions & 12 deletions OpenCO2_Sensor.ino
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ WebServer server(port);

//#define MQTT
#ifdef MQTT
#ifdef airgradient
#error only activate one: MQTT or airgradient
#endif /*airgradient*/
#include <ArduinoMqttClient.h>
WiFiClient wifiClient;
MqttClient mqttClient(wifiClient);
Expand Down Expand Up @@ -79,6 +82,8 @@ RTC_DATA_ATTR int ledbrightness = 5;
RTC_DATA_ATTR bool LEDonBattery = false;
RTC_DATA_ATTR bool LEDonUSB = true;
RTC_DATA_ATTR bool useSmoothLEDcolor = true;
RTC_DATA_ATTR bool invertDisplay = false;
RTC_DATA_ATTR bool useFahrenheit = false;
RTC_DATA_ATTR int HWSubRev = 1; //default only
RTC_DATA_ATTR float maxBatteryVoltage;
RTC_DATA_ATTR bool useWiFi;
Expand Down Expand Up @@ -212,6 +217,8 @@ void initOnce() {
LEDonUSB = preferences.getBool("LEDonUSB", true);
ledbrightness = preferences.getInt("ledbrightness", 5);
useSmoothLEDcolor = preferences.getBool("useSmoothLEDcolor", true);
invertDisplay = preferences.getBool("invertDisplay", false);
useFahrenheit = preferences.getBool("useFahrenheit", false);
preferences.end();

scd4x.stopPeriodicMeasurement(); // stop potentially previously started measurement
Expand Down Expand Up @@ -564,12 +571,12 @@ void toggleWiFi() {

enum MenuOptions {
LED,
RAINBOW,
DISPLAY_MENU,
CALIBRATE,
HISTORY,
WLAN,
INFO,
EXIT,
RAINBOW,
NUM_OPTIONS
};
enum LEDMenuOptions {
Expand All @@ -580,17 +587,23 @@ enum LEDMenuOptions {
EXIT_LED,
NUM_LED_OPTIONS
};
enum DisplayMenuOptions {
INVERT,
TEMP_UNIT,
EXIT_DISPLAY,
NUM_DISPLAY_OPTIONS
};

#define ENGLISH
#ifdef ENGLISH
const char* menuItems[NUM_OPTIONS] = {
"LED",
"Rainbow",//"Santa",
"Display",
"Calibrate",
"History",
"Wi-Fi",
"Info",
"Exit"
"Rainbow"//"Santa"
};
const char* LEDmenuItems[NUM_LED_OPTIONS] = {
"Battery",
Expand All @@ -599,15 +612,20 @@ const char* LEDmenuItems[NUM_LED_OPTIONS] = {
"Bright",
"Exit"
};
const char* OptionsMenuItems[NUM_DISPLAY_OPTIONS] = {
"Invert",
"Unit",
"Exit"
};
#else
const char* menuItems[NUM_OPTIONS] = {
"LED",
"Regenbogen",//"Weihnachten",
"Display",
"Kalibrieren",
"Historie",
"WLAN",
"Info",
"Beenden"
"Regenbogen"//"Weihnachten"
};
const char* LEDmenuItems[NUM_LED_OPTIONS] = {
"Batterie",
Expand All @@ -616,6 +634,11 @@ const char* LEDmenuItems[NUM_LED_OPTIONS] = {
"Hell",
"Beenden"
};
const char* OptionsMenuItems[NUM_DISPLAY_OPTIONS] = {
"Invert",
"Einheit",
"Beenden"
};
#endif

bool buttonPressedAgain = false;
Expand Down Expand Up @@ -648,9 +671,8 @@ void handleButtonPress() {
LEDMenu();
refreshes = 1;
return;
case RAINBOW:
rainbowMode();
setLED(co2);
case DISPLAY_MENU:
OptionsMenu();
refreshes = 1;
return;
case CALIBRATE:
Expand All @@ -669,9 +691,10 @@ void handleButtonPress() {
displayinfo();
while (digitalRead(BUTTON) != 0) delay(100); // wait for button press
refreshes = 1;
return;
case EXIT:
while(digitalRead(BUTTON) == 0) {} // wait until button is released
return;
case RAINBOW:
rainbowMode();
setLED(co2);
refreshes = 1;
return;
}
Expand Down Expand Up @@ -762,6 +785,59 @@ void LEDMenu() {
}
}

void OptionsMenu() {
uint8_t selectedOption = 0;
displayOptionsMenu(selectedOption);

uint16_t mspressed;
unsigned long menuStartTime = millis();

for (;;) {
if ((millis() - menuStartTime) > 20000) return; // display up to 20 sec
mspressed = 0;
if (digitalRead(BUTTON) == 0) {
while(digitalRead(BUTTON) == 0) { // calculate how long BUTTON is pressed
delay(100);
mspressed += 100;
if (mspressed > 1000) break;
}
if (mspressed > 1000) { // long press
switch (selectedOption) {
case INVERT:
invertDisplay = !invertDisplay;
preferences.begin("co2-sensor", false);
preferences.putBool("invertDisplay", invertDisplay);
preferences.end();
break;
case TEMP_UNIT:
useFahrenheit = !useFahrenheit;
preferences.begin("co2-sensor", false);
preferences.putBool("useFahrenheit", useFahrenheit);
preferences.end();
break;
case EXIT_DISPLAY:
while(digitalRead(BUTTON) == 0) {} // wait until button is released
return;
}
displayOptionsMenu(selectedOption);
menuStartTime = millis(); // display again for 20 sec
} else { // goto next Menu point
buttonPressedAgain = true; // display at least once
while (buttonPressedAgain) {
buttonPressedAgain = false;
selectedOption++;
selectedOption %= NUM_DISPLAY_OPTIONS;
attachInterrupt(digitalPinToInterrupt(BUTTON), buttonInterrupt, FALLING);
displayOptionsMenu(selectedOption);
detachInterrupt(digitalPinToInterrupt(BUTTON));
menuStartTime = millis(); // display again for 20 sec
if (digitalRead(BUTTON) == 0) break; // long press detected
}
}
}
}
}

void startWiFi() {
wifiManager.setSaveConfigCallback([]() {
#ifdef MQTT
Expand Down
89 changes: 60 additions & 29 deletions epd_abstraction.ino
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,11 @@ void displayInitTestMode() {
#ifdef EINK_1IN54V2
Paint_DrawBitMap(gImage_init);
Paint_DrawString_EN(1, 1, VERSION, &Font16, WHITE, BLACK);
Paint_DrawNum(125, 25, 1, &mid, BLACK, WHITE);
Paint_DrawNum(125, 25, 1, &mid, BLACK, WHITE); // 15 sec for testmode
EPD_1IN54_V2_Display(BlackImage);
#endif
#ifdef EINK_4IN2
Paint_DrawString_EN(1, 1, VERSION, &Font16, WHITE, BLACK);
EPD_4IN2_Display(BlackImage);
#endif
}
Expand All @@ -95,6 +96,7 @@ void displayInit() {
EPD_1IN54_V2_Sleep();
#endif
#ifdef EINK_4IN2
Paint_DrawString_EN(1, 1, VERSION, &Font16, WHITE, BLACK);
EPD_4IN2_Display(BlackImage);
EPD_4IN2_Sleep();
#endif
Expand Down Expand Up @@ -141,20 +143,13 @@ void displayWriteMeasuerments(uint16_t co2, float temperature, float humidity) {
Paint_DrawString_EN(144, 150, "ppm", &Font24, WHITE, BLACK);

/* temperature */
//#define useFahrenheit
#ifdef useFahrenheit
temperature = (temperature*1.8f)+32.0f; // convert to °F
char unit[3] = "*F";
#else
char unit[3] = "*C";
#endif
if (useFahrenheit) temperature = (temperature*1.8f)+32.0f; // convert to °F
if (temperature < 10.0f) Paint_DrawNum(30, 5, temperature, &mid, BLACK, WHITE);
else Paint_DrawNum( 1, 5, temperature, &mid, BLACK, WHITE);
int offset = 0;
#ifdef useFahrenheit
if (temperature >= 100) offset = 29;
#endif
Paint_DrawString_EN(60+offset, 4, unit, &sml, WHITE, BLACK);
if (temperature >= 100) offset = 29; // for Fahrenheit

Paint_DrawString_EN(60+offset, 4, useFahrenheit? "*F" : "*C", &sml, WHITE, BLACK);
Paint_DrawString_EN(60+offset, 32, ",", &sml, WHITE, BLACK);
char decimal[4];
sprintf(decimal, "%d", ((int)(temperature * 10)) % 10);
Expand All @@ -164,6 +159,7 @@ void displayWriteMeasuerments(uint16_t co2, float temperature, float humidity) {
Paint_DrawNum(124, 5, humidity, &mid, BLACK, WHITE);
Paint_DrawString_EN(184, 5, "%", &sml, WHITE, BLACK);
#endif /* EINK_1IN54V2 */

#ifdef EINK_4IN2
/* co2 */
// Xstart,Ystart
Expand Down Expand Up @@ -289,19 +285,14 @@ void displayHistory(uint16_t measurements[24][120]) {
}

void displayMenu(uint8_t selectedOption) {
extern const char* menuItems[NUM_OPTIONS];
Paint_Clear(WHITE);
Paint_DrawString_EN(66, 0, "Menu", &Font24, WHITE, BLACK);
Paint_DrawLine(10, 23, 190, 23, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);

for (int i=0; i<NUM_OPTIONS; i++) {
if (i == selectedOption) {
Paint_DrawRectangle(0, 25*(i+1), 200, 25*(i+2), BLACK, DOT_PIXEL_1X1, DRAW_FILL_FULL);
Paint_DrawString_EN(5, 25*(i+1), menuItems[i], &Font24, BLACK, WHITE);
} else {
Paint_DrawString_EN(5, 25*(i+1), menuItems[i], &Font24, WHITE, BLACK);
}
Paint_DrawString_EN(5, 25*(i+1), menuItems[i], &Font24, WHITE, BLACK);
}
invertSelected(selectedOption);
updateDisplay();
}

Expand All @@ -313,6 +304,7 @@ void displayLEDMenu(uint8_t selectedOption) {
for (int i=0; i<NUM_LED_OPTIONS; i++) {
Paint_DrawString_EN(5, 25*(i+1), LEDmenuItems[i], &Font24, WHITE, BLACK);
}

#ifdef ENGLISH
Paint_DrawString_EN(149, 25, (LEDonBattery? "ON":"OFF"), &Font24, WHITE, BLACK);
Paint_DrawString_EN(149, 50, (LEDonUSB? "ON":"OFF"), &Font24, WHITE, BLACK);
Expand All @@ -325,13 +317,40 @@ void displayLEDMenu(uint8_t selectedOption) {
Paint_DrawNum(149, 100, (int32_t)(ledbrightness/20+1), &Font24, BLACK, WHITE); // 5 25 45 65 85
Paint_DrawString_EN(166, 100, "/5", &Font24, WHITE, BLACK);

/* invert the selectedOption */
invertSelected(selectedOption);
updateDisplay();
}

void displayOptionsMenu(uint8_t selectedOption) {
Paint_Clear(WHITE);
Paint_DrawString_EN(40, 0, "DISPLAY", &Font24, WHITE, BLACK);
Paint_DrawLine(10, 23, 190, 23, BLACK, DOT_PIXEL_1X1, LINE_STYLE_SOLID);

for (int i=0; i<NUM_DISPLAY_OPTIONS; i++) {
Paint_DrawString_EN(5, 25*(i+1), OptionsMenuItems[i], &Font24, WHITE, BLACK);
}
Paint_DrawString_EN(166, 50, (useFahrenheit? "*F":"*C"), &Font24, WHITE, BLACK);
invertSelected(selectedOption);
updateDisplay();
}

void invertSelected(uint8_t selectedOption) {
#ifdef EINK_1IN54V2
for (int x = 0; x < 200; x++) {
for (int y = 25*(selectedOption+1)/8; y < 25*(selectedOption+2)/8; y++) {
BlackImage[y+x*25] = ~BlackImage[y+x*25];
}
}
updateDisplay();
#endif /* EINK_1IN54V2 */
#ifdef EINK_4IN2
int Y_start = 25 * (selectedOption + 1);
int Y_end = 25 * (selectedOption + 2);
for (int j = 0; j < Y_end - Y_start; j++) {
for (int i = 0; i < 200/8; i++) {
BlackImage[(Y_start + j) * 50 + i] = ~BlackImage[(Y_start + j) * 50 + i];
}
}
#endif
}

void displayCalibrationWarning() {
Expand Down Expand Up @@ -650,7 +669,8 @@ void displayBattery(uint8_t percentage) {
BlackImage[y+x*25] = ~BlackImage[y+x*25];
}
}
#endif
#endif /* EINK_1IN54V2 */

#ifdef EINK_4IN2
Paint_DrawRectangle(279, 10, 385, 37, BLACK, DOT_PIXEL_2X2, DRAW_FILL_EMPTY); //case
Paint_DrawRectangle(385, 16, 390, 31, BLACK, DOT_PIXEL_2X2, DRAW_FILL_EMPTY); //nippel
Expand All @@ -670,15 +690,24 @@ void displayBattery(uint8_t percentage) {
}

void updateDisplay() {
if (invertDisplay) {
#ifdef EINK_1IN54V2
//#define invertDisplay
#ifdef invertDisplay
for (int x = 0; x < 200; x++) {
for (int y = 0; y < 200/8; y++) {
BlackImage[y+x*25] = ~BlackImage[y+x*25];
for (int x = 0; x < 200; x++) {
for (int y = 0; y < 200/8; y++) {
BlackImage[y+x*25] = ~BlackImage[y+x*25];
}
}
#endif /* EINK_1IN54V2 */
#ifdef EINK_4IN2
for (int j = 0; j < 300; j++) {
for (int i = 0; i < 400/8; i++) {
BlackImage[j * 50 + i] = ~BlackImage[j * 50 + i];
}
}
#endif /* EINK_4IN2 */
}
#endif

#ifdef EINK_1IN54V2
if (comingFromDeepSleep && !BatteryMode) refreshes = 1;
if (refreshes == 1) {
// Full update
Expand All @@ -695,7 +724,8 @@ void updateDisplay() {
EPD_1IN54_V2_DisplayPart(BlackImage);
}
EPD_1IN54_V2_Sleep();
#endif
#endif /* EINK_1IN54V2 */

#ifdef EINK_4IN2
if (refreshes == 1) {
EPD_4IN2_Init_Fast();
Expand All @@ -706,6 +736,7 @@ void updateDisplay() {
}
EPD_4IN2_Sleep();
#endif

if (refreshes == 720) { // every hour or every six hours on battery
refreshes = 0; // force full update
}
Expand Down

0 comments on commit 63c6faa

Please sign in to comment.