Estou usando um Mega 2560 para me comunicar com uma mistura de sensores analógicos (ou seja, medidos via analogRead ()) e sensores baseados em I2C. Os dados amostrados são colocados em uma matriz de 16 bytes, depois gravada em um cartão SD assim que um buffer de 512 bytes estiver completamente preenchido. O problema que estou enfrentando é que quando eu coleto dados de um oxímetro de pulso MAX30102 usando
measure.pox = pulseOx.getIR();
a partir do meu código abaixo, o tempo de ciclo do meu loop collectHR () cai para cerca de 20 ms. Se eu pré-alocar este ponto usando a linha diretamente abaixo dele (armazenando uma constante em vez de ler um novo uint32_t a cada loop), meu tempo de ciclo é de cerca de meio milissegundo. O que é confuso para mim é que se eu converter o uint32_t em uma string usando dtostrf:
dtostrf(pulseOx.getIR(),3,0,pOxBuf); // read pulseOx, convert it into a 3 byte string
leva apenas cerca de 1,2 ms para realmente ler uma amostra de o MAX30102. Parece-me que, ao favorecer uma estrutura em vez de uma string (de uma iteração anterior deste código que gravava todos os dados como um arquivo txt em vez de um arquivo bin) para que eu pudesse gravar binário em meu cartão SD, eu ” estou absolutamente estrangulando minha velocidade. Não deveria trabalhar bytewise ser mais eficiente do que trabalhar com uma string? O que está acontecendo com os outros 18 ms que ocorre entre a leitura do long sem sinal e colocá-lo em byte buffer, buffer1? Implementar este código usando arrays de string em vez de uma estrutura, Consegui funcionar a aproximadamente 125 Hz. Agora estou a cerca de 50 Hz. Agradeço qualquer insight aqui. Código relevante mostrado abaixo:
#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
é inicialmente0
, então você aumenta imediatamente para16
e, em seguida, você copia os dados para esse buffer no deslocamento16
. Mas e quanto ao primeiro16
bytes? Por que você os deixou sem uso? Além disso, não está claro por que você precisa bombear bytes constantemente demeasure
parabuffer1
, ou seja, de memória para memória. Por que não ' você apenas declara uma matriz de32
struct measure
elementos e usá-los diretamente?unsigned int
para buffLen, porque 15 * 3200 é mais do queint
pode levar