Project tutorial
Temperature & Humidity Data Logging

Temperature & Humidity Data Logging © MIT

A data logging system for temperature and humidity with the ability to see hourly, weekly, monthly data points.

  • 16 respects

Components and supplies

Apps and online services

GTT GUI Designer Software
Free fast development GUI/HMI Software for the Matrix Orbital GTT Intelligent HMI TFT Series of displays.
Ide web
Arduino IDE

About this project

This project demonstrates how easy it is to create a simple display panel (for a thermostat) by interfacing Matrix Orbital GTT Intelligent TFT HMI display with an Arduino Nano via I2C. A DHT22 temperature and humidity sensor is used to obtain temperature and humidity information. This information is processed by the Arduino Nano to display hourly, 24-hour, and weekly historical charts. A live chart is also available for viewing of the current temperature and humidity.

Adding in some electrical and/or electromechanical systems behind this display panel can turn this unit into a thermostat with a beautiful full colour TFT display.

Step 1: Designing the User Interface

The GTT Designer Suite allows users to easily drag and drop widgets on screen. Images and font files can also be imported for use when creating GUI's. For this project there are several screens created which will automatically be processed as a script when buttons are pressed. For the (HOME) first screen, we've dragged in:

  • labels (top label: temperature info in deg C; bottom label: humidity info in % rh)
  • buttons (invisible buttons hidden on the labels which will launch live data plotting of temperature or humidity and a 'MAX' button to set a maximum humidity alert

Screen 2 is the where the default MAX humidity alert is set. Widgets used are:

  • two triangle buttons (up and down) were dragged and dropped to be used to set the MAX humidity. Default MAX humidity is displayed (set at 70%), and the triangle buttons can be used to increase or decrease the settings. These two buttons report to the Arduino and the Arduino processes the button reports to either increment or decrement the MAX humidity setting.
  • button ('HOME' that will take the display back to the first screen)

Screen 3 is an ALERT screen where the users are alerted that the MAX humidity is reached. The Arduino continues to monitor humidity information and brings back to the HOME (first) screen when level falls below the MAX humidity setting.

The following screens: LiveTGraph, TGraph_1HR, TGraph_24HR, TGraph_1WK are historical graph plots of the temperature data. LiveHGraph, HGraph_1HR, HGraph_24HR, HGraph_1WK are historical graph plots of the humidity data. Widgets used are:

  • charts (live graph plot have 30 data points, and historical: 1 hr, 24-hr and 1 week charts are 180 points)
  • buttons (1 hour, 24-hour and 1 week buttons to launch respective charts)

Once the design is completed, the project can be deployed to the GTT. You'll need to connect your PC to the GTT's Mass Storage header, and hit "Deploy" in the GTT Designer. All the necessary files will be generated and deployed directly to the display.

In action

Step 2: Connecting the GTT

For this demo, we'll be using I2C to communicate between the Arduino Uno and the GTT. Using the breadboard Cable, connect the 4 pin header to the GTT's I2C header. Then connect the red breadboard cable lead to 5V power, and connect the black lead to ground. The yellow (SDA) and green (SCL) leads need to be connected to the Arduino Nano's SDA pin (A4) and SCL pin (A5) respectively. No I2C pull-up resistors are required for communication with the GTT (Arduino's Wire library automatically turns on internal pull-up resistors on SCL and SDA). Additional power can be applied through the displays barrel jack.

Step 3: Connecting the DHT22

A 4.7k Ohm resistor pull-up to +5V must be placed in the DHT22 data pin, otherwise the sensor will be unable to communicate properly. The data pin can be connected to any digital pin on the Arduino; in this case we selected pin 8.

Step 4: Installing Libraries

Before continuing, download and unzip the the following GTT Client Libraries. These libraries can also be found within the most recent GTT Firmware release. Once downloaded, copy over the contents of GttClient into \Users\YourUserName\Documents\Arduino\libraries\gtt.

GTT Client Library

