Sensordaten 5 sekunden lang auslesen und in Array speichern

Hi,

benutze den Arduino Fio und den Sensor LSM9DSO https://learn.adafruit.com/adafruit-lsm9ds0-accelerometer-gyro-magnetometer-9-dof-breakouts/wiring-and-test.

Benutze auch den Testsketch, der auf der Seite angeboten wird, um die Daten des Sensors auszulesen.

Nun habe ich diesen Sketch etwas versucht zu modifizieren, da ich die 5 sekunden lang den Sensor auslesen will und diese im Array speichern will. Nun habe ich gesagt, dass ich jede 100ms ihn auslesen will, müsste 50mal ausführen, damit ich 5 sekunden daten hätte.
Habe dies anhand einer For-Schleife realisiert, doch es sind mehr als 5sekunden bis er alle werte hat woran kann das liegen?

Hier nochmal die Funktion, die ich geschrieben habe:

void secBuffer()
{
  //for loop, 50 because every 100ms I read so in 1sek = 10 values --> 10Values*100ms
  // save 5secondes to analyse if static or dynamic + these data is needed to analyse in the 3.Phase 
  //if lying position intentional or not
  for (int count = 0; count < 50; count++)
  {
    /* Get a new sensor event */ 
    /*These events should be called in the for-loop*/
    /*so that u have every 100ms/every measurement actual data*/
    sensors_event_t accel, mag, gyro, temp;

    lsm.getEvent(&accel, &mag, &gyro, &temp); 
    // -y = g
     /*Problem: When y = g(9,81m/s²) sensor has value > 9.81 so calibration
     to 9.81m/s² & other axis to 0.00m/s² -> y shos down -> -9.81
     y < 0 && abs(y) > 9.81 is for -y = g
     abs(..) means -> when u have a value like -x = | x | Betragszeichen */
      if (accel.acceleration.y < 0 && abs(accel.acceleration.y) > 9.81)
      {
        accel.acceleration.y = 9.81 * (-1); // *(-1) to have negative value because z shows down
        accel.acceleration.x = 0.00;
        accel.acceleration.z = 0.00;
      }
       // y=g
       /*Problem: When y = g(9.81m/s²) sensor has value > 9.81 so calibration
        y > 0 && abs(y) > 9.81 is for y = g --> y shows up -> 9.81 m/s² */
       //abs(..) means -> when u have a value like -x = | x | Betragszeichen */
       if(accel.acceleration.y > 0 && abs(accel.acceleration.y) > 9.81)
       {
         accel.acceleration.y = 9.81;
         accel.acceleration.x = 0.00;
         accel.acceleration.z = 0.00;
       }  
       /*-----------------------Calibration of z axis------------------------*/
       // -z = g
       /*Problem: When z = g(9.81m/s²) sensor has value > 9.81 so calibration
       y < 0 && abs(y) > 9.81 is for -z = g --> y shows down -> -9.81 m/s² */
       //abs(..) means -> when u have a value like -x = | x | Betragszeichen */
       if (accel.acceleration.z < 0 && abs(accel.acceleration.z) > 9.81)
       {
         accel.acceleration.z = 9.81 * (-1);
         accel.acceleration.x = 0.00;
         accel.acceleration.y = 0.00;
       }
     
       // z = g
       /*Problem: When z = g(9.81m/s²) sensor has value > 9.81 or <> 9.81 so calibration
       z > 0 && abs(z) >= 9.7 is for z = g --> z shows up -> -9.81 m/s² */
       /*Here maybe no calibration because i have values for x around 9.7, 9.82!!!*/
       //abs(..) means -> when u have a value like -x = | x | Betragszeichen */
       if(accel.acceleration.z > 0 && abs(accel.acceleration.z) >= 9.7)
       {
         accel.acceleration.z = 9.81;
         accel.acceleration.x = 0.00;
         accel.acceleration.y = 0.00;
       }
       /*-----------------------Calibration of x axis------------------------*/
       // -x = g;
       /*Problem: When x = g(9.81m/s²) sensor has value > 9.81 so calibration
        x < 0 && abs(x) > 9.81 is for -x = g --> x shows down -> -9.81 m/s² */
        //abs(..) means -> when u have a value like -x = | x | Betragszeichen */
       if(accel.acceleration.x < 0 && abs(accel.acceleration.x) > 9.81)
       {
         accel.acceleration.x = 9.81 * (-1);
         accel.acceleration.y = 0.00;
         accel.acceleration.z = 0.00;
       }
       //x=g 
       /* when x = g(9,81 m/s²) has value > 9.81 so calibration
       x > 0 && abs(x) > 9.81 is for x = g --> x shows up -> 9.81 m/s² */
       //abs(..) means -> when u have a value like -x = | x | Betragszeichen */
       if(accel.acceleration.x > 0 && abs(accel.acceleration.x) >=9.4)
       {
         accel.acceleration.x = 9.81;
         accel.acceleration.y = 0.00;
         accel.acceleration.z = 0.00;
       }   
     
       /*Output of Axis-Values*/
       Serial.println("Accel: x,y,z");
       Serial.print(accel.acceleration.x); 
       Serial.print(";"); 
       Serial.print(accel.acceleration.y);      
       Serial.print(";"); 
       Serial.println(accel.acceleration.z);
       Serial.print("\r\n");
       Serial.println("Gyro: x,y,z");
       Serial.print(gyro.gyro.x);
       Serial.print(";");
       Serial.print(gyro.gyro.y);
       Serial.print(";");
       Serial.println(gyro.gyro.z);
       Serial.println("------------------------");
       /*--------Vektormagnitude in Array (Accel+Gyro)--------------*/
       //Array Accelerometer
       MagAccel_A[count]= sqrt(pow(accel.acceleration.x,2)+pow(accel.acceleration.y,2)+pow(accel.acceleration.z,2));
       Serial.println("Magnitude Accelerometer");
       Serial.println(MagAccel_A[count]);  
       Serial.print("\r\n");
       //Array Gyroscope  ---> sqrt = Wurzel , pow(zahl, potenz)
       MagGyro_A[count] = sqrt(pow(gyro.gyro.x,2)+pow(gyro.gyro.y,2)+pow(gyro.gyro.z,2));  
       Serial.println("Magnitude Gyroscope");
       Serial.println(MagGyro_A[count]);
       Serial.println("------------------------");
       
       delay(100);
  }
  Serial.println("5sekunden vorbei");
}

Kann mir da jemand helfen, woran das liegt?

Hallo,

wenn du nur delay(100) alleine 50x aufrufst, dann kommste bestimmt ziemlich nah an die gewünschten 5sec. ran. Du machst aber noch viel mehr. Serialausgaben braucht auch viel Zeit, aus µC Sicht gesehen.

Wenn Du statt delay mit millis() aller 100ms die Funktion aufrufst, kommste sicherlich genau und unabhängig von allem anderen auf 5sec.

Oder du reduzierst die 100 in delay() bis es paßt.

Da wird einiges an Overhead durch die Funktions-Aufrufe, Rechnungen und Serial-Ausgaben drin sein. Vielleicht mal die Baudrate hochsetzen. Bei 9600 Baud dauert ein Zeichen 1ms. Da kann schon mal schnell der Ausgangspuffer voll sein wenn man sehr schnell viel schreibt. Und dann wird erst mal blockiert.

Wenn dir die Zeit wichtig ist, frage mit millis() ab wie viel Zeit vergangen ist. Oder überlege dir ob die 5 Sekunden wirklich so wichtig sind, oder ob du es nicht auch solange machen kannst wie die 50 Durchläufe halt dauern.

Hi danke für die schnellen Antworten,

also mir wäre Wichtig, dass ich 5 sekunden daten in dem Array hättwe, um bestimmte Enscheidungen zu treffen.
D.h. ich müsste 5 sekunden daten in einem Buffer speichern und mit diesen 5 sekunden daten rechnen, um bestimmte Entscheidungen durchzuführen.

Frage: Gibt es vllt eine bessere Lösung?

Ist millis genauer als delay?

Danke sehr

milito:
Kann mir da jemand helfen, woran das liegt?

Tja, Du machst einerseits:

for (int count = 0; count < 50; count++)
  {
    // einen Haufen voll Plumpatsch
    // und dann noch   
       delay(100);
  }

Nach Adam Riese macht das 50*100ms = 5000ms.

Plus 50 mal den ganzen Plumpatsch in der Schleife noch obendrauf.

So what?

Deine fünf Sekunden kommen am Ende genau so unsauber raus wie Du sie programmiert hast.

Ok, die Kalibrierung muss ich während dem Auslesen machen anders geht es leider nicht? Oder was meisnt du?

millis() zeigt dir auf ein paar ms genau an wie viel Zeit vergangen ist:

unsigned long startTime = millis();
int count;

for (count = 0; count < 50; count++)
{
   //hier was tun

   if (millis() - startTime > 5000)
     break; 
}

