Augmenter fréquence d'acquisition arduino jusqu'à 1600hz

Bonjour,

Je suis novice en programmation et ce qui concerne arduino. Dans le cadre d'un projet, nous avons un capteur BMI 160 dont on voudrait lire les données à 1600hz. Nous avons remarqué que la taille du programme nous fait diminuer la fréquence d'acquisition.
En réduisant les données du programme nous avons pus augmenté la fréquence d'acquisition.
Nous voulons arriver à 1600Hz mais nous n'arrivons pas à avoir toutes les données. On a l'impression de perdre des données en cours de chemin.
Avez vous une idée de comment nous pouvons augmenter la fréquence d'acquisition des données de notre accéléromètre pour pouvoir receuillir les 1600hz de récolte des données de notre accéléromètres?

Nous avons paramétré la fréquence de récolte des données du BMI 160 à 1600hz dans le programme.

voici le programme utilisé jusqu'ici

#include <BMI160Gen.h>

void setup() {
 Serial.begin(2000000); // initialize Serial communication
 while (!Serial);    // wait for the serial port to open

 // initialize device
 Serial.println("Initializing IMU device...");
 //BMI160.begin(BMI160GenClass::SPI_MODE, /* SS pin# = */10);
 BMI160.begin(BMI160GenClass::I2C_MODE);
 uint8_t dev_id = BMI160.getDeviceID();
 Serial.print("DEVICE ID: ");
 Serial.println(dev_id, HEX);

// Set the accelerometer rate to 1600Hz
 BMI160.setAccelerometerRate(1600);

 Serial.println("Initializing IMU device...done.");

 uint16_t AccRate = BMI160.getAccelerometerRate();
 Serial.print("AccRate: ");
 Serial.println(AccRate, DEC);

 uint8_t AccRange = BMI160.getAccelerometerRange();
 Serial.print("AccRange: ");
 Serial.println(AccRange, DEC);

}
void loop() {

for (int i = 1 ; i <= 1000000 ; i++) {
  // int azRaw,ayRaw;         // raw gyro values
     int axRaw, ayRaw, azRaw;   
   // float ax, ay, az;

   // read raw gyro measurements from device
  // BMI160.readAccelerometer(axRaw, ayRaw, azRaw);
BMI160.readAccelerometer(axRaw, ayRaw, azRaw);
   // convert the raw gyro data to degrees/second
   //  ax = convertRawAccel(axRaw);
   //  ay = convertRawAccel(ayRaw);
   //  az = convertRawAccel(azRaw);

   // display tab-separated gyro x/y/z values
   //Serial.print("a:\t");
   Serial.print(axRaw);
   Serial.print("\t");
   Serial.print(ayRaw);
   Serial.print("\t");
   Serial.println(azRaw);

   //delay(10);
 }
 delay(10);

}

[code]

Ahah!!

