temperature flickering.

Hello all.

Im trying to make Fan control depending on temperature.

I have 4 sensors and 3 is just for viewing ambient temperature in the room etc. (MCP9700 sensors)
but all readings im displaying on my LCD flickers at about 0.5. for instanse its now showing 24.2 degrees C but its flickering between 24.2 and 24.7 and sometimes down to 23.7.

Any ideas as to how this is ? is it because the input into my index is raw sensor readings ?

Do i need to convert the data into degree C before putting it into the index ? and if so how do i do that ?

#include <LiquidCrystal.h>
#include <Encoder.h>

LiquidCrystal lcd(7, 8, 9, 10, 11, 12);


const int numReadings1 = 20;
const int numReadings2 = 20;
const int numReadings3 = 20;
const int numReadings4 = 20;

int readings1[numReadings1];      // the readings from the analog input
int readings2[numReadings2];
int readings3[numReadings3];
int readings4[numReadings4];

int index1 = 0;                  // the index of the current reading
int index2 = 0;
int index3 = 0;
int index4 = 0;

int total1 = 0;                  // the running total
int total2 = 0;
int total3 = 0;
int total4 = 0;

int average1 = 0;                // the average
int average2 = 0;
int average3 = 0;
int average4 = 0;

float temp1;                    //float for calculating temperature
float temp2;
float temp3;
float temp4;

int inputPin1 = A0; //sensor 1
int inputPin2 = A1; //sensor 2
int inputPin3 = A2; //sensor 3
int inputPin4 = A3; //sensor 4

const int LED = 13; //warning light for sensor 1
const int FAN = 3; // cooling fan PWM controlled
const int potPin = A4; //input to adjust the light level PWM controlled

int tempMin = 40;
int tempMax = 70;
int fanSpeed;
int fanLCD;

const int analogInPin = A4;  // Analog input pin that the potentiometer is attached to
const int analogOutPin = 5; // Analog output pin that the LED is attached to

int sensorValue = 0;        // value read from the pot
int outputValue = 0;        // value output to the PWM (analog out)
int lightLCD = 0;           // PWM output for LED light


void setup()

{
  Serial.begin(9600);
  lcd.begin(20, 4);
  pinMode(LED, OUTPUT);
  pinMode(FAN, OUTPUT);
  pinMode(5, OUTPUT);

  // initialize all the readings to 0:
  for (int thisReading1 = 0; thisReading1 < numReadings1; thisReading1++)
    readings1[thisReading1] = 0;         
  for (int thisReading2 = 0; thisReading2 < numReadings2; thisReading2++)
    readings2[thisReading2] = 0;         
  for (int thisReading3 = 0; thisReading3 < numReadings3; thisReading3++)
    readings3[thisReading3] = 0;         
  for (int thisReading4 = 0; thisReading4 < numReadings4; thisReading4++)
    readings4[thisReading4] = 0;         
}

