Tijekom pandemije COVID-19, e-radionica.com nastavlja s normalnim radom. Sve mjere opreza se redovno poduzimaju te su naručeni paketi sigurni. Opcija dostave uslugama Hrvatske Pošte i osobno preuzimanje privremeno su onemogućeni iz sigurnosnih razloga.

  • Worldwide Shipping

  • 24/7 Customer Support

  • FAQ
  • Worldwide Shipping

  • 24/7 Customer Support

  • FAQ

Adjustable thermostat with relay

What do I get with this tutorial?

First of all, the aim of this tutorial is to combine more modules with Croduino, and show it in a specific example. To combine means to make mutual conditions and correlations of certain readings and display them, i.e. control them. The modules we will use are in the table on the right, and most of them can be found in the CSP Hobby set.

Finally, we will get a device which will, depending on the temperature, turn the relay (heater) on, or off. The temperature at which this happens will be adjustable using keypad, and everything mentioned will be read on the LCD display.

List of components and individual tutorials:
Croduino Basic2 - driver installation
DHT11 - HUM
Matrix membrane keyboard - HUM
LCD 16x2 - HUM
Relay - product review

Module connecting

All modules have already been individually processed in HUMHow to use module tutorials. Therefore, we will not do the same again. In the previous chapter, you can find links for individual tutorials. Now connect the module, as shown in the picture below, and we will immediately begin with programming.

Podesivi termometar fritzing

All modules in one sketch

The plan is to copy a part of the code from the HUM tutorials needed for each module separately. After that, we will write the necessary conditions and fuctions for certain variables. So let's go..

DHT11

NOTE: make  sure you have previously installed the necessary libraries, as written in the HUM tutorials 

#include "dht.h" // adding dht library
// needs to be defined for readings off the DHT
dht DHT;
#define dht_dpin A0 //data pin DHT11 on the A0 Croduino pin
int ocitanaTemp = 0;
void setup(){
}
void loop(){
// reading the DHT11 condition
// this command saves the temperature reading to "DHT.temperature"
DHT.read11(dht_dpin);
// saving the temperature reading in the ocitanaTemp variable
ocitanaTemp = DHT.temperature;
delay(800); // the minimum clearance between readings from the DHT11 is 800ms
}

Matrix Membrane Keypad

NOTE: later on, we will only add new parts to the existing code, as indicated in the comments.

