Array loses data after millis() update

I am attempting to do a queue (shift an array), however every time I update a timer (I don't want to update the array but every once in a while), the value in the array is erased... In the code below, I initialize the array with 0 values. I then shift all the values one space to the left (element 0 gets element 1's value, element 2 gets element 3's value, etc). Once the shift is complete, I update the right most element (element 29 in this case). However the value doesn't stick. I am trying to debug using the serial stream and I can see that element is updated with the random number, however after time0 = millis(); executes, the value in element 29 is erased?



unsigned long time0 = 0;
float dataarray[29] = {}; //create data array
float datavar = 0;

void setup(void) {
  Serial.begin(9600);

  for ( int i = 0; i < 30; ++i ) { // reset data array elements to 0
    dataarray[ i ] = 0; // set element at location i to 0
    }

time0=millis();
}

void loop() {
 
   if (time0 + 2500 <= millis()) //only update every 1/2 second
  {

    for ( int i = 0; i <= 29; ++i ) { // data shift the dataarray
      dataarray[ i ] = dataarray[i+1]; 
      Serial.print(i);Serial.print(":");Serial.print(dataarray[i]); Serial.print("  ");
    }
  Serial.println("");

  dataarray[29] = (random(0,1023)*(20-9)/1023+9);

  Serial.println(dataarray[29]); 

  time0=millis();

  Serial.println(dataarray[29]);



  }

}

You are overrunning your array. You declare it as having 29 elements. That means you can access it from index 0..28.

You are going 1 too far.

try this

unsigned long time0 = 0;
float dataarray[29] = {};  //create data array
float datavar = 0;

void setup(void) {
  Serial.begin(9600);

  for (int i = 0; i < 29; ++i) {  // reset data array elements to 0
    dataarray[i] = 0;             // set element at location i to 0
  }

  time0 = millis();
}

void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - time0 > 2500)  //only update every 2.5 second
  {

    for (int i = 0; i < 28; i++) {  // data shift the dataarray
      dataarray[i] = dataarray[i + 1];
      Serial.print(i);
      Serial.print(":");
      Serial.print(dataarray[i]);
      Serial.print("  ");
    }
    Serial.println("");

    dataarray[28] = (random(0, 1023) * (20 - 9) / 1023 + 9);

    Serial.println(dataarray[28]);

    time0 = currentMillis;
  }
}

And sometimes 2 too far.

Most common is a for loop written

    for ( int i = 0; i < 29; ++i ) {

which experience readers instantly see as a loop doing something twenty nine times, with a variable that behaves and goes from 0 to 28, which as @blh64 points out are the only legal indices for an array of 29 elements.

So it's still bad when you add 1 to the index and land up with 29.

But why the shuffle? It may not be too soon to look into "ring" or "circular" buffering… the data stays in place, and the logic takes care of which element you want to think of as first or next or last.

It is usually not necessary to move data like that, and with larger numbers of elements might be a time waster, even if it is now easier to understand.

No! When i is 28, you grabbing index 29, the 30th element of the array…

a7

fixed

@HazardsMind, and anyone... when you tested the original code, you should have seen a warning

warning: iteration 28 invokes undefined behavior [-Waggressive-loop-optimizations]
dataarray[i] = dataarray[i + 1];

but maybe you have not yet gone to the IDE preferences and turned up all warnings and verbosity.

Do it now. Then heed the red ink if it spills during verification or uploading. It won't catch all your errors, but it can catch some very common ones and save time and hair.

a7

Thanks all. Not sure how I missed it. I had this working a few days ago, then went in and made a few edits and must have changed the size of the array or messed with it.

Thanks, I never did turn those on.

The awful truth is that it may have worked. If things were just right, there may have been no problem with the code. But that's luck, and luck should not enter into coding.

At least you should be aware that errors like that can travel around seeming to behave, then you do something totally unrelated and you have a very difficult time figuring it out.

Do not ask me how I know. :expressionless:

a7

Initializing that array to zeros in setup() is completely unnecessary. The array, being global, and having no explicit intializer, will automatically by intialized to all zeros.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.