Step 5: Code
//GTT Arduino Tempearature and Humidity Demo 
//Arduino Uno with Matrix Orbital GTT35A and DHT22
//Created by R Malinis, 25/05/2018
#include <Dhcp.h>
#include <Dns.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <EthernetUdp.h>
#include <gtt.h>
#include <gtt_device.h>
#include <gtt_enum.h>
#include <gtt_events.h>
#include <gtt_ext_types.h>
#include <gtt_packet_builder.h>
#include <gtt_parser.h>
#include <gtt_protocol.h>
#include <gtt_text.h>
#include <Wire.h>
#include <SimpleDHT.h>
#include "GTTProject12.c"
#include "GTTProject12.h"
#include <stdlib.h>
#define I2C_Address 0x28  //Define default 8bit I2C address of 0x50 >> 1 for 7bit Arduino
// Buffer for incoming data
uint8_t rx_buffer[128];
// Buffer for outgoing data
uint8_t tx_buffer[256];
gtt_device gtt; //Declare the GTT device
typedef enum
 NOGraph =0,
} GraphScreen;
// DHT11
int pinDHT22 = 8;
SimpleDHT22 dht22;
byte defaultMaxHumidity;
bool MaxHumidityScreen = false; 
GraphScreen Graph = NOGraph;
typedef struct
 byte ChartData;
 byte ChartObject;
 float rawData;
DataSourceType Temperature;
DataSourceType Humidity;
void LiveGraph(float temperature, float humidity)
 if (Graph == NOGraph)
 DataSourceType source;
 if (Graph == TempGraph)
   source = Temperature;  
   source.rawData = temperature;    
   source.ChartData = id_livetgraph_t_live_data0;
   source.ChartObject = id_livetgraph_t_live_;    
   source = Humidity;  
   source.rawData = humidity;    
   source.ChartData = id_livehgraph_h_live_data0;
   source.ChartObject = id_livehgraph_h_live_;    
 gtt25_dataset_push_data(&gtt, source.ChartData, (float) source.rawData); 
 gtt25_visualobject_invalidate(&gtt, source.ChartObject); 
 Serial.println("drawing LIVE graph");
void GTT25ButtonHandler(gtt_device* device, uint16_t ObjectID, uint8_t State)
 Serial.print("button handler: ");          
 Serial.print(" state: ");          
 if (State != 1)
 MaxHumidityScreen = false;
 Graph = NOGraph;                  
 switch (ObjectID)
   case id_screen2_triangle_button_1:
   case id_screen2_triangle_button_2:
   case id_screen1_max_btn:
   case id_screen1_image_button_1:      
     Graph = TempGraph;
   case id_screen1_image_button_2:      
     Graph = HumiGraph;
   // the following buttons take care of themselves as designed in the GTT Designer
   // only used here for serial debug
   case id_screen2_home_btn:       
   case id_screen3_home_btn:
   case id_livehgraph_home_btn:
   case id_hgraph_1hr_home_btn:
   case id_hgraph_24hr_home_btn:
   case id_hgraph_1wk_home_btn:
   case id_livetgraph_home_btn:   
     Serial.println("==== back to HOME screen");                
   case id_livetgraph_1_hr_btn:
   case id_tgraph_1hr_1_hr_btn:   
   case id_tgraph_24hr_1_hr_btn:
   case id_tgraph_1wk_1_hr_btn:  
   case id_livehgraph_1_hr_btn:
   case id_hgraph_1hr_1_hr_btn:   
   case id_hgraph_24hr_1_hr_btn:
   case id_hgraph_1wk_1_hr_btn:   
     Serial.println("==== displaying 1 HOUR");     
   case id_livetgraph_24_hr_btn:
   case id_tgraph_1hr_24_hr_btn:   
   case id_tgraph_24hr_24_hr_btn:
   case id_tgraph_1wk_24_hr_btn:     
   case id_livehgraph_24_hr_btn:
   case id_hgraph_1hr_24_hr_btn:   
   case id_hgraph_24hr_24_hr_btn:
   case id_hgraph_1wk_24_hr_btn:           
     Serial.println("==== displaying 24 HOUR");       
   case id_livetgraph_1_wk_btn:
   case id_tgraph_1hr_1_wk_btn:
   case id_tgraph_24hr_1_wk_btn:    
   case id_tgraph_1wk_1_wk_btn:    
   case id_livehgraph_week_btn:
   case id_hgraph_1hr_week_btn:
   case id_hgraph_24hr_week_btn:    
   case id_hgraph_1wk_week_btn:     
     Serial.println("==== displaying 1 WEEK");  
 char buf[] = {0};
 int16_t humid = defaultMaxHumidity;  
 sprintf(buf, "%d", humid); //Convert the humidity value to a string  
 gtt_set_screen2_humi_label_1_text(&gtt, gtt_make_text_ascii(buf)); //Update the GTT label    
 Serial.println("defaultMaxHumidity is set");
