Youen Toupin
3 years ago
6 changed files with 257 additions and 14 deletions
@ -0,0 +1,84 @@ |
|||||||
|
#include "DataLogger.h" |
||||||
|
|
||||||
|
#include "utils.h" |
||||||
|
|
||||||
|
#include <Preferences.h> |
||||||
|
|
||||||
|
DataLogger DataLogger::mainLogger; |
||||||
|
|
||||||
|
DataLogger::DataLogger() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
DataLogger::~DataLogger() |
||||||
|
{ |
||||||
|
} |
||||||
|
|
||||||
|
void DataLogger::open() |
||||||
|
{ |
||||||
|
if(isOpen()) return; |
||||||
|
|
||||||
|
lastLogTime = -std::numeric_limits<float>::max(); |
||||||
|
currentTime = 0.0f; |
||||||
|
|
||||||
|
Preferences preferences; |
||||||
|
preferences.begin("vm-log", false); |
||||||
|
uint16_t logFileIndex = preferences.getUShort("next", 1); |
||||||
|
preferences.putUShort("next", logFileIndex + 1); |
||||||
|
preferences.end(); |
||||||
|
|
||||||
|
// clear existing files until we have enough free space
|
||||||
|
const size_t requiredSpace = 300000; // in bytes
|
||||||
|
size_t totalSpace = SPIFFS.totalBytes(); |
||||||
|
auto logFolder = SPIFFS.open("/log"); |
||||||
|
auto file = logFolder.openNextFile(); |
||||||
|
while(file && SPIFFS.usedBytes() + requiredSpace > totalSpace) |
||||||
|
{ |
||||||
|
Serial.print("Deleting old log file: "); |
||||||
|
Serial.println(file.name()); |
||||||
|
|
||||||
|
SPIFFS.remove(file.name()); |
||||||
|
file = logFolder.openNextFile(); |
||||||
|
} |
||||||
|
|
||||||
|
char fileName[32]; |
||||||
|
sprintf(fileName, "/log/L%05d.csv", logFileIndex); |
||||||
|
|
||||||
|
file = SPIFFS.open(fileName, FILE_WRITE); |
||||||
|
if(!file) 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"); |
||||||
|
} |
||||||
|
|
||||||
|
void DataLogger::close() |
||||||
|
{ |
||||||
|
if(!isOpen()) return; |
||||||
|
file.close(); |
||||||
|
} |
||||||
|
|
||||||
|
void DataLogger::log(unsigned long timeMilliseconds, const Entry& entry) |
||||||
|
{ |
||||||
|
if(lastLogTime == -std::numeric_limits<float>::max()) lastTimeMilliseconds = timeMilliseconds; |
||||||
|
currentTime += (float)utils::elapsed(lastTimeMilliseconds, timeMilliseconds) / 1000.0f; |
||||||
|
lastTimeMilliseconds = timeMilliseconds; |
||||||
|
|
||||||
|
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); |
||||||
|
file.print(line); |
||||||
|
|
||||||
|
lastEntry = entry; |
||||||
|
lastLogTime = currentTime; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
bool DataLogger::isOpen() |
||||||
|
{ |
||||||
|
return file; |
||||||
|
} |
||||||
|
|
||||||
|
const char* DataLogger::currentLogFileName() |
||||||
|
{ |
||||||
|
return isOpen() ? file.name() : ""; |
||||||
|
} |
@ -0,0 +1,45 @@ |
|||||||
|
#include <cmath> |
||||||
|
#include <SPIFFS.h> |
||||||
|
|
||||||
|
class DataLogger |
||||||
|
{ |
||||||
|
public: |
||||||
|
struct Entry |
||||||
|
{ |
||||||
|
float batteryVoltage = 0.0f; // V
|
||||||
|
float batteryOutputCurrent = 0.0f; // A
|
||||||
|
float speed = 0.0f; // m/s
|
||||||
|
|
||||||
|
bool isDifferent(const Entry& other) |
||||||
|
{ |
||||||
|
const float scale = speed > 0.0f ? 1.0f : 5.0f; |
||||||
|
return |
||||||
|
std::abs(batteryVoltage - other.batteryVoltage) > 0.1f * scale |
||||||
|
&& std::abs(batteryOutputCurrent - other.batteryOutputCurrent) > 0.1f * scale |
||||||
|
&& std::abs(speed - other.speed) > 0.1f; |
||||||
|
} |
||||||
|
}; |
||||||
|
|
||||||
|
public: |
||||||
|
DataLogger(); |
||||||
|
~DataLogger(); |
||||||
|
|
||||||
|
static DataLogger& get() { return mainLogger; } |
||||||
|
|
||||||
|
void open(); |
||||||
|
void close(); |
||||||
|
void log(unsigned long timeMilliseconds, const Entry& entry); |
||||||
|
|
||||||
|
bool isOpen(); |
||||||
|
const char* currentLogFileName(); |
||||||
|
|
||||||
|
private: |
||||||
|
static DataLogger mainLogger; |
||||||
|
|
||||||
|
Entry lastEntry; |
||||||
|
unsigned long lastTimeMilliseconds = -1; |
||||||
|
float currentTime = 0.0f; |
||||||
|
float lastLogTime = 0.0f; |
||||||
|
|
||||||
|
File file; // @suppress("Abstract class cannot be instantiated")
|
||||||
|
}; |
@ -0,0 +1,19 @@ |
|||||||
|
#include "utils.h" |
||||||
|
|
||||||
|
namespace utils |
||||||
|
{ |
||||||
|
unsigned long elapsed(unsigned long from, unsigned long to) |
||||||
|
{ |
||||||
|
if(to >= from) |
||||||
|
{ |
||||||
|
return to - from; |
||||||
|
} |
||||||
|
else |
||||||
|
{ |
||||||
|
// if the counter overflowed, this computes the real duration
|
||||||
|
// of course it won't work if the counter made a "full turn" or more
|
||||||
|
const unsigned long biggestValue = (unsigned long)-1; |
||||||
|
return (biggestValue - from) + to + 1; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,4 @@ |
|||||||
|
namespace utils |
||||||
|
{ |
||||||
|
unsigned long elapsed(unsigned long from, unsigned long to); |
||||||
|
} |
Loading…
Reference in new issue