for (int i = 1 ; i <= 1000000 ; i++) {

int = une variable qui peut aller de -32768 à 32767 donc fatalement, ça ne va pas coller avec les bornes que tu entres.
Il faudrait peut-être utiliser un unsigned long int à la place. Et lire ça jusqu'au bout

Autrement, vite lire ça et ça si tu veux que ton fil de discussion dure suffisamment longtemps pour avoir le temps de mettre ton soft au point.

1600 Hz ça fait une acquisition toutes les 0.625 ms
Pour mesurer le temps qui passe, il existe des fonctions comme millis() et micros(). Ici, il faut utiliser micros() puisque millis() compte les millisecondes. Donc, il faut faire une acquisition a la période de 625 microsecondes.

Pour mesurer ce temps, il faut créer une variable qui va servir de chrono :

unsigned long chrono = 0;

puis l'initialiser dans le setup et la lire régulièrement : lorsqu'elle atteindra la valeur de la période, tu lances l'acquisition.

#include <BMI160Gen.h>
unsigned long chrono = 0;
unsigned long periode = 625ul;

void setup() {
  Serial.begin(115200); // initialize Serial communication
  while (!Serial);    // wait for the serial port to open

  // initialize device
  Serial.println("Initializing IMU device...");
  //BMI160.begin(BMI160GenClass::SPI_MODE, /* SS pin# = */10);
  BMI160.begin(BMI160GenClass::I2C_MODE);
  uint8_t dev_id = BMI160.getDeviceID();
  Serial.print("DEVICE ID: ");
  Serial.println(dev_id, HEX);

// Set the accelerometer rate to 1600Hz
  BMI160.setAccelerometerRate(1600);

  Serial.println("Initializing IMU device...done.");

  uint16_t AccRate = BMI160.getAccelerometerRate();
  Serial.print("AccRate: ");
  Serial.println(AccRate, DEC);

  uint8_t AccRange = BMI160.getAccelerometerRange();
  Serial.print("AccRange: ");
  Serial.println(AccRange, DEC);
  chrono = micros();

}

void loop() {

  int axRaw, ayRaw, azRaw;   
  if (micros()-chrono>periode) {
    chrono = micros();

    // read raw gyro measurements from device
    BMI160.readAccelerometer(axRaw, ayRaw, azRaw);

    Serial.print(chrono);
    Serial.print("\t");
    Serial.print(axRaw);
    Serial.print("\t");
    Serial.print(ayRaw);
    Serial.print("\t");
    Serial.println(azRaw);
  }
}

J'ai ajoute l'affichage du chrono afin de voir si l'affichage n'est pas trop long pour ta période...

fdufnews:
Ahah!!

for (int i = 1 ; i <= 1000000 ; i++) {

int = une variable qui peut aller de -32768 à 32767 donc fatalement, ça ne va pas coller avec les bornes que tu entres.

en pratique le compilateur va se rendre compte que un int sera toujours inférieur à 1 million et donc
Vous aurez un warning dans la console à la compilation si vous les avez activés:

** **.../sketch_feb17a.ino: In function 'void setup()': .../sketch_feb17a.ino:3:22: warning: comparison is always true due to limited range of data type [-Wtype-limits]   for (int i = 1 ; i <= 1000000 ; i++)  {                    ~~^~~~~~~~~~** **

Puis le compilateur ne va pas se laisser abattre, il va virer la boucle pour la remplacer par un while(true) et comme il n'a plus d'indice, il prendra sans doute un long pour i même si vous aviez dit int...

vous pouvez tester ce code sur un UNO par exemple

void setup() {
  Serial.begin(2000000);
  for (int i = 1 ; i <= 100000 ; i++)  {
    Serial.println(i);
  }
  Serial.println("FIN");
}

void loop() {}

et vous verrez que l'affichage de i fonctionne et grandit très loin mais qu'il ne s'arrête pas à 100000

--> leur code tel qu'il est va fonctionner dans une boucle infinie, mais c'est en gros ce qu'ils voulaient faire :slight_smile: (sans le savoir)

Pour le timing Il faudrait voir combien de temps prends BMI160.readAccelerometer() pour voir si c'est compatible avec les 1600Hz (et le reste du code mange aussi un peu de temps)

lesept:
Pour mesurer ce temps, il faut créer une variable qui va servir de chrono :

unsigned long chrono = 0;

puis l'initialiser dans le setup et la lire régulièrement : lorsqu'elle atteindra la valeur de la période, tu lances l'acquisition.
...

il ne faudrait pas faire chrono = micros(); sinon si on prend du retard on ne le rattrape pas, il vaut mieux faire chrono += periode;

par exemple période = 625

chrono = 0
à t = 628 on déclenche (micros a une résolution de 4µs)
si on met chono à micros() -> on a chrono = 628 et on demandera de déclencher à 1 253 (et ça se fera à 1 256)
si on met chrono += 625 -> on a chrono = 625 et donc on demander de déclencher à 1 250, qui est ce qu'on veut

en plus si par hasard un traitement prend du retard mais qu'en moyenne on tient la cadence, alors ça permet de gommer ce retard

Bien vu !

ça sent le TP..... et la poubelle....

Tic tac

Tic tac

Tic tac....

Bonjour,

Merci de vos réponses. J'avoue ne pas tout comprendre mais après test je n'ai remarqué aucun changement.
Peut on se baser sur l'horodatage du moniteur série?
Je remarque aussi que dans le moniteur série les microsecondes ne sont pas répétables.
C'est à dire que je n'ai pas une valeur tous les 625 microsecondes ce qui devrait correspondre à un point toutes les millisecondes alors qu'à la même millisecondes j'ai plusieurs points.

Merci lesept mais je n'arrive pas à comprendre les modofications apportées par J-M-L.
En effet ayant tenté de faire la fonction chrono += periode je n'ai vu aucun effet.
Ce qui ne correspond pas du tout à la valeur des 1600hz et encore moins à un rafraichissement des données toutes les 625 microsecondes dans la deuxième colonne.
Pire c'est irrégulier et ayant baissé la fréquence du capteur sur BMI160.setAccelerometerRate au minimum, je ne vois aucun changement dans l'actualisation de mes résultats

Voici le programme comme il est actuellement repris de lesept et ce que cela me donne dans le moniteur :

#include <BMI160Gen.h>
unsigned long chrono = 0;
unsigned long periode = 625ul;

void setup() {
Serial.begin(115200); // initialize Serial communication
while (!Serial);    // wait for the serial port to open

// initialize device
Serial.println("Initializing IMU device...");
//BMI160.begin(BMI160GenClass::SPI_MODE, /* SS pin# = */10);
BMI160.begin(BMI160GenClass::I2C_MODE);
uint8_t dev_id = BMI160.getDeviceID();
Serial.print("DEVICE ID: ");
Serial.println(dev_id, HEX);

// Set the accelerometer rate to 1600Hz
BMI160.setAccelerometerRate(1600);

Serial.println("Initializing IMU device...done.");

uint16_t AccRate = BMI160.getAccelerometerRate();
Serial.print("AccRate: ");
Serial.println(AccRate, DEC);

uint8_t AccRange = BMI160.getAccelerometerRange();
Serial.print("AccRange: ");
Serial.println(AccRange, DEC);
//chrono += periode;
chrono = micros();
}
void loop() {


int axRaw, ayRaw, azRaw;
if ((micros() - chrono) > periode) {
//    chrono = micros();
chrono += periode;
// read raw gyro measurements from device
BMI160.readAccelerometer(axRaw, ayRaw, azRaw);

Serial.print("\t");
Serial.print(chrono);
Serial.print("\t");
Serial.print(axRaw);
Serial.print("\t");
Serial.print(ayRaw);
Serial.print("\t");
Serial.println(azRaw);
}
}
[code]

Le moniteur série me donne ceci : 

11:42:49.684 -> 2462087 -1304 -2348 -15997
11:42:49.684 -> 169462712 -1280 -2338 -16093
11:42:49.684 -> 169463337 -1280 -2338 -16093
11:42:49.684 -> 169463962 -1280 -2338 -16093
997
11:42:49.684 -> 169462087 -1304 -2348 -15997
11:42:49.684 -> 169462712 -1280 -2338 -16093
11:42:49.684 -> 169463337 -1280 -2338 -16093
11:42:49.684 -> 169463962 -1280 -2338 -16093
11:42:49.684 -> 1N⸮S⸮Initializing IMU device...
11:42:50.669 -> DEVICE ID: D1
11:42:50.669 -> Initializing IMU device...done.
11:42:50.669 -> AccRate: 100
11:42:50.669 -> AccRange: 2
11:42:50.669 -> 93337 -1328 -2328 -15954
11:42:50.669 -> 93962 -1328 -2328 -15954
11:42:50.703 -> 94587 -1328 -2328 -15954
11:42:50.703 -> 95212 -1321 -2356 -16010
11:42:50.703 -> 95837 -1321 -2356 -16010
11:42:50.703 -> 96462 -1321 -2356 -16010
11:42:50.703 -> 97087 -1321 -2356 -16010
11:42:50.703 -> 97712 -1321 -2356 -16010
11:42:50.703 -> 98337 -1293 -2359 -15988
11:42:50.703 -> 98962 -1293 -2359 -15988
11:42:50.703 -> 99587 -1293 -2359 -15988
11:42:50.703 -> 100212 -1293 -2359 -15988
11:42:50.703 -> 100837 -1262 -2329 -15998

[/code]

D'abord, édite tes deux messages pour mettre tes codes entre balises "CODE" (c'est le bouton </> dans l'éditeur de message), sinon cette discussion va finir à la poubelle et tout le monde aura perdu son temps.

Pour éditer un message, c'est comme ça :
Image1.jpg

Ensuite tu sélectionnes ton code et tu cliques sur </>

Sinon, tu as bien un rafraîchissement toutes les 625 ms : le temps est dans la première colonne. Si j'en prends deux consécutifs au hasard

11:42:50.737 -> 103337 -1258 -2316 -16044
11:42:50.737 -> 103962 -1258 -2316 -16044

103962 - 103337 = 625

Pire c'est irrégulier et ayant baissé la fréquence du capteur sur BMI160.setAccelerometerRate au minimum, je ne vois aucun changement dans l'actualisation de mes résultats

Qu'est-ce qui est irrégulier ? Les valeurs d'accélération changent mais assez peu : entre 1258 et 1328 en X soit 5.5%. C'est plutôt correct, non ?

Image1.jpg

Merci j'ai refais un peu de propre dans mon post désolé je suis novice ici du coup je ne savais pas comment bien éditer. J'ai rédité du coup mais entre temps malheureusement j'ai supprimé une partie des données moniteur.

Mais du coup je faisais la différence avec l'horodatage qui par exemple à la même millisecondes me donne plusieurs valeurs alors qu'entre temps je suis passé à 0,625us+0,625us ainsi de suite.
L'horodatage moniteur est elle valable pour mesurer le temps d'acquisition en parallèle?

Je reprends un autre exemple pour mieux m'expliquer

Moniteur série

15:02:40.323 ->
15:02:40.323 -> 6
15:02:40.323 -> 383148337 -1838 -1908 -16007
15:02:40.323 -> 383148962 -1838 -1908 -16007
15:02:40.323 -> 383149587 -1838 -19J-1⸮Initializing IMU device...
15:02:41.306 -> DEVICE ID: D1
15:02:41.306 -> Initializing IMU device...done.
15:02:41.306 -> AccRate: 100
15:02:41.340 -> AccRange: 2
15:02:41.340 -> 93337 -1850 -1941 -16016
15:02:41.340 -> 93962 -1850 -1941 -16016
15:02:41.340 -> 94587 -1850 -1941 -16016
15:02:41.340 -> 95212 -1856 -1932 -15983
15:02:41.340 -> 95837 -1856 -1932 -15983
15:02:41.340 -> 96462 -1856 -1932 -15983
15:02:41.340 -> 97087 -1856 -1932 -15983
15:02:41.340 -> 97712 -1856 -1932 -15983
15:02:41.340 -> 98337 -1821 -1958 -15989
15:02:41.340 -> 98962 -1821 -1958 -15989
15:02:41.340 -> 99587 -1821 -1958 -15989
15:02:41.340 -> 100212 -1821 -1958 -15989
15:02:41.340 -> 100837 -1888 -1942 -16022
15:02:41.340 -> 101462 -1888 -1942 -16022
15:02:41.340 -> 102087 -1888 -1942 -16022
15:02:41.340 -> 102712 -1888 -1942 -16022
15:02:41.374 -> 103337 -1889 -1939 -15979
15:02:41.374 -> 103962 -1889 -1939 -15979
15:02:41.374 -> 104587 -1889 -1939 -15979
15:02:41.374 -> 105212 -1889 -1939 -15979
15:02:41.374 -> 105837 -1889 -1939 -15979
15:02:41.374 -> 106462 -1864 -1926 -16025
15:02:41.374 -> 107087 -1864 -1926 -16025
15:02:41.374 -> 107712 -1864 -1926 -16025
15:02:41.374 -> 108337 -1864 -1926 -16025
15:02:41.374 -> 108962 -1829 -1931 -15991
15:02:41.374 -> 109587 -1829 -1931 -15991
15:02:41.374 -> 110212 -1829 -1931 -15991
15:02:41.374 -> 110837 -1829 -1931 -15991
15:02:41.408 -> 111462 -1834 -1940 -15966
15:02:41.408 -> 112087 -1834 -1940 -15966
15:02:41.408 -> 112712 -1834 -1940 -15966
15:02:41.408 -> 113337 -1834 -1940 -15966
15:02:41.408 -> 113962 -1842 -1911 -16001
15:02:41.408 -> 114587 -1842 -1911 -16001
15:02:41.408 -> 115212 -1842 -1911 -16001
15:02:41.408 -> 115837 -1842 -1911 -16001
15:02:41.408 -> 116462 -1852 -1920 -16048
15:02:41.408 -> 117087 -1852 -1920 -16048
15:02:41.408 -> 117712 -1852 -1920 -16048
15:02:41.408 -> 118337 -1852 -1920 -16048
15:02:41.408 -> 118962 -1852 -1920 -16048
15:02:41.408 -> 119587 -1871 -1936 -16031
15:02:41.442 -> 120212 -1871 -1936 -16031
15:02:41.442 -> 120837 -1871 -1936 -16031
15:02:41.442 -> 121462 -1871 -1936 -16031
15:02:41.442 -> 122087 -1842 -1897 -15965
15:02:41.442 -> 122712 -1842 -1897 -15965
15:02:41.442 -> 123337 -1842 -1897 -15965
15:02:41.442 -> 123962 -1842 -1897 -15965
15:02:41.442 -> 124587 -1843 -1944 -16001
15:02:41.442 -> 125212 -1843 -1944 -16001
15:02:41.442 -> 125837 -1843 -1944 -16001
15:02:41.442 -> 126462 -1843 -1944 -16001
15:02:41.442 -> 127087 -1846 -1942 -15989
15:02:41.442 -> 127712 -1846 -1942 -15989
15:02:41.442 -> 128337 -1846 -1942 -15989
15:02:41.442 -> 128962 -1846 -1942 -15989
15:02:41.442 -> 129587 -1846 -1942 -15989
15:02:41.476 -> 130212 -1855 -1939 -15960
15:02:41.476 -> 130837 -1855 -1939 -15960
15:02:41.476 -> 131462 -1855 -1939 -15960
15:02:41.476 -> 132087 -1855 -1939 -15960
15:02:41.476 -> 132712 -1867 -1934 -15988
15:02:41.476 -> 133337 -1867 -1934 -15988
15:02:41.476 -> 133962 -1867 -1934 -15988
15:02:41.476 -> 134587 -1867 -1934 -15988
15:02:41.476 -> 135212 -1893 -1938 -15985
15:02:41.476 -> 135837 -1893 -1938 -15985
15:02:41.476 -> 136462 -1893 -1938 -15985
15:02:41.476 -> 137087 -1893 -1938 -15985
15:02:41.476 -> 137712 -1852 -1938 -15994
15:02:41.510 -> 138337 -1852 -1938 -15994
15:02:41.510 -> 138962 -1852 -1938 -15994
15:02:41.510 -> 139587 -1852 -1938 -15994
15:02:41.510 -> 140212 -1823 -1929 -16015
15:02:41.510 -> 140837 -1823 -1929 -16015
15:02:41.510 -> 141462 -1823 -1929 -16015
15:02:41.510 -> 142087 -1823 -1929 -16015
15:02:41.510 -> 142712 -1823 -1929 -16015
15:02:41.510 -> 143337 -1868 -1951 -16012
15:02:41.510 -> 143962 -1868 -1951 -16012
15:02:41.510 -> 144587 -1868 -1951 -16012
15:02:41.510 -> 145212 -1868 -1951 -16012
15:02:41.510 -> 145837 -1849 -1940 -16009
15:02:41.510 -> 146462 -1849 -1940 -16009
15:02:41.544 -> 147087 -1849 -1940 -16009
15:02:41.544 -> 147712 -1849 -1940 -16009
15:02:41.544 -> 148337 -1862 -1922 -16006
15:02:41.544 -> 148962 -1862 -1922 -16006
15:02:41.544 -> 149587 -1862 -1922 -16006
15:02:41.544 -> 150212 -1862 -1922 -16006
15:02:41.544 -> 150837 -1865 -1925 -16011
15:02:41.544 -> 151462 -1865 -1925 -16011
15:02:41.544 -> 152087 -1865 -1925 -16011
15:02:41.544 -> 152712 -1865 -1925 -16011
15:02:41.544 -> 153337 -1864 -1938 -16005
15:02:41.544 -> 153962 -1864 -1938 -16005
15:02:41.544 -> 154587 -1864 -1938 -16005
15:02:41.544 -> 155212 -1864 -1938 -16005
15:02:41.544 -> 155837 -1864 -1938 -16005
15:02:41.544 -> 156462 -1869 -1925 -15983
15:02:41.578 -> 157087 -1869 -1925 -15983
15:02:41.578 -> 157712 -1869 -1925 -15983
15:02:41.578 -> 158337 -1869 -1925 -15983

On voit par exemple que le temps qui s'écoule en microsecondes ramené aux milisecondes sur la case horodatage tout à gauche ne colle pas quand on additionne toutes les microsecondes.
Y a t'il un lien entre cet timing et celui de l'enregistrement des données propre au moniteur.
Je veux savoir en gros si je suis sûr d'acquérir tous les 625 microsecondes une valeur

Ce qui est important est l'exécution du programme. Par exemple dans cette ligne (prise au hasard) :

15:02:41.510 -> 138337 -1852 -1938 -15994

Le chiffre 138337 est le nombre de µs écoulées depuis le lancement du code, tel que mesuré par le microprocesseur.

  • La ligne précédente donnait 132712 soit un écart de 138337 - 132712 = 625 µs
  • La ligne suivante donne 138962 soit aussi un écart de 625 µs
    Du point de vue du microprocesseur, tout est bon, tu as bien une mesure toutes les 625 µs.

L'horodatage est fait par l'IDE. "15:02:41.510" correspond à l'heure de ton PC : quinze heures, deux minutes et quarante et une secondes, avec des millièmes de secondes dont je ne sais pas vraiment à quoi ils correspondent. Probablement une information plus précise de l'horloge interne du PC. Mais Windows n'est pas un OS temps réel, donc je ne me prononcerais pas sur la précision à ce niveau là.

L'unité d'affichage de l'horodatage est la ms visiblement, donc tu peux avoir deux mesures et affichages pendant que cette valeur de change pas. Mais les valeurs d'horodatage semblent sauter des pas, on dirait qu'elles sont remises à jour avec une "périodicité" variable (!) de près de 35 ms.

Donc, ne te base pas sur l'horodatage, tu peux même ne pas l'afficher (case à décocher en bas de la fenêtre) comme ça tu ne te poseras plus la question.

Je veux savoir en gros si je suis sûr d'acquérir tous les 625 microsecondes une valeur

Oui, en ce qui concerne l'horloge du microprocesseur et sa précision.