The data stored in the float array are missing

Dear Community,

I'm trying to do a project using Arduino to collect illuminance values from a light meter and then calculate the average value of all the data.

In my code, I tried to store the collected illuminance values in a array called LuxValue. All the stored data can be printed when running the LuxReading() function. However, when I tried to calculate the average number, the data stored in the array just disappeared except the last one (LuxValue[4]), so the average value cannot be calculated correctly.

Any advice will be appreciated. Thanks in advance.

Here is the data displayed in the serial monitor:

I received: 611.50 lux      // data stored in LuxValue[] array and printed when running the LuxReading() 
I received: 537.00 lux
I received: 498.30 lux
I received: 458.60 lux
I received: 444.50 lux
 Misson Completed!
0.00       // trying to read the LuxValue[] in the AverageLux() function, but data are missing
0.00
0.00
160.20
444.50
Sum: 604.70
Average Illuminance: 120.94

Here is my code:

char receivedChars[13];
char luxChars[5];
float LuxValue[5];  //measurement points
int b = 0;    //variable for multiple measurement points - LuxValue array

void setup()
{
  Serial.begin(9600);  
  Serial1.begin(9600,SERIAL_7E1); //according to the light meter communication method  
}

void loop()
{
  LuxReading(); // Call LuxReading Function
  delay(500);  // if I delete this delay code, it won't work. So it seems it takes some time to receive the data
  
  if (b == 5)  // Calculate Average
  {
     Serial.println(" Misson Completed!");   
     delay(1000);
     AverageLux();
     b = 0;     
  } 
}



void LuxReading()  //Lux Reading Function
{
  int ndx = 0;  //variable for receivedChars array
  int a = 0;    //variable for luxChars array
  
  while (Serial1.available() > 0) //when press the D-OUT button of the light meter, read data
  {
    char c = Serial1.read();  // store all received data into array
    if (c != '\n') 
    {
      receivedChars[ndx] = c; 
      ndx++;
    }
    else
    {
       Serial.print("I received: ");  // print received data on serial monitor
       for (int i=6; i<=10; i++)
       {            
       luxChars[a] = receivedChars[i];
       a++;        
       }
       LuxValue[b] = atof(luxChars);  //convert char into float and store the lux value in LuxValue Array
       Serial.print(LuxValue[b]);
       b++;
       Serial.println(" lux");  // print illuminance unit       
            
    }
  }   

}

void AverageLux()  //Average illuminance calculation
{
  float sum = 0;
  float averageLux;
  for (int i=0; i<=4; i++)
  {
    sum += LuxValue[i] ; 
    Serial.println(LuxValue[i]);   //print data stored in LuxValue array.The serial monitor shows the data are missing except the last one 
  }
  
  averageLux = sum / 5;
  Serial.print("Sum: ");
  Serial.println(sum);  // print average illuminance value of measurement points
  Serial.print("Average Illuminance: ");
  Serial.println(averageLux);  // print average illuminance value of measurement points
  
}

Your code overruns receivedChars corrupting the next thing in memory which is luxChars continuing on to LuxValue (ndx becomes significantly larger than 13 in LuxReading).

I suspect your code also overruns luxChars.

Thank you for your reply.

But I still can't understand what the overrun means? How can I fix this problem?

There is a buffer (an array) in your code. Let's call it receivedChars. Let's also say it has space for 13 text characters. The definition might look like this...

char receivedChars[13];

C / C++ does not prevent you from accessing elements in your buffer that do not exist. For example, this is valid...

receivedChars[1001] = 'x';

The compiler faithfully generates code that stores 'x' in the 1001st element of receivedChars. The problem is that location is not within the bounds of receivedChars. Something else, like LuxValue, may be stored there. Storing data past the end of a buffer, like my example, is an "overrun" or a "buffer overrun". Which makes a nice Google keyword search...

https://www.google.com/search?q=buffer+overrun

Thank you for your explanation.

So is it correct that I should increase the size of receivedChars[] array so that all the data are stored within the declared boundary?

MirkoZhou:
Thank you for your explanation.

So is it correct that I should increase the size of receivedChars[] array so that all the data are stored within the declared boundary?

Yes, or ensure that the array index never exceeds the present bounds.

Hi all,

I'm trying to read the measured multiple illuminance data from a light meter and store them into an array called luxchars[]. After that, the char array is converted into float char for calculation purpose.

The data printed on the serial monitor are correct in most of the cases, but sometimes the result is incorrect and this incorrect condition happens very randomly. I tried my best to figure out this issue but I failed. Still can't understand why this rare incorrect conditions sometimes happen, which affects the accuracy of the collected data.

Can anyone help me to figure it out? Thank you so much!

Here is the data printed on serial monitor:

