I2C accelerometer with delay using millis().

Ok, so I connected the GY-521 accelerometer/gyro to my arduino and it works fine by it self, but ofcourse, since it works via I2C putting any kind of delay in the code would result in a FIFO Overflow so i tried making a function that would substitute the delay and read the accelerometer.

I made this

unsigned long mill, mill2;

void loop() {
//do something
mill = millis();
mill2 = millis();
while(mill2 - mill < 1000){
lACC();
mill2 = millis();
}
// do something else
mill = millis();
mill2 = millis();
while(mill2 - mill < 1000){
lACC();
mill2 = millis();
}

note: lACC(); Is a function that reads the port and updates values from the accelerometer

But this doesn't work.
I end up with semi-random delays that don't really work and the code stops fully after 4 or so loops.

Any ideas?
Thanks

Peter

Can't see any delays in that code, it just continually calls IACC() (whatever that is) for 1000ms then continually calls IACC() (whatever that is) for another 1000ms, then repeats.

The full code would help (in code tags) along with an idea of what you want to achieve.

Putting in the full code would be massive since the accelerometer part isn't mine. I got it online, and it works.
anyways, what i want to do is put a wanted delay between two actions.
But if i literally put in delay(1000); the MPU6050 chip sending information to the arduino would overflow because data isn't being read in those 1000ms. I want to avoid that, so i'm trying to read the chip the whole time while other part of the program wait for the "delay" to be done.
That should work, as you described it, but it doesn't.

Could you give a link to that code online ?

Should IACC() be called as often as possible ? and you want other code to run once a second ? Which two actions do you mean ?
The code is probably a derivate from the I2Cdevlib.

This is an example of millis()

unsigned long prevMillis;

void setup()
{
  ...
  // At the end of setup(), set prevMillis
  prevMillis = millis();
}

void loop()
{
  // Do this part as often as possible.
  // Check for Serial.available() and so on.
  ...

  // Do this part once a second
  if( millis() - prevMillis >= 1000)
  {
    prevMillis += 1000;
    Serial.print(".");
  }
}

For the life of me, i can't find the exact link, but it is a I2CDEV Implementation.
I don't want the same action to be repeated.
I'm basically building a robot(on wheels) and what i want to do is to be able to make it for example turn left for one second but while avoiding the i2c overflow. But the thing is i don't want it to just turn left i actually want to program it however i want.
Basically, in short, i'm looking to make a function that would replace the delay command so that it reads the sensor while waiting. I don't know hot to explain it better.

lACC(); needs to be called as much as possible otherwise it will result in an overflow.

TERMINAL:
lACC(); needs to be called as much as possible otherwise it will result in an overflow.

That would be done in the part of what Peter posted above that says
"// Do this part as often as possible."

You want to turn something on, and it should turn off after some delay ?

That needs a flag, or a state machine.
This is one way to do it: you turn it on, set a flag, and timestamp the moment.
The timestamp is : prevMillis = millis();
In the loop() check for that flag, and if it has been set check the : if( millis() - prevMillis >= some_delay)
If the millis() is finally at that moment, reset the flag.

Don't create a variable for the time in the future. That would introduce a rollover problem with millis(). By timestamping the current moment, and checking it like that, it will always work.

Peter_n:
Don't create a variable for the time in the future. That would introduce a rollover problem with millis(). By timestamping the current moment, and checking it like that, it will always work.

Really? I'm puzzled. If millis() is about to roll over, wouldn't adding an unsigned integer to the value of a unsigned integer copy of millis(), still produce a timestamp that millis() will attain in the correct time? I thought all the time calculations would be correct as long as all math is done in unsigned arithmetic.

I do see what you're aiming at, but it wouldn't really work for the code i'm writing..
I have functions like this

int FD(int d)
{
  m.setM0Speed(mxS);
  m.setM1Speed(mxS);
if(d != 0){delay(d); ST(0);}
  else{delay(d);}
}

int ST(int d)
{
  m.setM0Speed(0);
  m.setM1Speed(0);
  if(d != 0){delay(d); ST(0);}
  else{delay(d);}
}

So that for example, FD(1000); would move the robot forward one second and then stop, and FD(0); would make it move forward until further change.

What i want to do is after i tell the motors to start for the lACC(); to be called while the motors move forward until one second (or whatever time) has passed, and then go to the next function/command in void loop. I'm not able to dedicate the whole code to that one task.

A quick read of This shows that it is interrupt driven. You need to implement an interrupt handler to manage the stream of data from this device.

So i would be able to stop the data when i want to?
If so it would solve all my problems.
I would just pause the data before any delay and then start it afterwards.

The general approach to imbedding a delay using millis() in a function, would be to leave flags and time stamps for the devices in loop(), and adjust timestamps, set/reset the flags inside the function.

Can you post an example?

TERMINAL:
Can you post an example?

I've never done it.
Okay, now I have. Realize that I have a lot of distractions in front of me today. You have to polish it up.

/* Blink without Delay
modified to show how time could be used in a function */

// constants won't change. Used here to set a pin number :
const int ledPin =  13;      // the number of the LED pin

// Variables will change :
int ledState = LOW;             // ledState used to set the LED
bool ledStatus = false;             // led active?

// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long ledMillis = 0;        // will store last time LED was updated

unsigned long interval = 0;           // interval at which to blink (milliseconds)
unsigned long currentMillis;

void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
  delay(2000);
  ledPulse (1000);
}

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  currentMillis = millis();

  if ((currentMillis - ledMillis >= interval) && ledStatus == true) {
    ledState = LOW;
    // set the LED off:
    digitalWrite(ledPin, ledState);
    ledStatus = false;
  }
}

