Array update strange behaviour

Hello,

I'm trying a build a program that records the max & min temperature for each hours for the 8 hours (want to have the max & min fo the night).

Here below the program (tested for 40 secondes).

I think this is working but after getting an update for exemple value #2 of the array, i can see in monitor that the last value is getting updated. And I can't understand why. :smiling_face_with_tear: !!

Must be some trouble somewhere but I don't know. Any clue ?

20:22:38.253 -> Init done
20:22:39.605 -> Check value #1
20:22:41.122 -> Check value #1
20:22:42.608 -> Check value #1
20:22:44.123 -> Check value #1
20:22:45.607 -> Check value #1
20:22:46.101 ->  - Value :1 : 24 - Value :2 : 24 - Value :3 : 24 - Value :4 : 24 - Value :5 : 24
20:22:47.123 -> Check value #2
20:22:48.637 -> Check value #2
20:22:50.115 -> Check value #2
20:22:51.633 -> Check value #2
20:22:51.633 -> UPDATE
20:22:53.118 -> Check value #2
20:22:54.104 ->  - Value :1 : 24 - Value :2 : 26 - Value :3 : 24 - Value :4 : 24 - Value :5 : 26
20:22:54.633 -> Check value #3
20:22:56.119 -> Check value #3
20:22:57.639 -> Check value #3
20:22:59.123 -> Check value #3
20:23:00.639 -> Check value #3
20:23:02.124 ->  - Value :1 : 24 - Value :2 : 26 - Value :3 : 25 - Value :4 : 24 - Value :5 : 25
20:23:02.124 -> Check value #4
20:23:03.614 -> Check value #4
20:23:05.131 -> Check value #4
20:23:06.617 -> Check value #4
20:23:08.137 -> Check value #4
20:23:09.621 -> Check value #4
20:23:10.118 ->  - Value :1 : 24 - Value :2 : 26 - Value :3 : 25 - Value :4 : 25 - Value :5 : 25
20:23:11.142 -> Check value #5
20:23:12.627 -> Check value #5
20:23:14.145 -> Check value #5
20:23:15.628 -> Check value #5
20:23:17.142 -> Check value #5
20:23:18.096 ->  - Value :1 : 24 - Value :2 : 26 - Value :3 : 25 - Value :4 : 25 - Value :5 : 25
20:23:18.622 -> Check value #1
20:23:20.142 -> Check value #1
20:23:21.624 -> Check value #1
20:23:23.142 -> Check value #1
20:23:24.627 -> Check value #1


#include <Adafruit_BME280.h> 
#define adresseI2CduBME280                0x76
Adafruit_BME280 bme;


#define interval_array 8000
#define size_array 5
#define interval_update_array 1500

long time_array = 0 ;
long time_update =0 ; 
int index = 1 ;
int temp_max_tempo ; 
int temp_min_tempo ; 
int array_max [size_array];
int array_min [size_array];
int temperature_loop ; 

void setup() 
{
  bme.begin(adresseI2CduBME280) ;
  Serial.begin(57600);
  
  temp_min_tempo = bme.readTemperature() ; 
  temp_max_tempo = bme.readTemperature() ; 
  
  for (int i=1; i < size_array; i++)
   {
    array_max [i] = bme.readTemperature();
    array_min [i] = bme.readTemperature();
   }
  Serial.println("Init done");
}

void loop() 
{

temperature_loop = bme.readTemperature();

        if((millis() - time_update) > interval_update_array) // Update of the current array position if temperature > / <
    {
      Serial.print("Check value #");Serial.println(index);
      if (temp_max_tempo < temperature_loop)
        {
          array_max[index] = temperature_loop;
          temp_max_tempo = temperature_loop; 
          Serial.println("UPDATE");
        }
        
        if (temp_min_tempo < temperature_loop)
        {
          array_min[index] = temperature_loop;
          temp_min_tempo = temperature_loop; 
        }
        time_update = millis(); 

    }   
    
  if((millis() - time_array) > interval_array) //Switch of array position and reset of old values
    {
      temp_max_tempo = temperature_loop; ;
      temp_min_tempo = temperature_loop; ;
      array_max[index] = temperature_loop;
      array_min[index] = temperature_loop;

      time_array = millis(); 

      index = index + 1; 
      if(index > size_array) 
       {
         index = 1 ;
       }

      for (int i=1; i <= size_array; i++)
      {
        Serial.print(" - ");          
        Serial.print("Value :");
        Serial.print(i);
        Serial.print(" : ");
        Serial.print(array_max[i]);
        if (i == size_array){Serial.println("");}
      }
    }      
}

