Az okosautó projekt kapcsán kezdtem el foglalkozni az ESP32 nevű kütyüvel. Elég hamar eljutottam oda, hogy jó lenne a futás közben összegyűlő infókat eltárolni későbbi elemzés céljából. Az eszköznek van kb 4 MB flash memóriája, ami erre tökéletesen alkalmas is, lássuk hogy lehet ezt használni!
A képen a saját példányom látható, értéke 4 USD - program nélkül! :)
Elég sok szvíás volt, mire rátaláltam egy lib-re, ami használható is volt - legalábbis úgy tűnt. Nem tudom, hogy a lapka horribilis ára, vagy a viszonylagos fiatalsága miatt, de elég kevés libet találtam hozzá. Ez lett a nyertes:
https://github.com/fabiuz7/esp-logger-lib
Könyvtár
Mutatom a lényeges részeket a példakódból:
LoggerSPIFFS myLog("/log/mylog.log");
/*...*/
void setup() {
/*...*/
Serial.print("Initializing SD card... ");
if(!myLog.begin()){
Serial.println("Failed!");
while(1)
delay(100);
} else {
Serial.println("Done!");
}
/*...*/
}
/*...*/
myLog.append(String("valami:") + i);
Egyszerűnek tűnik, nem?
- Definiálunk egy változót, aminem a konstruktorába megadjuk mi legyen a fájl neve és elérési útja.
- begin() függvényhívással megnyitjuk a loggolás előtt az utat.
- Amikor pedig valamit loggolni akarunk, akkor append() hívással ezt könnyedén megtehetjük.
Eddig rendben is lennénk, de a fájlrendszere ennek a kis kütyünek nem olyan egyszerűen érhető el, szóval valahogy ki is kellene nyerni belőle amit egyszer belepakoltunk. Erre a feladatra van egy flush() nevű hívás a lib-ben:
bool flushToSerial(char* buffer, int n) {
int index = 0;
while (index < n) {
Serial.print(buffer[index++]);
}
return true;
}
/*...*/
setup() {
Serial.begin(115200);
/*...*/
myLog.setFlusherCallback(flushToSerial);
/*...*/
}
/*...*/
myLog.flush();
Nos ez a nem túl impozáns kódrészlet arra jó, hogy ha meghívjuk a flsuh() függvényt, akkor az ennek segítségével fogja kiköpni magából a logfájl tartalmát. A fenti kód pedig a soros portra pakolja az infót nekünk.
Problémák és megoldások
Első problémám, hogy nem volt hajlandó a lib inicializálni magát. Nyitottam erről egy github issue-t is, a lib szerzője gyorsan válaszolt is, hogy milyen verziót is használok, és amint lesz ideje megnézi, de nekem nem volt sok türelmem, szóval elkezdtem utána menni a problémának.
Azt találtam, hogy van egy olyan hely, ahol az IDF egyik konstruktorhívásából kiderül, hogy a fájlokat a mikrokontroller /spiffs/ könyvtárába tudja csak kezelni. (Ez netto egy napomba került, de megtaláltam.) Szóval ha a konstruktorhívásban a fájlunk elérési útját így kezdjük, akkor menni fog a dolog.
A következő probléma az volt, hogy hiába sikerült látszólag sok infót találnom, amit én rendes emberhez méltón el is rakattam a logfájlba, de az valamiért csak nagyon keveset jegyzett meg ebből az egészből. (Amit megjegyzett, az szerencsére restart után is megmaradt, szóval legalább a perzisztenciával nem volt gond.) Kiderült, hogy a mikrokontroller limitációi miatt a lib szerzője folyamatosan figyeli, hogy mekkora lehet a fájlunk maximum és hogy egyszerre mekkora mennyiségű adatot próbálunk loggolni. Némi tornázás után rájöttem, hogy 1000 bájt a defual size limit a fájlra - ez szerintem még ilyen beágyazott könyezetben is sekély.
Próbáltam hát felemelni mondjuk 2 MB-ra, na ez nem sikerült: a gondos fejlesztőkolléga 16 bites előjel nélküli adattípust használt a limit változó deklarációjánál, szóval 65535 fölé nem érdemes menni... (Lehet van ennek valami logikus magyarázata, de ha csak hanyagség, akkor jár a tockos a derék olasz kollégának!) Sebaj, 64 kB azért már nem kevés, csak kicsit figyelni kell, hogy miket loggol az ember.