I received: 483.50 lux
404.20
416.40
429.70
429.60
432.10
435.00
443.80
0.50                     // Incorrect data, happens randamly
443.70
483.50
 Misson Completed!
Average Illuminance: 391.85
Maximum Illuminance: 483.50
Minimum Illuminance: 0.50
Uniormity: 1.24

Here is my code:

#include <SPI.h>
#include <TFT.h>
#include<stdlib.h>

#define cs   10   //TFT Screen pin defintion for Arduino
#define dc   9
#define rst  8  
TFT TFTscreen = TFT(cs, dc, rst);

const int NumOfPoints = 10;  // number of measurement points

char receivedChars[30];
char luxChars[6];

char averageLuxChars[5];
char maximumLuxChars[5];
char minimumLuxChars[5];
char uniformityChars[5];

float LuxValue[NumOfPoints];  //measurement points

float maxLux;
float minLux;
float averageLux;
float uniformityLux;

int b = 0;    //variable for multiple measurement points - LuxValue array


void setup()
{
  Serial.begin(9600);  
  Serial1.begin(9600,SERIAL_7E1); //according to the light meter communication method 
  delay(500); 
  
  TFTscreen.begin();
  TFTscreen.background(0, 0, 0);
  TFTscreen.setTextSize(1);

  
}

void loop()
{
  LuxReading(); // Call LuxReading Function
  delay(500);


  if (b == NumOfPoints)  // Calculate Average
  {
     
     Serial.println(" Misson Completed!");
     TFTscreen.stroke(255, 255, 255);
     TFTscreen.text(" Misson Completed!", 40, 30);   
     delay(2000);
     TFTscreen.stroke(0, 0, 0);
     TFTscreen.text(" Misson Completed!", 40, 30);  
     
     AverageLux();
     DisplayAverageLux();
     MaximumLux();
     DisplayMaxLux();
     MinimumLux();
     DisplayMinLux();
     UniformityLux();
     DisplayUniformity();
     b = 0;     
  } 
  
}


void LuxReading()  //Lux Reading Function
{
  int ndx = 0;  //variable for receivedChars array
  int a = 0;    //variable for luxChars array
  
  while (Serial1.available() > 0) //when press the D-OUT button of the light meter, read data
  {
    char c = Serial1.read();  // store all received data into array
    if (c != '\n') 
    {
      receivedChars[ndx] = c; 
      ndx++;
    }
    else
    {
       Serial.print("I received: ");  // print received data on serial monitor
       for (int i=6; i<=10; i++)
       {            
         luxChars[a] = receivedChars[i];
         a++;        
       }
       LuxValue[b] = atof(luxChars);  //convert char into float and store the lux value in LuxValue Array
       Serial.print(LuxValue[b]);
       b++;
       Serial.println(" lux");  // print illuminance unit 
       for (int i=0; i<=NumOfPoints-1; i++)
       { 
         Serial.println(LuxValue[i]);   //print data stored in LuxValue array.The serial monitor shows the data are missing except the last one 
       }                 
    }
  }   

}


void AverageLux()  //Average illuminance calculation
{
  float sum = 0;
  char buff[7];
  for (int i=0; i<=NumOfPoints-1; i++)
  {
    sum += LuxValue[i] ; 
  }
  
  averageLux = sum / NumOfPoints;
  
  Serial.print("Average Illuminance: ");
  Serial.println(averageLux);  // print average illuminance value of measurement points  
  String StrAverageLux = dtostrf(averageLux, 4, 2, buff);
  StrAverageLux.toCharArray(averageLuxChars, 7);
 
}

void MaximumLux()   //Maximum illuminance calculation
{
  char buff[7];
  maxLux = LuxValue[0];
  for (int i=1; i<=NumOfPoints-1; i++)
  {
    maxLux = max(LuxValue[i],maxLux);  
  }
  Serial.print("Maximum Illuminance: ");
  Serial.println(maxLux);  // print Maximum Illuminance value of measurement points 
  String StrMaximumLux = dtostrf(maxLux, 4, 2, buff);
  StrMaximumLux.toCharArray(maximumLuxChars, 7);
}

void MinimumLux()   //Minimum illuminance calculation
{
  char buff[7];
  minLux = LuxValue[0];
  for (int i=1; i<=NumOfPoints-1; i++)
  {
    minLux = min(LuxValue[i],minLux);  
  }
  Serial.print("Minimum Illuminance: ");
  Serial.println(minLux);  // print Minimum Illuminance value of measurement points 
  String StrMinimumLux = dtostrf(minLux, 4, 2, buff);
  StrMinimumLux.toCharArray(minimumLuxChars, 7);
}

void UniformityLux()    //Uniformity calculation
{
  char buff[7];
  uniformityLux = maxLux/averageLux;
  Serial.print("Uniormity: ");
  Serial.println(uniformityLux);  // print Uniformity value of measurement points 
  String StrUniformity = dtostrf(uniformityLux, 4, 2, buff);
  StrUniformity.toCharArray(uniformityChars, 7);
    
}

