Go Down

Topic: The data stored in the float array are missing (Read 408 times) previous topic - next topic

MirkoZhou

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:
Code: [Select]

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:
Code: [Select]


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
 
}

Coding Badly

#1
Dec 05, 2017, 07:55 am Last Edit: Dec 05, 2017, 07:58 am by Coding Badly

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.


MirkoZhou

Thank you for your reply.

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

Coding Badly

#3
Dec 05, 2017, 09:32 pm Last Edit: Dec 05, 2017, 09:33 pm by Coding Badly

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


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?

aarg

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.
  ... with a transistor and a large sum of money to spend ...
Please don't PM me with technical questions. Post them in the forum.

MirkoZhou

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:
Code: [Select]

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:
Code: [Select]

#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);     
}

Coding Badly


Please do not cross-post.  Threads merged.


Coding Badly


Printing ndx and a should reveal your mistake.


MirkoZhou

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.

evanmars

How many characters do you think 404.20 is?

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?

Coding Badly

I tried to print the ndx, which was printed as 28.
Do you expect ndx to reach 28?


Delta_G

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.
If at first you don't succeed, up - home - sudo - enter.

Go Up