In first part of this tutorial we started developing a wireless thermostat using Arduino Uno and one AirQ 305 control board. In that tutorial we designed a really simple thermostat that doesn’t interact with the user: the desired temperature is fully hardcoded inside the code and user can’t see the ambient temperature. In the second part of this tutorial we’ll push our thermostat to a more interesting level, adding a LCD display and two switches that allow to increase/decrease the wanted temperature. Moreover, we’ll remove the tmp36 temperature sensor attached to Arduino and we’ll use a more practical AirQ 100 wireless temperature sensor.
Bill of material
For this part of the tutorial we need the following material:
- One Arduino Uno.
- One AirQ ShielD for Arduino Uno.
- An AirQ 305 wireless relay board.
- An AirQ 100 low-cost wireless temperature sensor: different from the fist part of tutorial, we’ll use a wireless temperature sensor since it’s more practical to have the sensor separated from the Arduino. With a wireless sensor we are totally free to place it wherever we need. However, if you need to keep the budget low, you can simply rearrange this tutorial to use the tmp36 sensor.
- A character 16×2 LCD: we’ll use a cheap 16×2 LCD by Powertip (model PC1602F, which uses a compatible display driver for the Hitachi HD44780 display chip) but you are totally free to use every type of display.
- Two SPST switches.
The hardware setup
The hardware setup is quite simple also for this part of the tutorial. The following diagram, made with Fritzing, clearly shows wiring. This first step is connecting the LCD display. Since LCD consumes just 3mA when used without backlight, we can safely power it using Arduino. Next, we connect Contrast and R/W pins to GND since it’s not useful for our project to control them by digital pins. Next, we connect the R/S and Enable pins to Arduino pin 5 and 4 and finally we connect the databus lines D3..D7 to Arduino pins 3..0 (we use 4-bit mode to interface LCD, since update speed is not demanding for our project). The final step is connecting the switches. To reduce components, we connect them to ground and we’ll use internal Arduino pull-up resistors. In this way, when the digital pin is HIGH it means that the switch is unpressed; when it’s LOW the switch is pressed. We connect switches to pins 7 and 6. Compared to the first part of this tutorial, we removed the LED that signals if RELAY1 is ON or OFF: we’ll show this info directly on LCD.
The code
Here again, the code to drive our wireless thermostat is really simple.
#include <SoftwareSerial.h> #include <sNET.h> #include <LiquidCrystal.h> float setTemp = 17.5; // This variabile sets the desired ambient temperature char blank[] = " "; // Clears a LCD line char line1[16], line2[16]; uint8_t upBTN = 6; uint8_t downBTN = 7; sNET snet(2); LiquidCrystal lcd(5, 4, 3, 2, 1, 0); AIRQ305 *board; AIRQ101 *sensor; void lcdUpdate(char* line1, char *line2) { if(line1 != 0) { lcd.setCursor(0,0); lcd.print(blank); lcd.setCursor(0,0); lcd.print(line1); } if(line2 != 0) { lcd.setCursor(0,1); lcd.print(blank); lcd.setCursor(0,1); lcd.print(line2); } } /* Since Arduino sprintf lacks support for float conversion, this a convinient routine to convert a float to a string with a precision of 1 decimal */ char *float2char(float x) { static char str[5]; int i; i = x*10; /* 1 digit precision */ if(i> 0) sprintf(str, "%d.%d", i/10, i%10); else sprintf(str, "%d.%d", i/10, -i%10); return str; } void setup() { snet.begin(); lcd.begin(16, 2); pinMode(upBTN, INPUT); pinMode(downBTN, INPUT); digitalWrite(upBTN, HIGH); /* Enables pull-up resistors on both pins */ digitalWrite(downBTN, HIGH); /* We wait until both AIRQ 305 and AIRQ 100 are detected */ lcdUpdate("Waiting R1...", "Waiting sensor..."); while((board = (AIRQ305*)snet.getDeviceForDeviceID(5,0,1,3)) == 0) snet.processMessages(); lcdUpdate("Connected!", "Waiting sensor..."); while((sensor = (AIRQ101*)snet.getDeviceForDeviceID(101,2,1,0)) == 0) snet.processMessages(); lcdUpdate("Connected!", "Connected!"); } void loop() { /* sNET::processMessages() is responsibile to process messages coming from AirQ Networks devices and to update corresponding device object (in this example, the AIRQ305 and AIRQ100 objects). User code should call this method as soon as possible and continuosly */ snet.processMessages(); delay(150); //A little bit of debouncing if(!digitalRead(upBTN)) setTemp += 0.1; if(!digitalRead(downBTN)) setTemp -= 0.1; sprintf(line1, "Temp: %s", float2char(sensor->getTEMP())); sprintf(line2, "SET:%s - R1:%d", float2char(setTemp), board->getRELAY1()); lcdUpdate(line1, line2); if(sensor->getTEMP() > setTemp) /* Temperature raised too much: turn off bolier */ board->setRELAY1(OFF); else if(sensor->getTEMP() < setTemp) /* Temperature decreased too much: turn on bolier */ board->setRELAY1(ON, false); }
The first fifteen lines of code are all about declaring global variables and objects we use in the sketch. To drive LCD display we use excellent LiquidCrystal library and we create the lcd object passing as argument the digital pins where the LCD lines are connected to. Since this time we use two AirQ Networks wireless devices (one AirQ 305 relay board and one AirQ 100 wireless temperature sensor), we instantiate the sNET object passing the number 2 to the constructor: in this way, sNET library will create sufficient memory room to arrange messages coming from the two devices. lcdUpdate() is just a convenient function to update the two LCD lines without flooding our sketch with repeating lines of code. As the name suggests, float2char() is a function that converts a float to a string: since Arduino sprintf() function doesn’t support float conversion, we need a way to convert temperature to string in order to send it to the LCD. float2char() addresses this, giving a precision of one decimal (it simply truncates the float; eg: 18.24 -> 18.2). The setup() function is responsible to setup our sketch according the hardware configuration. We configure the digital pins attached to switches as INPUT pins, enabling Arduino internal pull-up resistors (this allows us to save two external pull-up resistors). Finally, we wait until both AirQ 305 and AirQ 100 are connected to AirQ ShielD. The loop() function is the core part of our wireless thermostat. Thanks to the sNET library we can create a wireless device with just thirteen lines of code! Isn’t this amazing? The code is really self-explaining. If one of upBTN or downBTN buttons is pressed, we increase/decrease the desired ambient temperature. When the current temperature is lower, we turn RELAY1 ON; otherwise we turn it OFF. The following video shows how thermostat works
The source code of this sketch is inside the example subdirectory of sNET repository, or it can directly downloaded using this link