Die Abfrage am Ende bricht die for-Schleife ab wenn 5 Sekunden vorbei sind. Und wenn count wie hier außerhalb deklariert ist, weißt du am Ende auch wie viele Einträge gemacht wurden

Danke sehr :slight_smile:
Werde es probieren !!!

milito:
Ok, die Kalibrierung muss ich während dem Auslesen machen anders geht es leider nicht? Oder was meisnt du?

Vielleicht versuchst Du mal sowas:

  int loopsToGo=50;
  unsigned long lastLoopStart=-100;
  while (loopsToGo>0)
  {
    if (millis()-lastLoopStart>=100)
    {
       loopsToGo--;
       lastLoopStart+=100;
      // einen Haufen voll Plumpatsch
    }
  }

Danke jurs und danke an Serenifly,

werde es versuchen, zu deinem Tipp jurs habe ich eine Frage und zwar: dein Ansatz is mir leider noch nicht klar, warum die -100 und die 50 und das kombiniert mit einer while schleife ?

milito:
Danke jurs und danke an Serenifly,

werde es versuchen, zu deinem Tipp jurs habe ich eine Frage und zwar: dein Ansatz is mir leider noch nicht klar, warum die -100 und die 50 und das kombiniert mit einer while schleife ?

Die -100 sind Millisekunden und verlegen die Startzeit in die Vergangenheit, so dass beim Eintritt in die Schleife sofort die Bedingung erfüllt ist, der Schleifenzähler 1 runterzählt und der Plumpatsch ausgeführt wird. Bei 50 Schleifendurchläufen tritt dadurch 49 mal der Timeout auf, so dass die Schleife insgesamt 49100 Millisekunden dauert plus einmal die Dauer für die Ausführung des Plumpatsch. Wenn die Dauer 50100 Millisekunden plus die einmal die Dauer des Plumpatsch betragen soll, initialisiere auf 0.

Die 50 sind der Schleifenzähler.

HI so habe es aussprobiert. Bei dem Lösungsansatz von Serenifly passt es mit den 5 sekunden soweit. HAbe mir den schleifenzähler nach den 5 sekunden ausgeben lassen und bekomme 53 , wie kann das sein?

Eigentlich gar nicht. Die for-Schleife sollte maximal von 0-49 laufen.

Das habe ich von 0-49 und wenn ich mir dne counter ausgeben lasse kommt 53.

HIer der Code:

