diff --git a/.pioenvs/.sconsign.dblite b/.pioenvs/.sconsign.dblite index e53a203..a79c2f7 100644 Binary files a/.pioenvs/.sconsign.dblite and b/.pioenvs/.sconsign.dblite differ diff --git a/.pioenvs/structure.hash b/.pioenvs/structure.hash index 1f5e1ae..205dda6 100644 --- a/.pioenvs/structure.hash +++ b/.pioenvs/structure.hash @@ -1 +1 @@ -48395daee54e3878fbc0131b4ad59e5b91fe6378 \ No newline at end of file +d0b2a87cf0a77e923379f54bea377ed7b8197882 \ No newline at end of file diff --git a/data/index.html b/data/index.html index 325a59d..2cab514 100644 --- a/data/index.html +++ b/data/index.html @@ -59,7 +59,7 @@ V - / + V / V @@ -73,7 +73,7 @@ A - / + A / A @@ -87,7 +87,7 @@ W - / + W / W diff --git a/src/PowerAnalyzer.ino b/src/PowerAnalyzer.ino index 42606f8..a4796a3 100644 --- a/src/PowerAnalyzer.ino +++ b/src/PowerAnalyzer.ino @@ -28,6 +28,7 @@ Scheduler task; Preferences nvs; //Konstanten +#define debug_serial //Shunt Config - 60A / 60mV #define R_SHUNT 0.001 #define V_SHUNT_MAX 0.060 @@ -49,7 +50,6 @@ Preferences nvs; void lcd_print(); void lcd_init(); void lcd_header(); -void eeprom_save(); void i2c_receive(); void i2c_respond(); void readCurrent(); @@ -58,6 +58,7 @@ void read_button(); void web_measuring_stop(AsyncWebServerRequest *request); void web_measuring_run(AsyncWebServerRequest *request); void web_measuring_reset(AsyncWebServerRequest *request); +void web_measuring_delete(AsyncWebServerRequest *request); void web_get_values(AsyncWebServerRequest *request); void data_logging(); @@ -73,9 +74,9 @@ float shuntvoltage_V = 0, shuntvoltage_mV = 0, busvoltage_V = 0, busvoltage_mV = float busvoltage_V_max = 0, current_A_max = 0, power_W_max = 0, busvoltage_V_min = 0, current_A_min = 0, power_W_min = 0; float Ah = 0, mAh = 0, Wh = 0, mWh = 0; float battery_voltage, battery_average; -int i_header = 0; +int i_header = 0, battery_meas_init; bool button1, button2, button3, button3long; -bool lcd_light = true, lcd_minmax = false, lcd_cleared = true, wifi_enabled = true, test_mode = false; +bool lcd_light = true, lcd_minmax = false, lcd_cleared = true, lcd_header_run = false, wifi_enabled = true, test_mode = false; bool measuring_run = false, measuring_init = false, reset_actual = false, reset_minmax = false, battery_low = false, errorID = false; unsigned long lastread = 0, tick, previousMillisReadData = 0, previousMillisDisplay = 0, data_timestamp = 0, button3timer = 0; @@ -86,11 +87,12 @@ void setup() { pinMode(button1_pin, INPUT_PULLUP); pinMode(button2_pin, INPUT_PULLUP); pinMode(button3_pin, INPUT_PULLUP); - battery_average = analogRead(adc_battery_pin); - //Setup Debug Serial - Serial.begin(115200); - Serial.println("Power Analyzer by Carsten Schmiemann (C) 2018"); +#ifdef debug_serial + //Setup Debug Serial + Serial.begin(115200); + Serial.println("Power Analyzer by Carsten Schmiemann (C) 2018"); +#endif //Setup Over The Air - Update ArduinoOTA @@ -106,35 +108,71 @@ void setup() { lcd.clear(); lcd.setCursor(0,0); lcd.print("OTA Firmware Update"); - Serial.println("OTA Firmware Update"); + #ifdef debug_serial + Serial.println("OTA Firmware Update"); + #endif lcd.setCursor(7,1); lcd.print("Init"); - Serial.println("Init"); + #ifdef debug_serial + Serial.println("Init"); + #endif }) .onEnd([]() { lcd.setCursor(7,2); lcd.print("Done."); - Serial.println("Done."); + #ifdef debug_serial + Serial.println("Done."); + #endif delay(5000); ESP.restart(); }) .onProgress([](unsigned int progress, unsigned int total) { lcd.setCursor(3,1); lcd.print(progress / (total / 100)); lcd.print("% Complete"); - Serial.println(progress / (total / 100)); lcd.print("% Complete"); + #ifdef debug_serial + Serial.println(progress / (total / 100)); lcd.print("% Complete"); + #endif }) .onError([](ota_error_t error) { lcd.setCursor(3,3); digitalWrite(led_error_pin, HIGH); - if (error == OTA_AUTH_ERROR) {lcd.print("Auth Failed"); Serial.println("Auth Failed"); } - else if (error == OTA_BEGIN_ERROR) {lcd.print("Begin Failed"); Serial.println("Auth Failed"); } - else if (error == OTA_CONNECT_ERROR) {lcd.print("Connect Failed"); Serial.println("Connect Failed"); } - else if (error == OTA_RECEIVE_ERROR) {lcd.print("Receive Failed"); Serial.println("Receive Failed"); } - else if (error == OTA_END_ERROR) {lcd.print("End Failed"); Serial.println("End Failed"); } + if (error == OTA_AUTH_ERROR) { + lcd.print("Auth Failed"); + #ifdef debug_serial + Serial.println("Auth Failed"); + #endif + } + else if (error == OTA_BEGIN_ERROR) { + lcd.print("Begin Failed"); + #ifdef debug_serial + Serial.println("Auth Failed"); + #endif + } + else if (error == OTA_CONNECT_ERROR) { + lcd.print("Connect Failed"); + #ifdef debug_serial + Serial.println("Connect Failed"); + #endif + } + else if (error == OTA_RECEIVE_ERROR) { + lcd.print("Receive Failed"); + #ifdef debug_serial + Serial.println("Receive Failed"); + #endif + } + else if (error == OTA_END_ERROR) { + lcd.print("End Failed"); + #ifdef debug_serial + Serial.println("End Failed"); + #endif + } }); ArduinoOTA.setPort(ota_port); ArduinoOTA.setPassword(ota_pass); ArduinoOTA.begin(); + #ifdef debug_serial + Serial.println("OTA Update Init"); + #endif //Init LCD, Custom Chars and test LEDs lcd.init(); @@ -152,7 +190,9 @@ void setup() { lcd.print("Power Analyzer"); lcd.setCursor(6,2); lcd.print("V0.36 Beta"); - Serial.println("V0.36 Beta"); + #ifdef debug_serial + Serial.println("V0.36 Beta"); + #endif lcd.setCursor(7,3); lcd.print("CS,2018"); lcd.write(1); @@ -191,6 +231,9 @@ void setup() { lcd.clear(); lcd.setCursor(0,0); lcd.print("OTA Firmware Update"); + #ifdef debug_serial + Serial.println("OTA Firmware Update Init"); + #endif lcd.setCursor(7,1); lcd.print("Init"); }) @@ -253,6 +296,7 @@ void setup() { server.on("/meas/run", HTTP_GET, web_measuring_run); server.on("/meas/stop", HTTP_GET, web_measuring_stop); server.on("/meas/reset", HTTP_GET, web_measuring_reset); + server.on("/meas/delete", HTTP_GET, web_measuring_delete); server.on("/meas/values", HTTP_GET, web_get_values); server.on("/datalog.csv", HTTP_ANY, [](AsyncWebServerRequest *request){ request->send(SPIFFS, "/datalog.csv"); @@ -288,6 +332,13 @@ void setup() { nvs.begin("usage", true); Ah = nvs.getFloat("Ah"); Wh = nvs.getFloat("Wh"); + busvoltage_V_max = nvs.getFloat("Voltage_Max"); + busvoltage_V_min = nvs.getFloat("Voltage_Min"); + current_A_max = nvs.getFloat("Current_Max"); + current_A_min = nvs.getFloat("Current_Min"); + power_W_max = nvs.getFloat("Power_Max"); + power_W_min = nvs.getFloat("Power_Min"); + data_timestamp = nvs.getFloat("Date_Timestamp"); nvs.end(); //Enable Tasks t1.enable(); @@ -347,29 +398,34 @@ void lcd_print() { } else { if (lcd_cleared) {lcd_init();} lcd.setCursor(0,1); - if (current_A < 100 && current_A >= 10) {lcd.print(" ");} else if (current_A < 10 && current_A >= 0) {lcd.print(" ");}; - if (current_A > -100 && current_A <= -10) {lcd.print(" ");} else if (current_A > -10 && current_A < 0) {lcd.print(" ");}; + if (current_A < 100 && current_A >= 10) {lcd.print(" ");} else if (current_A < 10 && current_A >= 0) {lcd.print(" ");} + if (current_A > -100 && current_A <= -10) {lcd.print(" ");} else if (current_A > -10 && current_A < 0) {lcd.print(" ");} lcd.print(current_A); lcd.setCursor(0,2); - if (power_W < 1000 && power_W > 100) {lcd.print(" ");} else if (power_W < 100 && power_W >= 10) {lcd.print(" ");} else if (power_W < 10) {lcd.print(" ");}; + if (power_W < 1000 && power_W >= 100) {lcd.print(" ");} else if (power_W < 100 && power_W >= 10) {lcd.print(" ");} else if (power_W < 10) {lcd.print(" ");} lcd.print(power_W); lcd.setCursor(0,3); - if (busvoltage_V < 100 && busvoltage_V >= 10) {lcd.print(" ");} else if (busvoltage_V < 10) {lcd.print(" ");}; + if (busvoltage_V < 100 && busvoltage_V >= 10) {lcd.print(" ");} else if (busvoltage_V < 10) {lcd.print(" ");} lcd.print(busvoltage_V); lcd.setCursor(11,1); - if (Ah < 1000 && Ah > 100) {lcd.print(" ");} else if (Ah < 100 && Ah >= 10) {lcd.print(" ");} else if (Ah < 10) {lcd.print(" ");}; - if (Ah > -100 && Ah <= -10) {lcd.print(" ");} else if (Ah > -10 && Ah < 0) {lcd.print(" ");}; + if (Ah < 1000 && Ah >= 100) {lcd.print(" ");} else if (Ah < 100 && Ah >= 10) {lcd.print(" ");} else if (Ah < 10 && Ah >= 0) {lcd.print(" ");} + if (Ah > -100 && Ah <= -10) {lcd.print(" ");} else if (Ah > -10 && Ah < 0) {lcd.print(" ");} lcd.print(Ah); lcd.setCursor(11,2); - if (Wh < 1000 && Wh > 100) {lcd.print(" ");} else if (Wh < 100 && Wh >= 10) {lcd.print(" ");} else if (Wh < 10) {lcd.print(" ");}; + if (Wh < 1000 && Wh > 100) {lcd.print(" ");} else if (Wh < 100 && Wh >= 10) {lcd.print(" ");} else if (Wh < 10) {lcd.print(" ");} lcd.print(Wh); + //Wait seven battery check cylces before display battery voltage due adc noise lcd.setCursor(14,3); - if (battery_voltage > 3.4) {lcd.print(battery_voltage);} else {lcd.print("LOW ");} + if (battery_meas_init == 7) { + if (battery_voltage > 3.4) {lcd.print(battery_voltage);} else {lcd.print("LOW ");} + } else { + lcd.print("-.--"); + } } } @@ -395,7 +451,8 @@ void lcd_init() { } void lcd_header() { - if (measuring_run && lcd_minmax == false) { + //"Animated" lcd header when running measurement + if (measuring_run && lcd_header_run && lcd_minmax == false) { i_header++; if (i_header == 1) { lcd.setCursor(0,0); @@ -423,13 +480,19 @@ void lcd_header() { i_header = 0; } } - //Flash Error LED + //Flash Error LED on error or batt low if ((battery_low || errorID) && digitalRead(led_error_pin)) { digitalWrite(led_error_pin, LOW); } else if ((battery_low || errorID) && digitalRead(led_error_pin) == false) { digitalWrite(led_error_pin, HIGH); } if (battery_low == false && errorID == false && digitalRead(led_error_pin)) { digitalWrite(led_error_pin, LOW); } + //Wait for "measuring run" Message before Updating animated LCD head line + if (measuring_run) { + lcd_header_run = true; + } else { + lcd_header_run = false; + } } void readCurrent() { @@ -475,6 +538,7 @@ void readCurrent() { power_W_min = power_W; } } + //Set measurements variables to zero if reset pressed if (reset_actual) { Ah = 0; Wh = 0; @@ -487,6 +551,7 @@ void readCurrent() { current_A_min = 0; power_W_min = 0; } + //One time steps when measurement starts if (measuring_run && measuring_init == false) { busvoltage_V_max = 0; current_A_max = 0; @@ -494,16 +559,35 @@ void readCurrent() { busvoltage_V_min = busvoltage_V; current_A_min = current_A; power_W_min = power_W; + lcd.setCursor(2,0); + lcd.print(" Measuring started "); + #ifdef debug_serial + Serial.println("Measuring start"); + #endif measuring_init = true; } + //One time steps when measurement stops if (measuring_run == false && measuring_init) { nvs.begin("usage", false); nvs.putFloat("Ah", Ah); nvs.putFloat("Wh", Wh); + nvs.putFloat("Voltage_Max", busvoltage_V_max); + nvs.putFloat("Voltage_Min", busvoltage_V_min); + nvs.putFloat("Current_Max", current_A_max); + nvs.putFloat("Current_Min", current_A_min); + nvs.putFloat("Power_Max", power_W_max); + nvs.putFloat("Power_Min", power_W_min); + nvs.putFloat("Date_Timestamp", data_timestamp); nvs.end(); + lcd.setCursor(0,0); + lcd.print(" Measuring stopped "); + #ifdef debug_serial + Serial.println("Measuring stop"); + #endif measuring_init = false; } - if (busvoltage_V > 26 || current_A > 62) { + //Check if shunt is within operating parameters + if (busvoltage_V > 26 || current_A > 62 || busvoltage_V < 0 || current_A < -62) { errorID = true; measuring_run = false; } else { @@ -515,15 +599,18 @@ void readCurrent() { void read_bat() { battery_average += (analogRead(adc_battery_pin) - battery_average) * 0.3; battery_voltage = map(battery_average,0,4096,0,440)/100.0; - if (battery_voltage < 3.3 && battery_low == false) { - battery_low = true; - lcd.noBacklight(); - } - if (battery_voltage > 3.6 && battery_low) { - battery_low = false; - digitalWrite(led_error_pin,LOW); - lcd.backlight(); - } + //Wait seven battery check cylces before battery low warnings due adc noise + if (battery_meas_init == 7) { + if (battery_voltage < 3.3 && battery_low == false) { + battery_low = true; + lcd.noBacklight(); + } + if (battery_voltage > 3.6 && battery_low) { + battery_low = false; + digitalWrite(led_error_pin,LOW); + lcd.backlight(); + } + } else { battery_meas_init++; } } void read_button() { @@ -581,20 +668,22 @@ void read_button() { void web_measuring_stop(AsyncWebServerRequest *request) { if (errorID == false) {measuring_run = false;} - //request->send(200); - request->send(SPIFFS, "/index.html"); -} + request->send(200); + } void web_measuring_run(AsyncWebServerRequest *request) { if (errorID == false) {measuring_run = true;} - //request->send(200); - request->send(SPIFFS, "/index.html"); + request->send(200); } void web_measuring_reset(AsyncWebServerRequest *request) { reset_actual = true; - //request->send(200); - request->send(SPIFFS, "/index.html"); + request->send(200); +} + +void web_measuring_delete(AsyncWebServerRequest *request) { + SPIFFS.remove("/datalog.csv"); + request->send(200); } void web_get_values(AsyncWebServerRequest *request) {