void HumidityCheck(float humidityVal)
 if (humidityVal > defaultMaxHumidity)
   Serial.print("max: "); Serial.print((int)defaultMaxHumidity); 
   Serial.print(" current:"); Serial.println((int)humidityVal); 
   if (MaxHumidityScreen == false)
     gtt_run_script(&gtt, (char*)("GTTProject12\\Screen3\\Screen3.bin"));
     MaxHumidityScreen = true;        
 if (MaxHumidityScreen == true &&  (humidityVal < defaultMaxHumidity))
     gtt_run_script(&gtt, (char*)("GTTProject12\\Screen1\\Screen1.bin"));      
     MaxHumidityScreen = false;        
float TempData[10] = {0,0,0,0,0,0,0,0,0,0};
float HumiData[10] = {0,0,0,0,0,0,0,0,0,0};
bool OldDataLoaded = false;
void UpdateDataCollection(float temperature, float humidity)
     float avgTempData, avgHumiData;
     static byte counter20sec = 0; // 180 data points = 1hr
     static byte counter8mins = 0; // 180 data points = 24hrs
     static byte counter56mins = 0;// 180 data points = 1week
     DataSourceType dataSource;
     static byte HrMaxH = 15;
     static byte HrMinH = 25;
     static byte HrMaxT = 20;
     static byte HrMinT = 25;
     static byte T24HrMaxH = 15;
     static byte T24HrMinH = 25;
     static byte T24HrMaxT = 20;
     static byte T24HrMinT = 25;    
     static byte count20secP = 0;
     static byte count8minP = 0;
     static byte count56minP = 0;  
     LiveGraph(temperature, humidity);
     //Serial.print("Data (not collected): ");
     //Serial.print((float)temperature); Serial.print(" *C, ");
     //Serial.print((float)humidity); Serial.println(" RH%");     
     eStatusCode r;
     if (OldDataLoaded == false)
       OldDataLoaded = true;
       r = gtt25_dataset_load(&gtt, id_tgraph_24hr_24_hr_chart_data0, gtt_make_text_ascii("Temp24hrMax.dat"));  
       r = gtt25_dataset_load(&gtt, id_tgraph_24hr_24_hr_chart_data1, gtt_make_text_ascii("Temp24hrMin.dat"));        
       r = gtt25_dataset_load(&gtt, id_hgraph_24hr_24_hr_chart_data0, gtt_make_text_ascii("Humidity24hrMax.dat"));  
       r = gtt25_dataset_load(&gtt, id_hgraph_24hr_24_hr_chart_data1, gtt_make_text_ascii("Humidity24hrMin.dat"));        
       r = gtt25_dataset_load(&gtt, id_tgraph_1wk_1_wk_chart_data0, gtt_make_text_ascii("Temp1WkMax.dat"));  
       r = gtt25_dataset_load(&gtt, id_tgraph_1wk_1_wk_chart_data1, gtt_make_text_ascii("Temp1WkMin.dat"));        
       r = gtt25_dataset_load(&gtt, id_hgraph_1wk_1_wk_chart_data0, gtt_make_text_ascii("Humidity1WkMax.dat"));  
       r = gtt25_dataset_load(&gtt, id_hgraph_1wk_1_wk_chart_data1, gtt_make_text_ascii("Humidity1WkMin.dat"));        
       if (r != eStatusCode_Success)
         Serial.println("Check uSD card");
     // collect data for averaging after 20 seconds (10 readings)
     TempData[counter20sec] = temperature; 
     HumiData[counter20sec] = humidity;
     //Serial.print("temp: ");  
     //Serial.print(" humidity: ");  
     Serial.print("  20 sec counter: ");  
     if (counter20sec < 10) // 10x 2sec refresh rate = 20 seconds
     // take the avg of the 10 data points, that is what we will set as hr data points
     avgTempData = 0;
     avgHumiData = 0;
     for (byte i=0; i < 10; i++)
       avgTempData += TempData[i]; 
       avgHumiData += HumiData[i];
     avgTempData = avgTempData/10; 
     avgHumiData = avgHumiData/10;
     Serial.print("AVG temp: ");  
     Serial.print(" AVG humidity: ");  
     Serial.print("Data collection: 1hr data points: ");  
     Serial.println(" ");      
     Serial.print("Data collection: 24hr data points: ");      
     Serial.println(" ");      
     Serial.print("Data collection: 1wk data points: ");      
     Serial.println(" ");      
     counter20sec = 0;
     // update 1hr graph
     Temperature.ChartData = id_tgraph_1hr_1_hr_chart_data0;
     Temperature.ChartObject = id_tgraph_1hr_1_hr_chart_;
     dataSource = Temperature;      
     gtt25_dataset_push_data(&gtt, dataSource.ChartData, avgTempData); 
     if ((byte)temperature > HrMaxT)
       HrMaxT = (byte)temperature;
     if ((byte)temperature < HrMinT)
       HrMinT = (byte)temperature;
     Humidity.ChartData = id_hgraph_1hr_1_hr_chart_data0;
     Humidity.ChartObject = id_hgraph_1hr_1_hr_chart_;
     dataSource = Humidity;      
     gtt25_dataset_push_data(&gtt, dataSource.ChartData, avgHumiData); 
     if ((byte)humidity > HrMaxH)
       HrMaxH = (byte)humidity;
     if ((byte)humidity < HrMinH)
       HrMinH = (byte)humidity;  
     if (counter8mins > 23) // <-- 23
       Serial.print("Data collection: 24hr data points: ");      
       Serial.print(" ");      
       counter8mins = 0;
       // update 24hr graph, 2 plots, temp min and max
       gtt25_dataset_push_data(&gtt, id_tgraph_24hr_24_hr_chart_data0, HrMaxT); 
       gtt25_dataset_push_data(&gtt, id_tgraph_24hr_24_hr_chart_data1, HrMinT); 
       r = gtt25_dataset_save(&gtt, id_tgraph_24hr_24_hr_chart_data0, gtt_make_text_ascii("Temp24hrMax.dat"));  
       r = gtt25_dataset_save(&gtt, id_tgraph_24hr_24_hr_chart_data1, gtt_make_text_ascii("Temp24hrMin.dat"));  
       if ((byte)temperature > T24HrMaxT)
         T24HrMaxT = (byte)temperature;
       if ((byte)temperature < T24HrMinT)
         T24HrMinT = (byte)temperature;
       // update 24hr graph, 2 plots, humidity min and max
       gtt25_dataset_push_data(&gtt, id_hgraph_24hr_24_hr_chart_data0, HrMaxH);
       gtt25_dataset_push_data(&gtt, id_hgraph_24hr_24_hr_chart_data1, HrMinH);         
       r = gtt25_dataset_save(&gtt, id_hgraph_24hr_24_hr_chart_data0, gtt_make_text_ascii("Humidity24hrMax.dat"));        
       r = gtt25_dataset_save(&gtt, id_hgraph_24hr_24_hr_chart_data1, gtt_make_text_ascii("Humidity24hrMin.dat"));        
       if ((byte)humidity > T24HrMaxH)
         T24HrMaxH = (byte)humidity;
       if ((byte)humidity < T24HrMinH)
         T24HrMinH = (byte)humidity;
       if (counter56mins > 6) //<-- 6
         Serial.print("Data collection: 1wk data points: ");      
         Serial.print(" ");      
         counter56mins = 0;
         // update Week graph
         gtt25_dataset_push_data(&gtt, id_tgraph_1wk_1_wk_chart_data0, T24HrMaxT); 
         gtt25_dataset_push_data(&gtt, id_tgraph_1wk_1_wk_chart_data1, T24HrMinT); 
         gtt25_dataset_save(&gtt, id_tgraph_1wk_1_wk_chart_data0, gtt_make_text_ascii("Temp1WkMax.dat")); //< change file names      
         gtt25_dataset_save(&gtt, id_tgraph_1wk_1_wk_chart_data1, gtt_make_text_ascii("Temp1WkMin.dat")); //< change file names       
         gtt25_dataset_push_data(&gtt, id_hgraph_1wk_1_wk_chart_data0, T24HrMaxH); 
         gtt25_dataset_push_data(&gtt, id_hgraph_1wk_1_wk_chart_data1, T24HrMinH); 
         gtt25_dataset_save(&gtt, id_hgraph_1wk_1_wk_chart_data0, gtt_make_text_ascii("Humidity1WkMax.dat"));//< change file names                  
         gtt25_dataset_save(&gtt, id_hgraph_1wk_1_wk_chart_data1, gtt_make_text_ascii("Humidity1WkMin.dat"));//< change file names                  
     Serial.println(" ");                
     count20secP %= 180;
     count8minP %= 180;
     count56minP %= 180;     