void loop() {

  

//1 temperatur sensor 1

  total1= total1 - readings1[index1];      
  readings1[index1] = analogRead(inputPin1);
  total1= total1 + readings1[index1];
  index1 = index1 + 1;     
  if (index1 >= numReadings1)
  index1 = 0;
  average1 = total1 / numReadings1;      
  temp1 = (average1 * 5.0 / 1024.0) - 0.5;
  temp1 = temp1 / 0.01;
  delay(1);        // delay in between reads for stability 
  
  
//2 temperatur sensor 2
  total2= total2 - readings2[index2]; 
  readings2[index2] = analogRead(inputPin2);
  total2= total2 + readings2[index2];
  index2 = index2 + 1; 
  if (index2 >= numReadings2)
  index2 = 0;
  average2 = total2 / numReadings2;        
  temp2 = (average2 * 5.0 / 1024.0) - 0.5;
  temp2 = temp2 / 0.01;
  delay(1);
  
//3 temperatur sensor 3
  total3= total3 - readings3[index3]; 
  readings3[index3] = analogRead(inputPin3);
  total3= total3 + readings3[index3];
  index3 = index3 + 1; 
  if (index3 >= numReadings3) 
  index3 = 0;
  average3 = total3 / numReadings3;        
  temp3 = (average3 * 5.0 / 1024.0) - 0.5;
  temp3 = temp3 / 0.01;
  delay(1);
  
//4 temperatur sensor 4
  total4= total4 - readings4[index4]; 
  readings4[index4] = analogRead(inputPin4);
  total4= total4 + readings4[index4]; 
  index4 = index4 + 1;  
  if (index4 >= numReadings4)  
  index4 = 0;
  average4 = total4 / numReadings4;    
  temp4 = (average4 * 5.0 / 1024.0) - 0.5;
  temp4 = temp4 / 0.01;
  delay(1); 
   
   
   // read the analog in value:          For light control. 
  sensorValue = analogRead(analogInPin);            
  // map it to the range of the analog out:
  outputValue = map(sensorValue, 0, 1023, 0, 255);  
  // change the analog out value:
  lightLCD = map(outputValue, 0, 255, 0, 100);
  analogWrite(analogOutPin, outputValue);   
  
  lcd.setCursor(0, 0);
  lcd.print("INDE ");
  lcd.print(temp1);
  lcd.setCursor(9, 0);
  lcd.print("  ");
  lcd.setCursor(0, 1);
  lcd.print("UDE  ");
  lcd.print(temp2);
  lcd.setCursor(9, 1);
  lcd.print("  ");
  lcd.setCursor(0, 2);
  lcd.print("KOLE ");
  lcd.print(temp3);
  lcd.setCursor(9, 2);
  lcd.print("  ");
  lcd.setCursor(0, 3);
  lcd.print("FAN  ");
  lcd.print(temp4); 
  lcd.setCursor(9, 3);
  lcd.print("  ");  
  
  
  
// Fan control according to temperature sensor 1  
if (temp1 < tempMin) {
    fanSpeed = 0;
    digitalWrite(FAN, LOW);
    }
    
if((temp1 >= tempMin) && (temp1 <= tempMax)) {
    fanSpeed = map(temp1, tempMin, tempMax, 32, 255);
    fanLCD = map(temp1, tempMin, tempMax, 0, 100);
    analogWrite(FAN, fanSpeed);
    }

// Warning light for temperature sensor 1    
if(temp1 > tempMax) {
  digitalWrite(LED, HIGH);
} else {
  digitalWrite(LED, LOW);
}

lcd.setCursor(11, 0);
lcd.print("FAN SPEED");
lcd.setCursor(11, 1);
lcd.print(fanLCD);
lcd.print("%");
lcd.setCursor(11, 2);
lcd.print("LYS");
lcd.setCursor(11, 3);
lcd.print(lightLCD);
lcd.print("%"); 
}
// initialize all the readings to 0:
  for (int thisReading1 = 0; thisReading1 < numReadings1; thisReading1++)
    readings1[thisReading1] = 0;         
  for (int thisReading2 = 0; thisReading2 < numReadings2; thisReading2++)
    readings2[thisReading2] = 0;         
  for (int thisReading3 = 0; thisReading3 < numReadings3; thisReading3++)
    readings3[thisReading3] = 0;         
  for (int thisReading4 = 0; thisReading4 < numReadings4; thisReading4++)
    readings4[thisReading4] = 0;

Waste of code space - they’re already zero.

Do you really need the granularity of .5 of a degree? Don't forget that loop() is being executed pretty damn fast which could cause flickering just from the frequent updates to the display.

Two things:

  1. if you can tolerate a .75 degree swing (or whatever), maintain a lastRead[5] array for the previous readings. If the current and previous temps are less than .75 degree apart, don't bother updating the display.

  2. do your analogRead()'s at some interval you can live with. If you really need one second updates, use the millis() function to build your own delay for one second (or whatever you need). As it stands now, updates are coming so fast the fan probably couldn't keep up anyway.

total1= total1 - readings1[index1];      
  readings1[index1] = analogRead(inputPin1);
  total1= total1 + readings1[index1];
  index1 = index1 + 1;     
  if (index1 >= numReadings1)
  index1 = 0;
  average1 = total1 / numReadings1;      
  temp1 = (average1 * 5.0 / 1024.0) - 0.5;
  temp1 = temp1 / 0.01;
  delay(1);        // delay in between reads for stability
total2= total2 - readings2[index2]; 
  readings2[index2] = analogRead(inputPin2);
  total2= total2 + readings2[index2];
  index2 = index2 + 1; 
  if (index2 >= numReadings2)
  index2 = 0;
  average2 = total2 / numReadings2;        
  temp2 = (average2 * 5.0 / 1024.0) - 0.5;
  temp2 = temp2 / 0.01;
  delay(1);

Repeated code screams "Function!"

AWOL:
Repeated code screams "Function!"

this screams "Arrays!"

int index1 = 0;                  // the index of the current reading
int index2 = 0;
int index3 = 0;
int index4 = 0;

int total1 = 0;                  // the running total
int total2 = 0;
int total3 = 0;
int total4 = 0;

int average1 = 0;                // the average
int average2 = 0;
int average3 = 0;
int average4 = 0;

float temp1;                    //float for calculating temperature
float temp2;
float temp3;
float temp4;

Thanks for the answers. I can see what you mean by the functions and will try that tomorrow (getting late here)

as for the array that one i dont get. (complete newbie at coding tbh,) whats the difference between index and array ?

ravsen:
Thanks for the answers. I can see what you mean by the functions and will try that tomorrow (getting late here)

as for the array that one i dont get. (complete newbie at coding tbh,) whats the difference between index and array ?

This will show how an array can be used to average temperature:

Ray

What you are seeing is to be expected, small scale changes include the very circuit you measure with.

The answer is hysteresis.

It's the way digital pins and thermostats and many other devices work and have for a long time now.

The set point for ON should be different from the set point for OFF, not a knife edge balance but a stable flat.

Digital pin goes from LOW to HIGH at a higher voltage than the switch from HIGH to LOW.

Hysteresis has inherent stability.