// PREDEFINING
#include "Keypad.h" // adding library Keypad
// needs to be defined for the Matrix keypad
const byte red = 4; // keypad has 4 rows
const byte stupac = 4; // and 4 columns
char tipke[red][stupac] = { // define position of the keys on the keypad
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte red_pinovi[red] = {7,6,5,4}; // we connect the row pins to PIN9, PIN8, PIN7, PIN6, one after the other
byte stupac_pinovi[stupac] = {3,2,1,0}; // and the column pins to PIN5, PIN4, PIN3, PIN2, one after the other
Keypad tipkovnica = Keypad(makeKeymap(tipke), red_pinovi, stupac_pinovi, red, stupac);
// we will listen to the pressed key using: "tipkovnica.getKey()"
// VOID SETUP()
// nothing here
// VOID LOOP()
// nothing here
// we will listen to the pressed key using "tipkovnica.getKey()"

LCD 16x2

// PREDEFINING
#include "LiquidCrystal_I2C.h" // adding a library necessary for the LCD
#include "Wire.h" // since we use I2C for the LCD
// needs to be defined for the LCD
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
// VOID SETUP()
lcd.begin(16,2); // adjust LCD to 16x2
lcd.backlight(); // turn the backlighting of the LCD on
// write out a greeting message
lcd.setCursor(0,0); // set the writing cursor to the first column and first row
lcd.print("Termostat"); // make sure that the String does not exceed 16 characters
lcd.setCursor(0,1) // set the cursor to the first column, second row
lcd.print("e-radionica.com");
// VOID LOOP()
// nothing for now

Relay

// PREDEFINING
int relej = 8; // we connect the relay to D8
// VOID SETUP()
pinMode(relej, OUTPUT); // defining relay as an output component
// VOID SETUP
// nothing here

The Sketch now looks like this:

#include "dht.h" // adding dht library
#include "Keypad.h" // adding library Keypad
#include "LiquidCrystal_I2C.h" // adding a library necessary for the LCD
#include "Wire.h" // since we use I2C for the LCD
// needs to be defined for readings off the DHT
dht DHT;
#define dht_dpin A0 //data pin DHT11 on the A0 Croduino pin
int ocitanaTemp = 0;
// needs to be defined for the Matrix keypad
const byte red = 4; // Keypad has 4 rows
const byte stupac = 4; // and 4 columns
char tipke[red][stupac] = { // define position of the keys on the keypad
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte red_pinovi[red] = {7,6,5,4}; // we connect the row pins to PIN9, PIN8, PIN7, PIN6, one after the other
byte stupac_pinovi[stupac] = {3,2,1,0}; // we connect the column pins to PIN5, PIN4, PIN3, PIN2, one after the other
Keypad tipkovnica = Keypad(makeKeymap(tipke), red_pinovi, stupac_pinovi, red, stupac);
// we will listen to the pressed key using: "tipkovnica.getKey()"
// needs to be defined for the LCD
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
// needs to be defined for the relay
int relej = 8; // we connect the relay to D8
void setup(){
pinMode(relej, OUTPUT); // defining relay as an output component
lcd.begin(16,2); // adjust LCD to 16x2
lcd.backlight(); // turn the backlighting of the LCD on
// write out greeting message
lcd.setCursor(0,0); // set the writing cursor to the first column and first row
lcd.print("Termostat"); // make sure that the String does not exceed 16 characters
lcd.setCursor(0,1); // set the cursor to the first column, second row
lcd.print("e-radionica.com");
delay(1000); // let's have this message displayed for 1 second
lcd.clear(); // after which we will delete it
}
void loop(){
// reading the DHT11 condition
// this command saves the temperature reading to "DHT.temperature"
DHT.read11(dht_dpin);
// saving the temperature reading in the ocitanaTemp variable
ocitanaTemp = DHT.temperature;
delay(800); // the minimum clearance between readings from the DHT11 is 800ms
}

Writing conditions

For starters, let's print the temperature reading from the DHT11 sensor. We will make a special function which will do it. The function "Ispis()" can be written down before or after "setup()" and "void()" functions.

// the function which prints out readings
void Ispis() {
// DHT11 sensor temperature reading print
lcd.clear(); // delete everything previously written on the LCD
lcd.setCursor(0,0); // set the cursor to the first column, first row
lcd.print("Ocitano:" + String(ocitanaTemp));
}

It is time for us to set up the menu, in that menu we will designate the temperature at which the relay will turn on. We will set up the menu so that the key "#" on a membrane keypad opens the menu. Therefore, when we press the key "#", the menu, which will save the entry of the "set temperature", will open. Explanation in the code below.

// PREDEFINING
// for more about types of variables, check: https://e-radionica.com/hr/blog/2015/10/18/arduino-ide-varijable/
int podesenaTemp = 0; // a variable in which we save the set temperature
String unosString = ""; // a string variable in which we will "build" a keypad entry
boolean boolUnosTemp = false; // the condition of entry and exit from the menu

Now, let's write a piece of code that will listen when the key which calls up the menu - "#" is pressed. We want the sketch to constantly be able to enter the menu so we write it under void loop() . 

// VOID LOOP()
char pritisnuto = tipkovnica.getKey(); // the pressed key is saved to the pressed variable
// because of the delay(800) which is necessary for reading off the DHT11
// it is possible that the key will have to be held pressed for 800ms
// in order for it to be registered by this part of sketch
// the entry to Menu for setting temperature
if( pritisnuto == '#' && boolUnosTemp == false) { // if the key '#' is pressed and we have not yet entered the menu
boolUnosTemp = true; // we have entered the Menu
// print the text of the Menu
lcd.clear();
lcd.setCursor(0,0);
lcd.print("postavi temp:");
unosString = "";
// let's make a loop which will listen to the entry of temperature, up until we have pressed the key "#" again
// after which we will exit the Menu
while( boolUnosTemp == false)
{
// save the pressed button to "unos"
char unos = tipkovnica.getKey();
// since we want only numbers in temperature, every other character must be ignored:
// if one of the above conditions is satisfied, the entry is a "blank" char
if( unos == 'A' || unos == 'B' || unos == 'C' || unos == 'D' || unos == '*' ) unos = '\0';
// yet, if the "#" is pressed, we will exit the menu, then print out and compare the entered temperature
else if( unos == '#' ) {
boolUnosTemp = false; // this will come out of the given while
unos = '\0'; // we do not want anything to be added to our unosString
}
// let's save every individual key to one string, which will later be compared to current temperature
// and taking that into consideration, turn the relay on or off
unosString += String(unos);
//printing out what we are writing
lcd.setCursor(0,1);
lcd.print(unosString);
}
}

unosString is a set temperature of our system. So, let's add this temperature to the print out of the LCD printing function, which now looks like this :

// function printing out the readings
void Ispis() {
// DHT11 sensor temperature reading print
lcd.clear(); // delete everything previously written on the LCD
lcd.setCursor(0,0); // set the cursor to first column, first row
lcd.print("Ocitano:" + String(ocitanaTemp));
// printing out the temperature set in the Menu
lcd.setCursor(0,1); // we set the cursor to the first column, second row
lcd.print("Podeseno:" + unosString);
}

In order for the relay to constantly turn on or off, considering the read and appointed temperature, in the loop, it is necessary to set a condition:

// the condition under which the relay turns on, or off
// in case the set temperature is lower than the read temperature, turn the relay on
if( unosString.toInt() > ocitanaTemp ) digitalWrite(relej, HIGH);
// turn the relay off in every other case
else digitalWrite(relej, LOW);

If we do not want the temperature we have set when resetting the Croduino or when losing the power on the board to be lost, we must save it to EEPROM controller memory. Read more about it in the EEPROM tutorial.

// PREDEFINING
#include "EEPROM.h"
// we read the value saved to the EEPROM memory address
// to that address, we will save every change we make in this variable
String unosString = String(EEPROM.read(10));
// VOID LOOP()
// in the place where we made changes to the variables, it is necessary to save them to the EEPROM memory
//we save the changes to EEPROM memory 10 address
EEPROM.write(10,unosString.toInt());

We can additionally define keys A, B, C and D as predefined values of the set temperature.

// VOID LOOP()
// if the key 'A' is pressed, set the temperature to 15 degrees
else if( pritisnuto == 'A' ) unosString = "15";
// if the key 'B' is pressed, set the temperature to 20 degrees
else if( pritisnuto == 'B' ) unosString = "20";
// if the key 'C' is pressed, set the temperature to 25 degrees
else if( pritisnuto == 'C' ) unosString = "25";
// if the key 'D' is pressed, set the temperature to 30 degrees
else if( pritisnuto == 'D' ) unosString = "30";

The whole, final code

The whole, final code is a bit messy and you can copy it here. It contains a bunch of comments so you can skip the passage above. If you have a problem understanding it, you can always take a peek there for further clarification.

The aim of this tutorial is to, in the example, show logic after which we encourage you to write the code yourselves. The same menu can be written in many ways and is a great practice. If you have any trouble, feel free to contact us with specific questions (please comment the code). Do not forget to install the necessary libraries.

#include "dht.h" // adding dht library
#include "Keypad.h" // adding Keypad library
#include "LiquidCrystal_I2C.h" // adding the necessary library for the LCD
#include "Wire.h" // since we use I2C for the LCD
#include "EEPROM.h"
// needs to be defined for readings off the DHTa
dht DHT;
#define dht_dpin A0 //data pin DHT11 on the A0 Croduino pin
int ocitanaTemp = 0;
// needs to be defined for the Matrix keypad
const byte red = 4; // keypad has 4 rows
const byte stupac = 4; // and 4 columns
char tipke[red][stupac] = { // define key positions on the keypad
{'1','2','3','A'},
{'4','5','6','B'},
{'7','8','9','C'},
{'*','0','#','D'}
};
byte red_pinovi[red] = {7,6,5,4}; // we connect the row pins to PIN9, PIN8, PIN7, PIN6, one after the other
byte stupac_pinovi[stupac] = {3,2,1,0}; // we connect the column pins to PIN5, PIN4, PIN3, PIN2, one after the other
Keypad tipkovnica = Keypad(makeKeymap(tipke), red_pinovi, stupac_pinovi, red, stupac);
// we will listen to the pressed key using: "tipkovnica.getKey()"
// needs to be defined for the LCD
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
// needs to be defined for the relay
int relej = 8; // relej spajamo na D8
// additional menu settings
int podesenaTemp = 0; // the variable in which we will save the set temperature
// reading the value saved to the EEPROM memory 10 address
// to that address we will save every change made in this variable
String unosString = String(EEPROM.read(10)); // string variable in which we "build" the keypad entry
boolean boolUnosTemp = false; // the condition of entry and exit from the menu
void setup(){
pinMode(relej, OUTPUT); // defining relay as an output component
lcd.begin(16,2); // adjust the LCD to 16x2
lcd.backlight(); // turn the backlighting of the LCD on
// write out a greeting message
lcd.setCursor(0,0); // set the writing cursor to the first column and first row
lcd.print("Termostat"); // make sure that the String does not exceed 16 characters
lcd.setCursor(0,1); // set the cursor to the first column, second row
lcd.print("e-radionica.com");
}
void loop(){
// reading the DHT11 condition
// this command saves the temperature reading to "DHT.temperature"
DHT.read11(dht_dpin);
// we save the temperature reading to the variable ocitanaTemp
ocitanaTemp = DHT.temperature;
char pritisnuto = tipkovnica.getKey(); // the pressed key is saved to the variable pressed
// because of the delay (800) which is necessary for reading off the DHT11
// it is possible that the key will have to be held pressed for 800ms
// in order for it to be registered as this part of sketch
// entering the menu for setting temperature
if( pritisnuto == '#' && boolUnosTemp == false) { // if the "#" key is pressed and we have not already entered the menu
boolUnosTemp = true; // we have entered the Menu
// print the text of the Menu
lcd.clear();
lcd.setCursor(0,0);
lcd.print("postavi temp:");
unosString = "";
// let's make a loop which will listen to the entry of temperature, up until we have pressed the key '#' again
// after which we will exit the Menu
while( boolUnosTemp == false)
{
// save the pressed key to "unos"
char unos = tipkovnica.getKey();
// since we only want numbers in temperature, every other character must be ignored:
// if one of the above conditions is satisfied, the entry is a "blank" char
if( unos == 'A' || unos == 'B' || unos == 'C' || unos == 'D' || unos == '*' ) unos = '\0';
// yet, if the '#' key is pressed, we will exit the Menu, then print out and compare the entered temperature
else if( unos == '#' ) {
boolUnosTemp = false; // this will come out of the given while
unos = '\0'; // we do not want anything to be added to our unosString
}
// we save every individual key to one string, which will later be used for comparison to the current temperature
// and taking that into consideration, turn the relay on or off
unosString += String(unos);
// printing out what we are writing
lcd.setCursor(0,1);
lcd.print(unosString);
// saving changes to EEPROM memory address 10
EEPROM.write(10,unosString.toInt());
}
}
// other condition, for keys A,B,C i D
// if the key 'A' is pressed, set the temperature to 15 degrees
else if( pritisnuto == 'A' ) unosString = "15";
// if the key 'B' is pressed, set the temperature to 20 degrees
else if( pritisnuto == 'B' ) unosString = "20";
// if the key 'C' is pressed, set the temperature to 25 degrees
else if( pritisnuto == 'C' ) unosString = "25";
// if the key 'D' is pressed, set the temperature to 30 degrees
else if( pritisnuto == 'D' ) unosString = "30";
// the condition under which the relay turns on or off
// in case the set temperature is lower than the read temperature, turn the relay on
if( unosString.toInt() > ocitanaTemp ) digitalWrite(relej, HIGH);
// turn the relay off in every other case
else digitalWrite(relej, LOW);
delay(800); // the minimum clearance between readings off the DHT11 is 800ms
}
// a function which prints out the readings
void Ispis() {
// DHT11 sensor temperature reading print
lcd.clear(); // delete everything previously written on the LCD
lcd.setCursor(0,0); // set the cursor to the first column, first row
lcd.print("Ocitano:" + String(ocitanaTemp));
// printing out the temperature set in the Menu
lcd.setCursor(0,1); // we set the cursor to the first column, second row
lcd.print("Podeseno:" + unosString);
}
Leave a Reply