diff --git a/ESP32/TempHumLoggerHomeKit/Battery analyze charge.xlsx b/ESP32/TempHumLoggerHomeKit/Battery analyze charge.xlsx new file mode 100644 index 0000000..cf5e7af Binary files /dev/null and b/ESP32/TempHumLoggerHomeKit/Battery analyze charge.xlsx differ diff --git a/ESP32/TempHumLoggerHomeKit/Battery analyze dicharge.xlsx b/ESP32/TempHumLoggerHomeKit/Battery analyze dicharge.xlsx new file mode 100644 index 0000000..c91628f Binary files /dev/null and b/ESP32/TempHumLoggerHomeKit/Battery analyze dicharge.xlsx differ diff --git a/ESP32/TempHumLoggerHomeKit/TempHumLogVizualization.xlsx b/ESP32/TempHumLoggerHomeKit/TempHumLogVizualization.xlsx index 4004a3d..8feeda7 100644 Binary files a/ESP32/TempHumLoggerHomeKit/TempHumLogVizualization.xlsx and b/ESP32/TempHumLoggerHomeKit/TempHumLogVizualization.xlsx differ diff --git a/ESP32/TempHumLoggerHomeKit/TempHumLoggerHomeKit.ino b/ESP32/TempHumLoggerHomeKit/TempHumLoggerHomeKit.ino index 2e46d15..d3495ee 100644 --- a/ESP32/TempHumLoggerHomeKit/TempHumLoggerHomeKit.ino +++ b/ESP32/TempHumLoggerHomeKit/TempHumLoggerHomeKit.ino @@ -9,7 +9,7 @@ #include "SD.h" #include "SPI.h" -#define Version "0.30" +#define Version "0.33" #define WIRE Wire #define DHTTYPE DHT22 #define DHTPIN 4 @@ -49,6 +49,10 @@ int adcVoltValue; float measuredVoltage = 0; float batteryVoltage = 0; +float quickBatteryVoltage = 0; +float quickBatteryVoltage2 = 0; +float quickBatteryVoltage3 = 0; +float quickBatteryVoltage4 = 0; float currentBatteryVoltage = 0; float lastBatteryVoltage = 0; int battLifeMins = 998; @@ -58,6 +62,12 @@ int estMins = 0; int batteryPercent = 0; int batteryBarWidth = 0; char dateString[21]; +std::string chrgState; + +unsigned long previousMillis = 0; +const unsigned long interval = 1000; +unsigned long currentMillis = millis(); + String formatNumber(float number, int decimalPlaces = 1 ) { String str = String(number, decimalPlaces); @@ -65,6 +75,96 @@ String formatNumber(float number, int decimalPlaces = 1 ) { return str; } + +String leadZero(float number) { + String str = String(int(number)); + str.trim(); + if (number < 10) { + str = "0" + str; + } + return str; +} + + + +float voltageToPercentage(float voltage) { + // Reprezentatywne punkty (wolt, procent) + const int nPoints = 9; + // Napięcia – uporządkowane malejąco + float vPoints[nPoints] = {4.06, 4.00, 3.95, 3.90, 3.85, 3.80, 3.70, 3.45, 2.75}; + // Odpowiednie poziomy naładowania + float pPoints[nPoints] = {100, 95, 90, 80, 70, 60, 50, 10, 0}; + if (voltage >= vPoints[0]) + return pPoints[0]; + if (voltage <= vPoints[nPoints - 1]) + return pPoints[nPoints - 1]; + for (int i = 0; i < nPoints - 1; i++) { + if (voltage <= vPoints[i] && voltage > vPoints[i + 1]) { + // Obliczamy współczynnik interpolacji + float fraction = (voltage - vPoints[i + 1]) / (vPoints[i] - vPoints[i + 1]); + // Interpolacja liniowa między punktami + return pPoints[i + 1] + fraction * (pPoints[i] - pPoints[i + 1]); + } + } + return 0; // Domyślnie – choć powinno się tu już nie dojść +} + +// Funkcja liniowej interpolacji +float interpolate(float x, float x0, float x1, float y0, float y1) { + return y0 + (x - x0) * (y1 - y0) / (x1 - x0); +} + +// Funkcja przeliczająca napięcie (w V) na procent naładowania baterii w trakcie ładowania +float chargeVoltageToPercentage(float voltage) { + // Przykładowe punkty (napięcie w V rosnąco) + // Dopasuj je do własnych obserwacji / charakterystyki baterii + const int nPoints = 10; + float vPoints[nPoints] = { + 4.03, // ~0% + 4.06, // ~1% + 4.12, // ~5% + 4.14, // ~10% + 4.16, // ~30% + 4.18, // ~60% + 4.19, // ~80% + 4.20, // ~95% + 4.21, // ~98% + 4.22 // 100% + }; + float pPoints[nPoints] = { + 0, // 4.03 V + 1, // 4.06 V + 5, // 4.12 V + 10, // 4.14 V + 30, // 4.16 V + 60, // 4.18 V + 80, // 4.19 V + 95, // 4.20 V + 98, // 4.21 V + 100 // 4.22 V + }; + + // 1. Jeśli napięcie jest poniżej najniższego punktu, zwróć minimalny procent + if (voltage <= vPoints[0]) { + return pPoints[0]; + } + + // 2. Jeśli napięcie przekracza najwyższy punkt, zwróć maksymalny procent + if (voltage >= vPoints[nPoints - 1]) { + return pPoints[nPoints - 1]; + } + + // 3. Znajdź przedział, w którym mieści się zmierzone napięcie + for (int i = 0; i < nPoints - 1; i++) { + if (voltage >= vPoints[i] && voltage < vPoints[i + 1]) { + // Interpolacja liniowa między sąsiednimi punktami + return interpolate(voltage, vPoints[i], vPoints[i + 1], pPoints[i], pPoints[i + 1]); + } + } + // Nie powinniśmy tu trafić, ale na wszelki wypadek: + return 0.0; +} + void setup() { Serial.begin(115200); Wire.begin(21, 22); @@ -151,11 +251,16 @@ void setup() { measuredVoltage = (adcVoltValue * adcMaxVoltage) / adcResolution; batteryVoltage = (measuredVoltage * voltageDividerFactor)+0.1; currentBatteryVoltage = batteryVoltage; + quickBatteryVoltage = batteryVoltage; + quickBatteryVoltage2 = batteryVoltage; + quickBatteryVoltage3 = batteryVoltage; + quickBatteryVoltage4 = batteryVoltage; //setup END //###################### } void loop() { + currentMillis = millis(); display.clearDisplay(); ////DIAGNOSTIC menu nr diag // display.setCursor(75, 16); @@ -339,19 +444,30 @@ void loop() { display.setCursor(80,8); display.print("V:"); display.setCursor(95, 8); - display.print(batteryVoltage); + display.print(formatNumber(batteryVoltage,2)); display.setCursor(0, 24); if (currentBatteryVoltage >= 4.20 ){ display.print("Full"); - } else if ((lastBatteryVoltage < currentBatteryVoltage && currentBatteryVoltage >= 2.0) || currentBatteryVoltage >= 4.06 ){ + chrgState = "FUL"; + } else if ((lastBatteryVoltage < currentBatteryVoltage && currentBatteryVoltage >= 2.0&& currentBatteryVoltage >= 4.0 ) || currentBatteryVoltage >= 4.10 ){ display.print("Charging"); + chrgState = "CHR"; } else if (lastBatteryVoltage > currentBatteryVoltage && currentBatteryVoltage >= 2.0 ) { display.print("Discharge"); + chrgState = "DSG"; } else { display.print("---"); + chrgState = "---"; } - batteryPercent = voltageToPercentage(currentBatteryVoltage); + if (chrgState == "DSG"){ + batteryPercent = voltageToPercentage(currentBatteryVoltage); + } else if (chrgState == "CHR") { + batteryPercent = chargeVoltageToPercentage(currentBatteryVoltage); + } else { + batteryPercent = 100; + } + display.setCursor(60, 24); display.print("Est:"); @@ -434,10 +550,17 @@ void loop() { } } - adcVoltValue = analogRead(VOLT_IN); // Odczyt wartości ADC z GPIO36 - measuredVoltage = (adcVoltValue * adcMaxVoltage) / adcResolution; - batteryVoltage = (measuredVoltage * voltageDividerFactor)+0.1; - + if (currentMillis - previousMillis >= interval) { + previousMillis = currentMillis; + adcVoltValue = analogRead(VOLT_IN); // Odczyt wartości ADC z GPIO36 + measuredVoltage = (adcVoltValue * adcMaxVoltage) / adcResolution; + quickBatteryVoltage4 = quickBatteryVoltage3; + quickBatteryVoltage3 = quickBatteryVoltage2; + quickBatteryVoltage2 = quickBatteryVoltage; + quickBatteryVoltage = (measuredVoltage * voltageDividerFactor)+0.1; + batteryVoltage = (quickBatteryVoltage + quickBatteryVoltage2 + quickBatteryVoltage3 + quickBatteryVoltage4)/4; + } + // Log napiećia docelowoe procent baterii // kiedy zaden przycisk nie jest wcisniety if (abs (batteryVoltage - currentBatteryVoltage) >= 0.14 && digitalRead(BTN_DOWN) == LOW && digitalRead(BTN_UP) == LOW && digitalRead(BTN_ENTER) == LOW ) { @@ -457,7 +580,9 @@ void loop() { display.fillRect(0, 0, 124, 64, SSD1306_WHITE); file.print(dateString); file.print(" Battery %: "); - file.println(batteryPercent); + file.print(batteryPercent); + file.print(" V: "); + file.println(currentBatteryVoltage); file.close(); } } @@ -491,43 +616,9 @@ void loop() { yield(); } -String leadZero(float number) { - String str = String(int(number)); - str.trim(); - if (number < 10) { - str = "0" + str; - } - return str; -} - - - -float voltageToPercentage(float voltage) { - // Reprezentatywne punkty (wolt, procent) - const int nPoints = 9; - // Napięcia – uporządkowane malejąco - float vPoints[nPoints] = {4.06, 4.00, 3.95, 3.90, 3.85, 3.80, 3.70, 3.45, 2.75}; - // Odpowiednie poziomy naładowania - float pPoints[nPoints] = {100, 95, 90, 80, 70, 60, 50, 10, 0}; - if (voltage >= vPoints[0]) - return pPoints[0]; - if (voltage <= vPoints[nPoints - 1]) - return pPoints[nPoints - 1]; - for (int i = 0; i < nPoints - 1; i++) { - if (voltage <= vPoints[i] && voltage > vPoints[i + 1]) { - // Obliczamy współczynnik interpolacji - float fraction = (voltage - vPoints[i + 1]) / (vPoints[i] - vPoints[i + 1]); - // Interpolacja liniowa między punktami - return pPoints[i + 1] + fraction * (pPoints[i] - pPoints[i + 1]); - } - } - return 0; // Domyślnie – choć powinno się tu już nie dojść -} - - //Main feature: // RTC z możliwością ustawienia godziny // odczyt wilgotności, temperatury i temperatury odcuwalnej -// zasilanie bateryjne +// zasilanie bateryjne wraz z obsługą poziomu baterii i estymowanym czasem pracy na baterii // menu //2DO zapis na karcie SD