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