Arduino freezes in while loop

Hey everyone!

I have problem with my arduino (Sparkfun pro micro 5v) freezing.

#include <Arduino.h>
#include <SPI.h>
#include <SD.h>
#include "gyro.h"
#include "CustomI2C.h"

#define SD_CS 10
#define GYRO_ADDRESS 0x6B
#define SAMPLE_SIZE 100

Gyro gyro;
Quaternion attitudeQuaternion = Quaternion(1,0,0,0);
long looptimer;

void setup() {
    Serial.begin(9600);
    while(!Serial);
    SD.begin(SD_CS);
    CustomI2C::init();
    gyro.init(GYRO_ADDRESS, SAMPLE_SIZE);
    looptimer = micros();
}

void loop() {
  Serial.println("A");
  Quaternion updateQuaternion = gyro.getAngles();
  Serial.println();
  Serial.println("B");
  attitudeQuaternion.rotate(updateQuaternion);
  attitudeQuaternion.getEulerAngles();

  while(looptimer + 5263 > micros())
    Serial.println("Wait");
  Serial.println("continue");
  looptimer += 5263;
}

the loop gets completed several times but then after a few seconds the Arduino freezes.
The last bit of output is:

Wait
Wait
Wait
Wait
Wait
Wait
Wait

So the while loop is not exited.

I am using platformIO on Atom for programming.

Thank you for your help in advance as always (=

Printing the value of looptimer and micros() inside the loop might be helpful?

MK1888:
Printing the value of looptimer and micros() inside the loop might be helpful?

Yeah you are right:

  while(looptimer + 5263 > micros()) {
    Serial.print("looptimer: ");
    Serial.println(looptimer);
    Serial.print("micros(): ");
    Serial.println(micros());
  }

Output:

looptimer: 9591068
micros(): 9595244
looptimer: 9591068
micros():

so micros() seems to cause the freeze. Any idea?

Have a look at how millis() is used to manage timing in Several things at a time. You can use the same technique with micros().

…R

You should declare ‘looptimer’ as ‘unsigned long’ so you don’t run into trouble when it overflows into negative numbers in about 36 minutes.

You should use (currentTime - pastTime < interval) instead of (pastTime + interval > currentTime) so you don’t get into trouble every 72 minutes when micros() overflows from very large numbers to very small numbers.

Robin2:
Have a look at how millis() is used to manage timing in Several things at a time. You can use the same technique with micros().

…R

Thank you for your reply! But I don’t want to do several things at once… I just need to wait a certain time before I grab the new data from the gyro and process it. Should I still do something like:

loop() {
   if(micros() - lastTime < interval) {
      //do my stuff
      lastTime = micros();
   }

}

but isn’t that basically the same?

johnwasser:
You should declare ‘looptimer’ as ‘unsigned long’ so you don’t run into trouble when it overflows into negative numbers in about 36 minutes.

You should use (currentTime - pastTime < interval) instead of (pastTime + interval > currentTime) so you don’t get into trouble every 72 minutes when micros() overflows from very large numbers to very small numbers.

Thank you for your help as well! I will make those changes. However, the Arduino freezes in a matter of seconds so that is not the solution to my problem.

MarkGoingToSpace:
but isn't that basically the same?

Mathematically, yes. Unfortunately for us, computer variables can't count to infinity in both directions.

johnwasser:
Mathematically, yes. Unfortunately for us, computer variables can't count to infinity in both directions.

johnwasser:
Mathematically, yes. Unfortunately for us, computer variables can't count to infinity in both directions.

Haha I know that. That was in response to Robin2's answer.

MarkGoingToSpace:
but isn’t that basically the same?

Not if it works. :slight_smile:

Post your complete program using the subtraction technique.

…R

Ups… I messed up. I tested some more and realized that my “waiting loop” works just fine if the loop() is otherwise empty. I think the Arduino is running out of memory and that calling micros() is just the straw that breaks the camel’s back.

So I looked into it and found out that attitudeQuaternion.getEulerAngles(); is the culprit. (Yes, Yes I know - another reminder that I should post the entire code not just the pieces that I deem relevant.)

I wanted the function to return the euler angles as an array. But since c++ dosen’t support returning arrays directly I googled and found a workaround with a pointer:

double *Quaternion::getEulerAngles() {
  double *arr= new double[3];
  arr[0] = atan2(2*(a*b + c*d), 1-2*(b*b + c*c)) * 180 / PI;
  arr[1] = asin(2*(a*c - d*b)) * 180 / PI;
  arr[2] = atan2(2*(a*d + b*c), 1-2*(c*c + d*d)) * 180 / PI;

  for(int i=0; i<3; i++) {
    Serial.print(arr[i]);
    Serial.print(" \t");
  }
  Serial.println();

  return arr;
}

Apparently this doesn’t work out to well… Ironically I ended up not even catching that returned array. Funny isn’t it? bangs head against keyboard

Can you please explain to me what this code does exactly? Is a new array created whenever I call that function and is never deleted? Then I would understand why I ran into problems. Furthermore, how can I return an array from an function without having the same issue?

Sorry I wasted your time with the wrong question…

Moderator edit: Mind your language

MarkGoingToSpace:
Is a new array created whenever I call that function and is never deleted?

Yes. When you allocate memory it is up to you to release it when you are done with it.

MarkGoingToSpace:
how can I return an array from an function without having the same issue?

I would create a structure containing the three angles and have the function take a reference to that structure. The function can then fill in the values.