mrburnette:

ravsen:
Thanks for the answers. I can see what you mean by the functions and will try that tomorrow (getting late here)

as for the array that one i dont get. (complete newbie at coding tbh,) whats the difference between index and array ?

This will show how an array can be used to average temperature:
http://arduino.cc/en/Tutorial/Smoothing

Ray

Arrays are being used for smoothing, using the same technique set out in the tutorial.

Yes the array is being used for smoothing. The flickering is considerably lower when i use a 7V SMPS rather than the 5 V USB outlet and i can live with the SMPS. but the main thing here is i want the temperature to be displayed in .1 increments not either .7 or .2..

I think the problem lies in the average section.

The average takes the 10 raw readings and divides it by 10. and after that i make that data into temp via the * 5.0 / 1024.0 -0.5

But will it be better if i can get the converted data into the array and then use the average on that ? so if i divide the 10 readings (wich have already been converted into degree C) will that give me a better resolution on the output i give to the display ? so i get the .1 increment on the temperature displayed ?

And if so how do i get the converted data into the array ? ive tried converting it at the input into the array but it gives me an error when compiling.

HI, what are you using for temperature sensors? (Sorry just saw MCP9700)
How long are the leads between the arduino and the sensors?
Have you bypassed the analog inputs?

Tom...... :slight_smile:

Hi, just looked at the MCP9700 specs, its output is from 0 to 1.8V, 10mV/C. Gives 1.8/.01=180Deg range.

But only from 0 to 1.8V, you are using the 5V ref for the ADC.

So if 5V=1024 counts

1.8V= 1024 * 1.8/5=368 counts

180 range / 368 counts = 0.489 DegC per count. or close enough to 0.5, which is your readings "flicker".

You need to use a lower Vref to increase your resolution.

Tom....... :slight_smile:

Hi, back again.

 temp1 = temp1 / 0.01;

This is the last thing you do to get your temperature in DegC, you are multipying the temp by 100.
Hence you are multiplying any "flicker" by 100.

You would be better to calculate temperature for each analog read, THEN average.

Tom.... :slight_smile:
Can't believe it took me this long to see it all, must be getting old in my old age, or too many late nights and long days. LOL

Hence you are multiplying any "flicker" by 100.

And, since multiplication is orders of magnitude faster than division, you are doing it in the slowest way possible.

Hello Tom.

Thanks for your input.

The leads to the sensors are very short as they are all next to one another on the breadboard for now :wink:

And yes im using the 5Vref. You think i should go with the 1.1 Vref instead ?

I figured that my flickering was because i i do the calculation into degree after they have been averaged. but i cant for the life of me figure how to do it before ? any ideas ?

Thanks .

Hi, if your max input voltage is going to be 1.8V , then you would be advised to set it at 1.8V, 1.1V will give you better resolution but any temp over 1.1V will be 1023.
Ref 1.8V=180DegC so 180/1024=0.175DegC per count

Ref 1.1V=110DegC so 110/1024=0.107DegC per count.

What ever resolution you like, if its only room temp then 0.5DegC is probably fine, can you feel 0.5DegC difference in room temp?

Convert your analog input reading to temp immediately after your take the reading.
Then add the temp each time you loop, instead of the analog reading.
Then divide the summed result by the number of additions.

Its the same as you have been doing, just you do it with temperature instead of analog counts.

Tom...... :slight_smile:

TomGeorge:
Convert your analog input reading to temp immediately after your take the reading.
Then add the temp each time you loop, instead of the analog reading.
Then divide the summed result by the number of additions.

Its the same as you have been doing, just you do it with temperature instead of analog counts.

Tom… :slight_smile:

//1 temperatur sensor 1

  total1= total1 - readings1[index1];      
  readings1 = analogRead(inputPin1);
  readings1 = (readings1 * 5.0 / 1024.0) - 0.5;
  readings1[index1] = readings1 / 0.01;
  total1= total1 + readings1[index1];
  index1 = index1 + 1;     
  if (index1 >= numReadings1)
  index1 = 0;
  average1 = total1 / numReadings1;      
 // temp1 = (average1 * 5.0 / 1024.0) - 0.5;
 // temp1 = temp1 / 0.01;
  delay(1);        // delay in between reads for stability

so something like this then ? because this gives me an error ;

sketch_aug13a.ino: In function ‘void loop()’:
sketch_aug13a:86: error: incompatible types in assignment of ‘int’ to ‘int [20]’
sketch_aug13a:87: error: invalid operands of types ‘int [20]’ and ‘double’ to binary ‘operator*’
sketch_aug13a:88: error: invalid operands of types ‘int [20]’ and ‘double’ to binary ‘operator/’

or how should i go about it ? im unsure as to the workings of the [index1] after the readings1. is that a pointer that its in index1 or ??

readings1 = analogRead(inputPin1);

You can't assign an "int" to an array.
That's what the error message is telling you.

readings1 [someIndex] = analogRead(inputPin1);

Please use code tags when posting code.

sorry about that AWOL.

So how would you go about putting the converted sensor data into the array ?