Stop. Throughout your code are several indexing errors. Your array indices should be 0...(size-1), NOT 1...size.
Erroneous values will occur all over the place, including writing outside the bounds of your array.

Okay, I also modify the last for as :

      for (int i=0; i < size_array; i++)
      {
        Serial.print(" - ");          
        Serial.print("Value :");
        Serial.print(i);
        Serial.print(" : ");
        Serial.print(array_max[i]);
        if (i == size_array-1){Serial.println("");}
      }

So it was only a printing issue, I was printing a value that doesn't exist ?

Another question now, for the whole program : would you have done it this way or is there a way to do it easier ?

Update, please, show us all.

The whole code you mean ?


#include <Adafruit_BME280.h> 
#define adresseI2CduBME280                0x76
Adafruit_BME280 bme;


#define interval_array 8000
#define size_array 5
#define interval_update_array 1500

long time_array = 0 ;
long time_update =0 ; 
int index = 1 ;
int temp_max_tempo ; 
int temp_min_tempo ; 
int array_max [size_array];
int array_min [size_array];
int temperature_loop ; 

void setup() 
{
  bme.begin(adresseI2CduBME280) ;
  Serial.begin(57600);
  
  temp_min_tempo = bme.readTemperature() ; 
  temp_max_tempo = bme.readTemperature() ; 

  Serial.println("Init done");

  for (int i=0; i < size_array; i++)
   {
    array_max [i] = bme.readTemperature();
    array_min [i] = bme.readTemperature();
   }

  Serial.println("Init done1");
}

void loop() 
{

temperature_loop = bme.readTemperature();

        if((millis() - time_update) > interval_update_array) // Update of the current array position if temperature > / <
    {
      Serial.print("Check value #");Serial.println(index);
      if (temp_max_tempo < temperature_loop)
        {
          array_max[index] = temperature_loop;
          temp_max_tempo = temperature_loop; 
          Serial.println("UPDATE");
        }
        
        if (temp_min_tempo < temperature_loop)
        {
          array_min[index] = temperature_loop;
          temp_min_tempo = temperature_loop; 
        }
        time_update = millis(); 

    }   
    
  if((millis() - time_array) > interval_array) //Switch of array position and reset of old values
    {
      temp_max_tempo = temperature_loop; ;
      temp_min_tempo = temperature_loop; ;
      array_max[index] = temperature_loop;
      array_min[index] = temperature_loop;

      time_array = millis(); 

      index = index + 1; 
      if(index > size_array) 
       {
         index = 1 ;
       }

      for (int i=0; i < size_array; i++)
      {
        Serial.print(" - ");          
        Serial.print("Value :");
        Serial.print(i);
        Serial.print(" : ");
        Serial.print(array_max[i]);
        if (i == size_array-1){Serial.println("");}
      }
    }      
}

If this index is being used to index an array, it also is indexing beyond the array. You tell me.

Here too probably.

      if (index >= size_array) 
       {
         index = 0;
       }

In general testing for reaching or exceeding a limit, even if you are sure you were gonna step right in the limit.

a7

Hopefully, you will now review all of your indexing and looping. Post a new code when you think you're done.

The index is there to change the position of the update of the array.

The first hour the first value of the array, the second hour the second position etc...

So you are probably right and i need update what you said and test.

Is there a way to test the code on an arduino vm machine when you are away from the board ?

Others point to Wokwi as an Arduino simulation environment. I've not had reason to dabble with it, but it sounds like it would be worth a look.

I will make a stronger statement.

The wokwi simulator is currently the best of them, it is very faithful and has a large and growing number of hardware peripherals that can be used in virtual models of you projects.

