Miért van az aláíratlan hosszú megölt memcpy a mintavételi sebességem?

Mega 2560-at használok az analóg (azaz az analogRead () segítségével mért és I2C alapú érzékelők keverékével való kommunikációhoz. A mintába vett adatokat a egy 16 bájtos tömböt, majd egy 512 bájtos puffer teljes kitöltése után írunk egy SD-kártyára. Az a probléma merül fel bennem, hogy amikor MAX30102 impulzusoximéterről gyűjtöm az adatokat

az alábbi kódomból a collectHR () ciklusom ciklusideje körülbelül 20 mS-re csökken. Ha ezt a helyet előre lefektetem a közvetlenül alatta lévő vonal használatával (konstans tárolása ahelyett, hogy minden egyes ciklusban új uint32_t-t olvasnék), akkor a ciklusidőm körülbelül fél milliszekundum. Ami zavaró számomra, hogy ha az uint32_t-t egy karakterláncba vetem a dtostrf használatával:

dtostrf(pulseOx.getIR(),3,0,pOxBuf); // read pulseOx, convert it into a 3 byte string 

csak kb. 1,2 mS-re van szükség ahhoz, hogy ténylegesen olvasson egy mintát a MAX30102. Úgy tűnik számomra, hogy a struktúrát előnyben részesítve egy karakterlánccal szemben (ennek a kódnak egy korábbi iterációjából, amely az összes adatot bináris fájl helyett txt fájlként írta), hogy binárisan írhassak az SD-kártyámra, ” m teljesen elfojtom a sebességemet. Nem kellene hatékonyabban működnie a bájtonként, mint egy karakterlánccal? Mi történik a másik 18 mS-sel, ami az előjel nélküli hosszú beolvasása és a byte-os pufferbe, a buffer1 közé kerül? Ezt a kódot string-tömbök használatával struktúra helyett hajtják végre, Körülbelül 125 Hz-en tudtam futni. Most nagyjából 50 Hz-en vagyok. Nagyra értékelném az itteni betekintést. Az alább látható kód:

#include <Wire.h> #include "MAX30105.h" #include <SPI.h> #include <SdFat.h> #define moisture0 A0 // Upper back sensor analog pin #define moisture1 A7 // Trunk sensor analog pin #define ECGpin A3 // ECG analog pin SdFat SD; // replace SD with SDfat. File sdLog; // placeholder to create datalogger struct meas // a 16 byte structure to hold all of our measurements { unsigned long mils; int ECG; uint32_t pox; int tempInt; int m1; int m2; }; struct meas measure; // create an instance of the above structure byte buffer1[512]; byte *measureLoc = (byte *) &measure; // to access measure structure as bytes char fileName[] = "WIHMSlog.bin"; void setup { Serial.begin(230400); } void loop() { sdLog = SD.open(fileName, O_WRITE | O_CREAT | O_AT_END); // Create file for the datalogging and verify its existance collectHR(); sdlog.close() } void collectHR() { unsigned int loopCount = 0; int buffLen = 0; // starting position in buffer int buffSize = 16; while (loopCount < 3200) { // some multiple of 32 (since 512 byte/sd block divided by 16 bytes per loop cycle = 32 cycles per sd write cycle measure.ECG = analogRead(ECGpin); // read ECG and stick the int into measures measure.pox = pulseOx.getIR(); //measure.pox = 5555; // Placeholder value measure.mils = micros(); measure.m1 = analogRead(moisture0); measure.m2 = loopCount; // just a test to ensure this is actually iterating in the card if (buffLen == 512) { // SD buffer is full, time to write! sdLog.write(buffer1, 512); buffLen = 0; } memcpy(buffer1 + buffLen, measureLoc, buffSize); // place the 16 byte data structure into the buffer buffLen = buffLen + buffSize; // increase the index size in the array loopCount++; Serial.println(micros()); } } 

Megjegyzések

  • A sorrend A műveletek kissé furcsának tűnnek. Vegyük fontolóra, mi történik a legelején: buffLen kezdetben 0, majd azonnal megnöveli 16, majd átmásolja az adatokat a pufferbe a 16 eltolással. De mi van az első 16 bájt? Miért hagytad kihasználatlanul? Továbbá nem világos, hogy miért is kell folyamatosan bájtokat pumpálnod measure -ről buffer1 , azaz a memóriából a memóriába. Miért ne ' t deklarálná egy 32 struct measure elemeket, és közvetlenül használja?
  • Köszönöm a hozzájárulást! Ön ' teljesen igaza van abban, hogy az első 16 bájt üres marad. Kezdetben azt gondoltam, hogy csináld meg 16 0 ' s keresésével könnyebben megállapítható, hogy az egyes collectHR () hurkok mikor zárultak le a fájlban, de most, amikor rámutattál rá, a memória teljes pazarlásának tűnik. Alább mozgattam a növekményt. a memcpy felhívás erre. Nem gondoltam ' arra, hogy egy sor tömböt leadjak; ' megadom. Van valamilyen rálátása arra, hogy miért éppen a pulseOx.getIR () hívás memcpy-je sokkal lassabb, mint amennyi időbe telik a 4 bájt lekérése az érzékelőből?
  • use unsigned int a buffLen esetében, mert a 15 * 3200 több, mint amennyit int eltarthat
  • Biztosan rendelkezik 512 bájt szabad RAM-mal? Az SDfat könyvtár amúgy is tartalmaz 512 bájtos puffert, és még egyet magának a fájlrendszernek. Amúgy fizikailag csak teljes blokkokat ír az SD-re.
  • Juraj Jó fogást, köszönöm! Ezt ' módosítottam fent. @DataFiddler Állítólag kb. 5800 bájtom van hátra. <

tudom, hogy az SDfat 512 bájtos puffert használ, de ez azt jelenti, hogy minden írási () hívás 512 bájtot tol a kártyára, vagy egyáltalán nem küldenek semmit a kártyára. 512 bájt értékű írás () halmozódik fel? Elnézést a millisSet () megbántott, én ' eltávolítottam. Megpróbáltam csak a kód megfelelő részeit közzétenni, de úgy tűnik, hogy hiányzott az a változó az első bejegyzésben. A szemetet elszállítják …

Vélemény, hozzászólás?

Az email címet nem tesszük közzé. A kötelező mezőket * karakterrel jelöltük