pourquoi memcpy de non signé tue ma vitesse déchantillonnage?

Jutilise un Mega 2560 pour communiquer avec un mélange de capteurs analogiques (mesurés via analogRead ()) et basés sur I2C. Les données échantillonnées sont placées dans un tableau de 16 octets, puis écrit sur une carte SD une fois quun tampon de 512 octets est complètement rempli. Le problème que je rencontre est que lorsque je collecte des données à partir dun oxymètre de pouls MAX30102 en utilisant

measure.pox = pulseOx.getIR(); 

daprès mon code ci-dessous, le temps de cycle de ma boucle collectHR () tombe à environ 20 mS. Si je préalloue cet endroit en utilisant la ligne directement en dessous (en stockant une constante au lieu de lire un nouveau uint32_t à chaque boucle), mon temps de cycle est denviron une demi-milliseconde. Ce qui est déroutant pour moi, cest que si je transforme uint32_t en une chaîne en utilisant dtostrf:

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

il ne faut quenviron 1,2 mS pour lire un échantillon à partir de le MAX30102. Il me semble quen privilégiant une structure sur une chaîne (dune itération antérieure de ce code qui écrivait toutes les données sous forme de fichier txt au lieu dun fichier bin) afin que je puisse écrire du binaire sur ma carte SD, je  » Je ralentis absolument ma vitesse. Ne devrait-il pas être plus efficace de travailler par octet que de travailler avec une chaîne? Que se passe-t-il pour les 18 autres ms qui se produisent entre la lecture du long unsigned et son placement dans byte buffer, buffer1? Implémentation de ce code en utilisant des tableaux de chaînes au lieu dune structure, Jai pu courir à environ 125 Hz. Maintenant, je suis à environ 50 Hz. Japprécierais tout renseignement ici. Code pertinent indiqué ci-dessous:

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

Commentaires

  • La séquence des opérations semble un peu étrange. Considérez ce qui se passe au tout début: buffLen est initialement 0, puis vous laugmentez immédiatement à 16, puis copiez les données dans cette mémoire tampon au décalage 16. Mais quen est-il du premier 16 octets? Pourquoi les avez-vous laissés inutilisés? De plus, la raison pour laquelle vous devez constamment pomper des octets de measure à buffer1 nest pas claire. , cest-à-dire de mémoire en mémoire. Pourquoi ne ' que vous déclarez simplement un tableau de 32 struct measure et les utiliser directement?
  • Merci pour votre contribution! Vous ' avez tout à fait raison de dire que les 16 premiers octets restent vides. Javais initialement pensé que ce serait fais-le plus facile de déterminer quand chaque boucle collectHR () sest terminée dans le fichier en recherchant 16 0 ' s, mais maintenant que vous le signalez, cela semble être un gaspillage total de mémoire. Jai déplacé lincrément ci-dessous. lappel memcpy pour en rendre compte. Je navais pas ' pensé à lancer un tableau de structures; Je ' je vais essayer. Avez-vous une idée de la raison pour laquelle le memcpy de lappel pulseOx.getIR () est tellement plus lent que le temps quil faut pour récupérer ces 4 octets du capteur?
  • utilisez unsigned int pour buffLen, car 15 * 3200 est plus que ce que int peut prendre
  • Êtes-vous sûr de disposer de 512 octets de RAM libre? La bibliothèque SDfat contient de toute façon un tampon de 512 octets, et un autre pour le système de fichiers lui-même. Il nécrit physiquement en SD que des blocs complets de toute façon.
  • Juraj Bonne prise, merci! Jai ' modifié ceci ci-dessus. @DataFiddler Il me reste environ 5800 octets pour jouer. Je ' m conscient que SDfat utilise un tampon de 512 octets, mais cela signifie-t-il que chaque appel write () pousse 512 octets vers la carte, ou que rien n’est envoyé à la carte du tout jusqu’à ce que 512 octets de write () sont amassés? Désolé millisSet () vous a offensé, je ' lai supprimé. Jai essayé de publier uniquement les parties pertinentes du code mais je semble avoir manqué cette variable dans le message initial. Les déchets sont supprimés …

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *