Finding the max and min value of sensor reading

Hello everybody,

I have been trying nearly all the ways and i opened this topic into discussion but got not proper answer..

I have a sensor and i would like to find the max and min value after 10 readings. any idea? basically put one for loop then save them into readings[index]

int min=0,max=0;
int readings[10];
for(int index=0; index<10; index++)
{
  readings[index] = analogRead(A0);

but how can i find and store max and min value among 10 values?

thanks for your help in advance

Set min to 1024, max to -1.
Within your loop, use an if to test whether the latest reading is less than min and if so, set min to the new value. Similar thing for max.

  minim = 1023;
  maxim = 0;

  for ( int i = 0; i < INBUF; i++){                                
    if ( x[chan][i] > maxim ) maxim = x[chan][i];
    if ( x[chan][i] < minim ) minim = x[chan][i];
  }

INFUF - is a size (10 in your case), x[] an array of samples

Hi,

Thanks for your answer. Here i have done something .I can see sensor reading and running average but can not see max and min value shows me always zero! Any idea?

 */
const int numReadings=5;
int readings[numReadings];            //Number of readings
int index;                           // the index of current reading
int sensorMin=1023;                  //min sensor value
int sensorMax=0;                     //max sensor value
int deltaMax;                        // Max_value- Average
int deltaMin;                        // Min_value- Average
int total;                           //the running total
int average;                         // The average

void setup() {
  
Serial.begin(9600);
pinMode(10, OUTPUT); 
pinMode(11, OUTPUT);

readings[index]=analogRead(A0);
for (int i=0 ;i<numReadings;i++)
readings[i]=0;
 
//record the min ,max sensor value
if (readings[index]<sensorMin){
sensorMin=readings[index]; 
}
if (readings[index]>sensorMax){
sensorMax=readings[index]; 
}
}

void loop() 
{
  
  total=total-readings[index];        //substract the last reading
  readings[index]=analogRead(A0);  //read from the sensor
  total=total+readings[index];         //add the reading in the total
  index=index+1;
  if (index >= numReadings)                
  index = 0;                           
  average=total /numReadings;          //running average
 
  deltaMax=sensorMax-average;     
  deltaMin=average-sensorMin;
  
if(deltaMax >1||deltaMin >1){
digitalWrite(11,LOW);
digitalWrite(10,LOW);
index=0 ;                                       //turn the beginning read the sensor again
}
if(deltaMax>average){
digitalWrite(11,LOW);
digitalWrite(10,readings[index]);
}
if(deltaMin<average){ 
digitalWrite(10,LOW);
digitalWrite(11,readings[index]);
}
Serial.println (average);
delay(100);
}
1 Like

You manually set the whole array to 0 before checking it against the max/min. 0 will always be >= 0, and 0 will always be < 1023. Set the array to the input data instead of initializing it to 0 directly before checking for min/max.

So your problem is,

for (int i=0 ;i<numReadings;i++)
readings[i]=0;

Hi,
Thanks for your reply..

I did not get exacyly what you mean.with this code readings*=0; i initialitze the array and fill the array with sensor readings.when i delete this sensor shows 0 for the average values then i say*
* *if (readings[index]<sensorMin){ sensorMin=readings[index]; } if (readings[index]>sensorMax){ sensorMax=readings[index]; }* *
and my codes shows me the sensor readings, average but my codes does not show the min and max values among sensor readings :S
* *//record the min ,max sensor value if (readings[index]<sensorMin){ sensorMin=readings[index]; } if (readings[index]>sensorMax){ sensorMax=readings[index]; } }* *

You can check this library too - Arduino Playground - Statistics -

It will give you min, max and the average and optional std_dev

You're calculating the average in your loop, but only calculating the min/max once in the setup function. Further, you calculate the min/max directly after initializing the entire array to 0. Of course they're going to read 0.

Hello again,

Yes now i am able to see the running average value of 5 readings and max value also.but i cant see min value..it always shows me ''0''

int sensorMin=1023;                  //min sensor value
int sensorMax=0;                     //max sensor value
void setup() {
Serial.begin(9600);
pinMode(10, OUTPUT); 
pinMode(11, OUTPUT);
readings[index]=analogRead(A0);
for (int i=0 ;i<numReadings;i++)
readings[i]=0;
}

void loop() 
{
//record the min ,max sensor value
if (readings[index]>sensorMax){
sensorMax=readings[index]; 
}
if (readings[index]<sensorMin){
sensorMin=readings[index]; 
}
total=total-readings[index];         //substract the last reading
readings[index]=analogRead(A0);  //read from the sensor
total=total+readings[index];         //add the reading in the total
index=index+1;
if (index >= numReadings)                
index = 0;  
average=total /numReadings;          //running average

any idea??

readings[index]=analogRead(A0);
for (int i=0 ;i<numReadings;i++)
readings[i]=0;

in this for loop you make all your readings 0 so the analogRead() you did is gone...

then in loop() you do

if (readings[index]<sensorMin){
sensorMin=readings[index];
}

which forces sensorMin to 0.

follow your code with paper and pencil and be the processor. Draw boxes for the variables and you will see.

Hi again,

Here i have changed the codes a little bit ..i see the max value and mix value perfectly! but average value shows always 0!

void setup() {
Serial.begin(9600);
pinMode(10, OUTPUT); 
pinMode(11, OUTPUT);
}

void loop() {
for (int i=0 ;i<numReadings;i++)
//read from the sensor
readings[index]=analogRead(A0);       //read from the sensor
//record the min ,max sensor value
sensorMax=sensorMax-readings[index];  //substract the last reading
if (readings[index]>sensorMax){
sensorMax=analogRead(A0); 
}
sensorMin=sensorMin+readings[index];  
if (readings[index]<sensorMin){
sensorMin=readings[index]; 
}

total=total-readings[index];          //substract the last reading
readings[index]=analogRead(A0);
total=total+readings[index];         //add the reading in the total
index=index+1;
if (index >= numReadings)                
index = 0;  
average=total /numReadings;          //running average 
deltaMax=sensorMax-average;     
deltaMin=average-sensorMin;

I really need your idea and help..thanks a lot in advance

What you still need to learn is improve your writing style/layout.
Press CTRL-T in the IDE autoformats the code and that improves readability a lot.
Furthermore some spaces and empty lines

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

  pinMode(10, OUTPUT); 
  pinMode(11, OUTPUT);
}

void loop() {

  for (int i=0 ;i<numReadings;i++)
    readings[index]=readings[index];           //read from the sensor

  //record the min ,max sensor value
  sensorMax = sensorMax - readings[index];  //substract the last reading
  if (readings[index] > sensorMax){
    sensorMax = analogRead(A0); 
  }
  sensorMin = sensorMin + readings[index];  
  if (readings[index] < sensorMin){
  sensorMin = readings[index]; 
  }

  total = total - readings[index];          //substract the last reading
  readings[index] = analogRead(A0);
  total=total + readings[index];         //add the reading in the total
  index=index + 1;
  if (index >= numReadings)                
  index = 0;  
  average = total /numReadings;          //running average 

  deltaMax = sensorMax - average;     
  deltaMin = average - sensorMin;

finally
sensorMax = sensorMax - readings[index];
can be shortenend to
sensorMax -= readings[index];

works also for += *= /= and some more

@robtillart

Thanks for the informative answer and tipps but i still did not solve the problem of calculation average value..
as i told in previous post that now i am able to read the sensor and find the max and min value ..however average value still shows ''0'' .

void setup() {
  Serial.begin(9600);
  pinMode(10, OUTPUT); 
  pinMode(11, OUTPUT);
}

void loop() {
  for (int i=0 ;i<numReadings;i++)
    readings[index]=analogRead(A0);   //read from the sensor
  //record the min ,max sensor value
  sensorMax-=readings[index];  //substract the last reading
  if (readings[index]>sensorMax){
    sensorMax=readings[index]; 
  }
  sensorMin+=readings[index];  //substract the last reading
  if (readings[index]<sensorMin){
    sensorMin=readings[index]; 
  }
  total-=readings[index];        //substract the last reading
  readings[index]=analogRead(A0);
  total+=readings[index];         //add the reading in the total
  index=index+1;
  if (index >= numReadings)                
    index = 0;  
  average=total /numReadings;          //running average

is it maybe i did not initialize the array? but when i make this then i cant get min and max values..:S
thanks for your help in advance

sensorMin+=readings[index]; //substract the last reading

code comment conflict

Simplified your code, may contain typo or so, not tested, but it should work with minor mods

int numReadings = 10;
int readings[10];
int index = 0;

int sensorMax = 0;
int sensorMin = 0;

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

  pinMode(10, OUTPUT); 
  pinMode(11, OUTPUT);

  sensorMax = analogRead(A0);
  sensorMin = sensorMax;
}

void loop()
{
  // MEASUREMENTS
  // every iteration of loop makes one additional measurement,
  // so the first 10 readings will display too low average
  int value = analogRead(A0);
  readings[index] = value;
  index++;
  if (index >= numReadings) index = 0;  

  // DO SOME MATH
  if (value > sensorMax) sensorMax = value; 
  if (value < sensorMin) sensorMin = value; 

  //running average
  float total = 0;
  for (int i = 0; i< numReadings; i++) total += readings[index];
  float average = total /numReadings;          

  // OUTPUT TO SERIAL
  Serial.print("\tMIN:\t");
  Serial.print(sensorMin);
  Serial.print("\tMAX:\t");
  Serial.print(sensorMax);
  Serial.print("\tAVG:\t");
  Serial.println(average, 1);  // 1 decimal
}

there was one typo in my code as I didn't check, now it should work

int numReadings = 10;
int readings[10];
int index = 0;

int sensorMax = 0;
int sensorMin = 0;

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

  pinMode(10, OUTPUT); 
  pinMode(11, OUTPUT);

  sensorMax = analogRead(A0);
  sensorMin = sensorMax;
}

void loop()
{
  // MEASUREMENTS
  // every iteration of loop makes one additional measurement,
  // so the first 10 readings will display too low average
  int value = analogRead(A0);
  readings[index] = value;
  index++;
  if (index >= numReadings) index = 0;  

  // DO SOME MATH
  if (value > sensorMax) sensorMax = value; 
  if (value < sensorMin) sensorMin = value; 

  //running average
  float total = 0;
  for (int i = 0; i< numReadings; i++) total += readings[i];
  float average = total /numReadings;          

  // OUTPUT TO SERIAL
  Serial.print("\tMIN:\t");
  Serial.print(sensorMin);
  Serial.print("\tMAX:\t");
  Serial.print(sensorMax);
  Serial.print("\tAVG:\t");
  Serial.println(average, 1);  // 1 decimal
}

output, as predicted it takes 10 readings to stabilize ..

	MIN:	680	MAX:	682	AVG:	68.2
	MIN:	680	MAX:	694	AVG:	137.6
	MIN:	680	MAX:	707	AVG:	208.3
	MIN:	680	MAX:	730	AVG:	281.3
	MIN:	680	MAX:	730	AVG:	349.5
	MIN:	657	MAX:	730	AVG:	415.2
	MIN:	657	MAX:	738	AVG:	489.0
	MIN:	637	MAX:	738	AVG:	552.7
	MIN:	637	MAX:	738	AVG:	622.3
	MIN:	637	MAX:	738	AVG:	691.0
	MIN:	633	MAX:	738	AVG:	686.1
	MIN:	633	MAX:	738	AVG:	689.6
	MIN:	633	MAX:	738	AVG:	682.2
	MIN:	633	MAX:	738	AVG:	674.7
	MIN:	633	MAX:	738	AVG:	676.7
	MIN:	615	MAX:	738	AVG:	672.5
	MIN:	615	MAX:	738	AVG:	668.2
	MIN:	615	MAX:	738	AVG:	668.8
	MIN:	615	MAX:	738	AVG:	661.6
	MIN:	615	MAX:	738	AVG:	663.5
	MIN:	604	MAX:	738	AVG:	660.6
	MIN:	604	MAX:	738	AVG:	654.2
	MIN:	604	MAX:	738	AVG:	656.4
...

@ robtillaart

Thanks a lot for your answer,i really appreciate it.
I have also tested the codes ,at the beginning it works ..(i am using a strain sensor so depending on position UP/DOWN the sensor value changes) so when i dont apply strain it shows ;

MIN: 374 MAX: 374 AVG: 74.8
MIN: 374 MAX: 374 AVG: 112.2
MIN: 374 MAX: 374 AVG: 149.6
MIN: 374 MAX: 374 AVG: 187.0
MIN: 374 MAX: 374 AVG: 224.4
MIN: 374 MAX: 374 AVG: 261.8
MIN: 374 MAX: 374 AVG: 299.2
MIN: 374 MAX: 374 AVG: 336.6
MIN: 374 MAX: 374 AVG: 374.0
MIN: 374 MAX: 374 AVG: 374.0
MIN: 374 MAX: 374 AVG: 374.0
MIN: 374 MAX: 374 AVG: 374.0
MIN: 374 MAX: 375 AVG: 374.1
MIN: 374 MAX: 375 AVG: 374.1

which is true..Now i apply strain in both directions and I stop applying strain [it supposed to come back the inital values);

MIN: 374 MAX: 375 AVG: 374.1
MIN: 374 MAX: 375 AVG: 374.1
MIN: 374 MAX: 375 AVG: 374.1
MIN: 374 MAX: 375 AVG: 374.1
MIN: 373 MAX: 375 AVG: 373.9
MIN: 373 MAX: 375 AVG: 374.0
MIN: 373 MAX: 375 AVG: 374.0
MIN: 373 MAX: 439 AVG: 385.2
MIN: 372 MAX: 439 AVG: 383.1
MIN: 369 MAX: 439 AVG: 380.9
MIN: 367 MAX: 439 AVG: 378.6
MIN: 365 MAX: 439 AVG: 376.3
MIN: 363 MAX: 439 AVG: 373.7
MIN: 362 MAX: 439 AVG: 371.4
MIN: 361 MAX: 439 AVG: 369.1
MIN: 361 MAX: 439 AVG: 365.6
MIN: 360 MAX: 439 AVG: 364.1
MIN: 360 MAX: 439 AVG: 362.9
MIN: 359 MAX: 439 AVG: 361.9
MIN: 359 MAX: 439 AVG: 360.1
MIN: 358 MAX: 439 AVG: 359.7
MIN: 358 MAX: 439 AVG: 359.5
MIN: 358 MAX: 439 AVG: 359.2
MIN: 358 MAX: 439 AVG: 358.7
MIN: 358 MAX: 439 AVG: 358.5
MIN: 357 MAX: 439 AVG: 358.3
MIN: 357 MAX: 439 AVG: 358.2
MIN: 357 MAX: 439 AVG: 358.0
MIN: 357 MAX: 439 AVG: 357.9
MIN: 357 MAX: 439 AVG: 357.8
MIN: 357 MAX: 439 AVG: 357.6
MIN: 357 MAX: 439 AVG: 357.6
MIN: 353 MAX: 439 AVG: 357.0
MIN: 353 MAX: 439 AVG: 357.1
MIN: 353 MAX: 439 AVG: 357.1
MIN: 353 MAX: 439 AVG: 357.8
MIN: 353 MAX: 439 AVG: 358.1
MIN: 353 MAX: 439 AVG: 393.6
MIN: 353 MAX: 443 AVG: 401.9
MIN: 353 MAX: 443 AVG: 406.5
MIN: 353 MAX: 443 AVG: 395.0
MIN: 353 MAX: 443 AVG: 394.8
MIN: 353 MAX: 443 AVG: 394.8
MIN: 353 MAX: 443 AVG: 395.2
MIN: 353 MAX: 443 AVG: 397.0
MIN: 353 MAX: 443 AVG: 401.7

as you see it works at the beginning but the values do not come back to their initial values when i stop applying strain.Therefore I am thinking in this way;

int sensorMax = 0;
int sensorMin = 1023;

//You have said 0 for both but we should set them min. high and read for anything lower than that

  sensorMax = analogRead(A0);        
  sensorMin = sensorMax;

I did not get this point..

abdkdrsnl:

  sensorMax = analogRead(A0);        

sensorMin = sensorMax;


I did not get this point..

I initialize both min and max with the first reading which is technically speaking 100% correct.
When you have only one reading it is the min and the max.

THis is a variation of the code that determines the min/max from the last 10 reads only, again the first 10 reads are biased.

int numReadings = 10;
int readings[10];
int index = 0;

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

  pinMode(10, OUTPUT); 
  pinMode(11, OUTPUT);
}

void loop()
{
  // MEASUREMENTS
  // every iteration of loop makes one additional measurement,
  // so the first 10 readings will display too low average
  int value = analogRead(A0);
  readings[index] = value;
  index++;
  if (index >= numReadings) index = 0;  

  //running average, min and max
  float total = 0;
  int sensorMax = 0;
  int sensorMin = 1023;
  for (int i = 0; i< numReadings; i++)
  {
    total += readings[i];
    if (readings[i] > sensorMax) sensorMax = readings[i]; 
    if (readings[i] < sensorMin) sensorMin = readings[i]; 
  }
  float average = total /numReadings;          

  // OUTPUT TO SERIAL
  Serial.print("\tMIN:\t");
  Serial.print(sensorMin);
  Serial.print("\tMAX:\t");
  Serial.print(sensorMax);
  Serial.print("\tAVG:\t");
  Serial.println(average, 1);  // 1 decimal
}

@robtillaart

Thanks a ton for your help and idea..after some small changes I have done it and now the codes is able to see running average,max and min values..
I want to go further though :slight_smile:

while there is no strain I would like to store my average value into average_offset variable..and then as I apply strain in up or down direction the average value will change but I want to keep the average_offset value same.(it must not change with average value somehow) and then depending on the comparison between average and average_offsett i will turn one of the led on.

within the loop it seems to be hard to keep the average_offsett value because this average_offset value will change when i do not apply any strain or when i come back to initial state....what about interrupts?

while there is no strain I would like to store my average value into average_offset variable..and then as I apply strain in up or down direction the average value will change but I want to keep the average_offset value same.(it must not change with average value somehow) and then depending on the comparison between average and average_offsett i will turn one of the led on.

I don't understand the above. It is ambiguous at best, these two parts conflict

    1. I would like to store my average value into average_offset variable*
    1. but I want to keep the average_offset value same*

The first states that average_offset will follow the value of average, the second denies it. Can you rephrase your needs?

  • is the average_offset a constant or is it a calculated value?
  • if calculated what does the formula looks like?
  • which inputs does this formula need

Sorry for being so vague..let me put the question in that way..

I have strain sensor and within the code as we have done before ,we read the sensor (eq 10 times) then we find the max ,mix and average value of this readings...when there is no applied strain the sensor will give only same value which is also max,min and average of the readings.

therefore I defined variables ; deltaMax=sensorMax-average ; deltaMin=average-sensorMin ; so when there is no strain deltaMax and deltaMin will be zero.By applying the strain in up or down direction these values will be non-zero and depending on thise cases leds for up and down position will be on or off.

Up to know I am able to see these values correctly..Here the problem starts...when I apply the strain in up or down position and hold it for a while the ''deltaMax and deltaMin'' values becomes 0 after 5 seconds because the max min values become same [which means there is no strain ] so even in the uppest position of sensor,,
Therefore I want to define a new variable '' average_offset'' ...while deltaMax and deltaMin= 0 ,average_offset=average; but this value must be same and every e.g 10 minutes I want to define ''new'' average_offset and go through the loop again..

So let me put in example [for 5 readings] readings ; 100,100,100,100,100 max=100, min=100,average=100,deltaMax and deltaMin= 0 so that average_offset=100
I apply strain and new reading =120 average=110 average_offset=100 ----reading >average_offset so strain is in UP directioon.

It is possible in this way ?

Thanks a lot!