void buffer()
{

unsigned long startTime = millis();
int count;

for (count = 0; count < 49; count++)
{
   sensors_event_t accel, mag, gyro, temp;

  lsm.getEvent(&accel, &mag, &gyro, &temp); 
  // -y = g
   /*Problem: When y = g(9,81m/s²) sensor has value > 9.81 so calibration
   to 9.81m/s² & other axis to 0.00m/s² -> y shos down -> -9.81
   y < 0 && abs(y) > 9.81 is for -y = g
   abs(..) means -> when u have a value like -x = | x | Betragszeichen */
    if (accel.acceleration.y < 0 && abs(accel.acceleration.y) > 9.81)
    {
      accel.acceleration.y = 9.81 * (-1); // *(-1) to have negative value because z shows down
      accel.acceleration.x = 0.00;
      accel.acceleration.z = 0.00;
    }
     // y=g
     /*Problem: When y = g(9.81m/s²) sensor has value > 9.81 so calibration
      y > 0 && abs(y) > 9.81 is for y = g --> y shows up -> 9.81 m/s² */
     //abs(..) means -> when u have a value like -x = | x | Betragszeichen */
     if(accel.acceleration.y > 0 && abs(accel.acceleration.y) > 9.81)
     {
      accel.acceleration.y = 9.81;
      accel.acceleration.x = 0.00;
      accel.acceleration.z = 0.00;
     }  
 /*-----------------------Calibration of z axis------------------------*/
     // -z = g
     /*Problem: When z = g(9.81m/s²) sensor has value > 9.81 so calibration
     y < 0 && abs(y) > 9.81 is for -z = g --> y shows down -> -9.81 m/s² */
     //abs(..) means -> when u have a value like -x = | x | Betragszeichen */
     if (accel.acceleration.z < 0 && abs(accel.acceleration.z) > 9.81)
     {
       accel.acceleration.z = 9.81 * (-1);
       accel.acceleration.x = 0.00;
       accel.acceleration.y = 0.00;
     }
     
     // z = g
     /*Problem: When z = g(9.81m/s²) sensor has value > 9.81 or <> 9.81 so calibration
     z > 0 && abs(z) >= 9.7 is for z = g --> z shows up -> -9.81 m/s² */
     /*Here maybe no calibration because i have values for x around 9.7, 9.82!!!*/
     //abs(..) means -> when u have a value like -x = | x | Betragszeichen */
     if(accel.acceleration.z > 0 && abs(accel.acceleration.z) >= 9.7)
     {
       accel.acceleration.z = 9.81;
       accel.acceleration.x = 0.00;
       accel.acceleration.y = 0.00;
     }
     /*-----------------------Calibration of x axis------------------------*/
     // -x = g;
     /*Problem: When x = g(9.81m/s²) sensor has value > 9.81 so calibration
      x < 0 && abs(x) > 9.81 is for -x = g --> x shows down -> -9.81 m/s² */
      //abs(..) means -> when u have a value like -x = | x | Betragszeichen */
     if(accel.acceleration.x < 0 && abs(accel.acceleration.x) > 9.81)
     {
       accel.acceleration.x = 9.81 * (-1);
       accel.acceleration.y = 0.00;
       accel.acceleration.z = 0.00;
     }
     //x=g 
     /* when x = g(9,81 m/s²) has value > 9.81 so calibration
     x > 0 && abs(x) > 9.81 is for x = g --> x shows up -> 9.81 m/s² */
     //abs(..) means -> when u have a value like -x = | x | Betragszeichen */
     if(accel.acceleration.x > 0 && abs(accel.acceleration.x) >=9.4)
     {
       accel.acceleration.x = 9.81;
       accel.acceleration.y = 0.00;
       accel.acceleration.z = 0.00;
     }   
     
     /*Output of Axis-Values*/
     /*
     Serial.println("Accel: x,y,z");
     Serial.print(accel.acceleration.x); 
     Serial.print(";"); 
     Serial.print(accel.acceleration.y);      
     Serial.print(";"); 
     Serial.println(accel.acceleration.z);
     Serial.print("\r\n");
     Serial.println("Gyro: x,y,z");
     Serial.print(gyro.gyro.x);
     Serial.print(";");
     Serial.print(gyro.gyro.y);
     Serial.print(";");
     Serial.println(gyro.gyro.z);
     Serial.println("------------------------");
     */
      /*--------Vektormagnitude in Array (Accel+Gyro)--------------*/
        //Array Accelerometer
        MagAccel_A[count]= sqrt(pow(accel.acceleration.x,2)+pow(accel.acceleration.y,2)+pow(accel.acceleration.z,2));
        Serial.println("Magnitude Accelerometer");
        Serial.println(MagAccel_A[count]);  
        Serial.print("\r\n");
        //Array Gyroscope  ---> sqrt = Wurzel , pow(zahl, potenz)
        MagGyro_A[count] = sqrt(pow(gyro.gyro.x,2)+pow(gyro.gyro.y,2)+pow(gyro.gyro.z,2));  
        Serial.println("Magnitude Gyroscope");
        Serial.println(MagGyro_A[count]);
        Serial.println(count);
        Serial.println("------------------------");

   if (millis() - startTime  > 5000)
   {
     break;
   } 

}
   Serial.print("5sekunden");
   
   StateMachine.Set(STATIC_POS);

}

Kann ich mir nicht erklären sobald ich diese for schleife ausführe ohne den ganzen kram, sondern ur den counter ausgebe geht sie :frowning:

So hab es lösen können, es lag an der abfrage mit den millis. habe mit delay gearbeitet d.h. nach jedem Schleifendurchlauf 100ms warten und siehe counter geht und 5 sekunden habe ich ungefähr auch raus.

Hätte aber trotzdem nicht mehr als 48 sein sollen. Die Idee war entweder das solange zu machen wie die for-Schleife zu Ende ist oder 5 Sekunden vorbei sind. Je nachdem was eher kommt.

Ja das verstehe ich auch nicht, warum es 53 mal. Kann das an den millis liegen, dass diese eventuell nicht genau ist?

So danke nochmals für eure tipps. Kam auf die idee aus Auslesen mit einem Ring buffer zu realisieren, d.h. ich hätte einen double Array[50] und würde die ersten 40 stellen (0-39) vorinitialisieren und dann würde ich gerne den Sensor auslesen für eine Sekunde im takt von 100ms somit 10 Messwerte und würde den rest des Array füllen.
Beim erneuten auslesen, sollen die ältesten Einträge überschrieben werden,

problem ist nur wie ich das mit der ring buffer realiseren kann, habt ihr eine Idee?

const int BUF_SIZE = 50;
double buffer[BUF_SIZE];

void addElement(double element)
{
  static int index;

  buffer[index] = element;
  index = (index + 1) % BUF_SIZE;
}