void DisplayAverageLux()  //Average illuminance display
{
  TFTscreen.stroke(255, 255, 0);
  TFTscreen.text("AVERAGE LUX: ", 40, 10);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text(averageLuxChars, 40, 20);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text("lux", 80, 20);     
}

void DisplayMaxLux()  //Maximum illuminance display
{
  TFTscreen.stroke(255, 255, 0);
  TFTscreen.text("MAXIMUM LUX: ", 40, 30);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text(maximumLuxChars, 40, 40);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text("lux", 80, 40);     
}

void DisplayMinLux()  //Minimum illuminance display
{
  TFTscreen.stroke(255, 255, 0);
  TFTscreen.text("MINIMUM LUX: ", 40, 50);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text(minimumLuxChars, 40, 60);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text("lux", 80, 60);     
}

void DisplayUniformity()  //Uniformity display
{
  TFTscreen.stroke(255, 255, 0);
  TFTscreen.text("UNIFORMITY: ", 40, 70);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text(uniformityChars, 40, 80);      
}

Please do not cross-post. Threads merged.

Printing ndx and a should reveal your mistake.

I tried to print the ndx, which was printed as 28. So I set the size of the array to be 30 to avoid the overrun issue. For the luxChars[] array, I stored 5 data in this array using For Loop and I set the size of the array to be 6, which is also more than the amount of stored data. The incorrect result happens very randomly.
Is it still because of the overrun issue? Thank you so much.

How many characters do you think 404.20 is?

Sorry, it's 6 characters. And they are stored in luxChars[0],luxChars[1],luxChars[2],luxChars[3],luxChars[4],luxChars[5]. Will the overrun issue happen if I set the size of the array to be 6?

MirkoZhou:
I tried to print the ndx, which was printed as 28.

Do you expect ndx to reach 28?

MirkoZhou:
Sorry, it's 6 characters. And they are stored in luxChars[0],luxChars[1],luxChars[2],luxChars[3],luxChars[4],luxChars[5]. Will the overrun issue happen if I set the size of the array to be 6?

You forgot to include space for the terminating null. It's 7 characters in that string.

The ndx variable is used for the ReceivedChars[] array, which depends on the data from the light meter. So I reckon the character length of the received data from the light meter is 28?

Hi all,

I modified my code to print the received data before and after they are stored in the receivedChars[] array. It seems like I found the problem: after I stored the data into the array, the printed result of receivedChars sometimes incorrect, as shown in the serial monitor result. It might because of the overrun issue of the array, but I can't really figure out where the exact problem. Any advice would be appreciated. Thank you.

Here is my modified code:

#include <SPI.h>
#include <TFT.h>
#include<stdlib.h>

#define cs   10   //TFT Screen pin defintion for Arduino
#define dc   9
#define rst  8  
TFT TFTscreen = TFT(cs, dc, rst);

const int NumOfPoints = 20;  // number of measurement points

char receivedChars[29];
char luxChars[6];

char averageLuxChars[6];
char maximumLuxChars[6];
char minimumLuxChars[6];
char uniformityChars[5];

float LuxValue[NumOfPoints];  //measurement points

float maxLux;
float minLux;
float averageLux;
float uniformityLux;

int b = 0;    //variable for multiple measurement points - LuxValue array


void setup()
{
  Serial.begin(9600);  
  Serial1.begin(9600,SERIAL_7E1); //according to the light meter communication method 
  delay(500); 
  
  TFTscreen.begin();
  TFTscreen.background(0, 0, 0);
  TFTscreen.setTextSize(1);

  
}

void loop()
{
  LuxReading(); // Call LuxReading Function
  delay(500);


  if (b == NumOfPoints)  // Calculate Average
  {
     
     Serial.println(" Misson Completed!");
     TFTscreen.stroke(255, 255, 255);
     TFTscreen.text(" Misson Completed!", 40, 30);   
     delay(2000);
     TFTscreen.stroke(0, 0, 0);
     TFTscreen.text(" Misson Completed!", 40, 30);  
     
     AverageLux();
     DisplayAverageLux();
     MaximumLux();
     DisplayMaxLux();
     MinimumLux();
     DisplayMinLux();
     UniformityLux();
     DisplayUniformity();
     b = 0;     
  } 
  
}


