Browse Source

added temperature and altitude estimation from atmospheric pressure

master
Youen Toupin 3 years ago
parent
commit
532cca230b
  1. 4
      ESP32/src/DataLogger.cpp
  2. 6
      ESP32/src/DataLogger.h
  3. 81
      ESP32/src/vehicle-monitor.cpp

4
ESP32/src/DataLogger.cpp

@ -51,7 +51,7 @@ void DataLogger::open()
file = SPIFFS.open(fileName, FILE_WRITE); file = SPIFFS.open(fileName, FILE_WRITE);
if(!isOpen()) Serial.println("DataLogger: failed to open file"); 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() 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) if((lastEntry.isDifferent(entry) || currentTime >= lastLogTime + 20.0f) && currentTime >= lastLogTime + 0.2f)
{ {
char line[128]; 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); file.print(line);
lastEntry = entry; lastEntry = entry;

6
ESP32/src/DataLogger.h

@ -9,6 +9,8 @@ public:
float batteryVoltage = 0.0f; // V float batteryVoltage = 0.0f; // V
float batteryOutputCurrent = 0.0f; // A float batteryOutputCurrent = 0.0f; // A
float speed = 0.0f; // m/s float speed = 0.0f; // m/s
float temperature = 0.0f; // in °C
float altitude = 0.0f; // in m
bool isDifferent(const Entry& other) bool isDifferent(const Entry& other)
{ {
@ -16,7 +18,9 @@ public:
return return
std::abs(batteryVoltage - other.batteryVoltage) > 0.1f * scale std::abs(batteryVoltage - other.batteryVoltage) > 0.1f * scale
|| std::abs(batteryOutputCurrent - other.batteryOutputCurrent) > 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;
} }
}; };

81
ESP32/src/vehicle-monitor.cpp

@ -6,6 +6,8 @@
#include <SPIFFS.h> #include <SPIFFS.h>
#include <ESPAsyncWebServer.h> #include <ESPAsyncWebServer.h>
#include <Dps310.h>
#include "ADC.h" #include "ADC.h"
#include "OTA.h" #include "OTA.h"
#include "DataLogger.h" #include "DataLogger.h"
@ -13,14 +15,19 @@
#include "wifi-credentials.h" #include "wifi-credentials.h"
#include <limits>
#define DUMMY_DATA 0 #define DUMMY_DATA 0
AsyncWebServer server(80); AsyncWebServer server(80);
ADC currentSensor(36); ADC currentSensor(36);
ADC batterySensor(39); ADC batterySensor(39);
Dps310 pressureSensor = Dps310();
const int8_t speedSensorPin = 13; const int8_t speedSensorPin = 13;
const int8_t debugLedPin = 2; const int8_t debugLedPin = 2;
const int8_t I2C_SDA = 12;
const int8_t I2C_SCL = 15;
const float wheelDiameterInches = 20; const float wheelDiameterInches = 20;
const int numImpulsesPerTurn = 2; const int numImpulsesPerTurn = 2;
@ -28,6 +35,8 @@ const float wheelCircumferenceMeters = wheelDiameterInches * 0.0254f * 3.1415f /
uint16_t batteryVoltage = 0; // in mV uint16_t batteryVoltage = 0; // in mV
uint16_t batteryOutputCurrent = 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; WiFiMulti wifiMulti;
wl_status_t wifi_STA_status = WL_NO_SHIELD; wl_status_t wifi_STA_status = WL_NO_SHIELD;
@ -163,10 +172,16 @@ void setup()
OTA.begin(); OTA.begin();
Wire.begin(I2C_SDA, I2C_SCL);
pressureSensor.begin(Wire);
server.on("/api/status", HTTP_GET, [](AsyncWebServerRequest *request){ server.on("/api/status", HTTP_GET, [](AsyncWebServerRequest *request){
int v = batteryVoltage; int v = batteryVoltage;
int c = batteryOutputCurrent; int c = batteryOutputCurrent;
int s = (int)(getSpeed() * 1000.0f + 0.5f); int s = (int)(getSpeed() * 1000.0f + 0.5f);
int t = temperature;
int alt = altitude;
const char* logFileName = DataLogger::get().currentLogFileName(); const char* logFileName = DataLogger::get().currentLogFileName();
if(String(logFileName).startsWith("/log/")) logFileName += 5; if(String(logFileName).startsWith("/log/")) logFileName += 5;
@ -175,7 +190,7 @@ void setup()
int usedSize = (int)(SPIFFS.usedBytes() / 1000); int usedSize = (int)(SPIFFS.usedBytes() / 1000);
char json[128]; 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); request->send(200, "text/json", json);
}); });
@ -295,11 +310,73 @@ void handle_ADC_measures()
#endif #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<float>::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() void loop()
{ {
OTA.handle(); OTA.handle();
handle_wifi_connection(); handle_wifi_connection();
handle_ADC_measures(); handle_ADC_measures();
handle_pressure_measure(); // also measures temperature
unsigned long now = millis(); unsigned long now = millis();
static DataLogger::Entry entry; static DataLogger::Entry entry;
@ -333,5 +410,5 @@ void loop()
} }
DataLogger::get().log(now, entry); DataLogger::get().log(now, entry);
delay(10); delay(DataLogger::get().isOpen() ? 10 : 1000);
} }

Loading…
Cancel
Save