Thermostat with Arduino and touchscreen

..Hi, dear techno frieds (obviously male and female)!
My holidays unfortunately ended some day ago, and now it’s time to restart the work in my garret (and in the Garretlabs). It seems that your visits to my little blog during August increased…so many many many (many) thanks to you all! ๐Ÿ™‚
Once returned from my vacation, my dear friend Luka Cekka (it isn’t his real name, so he isn’t a Russian guy, but a real Italian guy, and he is a “spitting image” of Tim Robbins in “Antitrust”…have you seen the movie? ๐Ÿ˜‰ ) asked to me to realize a thermostat with touch screen for his new house thermo installation.

LukaCekka

My friend Tim Robbins… ehmm Luka Cekka! ๐Ÿ˜‰

So… I realized the first prototype using my old friend Arduino UNO, a temperature and humidity DHT22 sensor and the well known Adafruit TFT 2.8” touchscreen. (http://www.adafruit.com/products/1651). As usual, I bought the touchscreen from Robot Italy, my preferred italian store!
Well, in order to extract the necessary pins for DHT22 and a led (used as alarm monitor for the thermostat), I inserted between Arduino and the TFT screen a cheap proto shield (from Sparkfun) modified and transformed in a very useful “breakout shield”.

Once created the “sandwich” with Arduino, the breakout shield and the TFT, I connected to Arduino the DHT22 and the alarm led on the breadboard.
This is the Fritzing diagram (please, see the note and pay attention to the use of Arduino pins in order to drive the Adafruit TFT):

Cekka_controller_v1(one temp sensor)_bb
Regarding the software, I started using the following ad-hoc DHT22 library (and one very useful example found on internet) and verifying that the sensor was OK (and the alarm led ON/FF strategy).
Secondly, I added the code to manage the visualization of the temp on TFT, starting from the well coded examples from Adafruit libraries.
I decided to have two software modes: in the “temps” mode you can see the actual temperature acquired from DHT22. In this mode you can touch the software button “SETUP” on the touchescreen in order to enter “setup” mode. In “setup” mode you can adjust the alarm temperature using two software buttons on the touchscreen (one “+” button and one “-” button). You can return to “temps” mode touching the “TEMPS”software button. …All simple! ๐Ÿ˜‰

This is the complete Arduino code for my application:

#include "DHT.h"
#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ILI9341.h>
#include <Adafruit_STMPE610.h>

//Adafruit screen data
// This is calibration data for the raw touch data to the screen coordinates
#define TS_MINX 150
#define TS_MINY 130
#define TS_MAXX 3800
#define TS_MAXY 4000

//define screen and touch screen plus control signals
#define STMPE_CS 8
Adafruit_STMPE610 ts = Adafruit_STMPE610(STMPE_CS);
#define TFT_CS 10
#define TFT_DC 9
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC);

//temperatures frame
#define FRAME_X_T 80
#define FRAME_Y_T 6
#define FRAME_W_T 150
#define FRAME_H_T 150
//button frame
#define FRAME_X_B 210
#define FRAME_Y_B 180
#define FRAME_W_B 100
#define FRAME_H_B 50

//declare temp sensor
DHT dht;

//declare inital default max temp (setpoint) in order to signal an alarm
float max_temp=27.0;

//display modes--->used to define the menu (in the right-low corner) button text and behaviour
 #define MODE_TEMPS 1
 #define MODE_SETUP 2
 int current_display_mode=MODE_TEMPS;//at startup we see the temps..
 //coords and dimension for the + and - buttons, used to set max temps...
 #define X_PLUS_B 224
 #define X_MINUS_B 270
 #define Y_PLUS_B 3
 #define BUTTON_W 40
 #define BUTTON_H 35