I have always developed logic independently using C/C++ on the desktop, faking the peripherals and coding my own versions of things that only happen on the microprocessor… a real time-saver.

Now most of that happens on the wokwi, where I can also then move to start introducing most of the hardware I typically add to make a real device.

By the time I am at the IDE, I am mostly down to wiring errors, mechanical issues, power supply considerations and of course finding that in real life I need or want to rethink a few things now that I have something to take away and play with.

A game changer.

a7

1 Like

Would also be useful when participating on this board, then, when I'm away from my labspace. Must look.

Wokwi looks very good ! But no bme280 yet :frowning:

Made the change and looks like all is going very well.

Thank a lot for your help.

Now need to integrate a min & max check for each array and it will be good to be integrated in the main program and send the min & max through mqtt to adafruit IO and on my local server !

#include <Adafruit_BME280.h> 
#define adresseI2CduBME280                0x76
Adafruit_BME280 bme;


#define interval_array 2000
#define size_array 5
#define interval_update_array 500

long time_array = 0 ;
long time_update =0 ; 
int index = 1 ;
int temp_max_tempo ; 
int temp_min_tempo ; 
int array_max [size_array];
int array_min [size_array];
int temperature_loop ; 

void setup() 
{
  bme.begin(adresseI2CduBME280) ;
  Serial.begin(57600);
  
  temp_min_tempo = bme.readTemperature() ; 
  temp_max_tempo = bme.readTemperature() ; 

  Serial.println("Init done");

  for (int i=0; i < size_array; i++)
   {
    array_max [i] = bme.readTemperature();
    array_min [i] = bme.readTemperature();
   }

  Serial.println("Init done1");
}

void loop() 
{

temperature_loop = bme.readTemperature();

        if((millis() - time_update) > interval_update_array) // Update of the current array position if temperature > / <
    {
      Serial.print("Check value #");Serial.println(index);
      if (temp_max_tempo < temperature_loop)
        {
          array_max[index] = temperature_loop;
          temp_max_tempo = temperature_loop; 
          Serial.println("UPDATE");
        }
        
        if (temp_min_tempo < temperature_loop)
        {
          array_min[index] = temperature_loop;
          temp_min_tempo = temperature_loop; 
        }
        time_update = millis(); 

    }   
    
  if((millis() - time_array) > interval_array) //Switch of array position and reset of old values
    {
      temp_max_tempo = temperature_loop; ;
      temp_min_tempo = temperature_loop; ;
      array_max[index] = temperature_loop;
      array_min[index] = temperature_loop;

      time_array = millis(); 

      index = index + 1; 
      if(index >= size_array) 
       {
         index = 0 ;
       }

      for (int i=0; i < size_array; i++)
      {
        Serial.print(" - ");          
        Serial.print("Value :");
        Serial.print(i);
        Serial.print(" : ");
        Serial.print(array_max[i]);
        if (i == size_array-1){Serial.println("");}
      }
    }      
}

Hey,

Back again.

Here is the code which now includes a min and max value of the array.

It's working fine most of the time but sometimes not.

Example here, the maximum found if 39 when there is no 39 in the array. Any idea ?

I have replace the bme sensor by a random value so you can test it on Wokwi :wink:

Takes some times to see the mistake below, after few loops all is normal again.

18:51:30.342 -> Array maximum :
18:51:30.342 -> - Value :0 : -6.00 - Value :1 : 23.00 - Value :2 : 35.00 - Value :3 : 29.00 - Value :4 : 13.00
18:51:30.342 -> Maximum value is : 39.00
18:51:30.342 ->
18:51:30.342 -> Array minimum :
18:51:30.342 -> - Value :0 : -6.00 - Value :1 : -19.00 - Value :2 : -3.00 - Value :3 : -14.00 - Value :4 : -11.00
18:51:30.376 -> Minimum value is : -19.00

//#include <Adafruit_BME280.h> 
//#define adresseI2CduBME280                0x76
//Adafruit_BME280 bme;


#define interval_array 4000
#define size_array 5
#define interval_update_array 1000

long time_array = 0 ;
long time_update =0 ; 
byte index = 1 ;
float temp_max_tempo ; 
float temp_min_tempo ; 
float array_max [size_array];
float array_min [size_array];
float temperature_loop ; 
float global_max_val ;
float global_min_val ;

