Code Help for an Arduino Temperature Controller

clownfish chris

Active Member
View Badges
Joined
Dec 25, 2015
Messages
284
Reaction score
254
Rating - 0%
0   0   0
I have built a few things now with Arduino. A dosing pump, and a light timer were the two major projects that were met with success. I have also built a digital thermometer that works very well. Now I am wanting to add a pair of solid state relays (shield) to turn on and off a heater and DIY chiller.

I added this code to my thermometer:

Code:
 if ((float)raw / 16.0 <= 26.5)
  {
    digitalWrite(Heat, HIGH);
    digitalWrite(Chill, LOW);
  }
if ((float)raw / 16.0 >= 27)
  {
    digitalWrite(Heat, LOW);
    digitalWrite(Chill, HIGH);
  }
  else
  {
    digitalWrite(Heat, LOW);
    digitalWrite(Chill, LOW);
  }

After adding if and else statements, every thing works just as it did before except that the relays do not trigger. I have tested them using "Blink" and they work fine. I believe the problem is in the if and else statements.

Take it easy in your explanations as I have a very crude understanding of C++ which is most likely my over all problem.

Complete Code:

Code:
#include <OneWire.h>
#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x3f, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
int Heat = 3;
int Chill = 5;

OneWire  ds(2);  // USE 4.7K PULL DOWN RESISTOR!!!

void setup() {
lcd.begin(16, 2);
lcd.backlight();
lcd.clear();
lcd.print("Hi Chris,");
delay(3000);
lcd.clear();
lcd.print("How are you? ");
delay(3000);
}

void loop() {
byte i;
byte present = 0;
byte type_s;
byte data[12];
byte addr[8];
float celsius, fahrenheit;

if ( !ds.search(addr)) {
ds.reset_search();
delay(250);
return;
}
for ( i = 0; i < 8; i++) {
}
if (OneWire::crc8(addr, 7) != addr[7]) {
return;
}
// the first ROM byte indicates which chip
switch (addr[0]) {
case 0x10:
type_s = 1;
break;
case 0x28:
type_s = 0;
break;
case 0x22:
type_s = 0;
break;
default:
return;
}
ds.reset();
ds.select(addr);
ds.write(0x44, 1);        // start conversion, with parasite power on at the end
delay(1000);     // maybe 750ms is enough, maybe not
// we might do a ds.depower() here, but the reset will take care of it.
present = ds.reset();
ds.select(addr);
ds.write(0xBE);         // Read Scratchpad
for ( i = 0; i < 9; i++) {           // we need 9 bytes
data[i] = ds.read();
}
int16_t raw = (data[1] << 8) | data[0];
if (type_s) {
raw = raw << 3; // 9 bit resolution default
if (data[7] == 0x10) {
// "count remain" gives full 12 bit resolution
raw = (raw & 0xFFF0) + 12 - data[6];
}
} else {
byte cfg = (data[4] & 0x60);
// at lower res, the low bits are undefined, so let's zero them
if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
//// default is 12 bit resolution, 750 ms conversion time
}
if ((float)raw / 16.0 <= 26.5)
  {
    digitalWrite(Heat, HIGH);
    digitalWrite(Chill, LOW);
  }
if ((float)raw / 16.0 >= 27)
  {
    digitalWrite(Heat, LOW);
    digitalWrite(Chill, HIGH);
  }
  else
  {
    digitalWrite(Heat, LOW);
    digitalWrite(Chill, LOW);
  }
celsius = (float)raw / 16.0;
fahrenheit = celsius * 1.8 + 32.0;
lcd.clear();
delay(500);
lcd.setCursor(0, 0);
lcd.print("Your Aquarium Is");
lcd.setCursor(0, 1);
lcd.print(celsius);
lcd.print(" C");
lcd.setCursor(9, 1);
lcd.print(fahrenheit);
lcd.print(" F");
delay(1000);
}

Thanks in advance!
 

Psiber_Syn

Valuable Member
View Badges
Joined
Sep 28, 2015
Messages
2,349
Reaction score
2,659
Rating - 0%
0   0   0
It looks as though your if statement should look like

If (this true)
This happens
Else if (this true)
This happens
Else (neither true)
This happens
 

ReeferMadness0347

Community Member
View Badges
Joined
Jun 11, 2018
Messages
70
Reaction score
68
Rating - 0%
0   0   0
I’ve written quite a bit of code. Not a lot for arduino specifically but generally it’s the same with the 8 languages I’ve learned, when writing a new piece or part like this, I’d start with a fresh script. If needed load some demo data into a variable you can use for testing. It makes debugging much easier.
 

DarkSky

Well-Known Member
View Badges
Joined
Jan 23, 2017
Messages
863
Reaction score
1,051
Location
Minneapolis, MN
Rating - 0%
0   0   0
if ((float)raw / 16.0 <= 26.5) { digitalWrite(Heat, HIGH); digitalWrite(Chill, LOW); } if ((float)raw / 16.0 >= 27) { digitalWrite(Heat, LOW); digitalWrite(Chill, HIGH); } else { digitalWrite(Heat, LOW); digitalWrite(Chill, LOW); }

With this code block your heater will always be set to LOW. This is why:
Code:
//if raw / 16 is less than or equal to 26.5, set heater to high
if ((float)raw / 16.0 <= 26.5)
{
   digitalWrite(Heat, HIGH);
   digitalWrite(Chill, LOW);
}
//if raw / 16 is greater or equal to 27, set heater to low
if ((float)raw / 16.0 >= 27)
{
   digitalWrite(Heat, LOW);
   digitalWrite(Chill, HIGH);
}
else // set heater to low if condition above isn't true
{
   digitalWrite(Heat, LOW);
   digitalWrite(Chill, LOW);
}

Because your two statements are not joined in an "else if" block, it will evaluate and run both.

To make this section a bit more readable, you can do this:
Code:
temp = (float)raw/16;
if (temp <= 26.5)
{
     digitalWrite(Chill, LOW);
     digitalWrite(Heat, HIGH);
}
else if (temp >= 27.0)
{
     digitalWrite(Heat, LOW);
     digitalWrite(Chill, HIGH);
}
else {
     digitalWrite(Heat, LOW);
     digitalWrite(Chill, LOW);
}
 
Back
Top