hvorfor dreper minnet om usignert lang prøvetakingshastigheten min?

Jeg bruker en Mega 2560 for å kommunisere med en blanding av analoge (dvs. målt via analogRead ()) og I2C-baserte sensorer. Samplede data plasseres i en 16 byte matrise, deretter skrevet til et SD-kort når en 512 byte buffer er fullstendig fylt. Problemet jeg kjører på er at når jeg samler inn data fra et MAX30102 pulsoksymeter ved hjelp av

measure.pox = pulseOx.getIR(); 

fra koden min nedenfor, faller syklustiden til collectHR () -sløyfen til omtrent 20 mS. Hvis jeg forhåndslokaliserer dette stedet ved å bruke linjen rett under den (lagrer en konstant i stedet for å lese en ny uint32_t hver sløyfe), er syklustiden min omtrent et halvt millisekund. Det som er forvirrende for meg er at hvis jeg kaster uint32_t inn i en streng ved hjelp av dtostrf:

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

tar det bare omtrent 1,2 mS å lese en prøve fra MAX30102. Det virker for meg at ved å favorisere en struktur over en streng (fra en tidligere iterasjon av denne koden som skrev alle data som en txt-fil i stedet for en bin-fil) slik at jeg kan skrive binært til SD-kortet mitt, jeg » Jeg strupes absolutt av farten min. Bør ikke arbeid bytevis være mer effektivt enn å jobbe med en streng? Hva skjer med de andre 18 mS som oppstår mellom å lese den usignerte lange og plassere den i byte-buffer, buffer1? Implementere denne koden ved hjelp av strengarrayer i stedet for en struktur, Jeg klarte å løpe på omtrent 125 Hz. Nå er jeg omtrent 50 Hz. Jeg vil sette pris på noe innblikk her. Relevant kode vist nedenfor:

#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()); } } 

Kommentarer

  • Sekvensen av operasjoner ser litt rart ut. Tenk på hva som skjer helt i starten: buffLen er opprinnelig 0, så øker du det umiddelbart til 16 og deretter kopierer du dataene til den bufferen ved forskyvning 16. Men hva med den første 16 byte? Hvorfor la du dem ubrukt? Det er heller ikke klart hvorfor du til og med trenger å stadig pumpe byte fra measure til buffer1 , dvs. fra minne til minne. Hvorfor ikke ' t du bare erklærer en matrise med 32 struct measure elementer og bruke det direkte?
  • Takk for innspillene! Du ' har helt rett i at de første 16 byte forblir tomme. Jeg hadde opprinnelig trodd at det ville klare det lettere å bestemme når hver collectHR () -sløyfe endte i filen ved å søke etter 16 0 ' s, men nå som du påpeker det, virker det som et totalt sløsing med minne. Jeg har flyttet trinnet under. memcpy-samtalen for å gjøre rede for dette. Jeg hadde ikke ' ikke tenkt å kaste en rekke strukturer; Jeg ' Jeg får prøve. Har du noe innblikk i hvorfor spesifikt memcpy av pulseOx.getIR () samtalen er så mye tregere enn tiden det tar å hente de 4 byte fra sensoren?
  • bruk unsigned int for buffLen, fordi 15 * 3200 er mer enn int kan ta
  • Er du sikker på at du har 512 byte ledig RAM? SDfat-biblioteket har uansett en 512 byte-buffer, og en annen for selve filsystemet. Den skriver fysisk til SD bare fullblokker uansett.
  • Juraj God fangst, takk! Jeg ' har endret dette ovenfor. @DataFiddler Jeg har angivelig omtrent 5800 byte igjen å leke med. Jeg er ' klar over at SDfat bruker en 512 byte-buffer, men betyr det at hver skriveanrop skyver 512 byte til kortet, eller at ingenting sendes til kortet i det hele tatt til 512 bytes verdt å skrive () er samlet? Beklager millisSet () fornærmet deg, jeg ' har fjernet den. Jeg prøvde å legge ut bare de aktuelle delene av koden, men ser ut til å ha savnet den variabelen i det første innlegget. Søppel fjernes …

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert. Obligatoriske felt er merket med *