Używam Mega 2560 do komunikacji z mieszanką czujników analogowych (tj. mierzonych za pomocą analogRead ()) i czujników opartych na I2C. Próbkowane dane są umieszczane w 16-bajtowa tablica, a następnie zapisywana na karcie SD po całkowitym zapełnieniu 512-bajtowego bufora. Problem, z którym się spotykam, polega na tym, że kiedy zbieram dane z pulsoksymetru MAX30102 za pomocą
measure.pox = pulseOx.getIR();
z mojego kodu poniżej, czas cyklu mojej pętli collectHR () spada do około 20 mS. Jeśli wstępnie przydzielę to miejsce, używając linii bezpośrednio pod nim (przechowując stałą zamiast odczytywania nowej pętli uint32_t), mój czas cyklu wynosi około pół milisekundy. Mylące jest dla mnie to, że jeśli rzucę uint32_t na łańcuch za pomocą dtostrf:
dtostrf(pulseOx.getIR(),3,0,pOxBuf); // read pulseOx, convert it into a 3 byte string
odczytanie próbki z MAX30102. Wydaje mi się, że faworyzując strukturę nad ciągiem (z wcześniejszej iteracji tego kodu, który zapisywał wszystkie dane jako plik txt zamiast pliku bin), dzięki czemu mogę zapisać plik binarny na mojej karcie SD, ja ” m absolutnie dławi moją prędkość. Czy praca „bajtowo” nie powinna być bardziej wydajna niż praca ze stringiem? Co dzieje się z pozostałymi 18 ms, które zachodzą między odczytem długości bez znaku i umieszczeniem go w buforze bajtowym, buffer1? Implementacja tego kodu przy użyciu tablic ciągów zamiast struktury, Mogłem pracować z częstotliwością około 125 Hz. Teraz mam około 50 Hz. Byłbym wdzięczny za wszelkie uwagi tutaj. Odpowiedni kod pokazany poniżej:
#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
to początkowo0
, a następnie natychmiast zwiększasz do16
, a następnie kopiujesz dane do tego bufora z przesunięciem16
. Ale co z pierwszym16
bajtów? Dlaczego zostawiłeś je nieużywane? Poza tym nie jest jasne, dlaczego musisz nawet ciągle pompować bajty zmeasure
dobuffer1
, tj. z pamięci do pamięci. Dlaczego nie ', po prostu deklarujesz tablicę32
struct measure
i użyć go bezpośrednio?unsigned int
dla buffLen, ponieważ 15 * 3200 to więcej niżint
może zająć