diff --git a/ESP32/src/DataLogger.cpp b/ESP32/src/DataLogger.cpp index 9ec7f29..79e9a9e 100644 --- a/ESP32/src/DataLogger.cpp +++ b/ESP32/src/DataLogger.cpp @@ -51,7 +51,7 @@ void DataLogger::open() file = SPIFFS.open(fileName, FILE_WRITE); if(!isOpen()) Serial.println("DataLogger: failed to open file"); - if(!file.print("time,speed,battery voltage,battery output current\n")) Serial.println("DataLogger: failed to write to file"); + if(!file.print("time,speed,battery voltage,battery output current,temperature,altitude\n")) Serial.println("DataLogger: failed to write to file"); } void DataLogger::close() @@ -69,7 +69,7 @@ void DataLogger::log(unsigned long timeMilliseconds, const Entry& entry) if((lastEntry.isDifferent(entry) || currentTime >= lastLogTime + 20.0f) && currentTime >= lastLogTime + 0.2f) { char line[128]; - sprintf(line, "%.3f,%.3f,%.3f,%.3f\n", currentTime, entry.speed, entry.batteryVoltage, entry.batteryOutputCurrent); + sprintf(line, "%.3f,%.3f,%.3f,%.3f,%.1f,%.1f\n", currentTime, entry.speed, entry.batteryVoltage, entry.batteryOutputCurrent, entry.temperature, entry.altitude); file.print(line); lastEntry = entry; diff --git a/ESP32/src/DataLogger.h b/ESP32/src/DataLogger.h index cadae50..46b69d2 100644 --- a/ESP32/src/DataLogger.h +++ b/ESP32/src/DataLogger.h @@ -9,6 +9,8 @@ public: float batteryVoltage = 0.0f; // V float batteryOutputCurrent = 0.0f; // A float speed = 0.0f; // m/s + float temperature = 0.0f; // in °C + float altitude = 0.0f; // in m bool isDifferent(const Entry& other) { @@ -16,7 +18,9 @@ public: return std::abs(batteryVoltage - other.batteryVoltage) > 0.1f * scale || std::abs(batteryOutputCurrent - other.batteryOutputCurrent) > 0.1f * scale - || std::abs(speed - other.speed) > 0.1f; + || std::abs(speed - other.speed) > 0.1f + || std::abs(temperature - other.temperature) > 0.5f * scale + || std::abs(altitude - other.altitude) > 0.5f * scale; } }; diff --git a/ESP32/src/vehicle-monitor.cpp b/ESP32/src/vehicle-monitor.cpp index fe064db..c22acb7 100644 --- a/ESP32/src/vehicle-monitor.cpp +++ b/ESP32/src/vehicle-monitor.cpp @@ -6,6 +6,8 @@ #include #include +#include + #include "ADC.h" #include "OTA.h" #include "DataLogger.h" @@ -13,14 +15,19 @@ #include "wifi-credentials.h" +#include + #define DUMMY_DATA 0 AsyncWebServer server(80); ADC currentSensor(36); ADC batterySensor(39); +Dps310 pressureSensor = Dps310(); const int8_t speedSensorPin = 13; const int8_t debugLedPin = 2; +const int8_t I2C_SDA = 12; +const int8_t I2C_SCL = 15; const float wheelDiameterInches = 20; const int numImpulsesPerTurn = 2; @@ -28,6 +35,8 @@ const float wheelCircumferenceMeters = wheelDiameterInches * 0.0254f * 3.1415f / uint16_t batteryVoltage = 0; // in mV uint16_t batteryOutputCurrent = 0; // in mV +int16_t temperature = 0; // in tenth of °C +int32_t altitude = 0; // in mm above sea level (can be negative if below sea level, or depending on atmospheric conditions) WiFiMulti wifiMulti; wl_status_t wifi_STA_status = WL_NO_SHIELD; @@ -163,10 +172,16 @@ void setup() OTA.begin(); + Wire.begin(I2C_SDA, I2C_SCL); + + pressureSensor.begin(Wire); + server.on("/api/status", HTTP_GET, [](AsyncWebServerRequest *request){ int v = batteryVoltage; int c = batteryOutputCurrent; int s = (int)(getSpeed() * 1000.0f + 0.5f); + int t = temperature; + int alt = altitude; const char* logFileName = DataLogger::get().currentLogFileName(); if(String(logFileName).startsWith("/log/")) logFileName += 5; @@ -175,7 +190,7 @@ void setup() int usedSize = (int)(SPIFFS.usedBytes() / 1000); char json[128]; - sprintf(json, "{\"v\":%d,\"c\":%d,\"s\":%d,\"log\":\"%s\",\"tot\":%d,\"used\":%d}", v, c, s, logFileName, totalSize, usedSize); + sprintf(json, "{\"v\":%d,\"c\":%d,\"s\":%d,\"t\":%d,\"alt\":%d,\"log\":\"%s\",\"tot\":%d,\"used\":%d}", v, c, s, t, alt, logFileName, totalSize, usedSize); request->send(200, "text/json", json); }); @@ -295,11 +310,73 @@ void handle_ADC_measures() #endif } +void handle_pressure_measure() +{ + const uint8_t oversampling = 7; + int16_t ret; + + float temp; // in Celcius degrees + ret = pressureSensor.measureTempOnce(temp, oversampling); + if(ret != 0) + { + Serial.print("Failed to measure temperature: "); Serial.println(ret); + return; + } + temperature = (int16_t)(temp * 10.0f + 0.5f); + + float pressure; // in Pa + pressureSensor.measurePressureOnce(pressure, oversampling); + if(ret != 0) + { + Serial.print("Failed to measure pressure: "); Serial.println(ret); + return; + } + + struct PressureToAltitude + { + float pressure; // in Pa + float altitude; // in meters above sea level + }; + const PressureToAltitude altitudeTable[] = + { + { 101325.0f, 0.0f }, + { 100000.0f, 111.0f }, + { 95000.0f, 540.0f }, + { 90000.0f, 989.0f }, + { 85000.0f, 1457.0f }, + { 80000.0f, 1949.0f }, + { 75000.0f, 2466.0f }, + { 70000.0f, 3012.0f }, + { 65000.0f, 3591.0f }, + { 60000.0f, 4206.0f }, + { 55000.0f, 4865.0f }, + }; + const int8_t altitudeTableNumValues = sizeof(altitudeTable)/sizeof(altitudeTable[0]); + + float alt = -std::numeric_limits::max(); + for(int8_t i = 0; i < altitudeTableNumValues - 1; ++i) + { + if(i == altitudeTableNumValues - 2 || pressure >= altitudeTable[i+1].pressure) + { + const auto& p = altitudeTable[i]; + const auto& n = altitudeTable[i+1]; + alt = (pressure - p.pressure) / (n.pressure - p.pressure) * (n.altitude - p.altitude) + p.altitude; + break; + } + } + altitude = (int32_t)(alt * 1000.0f + 0.5f); + + /*Serial.print("temperature="); Serial.print(temp); Serial.print("°C"); + Serial.print(" pressure="); Serial.print(pressure); Serial.print("Pa"); + Serial.print(" altitude="); Serial.print(altitude); Serial.println("mm");*/ +} + void loop() { OTA.handle(); handle_wifi_connection(); handle_ADC_measures(); + handle_pressure_measure(); // also measures temperature unsigned long now = millis(); static DataLogger::Entry entry; @@ -333,5 +410,5 @@ void loop() } DataLogger::get().log(now, entry); - delay(10); + delay(DataLogger::get().isOpen() ? 10 : 1000); }