Temperature Controller Relay Issue

Hello,

I am having some trouble with my temperature controller project. The issue is that when I plug in the relay the temperature reading jumps up 10 C from what it should be reading. The other problem I noticed was that when the temperature is reached the relay should shut off but instead it flickers on and off. I understand that this may be due to hysteresis but that should only occur when the signal is fluctuating around a specific temperature; in my case it flickers until I adjust the set point to less than 10C below the actual temp.

My design was based off this design:

but I am using a different temperature controller so I made some minor modifications to the code. I would ask the author of the project but the website will not let me create an account to leave a reply.

I attached my wiring diagram and code. I am looking for a solution to the temperature increase when I plug in my relay.

#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(9, 8, 7, 6, 5, 4);

const int LED_RED=10; //Red LED
const int LED_GREEN=11; //Green LED
const int RELAY=12; //Lock Relay or motor

//Key connections with arduino
const int up_key=3;
const int down_key=2;

int SetPoint=50;
//=================================================================
//                  SETUP
//=================================================================
void setup(){
  pinMode(LED_RED,OUTPUT);
  pinMode(LED_GREEN,OUTPUT);  
  pinMode(RELAY,OUTPUT);  
  pinMode(up_key,INPUT);
  pinMode(down_key,INPUT);
  
  //Pull up for setpoint keys
  digitalWrite(up_key,HIGH);
  digitalWrite(down_key,HIGH);
  
   // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Andre Chavez");  
  lcd.setCursor(0,1); //Move coursor to second Line
  lcd.print("Temp. Controller");
  digitalWrite(LED_GREEN,HIGH);  //Green LED Off
  digitalWrite(LED_RED,LOW);     //Red LED On
  digitalWrite(RELAY,LOW);       //Turn off Relay
  delay(2000);
}
//=================================================================
//                  LOOP
//=================================================================  
void loop(){
  double Temperature = (((5.0/1024.0) * analogRead(A4)) - 1.24) / 0.005;  //10mV per degree 0.01V/C. Scalling

  lcd.setCursor(0,0);
  lcd.print("Temperature:");    //Do not display entered keys
  lcd.print(Temperature);
  
//Get user input for setpoints  
  if(digitalRead(down_key)==LOW)
  {
    if(SetPoint>0)
    {
      SetPoint--;    
    }
  }
  if(digitalRead(up_key)==LOW)
  {
    if(SetPoint<150)
    {
      SetPoint++;
    }
  }

//Display Set point on LCD
  lcd.setCursor(0,1);
  lcd.print("Set Point:");
  lcd.print(SetPoint);
  lcd.print("C   ");

//Check Temperature is in limit
if(Temperature > SetPoint)
{
   digitalWrite(RELAY,LOW);    //Turn off heater
   digitalWrite(LED_RED,LOW);
   digitalWrite(LED_GREEN,HIGH);  //Turn on Green LED
}
else
{
  digitalWrite(RELAY,HIGH);    //Turn on heater
  digitalWrite(LED_GREEN,LOW);
  digitalWrite(LED_RED,HIGH);  //Turn on RED LED  
}

  delay(100); //Update at every 100mSeconds
}

Just a guess, but since you are mixing floating point and integer arithmetic in your temperature calculation, you may be getting a different result every time through "loop". Why not debug your program by showing the raw temperature value on the serial monitor?

Paul

AChavez:
when I plug in the relay the temperature reading jumps up 10 C from what it should be reading.

in my case it flickers until I adjust the set point to less than 10C below the actual temp.

Your code assumes that the analog reference voltage is 5.0V. My guess is that something about the relay is lowering the analog reference voltage causing the analog input to read 100 mV (0.1V) high. This causes the temperature calculation to come out 10°C high. Do you have a multimeter with which you can check the voltage at the AREF pin?

Of course if the relay turning on causes the temperature to jump up 10°C the relay will be shut off 10°C early. The relay will deactivate and the power rail will recover... bringing the measured voltage back down. The code will sense the "drop in temperature" and activate the relay again. The cycle repeats.

Your Fritzing picture shows and Adafruit AD8495 thermocouple breakout board with analogue output.
That can only be read properly with an external A/D with fixed reference voltage, e.g. the ADS1115.
Arduino's default Aref is too instable for that (>10C fluctuations and low resolution).
You should have bought a thermocouple breakout board with buildin A/D.
Leo..

What may also work is using the fixed internal reference for the ADC, by setting in you setup()

analogReference(INTERNAL2V56);

As that board will supply a 0-5V output, you also need a voltage divider to cut that by half (say 2x 10k resistors).

2.56volt Aref will only work if the Arduino used has a 2.56volt Aref.
An Uno only has 1.1volt Aref.
That could be used with a ~1:4 voltage divider (e.g 3k3 and 12k).