void setup()
 {
   //serial
   Serial.begin(9600);
   Serial.println();
   Serial.println("Status\tHumidity (%)\tTemperature (C)\t(F)");
   //Use pin D2 to read temp/hum from DHT22
   dht.setup(2);
   //set pin D5 to output (alarm pin)
   pinMode(5,OUTPUT);
   
   //initialize touch screen
   tft.begin();
   if (!ts.begin()) {
      Serial.println("Unable to start touchscreen.");
   }
   else {
      Serial.println("Touchscreen started.");
   }
   tft.fillScreen(ILI9341_BLUE);
   // origin = left,top landscape (USB left upper)
   tft.setRotation(1);
   
   //draw button TS
   drawMenuButton(current_display_mode);
 }

void loop()
 {
   //set delay
   delay(dht.getMinimumSamplingPeriod());

   //get values from DHT22
   float humidity = dht.getHumidity();
   float temperature = dht.getTemperature();
   
   //debug: print value on serial
   Serial.print(dht.getStatusString());
   Serial.print("\t");
   Serial.print(humidity, 1);
   Serial.print("\t\t");
   Serial.print(temperature, 1);
   Serial.print("\t\t");
   Serial.println(dht.toFahrenheit(temperature), 1);
   
   //print value on Adafruit screen
   if (current_display_mode==MODE_TEMPS)
   {
      drawFrameT();
      RefreshTemp1Value(temperature);
   }
   else if (current_display_mode==MODE_SETUP)
   {
      //nothing
   }
   
   //Management of max temp in order to activate the alarm (led)
   if (temperature>=max_temp)
   {
      //set HIGH alarm pin (D5)
      digitalWrite(5,HIGH);
   }
   else
   {
      digitalWrite(5,LOW);
   }
 
   //Management of Adafruit touchscreen
   // See if there's any touch data for us
   if (!ts.bufferEmpty())
   {
       // Retrieve a point
       TS_Point p = ts.getPoint();
       // Scale using the calibration #'s
       // and rotate coordinate system
       p.x = map(p.x, TS_MINY, TS_MAXY, 0, tft.height());
       p.y = map(p.y, TS_MINX, TS_MAXX, 0, tft.width());
       int y = tft.height() - p.x;
       int x = p.y;

       //check if the Menu button is pressed
       if((x > FRAME_X_B) && (x < (FRAME_X_B + FRAME_W_B)))
       {
          if ((y > FRAME_Y_B) && (y <= (FRAME_Y_B + FRAME_H_B)))
          {
              if (current_display_mode==MODE_TEMPS)
              {
                  current_display_mode=MODE_SETUP;
                  tft.fillScreen(ILI9341_BLACK);
                  drawMenuButton(current_display_mode);
                  
                  //draw the Temp max set points controls
                  drawCurrentMaxTemp1(max_temp);
              }
              else
              {
                  current_display_mode=MODE_TEMPS;
                  tft.fillScreen(ILI9341_BLUE);
                  drawMenuButton(current_display_mode);
              }
          }
      }

      //check if + or - buttons are pressed and adjust max temp
      if((x > X_PLUS_B) && (x < (X_PLUS_B + 40)))
      {
          if ((y > Y_PLUS_B) && (y <= (Y_PLUS_B + 35)))
          {
             if (current_display_mode==MODE_SETUP)
             {
                max_temp=max_temp+0.5;
                tft.fillRect(6,6,X_PLUS_B-3,Y_PLUS_B+BUTTON_H,ILI9341_BLACK);
                drawCurrentMaxTemp1(max_temp);
             }
          }
      }
      
      if((x > X_MINUS_B) && (x < (X_MINUS_B + 40)))
      {
         if ((y > Y_PLUS_B) && (y <= (Y_PLUS_B + 35)))
         {
            if (current_display_mode==MODE_SETUP)
            {
                max_temp=max_temp-0.5;
                tft.fillRect(6,6,X_PLUS_B-3,Y_PLUS_B+BUTTON_H,ILI9341_BLACK);
                drawCurrentMaxTemp1(max_temp);
            }
         }
      }
   }
 }
 

//Adafruit screen functions
void RefreshTemp1Value(float value)
{
 //drawFrameT1();
 //tft.fillRect(REDBUTTON_X, REDBUTTON_Y, REDBUTTON_W, REDBUTTON_H, ILI9341_BLUE);
 tft.setCursor(6 , 6);
 tft.setTextColor(ILI9341_WHITE);
 tft.setTextSize(4);
 tft.print("T1= ");
 tft.println(value);
}

void drawFrameT()
{
 tft.fillRect(FRAME_X_T, FRAME_Y_T, FRAME_W_T, FRAME_H_T, ILI9341_BLUE);
}

void drawMenuButton(int current_mode)
{
 tft.fillRect(FRAME_X_B, FRAME_Y_B, FRAME_W_B, FRAME_H_B, ILI9341_BLUE);
 tft.drawRect(FRAME_X_B, FRAME_Y_B, FRAME_W_B, FRAME_H_B, ILI9341_BLACK);
 tft.setCursor(FRAME_X_B+ 6 , FRAME_Y_B + 15);
 tft.setTextColor(ILI9341_RED);
 tft.setTextSize(3);
 if (current_mode==MODE_TEMPS)
      tft.println("SETUP");
 else if (current_mode==MODE_SETUP)
      tft.println("TEMPS");
}
void drawCurrentMaxTemp1(float value)
{
 tft.setCursor(6 , 6);
 tft.setTextColor(ILI9341_WHITE);
 tft.setTextSize(3);
 tft.print("MAX T1=");
 tft.println(value);
 drawPlusButton(X_PLUS_B/*224*/,Y_PLUS_B/*3*/);
 drawMinusButton(X_MINUS_B/*270*/,Y_PLUS_B/*3*/);
}

void drawPlusButton(int x, int y)
{
 tft.fillRect(x, y, BUTTON_W, BUTTON_H, ILI9341_BLUE);
 tft.setCursor(x+10 , y+5);
 tft.setTextColor(ILI9341_WHITE);
 tft.setTextSize(4);
 tft.print("+");
}

void drawMinusButton(int x, int y)
{
 tft.fillRect(x, y, BUTTON_W, BUTTON_H, ILI9341_BLUE);
 tft.setCursor(x+10 , y+5);
 tft.setTextColor(ILI9341_WHITE);
 tft.setTextSize(4);
 tft.println("-");
}

Ok, these are the photos of the complete project.

wpid-storageemulated0DCIMCamera2014-09-15-17.08.25.png.png

wpid-storageemulated0DCIMCamera2014-09-10-06.39.30.png.png

Note that on the screen there are four temperature values: I’m now working on a more powerful application in order to match Luka request (he wants to use four DHT22 sensors in his house… I think I will use a input multiplexer with the Arduino UNO, or more simply an Arduino Mega! ๐Ÿ˜‰ ).
But you can use this project in order to add the powerful Adafruit TFT touchscreen to your application.
Only two notes on the Adafruit TFT:
1. the screen refresh is slow (very slow in my opinion), but it’s an acceptable issue in embedded projects
2. the touchscreen is natively very sensitive to human touch, so if your touch is “too long” it will be detected as a multiple touch. You could implement some “low-pass software filter” (i.e. you could manage the touch only after a multiple touch).

Well boys and girls, now you have a thermostat with a touch screen for your hi-tech house. I hope Luka will be happy with his new toy (but I’m not sure..he is a very perfectionist guy! ๐Ÿ˜‰ ).
…But attention friends, the touchscreen will record your fingerprints ;-), so clean it with attention…especially if you don’t like CSI! ๐Ÿ™‚

Bye bye!

Advertisements

2 thoughts on “Thermostat with Arduino and touchscreen

  1. I think Luka might like a more graphical thermostat, Have you looked at these…I have a GeoThermo heat pump and plan to use one of these interfaced to my system. I don’t know much about programming. I have had GeoThermo for over ten years and am appalled at the lack of feedback sensors in these furnaces. Mine was a DIY system that I installed myself. https://www.youtube.com/watch?v=L1TPs6dI11k

    • Hi dear Rob, thank you for your suggestion!
      It seems veeeeery interesting! ๐Ÿ™‚
      I will show the video to Luka. If he won’t be interested…. I will buy the system for me! ๐Ÿ˜‰
      Thank you again, and keep in touch!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s