Používám Mega 2560 ke komunikaci se směsí analogových (tj. měřených pomocí analogRead ()) a senzorů založených na I2C. Vzorkovaná data se ukládají do 16 bajtové pole, poté zapsané na SD kartu, jakmile je 512 bajtová vyrovnávací paměť zcela zaplněna. Problém, se kterým se setkávám, spočívá v tom, že když shromažďuji data z pulzního oxymetru MAX30102 pomocí
measure.pox = pulseOx.getIR();
z mého kódu níže klesne doba cyklu mé smyčky collectHR () na asi 20 mS. Pokud toto místo předem určím pomocí řádku přímo pod ním (uložení konstanty namísto čtení nové smyčky uint32_t každé smyčky), můj čas cyklu je asi půl milisekundy. Co je pro mě matoucí, je to, že když vrhnu uint32_t do řetězce pomocí dtostrf:
dtostrf(pulseOx.getIR(),3,0,pOxBuf); // read pulseOx, convert it into a 3 byte string
trvá to jen asi 1,2 mS, aby se skutečně odečetl vzorek z MAX30102. Zdá se mi, že upřednostňováním struktury před řetězcem (z dřívější iterace tohoto kódu, který zapsal všechna data jako soubor txt namísto souboru bin), abych mohl na svoji SD kartu psát binárně, Absolutně škrtím svou rychlostí. Neměl by být bytewisewise efektivnější než práce s řetězcem? Co se děje s ostatními 18 mS, ke kterému dochází mezi čtením nepodepsaného dlouhého a jeho vložením do byte bufferu, buffer1? Implementace tohoto kódu pomocí řetězcových polí místo struktury, Byl jsem schopen běžet na přibližně 125 Hz. Teď jsem zhruba na 50 Hz. Ocenil bych zde jakýkoli přehled. Relevantní kód zobrazený níže:
#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()); } }
buffLen
je zpočátku0
, pak jej okamžitě zvýšíte na16
a potom zkopírujete data do této vyrovnávací paměti při offset16
. A co první16
bajty? Proč jste je nechali nevyužité? Také není jasné, proč dokonce potřebujete neustále pumpovat bajty zmeasure
dobuffer1
, tj. z paměti do paměti. Proč ' t prostě deklarovat pole32
struct measure
a používat je přímo?unsigned int
pro buffLen, protože 15 * 3200 je více nežint
může trvat