void LuxReading()  //Lux Reading Function
{
  int ndx = 0;  //variable for receivedChars array
  int a = 0;    //variable for luxChars array
  
  while (Serial1.available() > 0) //when press the D-OUT button of the light meter, read data
  {
    char c = Serial1.read();  
    if (c != '\n') 
    {
      receivedChars[ndx] = c;   // store all received data into receivedChars array
      Serial.print(receivedChars[ndx]);   //Serial Monitor: print all the received data
      ndx++;
    }
    else
    {
       Serial.println();
       for (int i=0; i<=28; i++)
       {
         Serial.print(receivedChars[i]);   //Serial Monitor: print all the data stored in the receivedChars array
       }
       Serial.println();
       Serial.print("I received: ");  // print received data on serial monitor
       for (int i=6; i<=10; i++)
       {            
         luxChars[a] = receivedChars[i];
         a++;        
       }
       LuxValue[b] = atof(luxChars);  //convert char into float and store the lux value in LuxValue Array
       Serial.print(LuxValue[b]);
       Serial.println(" lux");  // print illuminance unit 
       b++;
       for (int i=0; i<=NumOfPoints-1; i++)
       { 
         Serial.println(LuxValue[i]);   //print data stored in LuxValue array
       }                 
    }
  }   

}


void AverageLux()  //Average illuminance calculation
{
  float sum = 0;
  char buff[5];
  for (int i=0; i<=NumOfPoints-1; i++)
  {
    sum += LuxValue[i] ; 
  }
  
  averageLux = sum / NumOfPoints;
  
  Serial.print("Average Illuminance: ");
  Serial.println(averageLux);  // print average illuminance value of measurement points  
  String StrAverageLux = dtostrf(averageLux, 4, 2, buff);
  StrAverageLux.toCharArray(averageLuxChars, 5);
 
}

void MaximumLux()   //Maximum illuminance calculation
{
  char buff[5];
  maxLux = LuxValue[0];
  for (int i=1; i<=NumOfPoints-1; i++)
  {
    maxLux = max(LuxValue[i],maxLux);  
  }
  Serial.print("Maximum Illuminance: ");
  Serial.println(maxLux);  // print Maximum Illuminance value of measurement points 
  String StrMaximumLux = dtostrf(maxLux, 4, 2, buff);
  StrMaximumLux.toCharArray(maximumLuxChars, 5);
}

void MinimumLux()   //Minimum illuminance calculation
{
  char buff[5];
  minLux = LuxValue[0];
  for (int i=1; i<=NumOfPoints-1; i++)
  {
    minLux = min(LuxValue[i],minLux);  
  }
  Serial.print("Minimum Illuminance: ");
  Serial.println(minLux);  // print Minimum Illuminance value of measurement points 
  String StrMinimumLux = dtostrf(minLux, 4, 2, buff);
  StrMinimumLux.toCharArray(minimumLuxChars, 5);
}

void UniformityLux()    //Uniformity calculation
{
  char buff[5];
  uniformityLux = maxLux/averageLux;
  Serial.print("Uniormity: ");
  Serial.println(uniformityLux);  // print Uniformity value of measurement points 
  String StrUniformity = dtostrf(uniformityLux, 4, 2, buff);
  StrUniformity.toCharArray(uniformityChars, 5);
    
}

void DisplayAverageLux()  //Average illuminance display
{
  TFTscreen.stroke(255, 255, 0);
  TFTscreen.text("AVERAGE LUX: ", 40, 10);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text(averageLuxChars, 40, 20);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text("lux", 80, 20);     
}

void DisplayMaxLux()  //Maximum illuminance display
{
  TFTscreen.stroke(255, 255, 0);
  TFTscreen.text("MAXIMUM LUX: ", 40, 30);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text(maximumLuxChars, 40, 40);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text("lux", 80, 40);     
}

void DisplayMinLux()  //Minimum illuminance display
{
  TFTscreen.stroke(255, 255, 0);
  TFTscreen.text("MINIMUM LUX: ", 40, 50);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text(minimumLuxChars, 40, 60);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text("lux", 80, 60);     
}

void DisplayUniformity()  //Uniformity display
{
  TFTscreen.stroke(255, 255, 0);
  TFTscreen.text("UNIFORMITY: ", 40, 70);  
  TFTscreen.stroke(255, 255, 255);
  TFTscreen.text(uniformityChars, 40, 80);      
}

Here is the result from serial monitor:

     462.3   .4239   .4092     // print the data before stored in receivedChars array, correct result
9   .4092 3   .4239   .4092     // print the data stored in receivedChars[] array, showing incorrect result

The buffer overrun causes undefined behavior. That means anything could happen. So it's really not useful to try to troubleshoot until you've fixed that.

Delta_G:
The buffer overrun causes undefined behavior. That means anything could happen. So it's really not useful to try to troubleshoot until you've fixed that.

Thank you Delta, but how can I find and fix that hidden overrun issue?

MirkoZhou:
Thank you Delta, but how can I find and fix that hidden overrun issue?

Observe the size of all your buffers and then analyze the range of indices that your program uses to access them. All of this information is available to you since you define them when you write the code.

This should help...
http://forum.arduino.cc/index.php?topic=396450