Touch Display Scene Controller

written by hek

Sometimes you might want to control more advanced scenarios in your home automation project. This is when a scene controller comes in handy.

In this example we’ve used a touch screen to display the scene launch options. The buttons can be customized in the sketch code to your preference. With a little hacking you could even change button functions depending on the time of the day or create a full fledged menu system.

If you prefer to keep it simple you can skip the touch display and just attach a few buttons to your arduino to trigger the scene commands.

The provided example also displays the time in the top right corner. If you need more space for your buttons you can remove this part if you want.

The touch screen used here did not like to share SPI with the NRF24L01 radio. We had to move the radio to a separate software driven SPI interface. The wire instructions below show where to connect things.


Here is a little video showing the scene controller in action:

For a more simple scene controller using keypad, have a look at [petewills]( project [here ](

Wiring Things Up

This sensor mostly consists of the ATMega 2650, shield and display which is easy to snap together. The only thing left you need to connect is the radio. We choose to solder the wires onto the display shield but you might be able to temporarily connect the cables using dupont wires while testing. The 3v3 output of the ATMega2650 is a bit noisy so we choose to use a step down regulator from 5V->3v3 to smooth things out a bit (see buying guide below).

| AtMega 2650 Arduino | Step Down Module/Radio | | --- | --- | | GND | GND | | 5V | Step Down module VCC | | 14 | SCK | | 15 | MOSI | | 16 | MISO | | 17 | CE | | 18 | CSN |


This example uses the external libraries UTFT, UTouch, UTFT_Buttons and TimeLib found here. Please install them and restart the Arduino IDE before trying to compile. It also depends on some external source files found in the example folder.

 * The MySensors Arduino library handles the wireless radio link and protocol
 * between your home built sensors/actuators and HA controller of choice.
 * The sensors forms a self healing radio network with optional repeaters. Each
 * repeater and gateway builds a routing tables in EEPROM which keeps track of the
 * network topology allowing messages to be routed to nodes.
 * Created by Henrik Ekblad <[email protected]>
 * Copyright (C) 2013-2015 Sensnology AB
 * Full contributor list:
 * Documentation:
 * Support Forum:
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * version 2 as published by the Free Software Foundation.
 * Version 1.0 - Henrik Ekblad
 * Touch Display Scene Controller build using a touch enabled tft display
 * attached to a ATMega 2560. This example fetches time from controller and sends
 * in scene commands to the controller. 
 * Short press sends V_SCENE_ON and long press (>0.5sec) sends V_SCENE_OFF.
 * Henrik Ekblad <[email protected]>
 * This example uses:
 * UTFT library:
 * Convert your own images here:
 * The 3v3 output on the ATMega2560 is especially bad. I had to use a step down 
 * on the 5V output to get solid transmissions.
 * Connect radio 
 * ----------------------------------
 * Radio               Arduino Pin
 * ----------------------------------
 * GND                 GND  
 * 5V  -> Step down -> 3V3   (see buying guide for help finding step-down)
 * SCK                 14 
 * MOSI                15 
 * MISO                16 
 * CE                  17   
 * CSN                 18

// Enable debug prints to serial monitor
#define MY_DEBUG 

// Enable soft spi as radio has a hard time sharing spi 
#define MY_SOFTSPI

// Enable and select radio type attached
#define MY_RADIO_RF24
//#define MY_RADIO_RFM69

#include <TimeLib.h> 
#include <SPI.h>
#include <MySensors.h>  
#include <stdarg.h>
#include <UTFT.h>
#include <UTouch.h>
#include <UTFT_Buttons.h>
#include <avr/pgmspace.h>
#include "arial_bold.c"
#include "ArialNumFontPlus.c"
#include "logo.c"

#define CHILD_ID 1

int LONG_PRESS = 500; // Number of millisecons to trinnger scene off for button push
int RESEND_DEBOUNCE = 2000; // Number of millisecons interval between sending of same 
                            // scene number again. 
                            // This is used to avoid unwanted re-trigger when using 
                            // a sensetive touch diplay.

// Add your buttons here. Max is 5 if you still want time at the top.
char *buttons[] = {
    (char *)"Good Morning", 
    (char *)"Clean Up!", 
    (char *)"All Lights Off", 
    (char *)"Music On/Off"
const int buttonCount = sizeof(buttons)/sizeof(char *);
const int padding = 10;
const int topBarHeight = 60;

MyMessage on(CHILD_ID, V_SCENE_ON);
MyMessage off(CHILD_ID, V_SCENE_OFF);

UTFT myGLCD(ITDB32S,38,39,40,41);
UTouch  myTouch( 6, 5, 4, 3, 2);
UTFT_Buttons  myButtons(&myGLCD, &myTouch);
bool timeReceived = false;
unsigned long lastTimeUpdate=0, lastRequest=0;
char timeBuf[20];

void setup()  
  myGLCD.setColor(100, 255, 100);
  myGLCD.setBackColor(0, 0, 0);
  myGLCD.drawBitmap (0, 0, 60, 60, (unsigned int*)logo);
  myButtons.setButtonColors(VGA_WHITE, VGA_GRAY, VGA_WHITE, VGA_RED, VGA_BLUE);
  int height = (myGLCD.getDisplayYSize()-topBarHeight-(padding*(buttonCount+2)))/buttonCount;
  // Add buttons
  for (int i=0; i<buttonCount;i++) {
    int y = topBarHeight + padding+(i*(height+padding));
    myButtons.addButton( padding, y, myGLCD.getDisplayXSize()-padding*2, height, buttons[i]);

  // Request time from controller. 

void presentation()  {
  // Send the sketch version information to the gateway and Controller
  sendSketchInfo("Scene Ctrl", "1.0");

int lastPressedButton = -1;
unsigned long lastPressedButtonTime = 0;

void loop()      
  unsigned long now = millis();
  if (myTouch.dataAvailable()) {
    int pressedButton = myButtons.checkButtons();

    if (pressedButton>=0) {
      bool longPress = millis()-now>(unsigned long)LONG_PRESS;
      if (pressedButton != lastPressedButton || now-lastPressedButtonTime > (unsigned long)RESEND_DEBOUNCE) {
        if (longPress) {
          Serial.print("Long pressed: ");
        } else {
          Serial.print("Pressed: ");    
        lastPressedButton = pressedButton;    

  // If no time has been received yet, request it every 10 second from controller
  // When time has been received, request update every hour
  if ((!timeReceived && now-lastRequest > (unsigned long)10*1000)
    || (timeReceived && now-lastRequest > (unsigned long)60*1000*60)) {
    // Request time from controller. 
    Serial.println("requesting time");
    lastRequest = now;

  // Update time every second
  if (timeReceived && now-lastTimeUpdate > 1000) {
    lastTimeUpdate = now;

// This is called when a new time value was received
void receiveTime(unsigned long time) {
  // Ok, set incoming time 
  timeReceived = true;

void printTime() {
  sprintf(timeBuf, "%02d:%02d:%02d", hour(), minute(), second());
  myGLCD.print(timeBuf, 60,7);

Shopping Guide

10pcs NRF24L01+ 2.4GHz Wireless Transceiver
This is what enables your sensors to communicate wirelessly across a nominal range of 60 meters.
1 available - $13.99   Buy
undefined   Buy
ATmega2560 + Touch screen
ATmega2560 Arduino clone, 3.2" TFT LCD Shield with Touch Screen and SD Reader
Unavailable   Buy
undefined   Buy
NRF24L01+ Socket Adapter Board
Another adapter for Arduino Pro Mini 5V that provide 3.3v regulated power to the radio. Solder free.
Unavailable   Buy
undefined   Buy


Sensors & Actuators

Related Content