void UpdateHomeScreen(float temperature, float humidity)
 char buf[6];
 char wholeTemp[3];
 char fracTemp[2];
 float temp = (float)temperature;
 int humid = (float)humidity;
 dtostrf(temp, 2, 2, buf);
 for (int i=0; i<3;i++)
   wholeTemp[i] = buf[i];
 wholeTemp[2] = 0; // null
 fracTemp[0] = buf[3];
 fracTemp[1] = 0; // null   
 gtt_set_screen1_temp_label_1_text(&gtt, gtt_make_text_ascii(wholeTemp)); //Update the GTT label
 gtt_set_screen1_temp_dec_label_1_text(&gtt, gtt_make_text_ascii(fracTemp)); //Update the GTT label
 gtt_set_screen1_humi_label_1_text(&gtt, gtt_make_text_ascii(buf)); //Update the GTT label
byte ReadSensor(float*  temperature, float* humidity)
   int err = SimpleDHTErrSuccess;
   if ((err = dht22.read2(pinDHT22, temperature, humidity, NULL)) != SimpleDHTErrSuccess) {
     Serial.print("Read DHT22 failed, err="); Serial.println(err);delay(2000);
     return 0;
   return 1;
void setup() {
 //Setup I2C bus
 gtt.Write = i2cWrite; //Set the write function
 gtt.Read = i2cRead; //Set the read function
 gtt.rx_buffer = rx_buffer; //Declare a buffer for input data
 gtt.rx_buffer_size = sizeof(rx_buffer); //Declare the size of the input buffer
 gtt.tx_buffer = tx_buffer; //Declare a buffer for output data
 gtt.tx_buffer_size = sizeof(tx_buffer); //Declare the size of the output buffer
 gtt25_set_button_clickhandler(&gtt, GTT25ButtonHandler);       
 Wire.begin(); //Begin I2C communication
 defaultMaxHumidity = 70;     
unsigned short count = 0;
unsigned short dataColCount = 0;
void loop() {
 // read without samples.
 byte temperature = 0;
 byte humidity = 0;  
 byte collectionRate = 2; // 30
 if (count > 2500) // cycle delay for DHT, refresh is 0.5HZ (2 seconds)
   count = 0;
   float temperature = 0;
   float humidity = 0;
   if (ReadSensor(&temperature, &humidity) == 1) 
     UpdateHomeScreen(temperature, humidity);
     if (dataColCount > collectionRate) 
       UpdateDataCollection(temperature, humidity);
       dataColCount = 0; // restart delay count
int i2cWrite(gtt_device* gtt_device, char* data, size_t data_length) {//Write an array of bytes over i2c
 size_t len = data_length;
 byte offset = 0;
 if (len > 32)
   len = 32;
 while (data_length)
   for (int i = 0; i < len; i++) 
   data_length = data_length - len;
   len = data_length; 
   if (len > 32) 
     len = 32;
   offset += 32;
 return 0;
byte i2cRead(gtt_device* gtt_device) { //Wait for one byte to be read over i2c
 byte data;
 Wire.requestFrom(I2C_Address, 1);
 if (Wire.available() < 1)
   return -1;
 else {
   data =;
   return data;

Step 5: The Case

Completed display

The two parts

Bottom of the unit. The case has three air holes for the flow of air, an USB port for the Arduino Nano, a hole for the DHT22 and two holes for screws.


Custom parts and enclosures

Wall Mount Case
Wall Mount 3.5" TFT with DHT22 Humidity Sensor


Similar projects you might like

Temperature and Humidity Data Logger

Project tutorial by Wimpie van den Berg

  • 22 respects

Temperature and Humidity Data logger - Breadboard

Project tutorial by Jed Hodson

  • 10 respects

Health Kit: Humidity and Temperature Control

Project tutorial by Diana Khalipina

  • 39 respects

Temperature and Humidity Logger (Using Arduino)

Project showcase by lmsousa

  • 34 respects

Beautifully Finished Humidity and Temperature Sensor

Project tutorial by Wicked Makers

  • 138 respects

Arduino DTH22 Humidity Temperature With LCD I2C 16x2 Display

Project tutorial by Team GiftedMedia

  • 35 respects
Add projectSign up / Login