void ledPulse (unsigned long pulseTime)
{
  ledState = HIGH;
  digitalWrite(ledPin, ledState);
  ledStatus = true;
  interval = pulseTime;
  ledMillis = millis();
}

TERMINAL, if you want to do another thing after the delay, you might need a variable that indicates the 'state'.
This is an example : help with multiple digital inputs for a car lighting circuit - #10 by Peter_n - Programming Questions - Arduino Forum
Inside the big switch/case, the millis() is used just once. That is because that example has only one delay.
Do you like that code ? does it make any sense ?

aarg, to avoid the rollover problem, it is necessary to use "unsigned long" and timestamp the current moment. That way the "millis() - prevMillis" is always a positive number and that prevents the rollover problem.
When for example the time in the future is remembered, millis() could be higher or lower than that value, and that is not possible with unsigned long.
Here is an example that shows what it is like to use unsigned variables that rollover : Arduino Playground - TimingRollover

Peter_n:
aarg, to avoid the rollover problem, it is necessary to use "unsigned long" and timestamp the current moment. That way the "millis() - prevMillis" is always a positive number and that prevents the rollover problem.
When for example the time in the future is remembered, millis() could be higher or lower than that value, and that is not possible with unsigned long.
Here is an example that shows what it is like to use unsigned variables that rollover : Arduino Playground - TimingRollover

There is something about this that is fishy. I modified that code to show a little more of the results of the arithmetic and comparisons. The idea behind it is to use byte to simulate unsigned time. I am giving a snippet here because a link is already provided to the source.

   p = 4;         // rollover of value 260
  q = 250;
  r = p - q;     // valid for unsigned variables
  Serial.println( F("260 (=4) - 250 = "));
  Serial.println( r, DEC);
  Serial.println( r < 10);
  Serial.println( p-q, DEC);
  Serial.println( p-q < 10);

which produces this:

260 (=4) - 250 = 
10
0
-246
1

Notice that unless an assignment is made to a byte, the value is incorrect.
But! This form of comparison seems like the comparison of long ints in the actual blink code that follows, the structure of which we are all so familiar:

  if ( ul_CurrentMillis - ul_PreviousMillis > ul_Interval)

It seems to me, that if the analogy to the byte example is valid, this expression should fail, as it did with

( p-q < 10)

above.
I'm just not quite buying into this at the moment. Something is wrong. For sure, it could be the way I'm seeing it, but I'm not sure how.
I modified the unsigned long portion of the test in an identical way:

  ulNew = 705032704UL;  // rollover of value 5,000,000,000
  ulOld = 4000000000UL;
  ul = ulNew - ulOld;   // valid for unsigned long
  Serial.println( F("5,000,000,000 (=705,032,704) - 4,000,000,000 = "));
  Serial.println( ul, DEC);
  Serial.println( ul < 1000000000);
  Serial.println( ulNew - ulOld, DEC);
  Serial.println( ulNew - ulOld < 1000000000);

and the result is more encouraging:

Test with unsigned long.
3,000,000,000 - 2,000,000,000 = 1000000000
5,000,000,000 (=705,032,704) - 4,000,000,000 = 
1000000000
0
1000000000
0

What is so "special" about the unsigned long comparison, that made it work, while the other unsigned data type, byte, didn't?

aarg, there is nothing fishy about it. As long as the millis() and micros() are used with unsigned long.

When bytes are converted to ints, then is doesn't work anymore. Some even try to detect a rollover "( if ( millis() < 100 )", or "( if ( millis() > 65530 )", that is when things go wrong.

To always get a positive valid output, even with a rollover value, no bits should be added to the left.
For the unsigned long, that means that the 33th bit should not be added. That will never happen, the compiler doesn't have a longer unsigned int.
For the byte, that means that the 9th bit should not be added, and that is what is happening when they are converted to ints.

Since unsigned ints are not converted, those will also work.

// aarg and unsigned ints

void setup()
{
  unsigned int aarg1, aarg2, r;

  Serial.begin( 9600);

  while (!Serial);    // Only for Leonardo.

  Serial.println( "-------------------");
  Serial.println( "\Started");
  Serial.println( F("Test with unsigned 16-bit."));

  aarg1 = 20000;
  aarg2 = 10000;
  r = aarg1 - aarg2;
  Serial.print( F("20000 - 10000 = "));
  Serial.println( r, DEC);

  aarg1 = 4464;         // rollover of value 70000
  aarg2 = 60000;
  r = aarg1 - aarg2;     // valid for unsigned variables
  Serial.print( F("70000 (=4464) - 60000 = "));
  Serial.println( r, DEC);
  
  Serial.println( r < 10);
  Serial.println( aarg1 - aarg2, DEC);
  Serial.println( aarg1 - aarg2 < 10);
  
  Serial.println();
}

void loop()
{
  static unsigned int fixed = 65528;
  static unsigned int counter = 65528;   // it may never be below the 'fixed'
  
  unsigned int r = counter - fixed;
  
  Serial.print( "fixed = ");
  Serial.print( fixed, DEC);
  Serial.print( ", counter = ");
  Serial.print( counter, DEC);
  Serial.print( ", r = ");
  Serial.print( r);
  Serial.print( ", counter - fixed = ");
  Serial.print( counter - fixed, DEC);
  Serial.println();
  
  counter++;
  delay(1000);
}

When those ints are converted to signed long, it doesn't work anymore.
Or when the counter is below the fixed value.