void setup() 
{
  //bme.begin(adresseI2CduBME280) ;
  Serial.begin(57600);
  
  //temp_min_tempo = bme.readTemperature() ; 
  //:temp_max_tempo = bme.readTemperature() ; 

    temp_min_tempo = 20 ; 
  temp_max_tempo = 20 ; 
  global_max_val = 20;
  global_min_val = 20 ;

  /*for (int i=0; i < size_array; i++)
   {
    array_max [i] = bme.readTemperature();
    array_min [i] = bme.readTemperature();
   }*/

     for (int i=0; i < size_array; i++)
   {
    array_max [i] = 20 ;
    array_min [i] = 20 ;
   }

  Serial.println("Setup all good");
}

void loop() 
{

temperature_loop = random(-20, 40);
global_max_val = array_max[0];
global_min_val = array_min[0];


    if((millis() - time_update) > interval_update_array) // Update of the current array position if temperature > / <
    {
      Serial.print("Check value #");Serial.println(index);

      if (temp_max_tempo < temperature_loop)
        {
          array_max[index] = temperature_loop;
          temp_max_tempo = temperature_loop; 
          Serial.println("UPDATE");
        }
        
        if (temp_min_tempo > temperature_loop)
        {
          array_min[index] = temperature_loop;
          temp_min_tempo = temperature_loop; 
        }
        time_update = millis(); 
    }   
    
  if((millis() - time_array) > interval_array) //Switch of array position and reset of old values
    {
      index = index + 1; 
      if(index >= size_array) 
       {
         index = 0 ;
       }

      temp_max_tempo = temperature_loop; ;
      temp_min_tempo = temperature_loop; ;
      array_max[index] = temperature_loop;
      array_min[index] = temperature_loop;

      time_array = millis(); 

        for (int i=0; i < size_array; i++)  // Check what is the biggest vallue in both array    
        {
          if (array_max[i] > global_max_val)
          {
            global_max_val=array_max[i];
          }
          if (array_min[i] < global_min_val)
          {
            global_min_val=array_min[i];
          }
        }

                Serial.println("");
                Serial.println("Array maximum : ");
                for (int i=0; i < size_array; i++)
                {
                  Serial.print(" - ");          
                  Serial.print("Value :");
                  Serial.print(i);
                  Serial.print(" : ");
                  Serial.print(array_max[i]);
                  if (i == size_array-1){Serial.println("");}
                }
                  Serial.print("Maximum value is : ");Serial.println(global_max_val);

                Serial.println("");
                Serial.println("Array minimum : ");
                for (int i=0; i < size_array; i++)
                {
                  Serial.print(" - ");          
                  Serial.print("Value :");
                  Serial.print(i);
                  Serial.print(" : ");
                  Serial.print(array_min[i]);
                  if (i == size_array-1){Serial.println("");}
                }
                  Serial.print("Minimum value is : ");Serial.println(global_min_val);
                Serial.println("");
    }   

    delay(10);   
}
  1. You're doing this at the end of your loop, but if you do it after the } that ends the loop, it's automatically emitted after the loop. (at least two places)
  2. if your present scan doesn't contain a value less than global_min_val, then the value remains at the previous minimum, from the previous scan. When you see a number that doesn't seem right, look back through your data to see if you've seen it before...
  3. Same problem as in 2) applies to max value.
  1. Is only there to return for the print, shouldn't disturb the test of min and max ?
  2. & 3. Loo, on the code I posted I put those lines at the beginning of the loop to prevent that :
global_max_val = array_max[0];
global_min_val = array_min[0];

This is to reset the value and to make sure I don't keep the max/min value for ever. Since I put those lines it's working better now.

1 - Agreed, but I was pointing out that instead of executing that test for end of array every pass through, you had the opportunity to just do the work at the right time. Efficiency. but, it's up to you.

2, 3 - so that was it, then? Sorry, I looked up Loo, but all I got was portapotty. (minor joke)
Probably best would be to set min to 1000 and max to -1000, that way they get updated all the time.

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