That circuits4you diagram (link in post#0) doesn't have a diode across the relay coil (bad mistake).
Use a 1N4148 or 1N4004.
I would also lower the base resistor to 470ohm.
Leo..

There is a trick that allow you to check the power rail voltage against the 1.1V +/- 10% internal reference. Run the sketch, send 'R' and use a good meter to measure the voltage on the AREF pin. Put the measured voltage in millivolts (should be between 1000 and 1200) into the sketch. Run the sketch again and send 'V' to read the current "+5V" voltage (should be around 5000 mV). Compare that to the voltage measured at the +5V pin. If the answer is not close enough, adjust the InternalReferenceMillivolts to get a closer result.

Now you can use "(getVccMillivolts()/1000.0)" in place of "5.0" in your sketch to get temperature reading less dependent on loads on the Vcc line.

void setup() {
  Serial.begin(115200);
  while (!Serial); // Wait for USB connection on Leonardo/Micro

  delay(1000);
  Serial.println("Send 'R' to measure reference voltage at AREF pin.");
  Serial.println("Send 'V' to measure supply voltage.");
}

void loop() {
  switch (Serial.read()) {
    case 'r':
    case 'R':
      analogReference(INTERNAL);
      delay(500);
      Serial.println("Now nmeasure reference voltage at the AREF pin.");
      Serial.println("Put that value in the sketch as .");
      break;

    case 'v':
    case 'V':
      Serial.print("Power rail (millivolts): ");
      Serial.println(getVccMillivolts());
      break;
  }
}

// Adjust this value to your boards specific internal BG voltage in millivolts
const unsigned long InternalReferenceMillivolts = 1080UL;

// Returns actual value of Vcc in millivolts
int getVccMillivolts() {
  // Set the analog reference to DEFAULT (AVcc == Vcc power rail)
  // Set the analog input to channel 14: the INTERNAL bandgap reference (1.1V +/- 10%)
  // REFS1 REFS0          --> 0b01   -Selects DEFAULT (AVcc) reference
  // MUX3 MUX2 MUX1 MUX0  --> 0b1110 -Selects channel 14, bandgap voltage, to measure
  ADMUX = (0 << REFS1) | (1 << REFS0) | (0 << ADLAR) | (1 << MUX3) | (1 << MUX2) | (1 << MUX1) | (0 << MUX0);
  delay(50);  // Let mux settle a little to get a more stable A/D conversion


  // Start a conversion to measure the INTERNAL reference relative to the DEFAULT reference.
  ADCSRA |= _BV( ADSC );
  // Wait for it to complete
  while (ADCSRA & (1 << ADSC));

  // Calculate the power rail voltage (reference voltage) relative to the known voltage
  return (InternalReferenceMillivolts * 1024UL) / ADC;
}

Yes, wanted to mention measuring/calibrating 5volt against 1.1volt Aref.
It guess OP is using (dirty) USB supply (the big temp jumps).
Then this has to be done dynamically in loop(), because relay current is changing Aref.

Maybe better/easier to just use 1.1volt Aref.
Leo..

johnwasser:
Your code assumes that the analog reference voltage is 5.0V. My guess is that something about the relay is lowering the analog reference voltage causing the analog input to read 100 mV (0.1V) high. This causes the temperature calculation to come out 10°C high. Do you have a multimeter with which you can check the voltage at the AREF pin?

Of course if the relay turning on causes the temperature to jump up 10°C the relay will be shut off 10°C early. The relay will deactivate and the power rail will recover... bringing the measured voltage back down. The code will sense the "drop in temperature" and activate the relay again. The cycle repeats.

John,

I do have a multimeter and I checked AREF voltage and when the relay is off it reeds 5v and I get the right temperature reading, when it is on it the DMM reads 4.89V and the temperature reading is 10 degrees higher than what it should be. Do I need to modify my code or my circuit to account for this? Or how do I work around this?

Power the relay from a separate 5V supply instead of through the Arduino.

Sounds like the power supply is weak, one or more connections are poor, or the relay is drawing too much power. Either sort out the power problem(s) or use the trick above to adjust the sketch dynamically as the power supply dips.

Okay I would like to power everything through the Arduino so I am ruling out the possibility of using a separate 5V power supply for now. I tried running the sketch provided by John but I am having issues incorporating that with my sketch. Is there an easier way to modify the temperature parameter like instead of using "5V" couldn't I use the actual voltage at ARef?

That you would like to doesn't necessarily make it a good idea, or even possible. Arduinos have very little power supply capability, and a relay may simply be too much - as you already found out.

On the other hand, if you would use a 5V power supply, you can power your Arduino with it as well (use the Vcc pin instead of the Vin pin) so you'd still have just one power supply.

So I tried using a separate 5V power supply to power the relay but the same issue occurs, the temperature jumps 10 degrees when the relay is engaged by the Arduino. So the current draw through digital pin 12 is causing the issue not the power supplying the relay. So I believe the only way to account for this is through modification of the code, which is what John suggested but I am having a hard time understanding how to incorporate that into my code. When I ran his code to measure the voltage at ARef I was getting values closer to 4mV not 1.1V. I am using an arduino uno and his code references to a Leonardo/micro so that may be causing the confusion here. I know I have to change my temperature calculation to use a reference voltage other than the 5V but what value or parameter do I use?

Pleas post your circuit diagram, as detailed as possible. Most likely there's a wrong connection somewhere, drawing too much current from your pin 12.

I have attached both my wiring diagram, the schematic for the relay I am using, and my code.

/* 
   Digital Temperature Controller
*/
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(9, 8, 7, 6, 5, 4);

const int LED_RED=10; //Red LED
const int LED_GREEN=11; //Green LED
const int RELAY=12; //Lock Relay or motor

//Key connections with arduino
const int up_key=3;
const int down_key=2;

int SetPoint=50;
//=================================================================
//                  SETUP
//=================================================================
void setup(){

// initialize serial communication at 9600 bits per second:
  Serial.begin(9600);
  
  pinMode(LED_RED,OUTPUT);
  pinMode(LED_GREEN,OUTPUT);  
  pinMode(RELAY,OUTPUT);  
  pinMode(up_key,INPUT);
  pinMode(down_key,INPUT);
  
  //Pull up for setpoint keys
  digitalWrite(up_key,HIGH);
  digitalWrite(down_key,HIGH);
  
   // set up the LCD's number of columns and rows: 
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Andre Chavez");  
  lcd.setCursor(0,1); //Move coursor to second Line
  lcd.print("Temp. Controller");
  digitalWrite(LED_GREEN,HIGH);  //Green LED Off
  digitalWrite(LED_RED,LOW);     //Red LED On
  digitalWrite(RELAY,LOW);       //Turn off Relay
  delay(2000);
}
//=================================================================
//                  LOOP
//=================================================================  
void loop(){
  double Temperature = (((5/1024.0) * analogRead(A4)) - 1.24) / 0.005;  //10mV per degree 0.01V/C. Scalling

  Serial.println(Temperature);

  lcd.setCursor(0,0);
  lcd.print("Temperature:");    //Do not display entered keys
  lcd.print(Temperature);
  
//Get user input for setpoints  
  if(digitalRead(down_key)==LOW)
  {
    if(SetPoint>0)
    {
      SetPoint--;    
    }
  }
  if(digitalRead(up_key)==LOW)
  {
    if(SetPoint<150)
    {
      SetPoint++;
    }
  }

//Display Set point on LCD
  lcd.setCursor(0,1);
  lcd.print("Set Point:");
  lcd.print(SetPoint);
  lcd.print("C   ");

//Check Temperature is in limit
if(Temperature > SetPoint)
{
   digitalWrite(RELAY,LOW);    //Turn off heater
   digitalWrite(LED_RED,LOW);
   digitalWrite(LED_GREEN,HIGH);  //Turn on Green LED
}
else
{
  digitalWrite(RELAY,HIGH);    //Turn on heater
  digitalWrite(LED_GREEN,LOW);
  digitalWrite(LED_RED,HIGH);  //Turn on RED LED  
}

  delay(100); //Update at every 100mSeconds
}
//=================================================================

AChavez:

That's a piece of Fritzy spaghetti. Not a readable circuit diagram. Even a rough hand-sketched one is better than this.

AChavez:

This is a clear circuit diagram (it's upside down, though).
About 2V for the LED, 0.7V for the transistor, so 150Ω with the remaining 2.3V means about 15 mA, that's reasonable and should not cause any problems. There's an LCD screen in play, that also draws quite some current so best be connected to the power supply directly as well.

Okay I finally took the advice of powering the relay, the sensor, and the LCD directly to a 5V source and that kind of fixed the problem of the 10C temperature jump but it still jumps 3C and I still get the chattering of the relay.

Relay circuit is drawn upside down, and therefore it's not easy to see that the transistor is connected wrong.
Emitter goes to ground, and collector to relay.

So what are you using. A relay with transistor, or the relay module in the fritzing picture.
Always post a REAL diagram and/or photo of the setup. Not a bloody Fritzing doodle.

If you had used a 3k3:12k divider on the output of your temp sensor, and 1.1volt Aref, then you wouldn't have needed a second 5volt supply (post#5).
A different (digital out) temp board would have been a better option.
Leo..

Hi,

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?
Please include, pin and component labels as well as power supplies.

Not a fritzy picture.

Can you post a picture of you project please, component layout could probably be a cause of the 3DegC jump due to daisy chain current.

Not a fritzy picture.

Thanks. Tom :slight_smile: