Touch Display for Raspberry Pi

By on June 10, 2015
Pin It

fig_0

We add to Raspberry Pi a TFT touch screen to display the system console, movies and favorite photos or control a relay board at your fingertips, literally!

To avoid using an HDMI monitor the cost well above that of Raspberry Pi, in previous articles we have always gone the way of connecting remotely to the microcomputer, using tools such as Putty and WinSCP. This approach has always bound to use Raspberry Pi in a “server” mode. Therefore we have always presented applications with user interface built to be accessible by web browser. What to do when we want to have an interface in traditional style, accessible directly from the desktop? Simple, you connect a monitor, a keyboard, a mouse and then you can code a standard desktop application using the classical languages ​​and libraries for creating graphical user interfaces. Yeah, but this way we transform Raspberry Pi in a PC with all devices attached, making it a traditional “cumbersome” uncomfortable device.

The solution we introduce instead of the “classical”, allows you to create graphical user interfaces using a nice 2.8-inch TFT color monitor with a touch resistive interface. No monitor, no keyboard and no mouse. The display board has more or less the same Raspberry Pi size, is already assembled and is compatible with all Raspberry Pi versions: A, B and B +. In this post we have adopted the model B + that provides a greater number of I / O pins than previous versions. The monitor has a resolution of 320 x 240 pixels with 16 bits color depth. The mini display is connected to Raspberry Pi through its SPI bus and can be used to redirect the console, or as a monitor to display the Raspbian X desktop, photos, video and user applications graphical interfaces. So far, so good. The downside is that the drivers are not included in Raspbian kernel.
This cute display allows us to introduce, in more detail than we have done up to now, the build of an embedded GNU / Linux system. In the “professional” field, embedded GNU / Linux distribution are the leanest possible, including only device drivers and essential applications to the basic microcontroller operation. This is to minimize the distribution memory footprint and maximize the target system performance. This approach allows the use of a reduced performance chip, with final solution physical dimensions as low as possible and minimum power consumption in order to allow battery operated solutions.

The downside is that you must customize the distribution kernel with the device drivers that you want to use, such as WiFi dongle, USB devices, LCD and LED panels. One of the advantages using Raspberry Pi has always been the ease of use, not having to deal with these issues. Being an “educational” microcomputer, Raspbian already includes a huge amount of drivers that meet automatically (plug and play) the most needs. This time, however, the TFT LCD drivers are not included. Fortunately, Adafruit (display producer) has provided a Raspian kernel, already compiled, that includes the required driver.

This avoid us having to customize Raspbian. We are still planning to propose a series of posts about the topic, because the continuous presence of new devices on the market requires fronting this issue definitely. In the Adafruit solution, there are in fact two problems. What to do when we have to connect a second device whose specific drivers are not included on the Linux kernel? Although the manufacturer makes available a “compiled” kernel for its device, we will lose other drivers integrations. The only solution is that we must configure and compile the kernel by our own, adding all the drivers requested. Second problem. Using the precompiled kernel, customized with the addition of a specific driver, it binds us to the kernel version used for compilation. In this condition, we will not be able to adopt new distributions with most recent kernels, unless the device manufacturer itself does not release a new version.

In this regard we remind that has just been released the 3.16 Linux kernel version, which has considerable additional functionality when it relates to ARM chip management with CPU and its graphics processors. A sign that we will see an increasing spread of our “philosophy”.

 

fig_1

 

But back to our graphic display based on TFT LCD module ILI9340, which comes pre-assembled and equipped with GPIO connector, present on all Raspberry Pi models: A, B and B +. The board includes the display controller STMPE610 communicating with Raspberry Pi through the SPI bus and then engages the corresponding GPIO connector pin (SCK, MOSI, MISO, CE0, CE1) in addition to GPIO25 and GPIO24 pins. The four additional buttons present on board are connected to pins GPIO23, GPIO22, GPIO21, and GPIO18. All other pins are unused and may be used for other needs. In this case it is appropriate to solder a connector on housing present on the right side of the card and use a flat cable extension. Be careful to follow the right pin matching. The GPIO pin number 1 is signed on the back of the board with a square shape and a small white arrow silkscreened.

 

How to customize Raspbian

The process we describe to set up the TFT LCD requires starting from Raspbian. We used the image released on 9 September 2014kernel release 3.12 .

 

fig_2

 

Now it is better not to install the display on the connector, we will do it after you install the software. To perform the installation process it is necessary that Raspberry Pi is connected to the local network so you can see” Internet. You also need to access to Raspberry Pi to use a terminal window and a file manager. As always, but especially in this case, we prefer to remotely access via SSH using (in Windows) Putty and WinSCP. Of course, you can also connect to the console via serial cable.
We login to Raspberry Pi with the user “rootand start the installation process with the usual commands to update the distribution:

apt-get update

apt-get upgrade

We go to a temporary folder to download the installation files. We can also create a specific folder for this process. The files are available as .deb packages which must then be installed with dpkg. We can use, for example, the “home” folder. We go there with the command:

cd /home

Now we download all the necessary packages to upgrade the kernel for the display management.

wget http://adafruit-download.s3.amazonaws.com/libraspberrypi-bin-adafruit.deb

wget http://adafruit-download.s3.amazonaws.com/libraspberrypi-dev-adafruit.deb

wget http://adafruit-download.s3.amazonaws.com/libraspberrypi-doc-adafruit.deb

wget http://adafruit-download.s3.amazonaws.com/libraspberrypi0-adafruit.deb

wget http://adafruit-download.s3.amazonaws.com/raspberrypi-bootloader-adafruit-20140917-1.deb

After the download, from the same folder, install everything with the command:

sudo dpkg -i -B *.deb

This takes quite a long time, you can take a break and relax for a moment. If you are using an old Raspbian (prior than September 2013), you must disable the use of the accelerated framebuffer X, with the command that removes the configuration file of the accelerator and saves it to the folder / home (you never know):

mv /usr/share/X11/xorg.conf.d/99-fbturbo.conf /home

Now we turn off Raspberry Pi with the traditional command:

shutdown –h now

We remove the power plug; insert the display on the GPIO connector, making sure that there is no false contact with any other Raspberry Pi connector or component and then we power on. Do not worry, on the small screen, for the moment, nothing will appear. We reconnect to Raspberry Pi with Putty and WinSCP. To test display operation we can quickly load the driver from the command line and launch Raspberry Pi desktop. We type the following commands in the order, as visible in figure:

 

fig_3

 

modprobe spi-bcm2708

modprobe fbtft_device name=adafruitts rotate=90

export FRAMEBUFFER=/dev/fb1

startx

You should see the Raspberry Pi desktop on the small screen.

 

 

fig_4

 

You can also use the menu bar and applications in “touch” mode. If all goes well the most important step has been made. Now we make sure that everything will start automatically when you turn on Raspberry Pi. We close the graphical desktop (actually the X server) from the terminal window by simultaneously pressing <ControlX>. We open the following file from WinSCP:

/etc/modules

and append at the end of the file the two modules to be loaded at startup:

spi-bcm2708

fbtft_device

Save and close the file. We insert password to save. One moment, we’re not done, we have to add a configuration file to customize the display rotation and image refresh rate parameters. Open the file:

/etc/modprobe.d/adafruit.conf

and add the following configurations:

options fbtft_device name=adafruitrt28 rotate=90 frequency=32000000

The parameter “rotateallows you to rotate the display to 0, 90, 180 or 270 degrees so that it can adapt to all assembly situations.

0 corresponds to the vertical display, with the lower side towards the printed markings on the base;
90 corresponds to the horizontal display, with the bottom towards the buttons;
180 corresponds to the vertical display, with the top side towards the printed markings on the base;
270 corresponds to the horizontal display, with the top side towards the buttons
.

The parameter frequency” indicates the refresh rate of the display. The value 32000000″ means 32MHz and corresponds to a frame rate of about 20FPS. If the total load of your application allows it, you can try to lower the frequency to 16 MHz (16 million). Let’s make the changes effective with a command:

reboot

After reconnected, check the console messages with the command:

dmesg

we focus on recognition of the STMPE610 controller and on the ILI9340 display frequency setting as shown in figure.

 

fig_5

 

We can double check if everything is working by launching the X desktop with the command:

FRAMEBUFFER=/dev/fb1 startx

To stop the execution, press <ControlX>.
It’s all done? Not yet, now we have to set up and calibrate the touch screen so that it can work both with the graphical desktop and with applications that we’re going to develop. As a first step we set a rule in the folder udev linking the touchscreen device to the correct input device. It can happen that the touchscreen is recognized in the / dev / input as a different “event” depending on whether or not there are keyboard, mouse or other input devices. We create the file

95-stmpe.rules

In folder:

/etc/udev/rules.d/

and insert the following configurations:

SUBSYSTEM==”input”, ATTRS{name}==”stmpe-ts”, ENV{DEVNAME}==”*event*”, SYMLINK+=”input/touchscreen”

 

fig_6

 

Remove and re-install the touchscreen driver with the commands:

rmmod stmpe_ts

modprobe stmpe_ts

At this point in /dev/input we will find the device touchscreen” that points to the correct device “event <x>”. You can check this with the command:

ls -l /dev/input/touchscreen

 

fig_7

 

We will see the description of the device file with the connection (the arrow) to a device “event (x)”. Now we must calibrate” our touch screen. There are two ways to do this, one a bit more coarse” but automatic, the other more accurate but more complex and long run. For our needs, since we are lazy too, we will use the “Automatic” method by using a Python program created and kindly provided by Adafruit. Before, we must install a library useful to perform tests on the touch screen.

apt-get install evtest tslib libts-bin

We can already do a test by typing:

evtest /dev/input/touchscreen

If we touch the display at various positions we will see events recognized and touch-point coordinates.

 

fig_8

 

For the real “coarse” calibration, we download the Python program from Adafruit site and make the folder to contain the configuration file. Download the program with the command:

wget https://github.com/adafruit/PiTFT_Extras/raw/master/pitft_touch_cal.py

Let’s create the folder xorg.conf.d:

mkdir /etc/X11/xorg.conf.d/

and execute the calibration program from the same folder where we downloaded:

python pitft_touch_cal.py

Look at the program output, before updating the configuration file the program asks you to confirm, if you are satisfied with the results confirm with Y”.

 

fig_9

 

Displaying the Console on the screen

A nice setting that you can do is to redirect console messages to the display instead of the standard video output. Although the screen is small, if you choose the right font you can get an area of 20 lines per 40 characters. To accomplish this we must edit the kernel configuration file in the file system boot partition. Open the file:

/boot/cmdline.txt

 

fig_10

 

The purpose of the change done is to redirect the console from the frame buffer HDMI / TV standard /dev/fb0 to the frame buffer of the display TFT /dev/fb1. To do that go down to the directives, after the entry “rootwait” and add the statements:

fbco n=map: 10 fbco n=fo nt: VGA8x8

 

fig_11

 

Save the file and reboot. Note that, during the initial load, you’ll miss the multicolored splash screen and the initial part of the console messages. This is absolutely normal, because, in order to work, the driver must be loaded by the kernel and activated, which occurs after the boot start process. Then you will see the console messages, as shown in figure.

 

fig_12

 

To change the VGA8x8 font into something more readable, i.e a 12×6, run the console reconfiguration command:

dpkg-reconfigure console-setup

follow the steps on figures to select the font “Terminus 6×12”.

 

fig_13

 

fig_14

 

fig_15

 

fig_16

 

Displaying videos

You can view on our display many video files with different extensions, if the resolution is 320 x 240 pixels. To see a video we use the package “mplayer”, if it is not already present in our system we install it with the command:

apt-get install mplayer

 

fig_17

 

To see the video we give the command on figures:

mplayer -vo fbdev2:/dev/fb1 -x 240 -y 320 -framedrop <file-video.ext>

as example “ProvaVideo.mp4”

 

 

fig_18

 

fig_19

 

fig_20

 

If the video is not in 320 x 240 resolution we can resize it using the tool HandBrake, Open Source and available for all operating systems. Download it from https://handbrake.fr/. Once installed we use it to resize the test video. Open the file, preferably with the .avi extension.

 

fig_21

 

The window shows many info from the uploaded file. In the “Destination” field insert the path and file name that we want to get.

 

fig_22

 

In the panel below: In “Output Settings” in the “Container” field, just select MP4″; in Width” we set 320. In Anamorphic select Custom” and Modulus” set 2.

 

fig_23

 

Click on the “Start” button to start conversion.

 

fig_24

 

At the end, if we run the conversion in Windows OS, just move the file to Raspberry Pi and run the command described at the beginning of the paragraph to play the file.

 

fig_25

 

Displaying pictures

Another nice application is for displaying pictures. To do this we use the package fbi”: frame buffer image viewer. We install it with the usual command:

apt-get install fbi

Also in this case the images must have a max size of 320 x 240 pixels. To view an image we use the command:

fbi -T 2 -d /dev/fb1 -noverbose -a <picture-name >.jpg

 

fig_26

 

Setting the backlight level

The backlight of the TFT display is done through four LEDs which absorb a total of about 75 mA. If we power the board through battery or if you still want to turn the backlight off, the STMPE610 touch controller has two I / O pins and one of these is connected to the transistor that controls the backlight. This pin is accessible from the command line as a Raspberry Pi GPIO terminal, recognizable as GPIO 252. To access the GPIO you must export its device file with the command:

echo 252 > /sys/class/gpio/export

with:

ls -l /sys/class/gpio

You can check the actual existence of the GPIO. We declare the pin I / O as output with the command:

echo ‘out’ > /sys/class/gpio/gpio252/direction

Now we turn the backlight on by setting the pin value to “1″ with the command:

echo ‘1’ > /sys/class/gpio/gpio252/value

To turn off the backlight, use the opposite command:

echo ‘0’ > /sys/class/gpio/gpio252/value

 

Writing an app

What can we do with such a nice display, other than managing Raspberry Pi console or desktop GUI? We can write our applications, to communicate with the GPIO and any other external sensors. The possibilities are so many.

But if we want to develop a very simple starting application, we have to reduce this possibilities, always doing something really interesting. We will use Python to create a graphical interface that can control the IN/OUT shield outputs. To interact with the TFT graphic display we will exploit the functionality available in pygame, the library to create video games and graphics applications in general. In recent Raspbian distributions, pygame library is already included and installed. If not, we install it through the Manared Python Package named “pip” (pips Installs Python), with the command:

pip install pygame

If we had not pip” installed, install it with the command:

Apt-get install pip

Done? Check the installation by using python from the command line. We check that everything is working by typing one after another the following instructions:

import pygame

import os

os.putenv(‘SDL_FBDEV’, ‘/dev/fb1’)

pygame.init()

lcd = pygame.display.set_mode((320, 240))

lcd.fill((255,0,0))

pygame.display.update()

pygame.mouse.set_visible(False)

lcd.fill((0,0,0))

pygame.display.update()

Among the important instructions, see the one that sets the fb1 device as framebuffer, the pygame library init. After, we set the display definition we called “LCDwith resolution of 320 x 240 pixels. The other instructions change the screen background color, using the usual RGB coding. We conclude with one last little project that allows us to command four relays with touch controls on the TFT display. We use the RELAY4CH2846 board (available from Futura Elettronica) which hosts four relays, is powered at 5 volts and is drivable with direct or optocoupled digital inputs: those accept voltages from 1.5 to 5V and therefore are compatible with the Raspberry Pi GPIO output. We choose the direct coupling by placing a jumper on the COM and GND terminals. Now connect the card to Raspberry Pi as in the diagram in figure.

 

fig_27

 

We connect the power supply and four GPIO pins driving the relays. We chose GPIO12, 16, 20 and 21 pins, very convenient to connect on the B+ version GPIO.

To power up the board weld a strip of male connectors on the GPIO “replica” present on TFT module using pins 2 (positive) and 6 (mass) with female-female cables. In Listing 1 we see the program to drive the relays. It is always a Python program. For the graphical interface we used the pygame library, which we have just described. The list is full of comments. The code logic is the initial construction of the graphic interface. The dictionary contains the central position coordinates where we want each pin description. The “for” loop outside the main loop prepares the display area with the writings for the four pins. The word “off” is added to each pin’s “name”. The whole is colored in red and positioned so that the center corresponds to the coordinates contained in the dictionary. Finally, the display is refreshed and the text become visible. When the code is running, if you tap on a pin name the corresponding relay changes state while the text color indicates its current status: red if off and green if on, as shown in the photo of figure.

 

fig_28

 

In future posts we will see how to use the display with other shields and with extended functionality, like the ability to operate a device directly from the display or from a webpage.

For now, just enjoy experimenting.

Listing 1


 

#!/usr/bin/python
# TFT_Rele.py.py
# Import librerie
import pygame
from pygame.locals import *
import os
from time import sleep
import RPi.GPIO as GPIO # GPIO management library 
# set pin as output
GPIO.setmode(GPIO.BCM) # uses GPIO enumeration
GPIO.setup(12, GPIO.OUT) # Set pin as OUTPUT
GPIO.setup(16, GPIO.OUT)
GPIO.setup(20, GPIO.OUT)
GPIO.setup(21, GPIO.OUT)
GPIO.output(12, False) # set pins to off
GPIO.output(16, False)
GPIO.output(20, False)
GPIO.output(21, False)
# color definitions (R, G, B)
WHITE = (255,255,255)
RED = (255,0,0) 
GREEN = (0,255,0)
BLACK = (0,0,0)
# system variables to define the device, the
# display and touchscreen
os.putenv('SDL_FBDEV', '/dev/fb1')
os.putenv('SDL_MOUSEDRV', 'TSLIB')
os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen')
# relays initial status
pin12='off'
pin16='off'
pin20='off'
pin21='off'
#init pygame
pygame.init()
# hydes the mouse pointer from display
pygame.mouse.set_visible(False)
lcd = pygame.display.set_mode((320, 240))
# black screen
lcd.fill(BLACK)
pygame.display.update()
# set font 
font_big = pygame.font.Font(None, 50)
# dictionary Key=pin value=coordinate writing center 
touch_buttons = {'12':(80,60), '16':(240,60), '20':(80,180), '21':(240,180)}
# set the initial screen status 
for k,v in touch_buttons.items():
b = k + ' off' # Scritta con pin + off
text_surface = font_big.render('%s'%b, True, RED) # red text
rect = text_surface.get_rect(center=v) # centers the text
lcd.blit(text_surface, rect) # put text on the display
pygame.display.update()
# main program loop
while True:
# waiting display event 
for event in pygame.event.get():
if(event.type is MOUSEBUTTONDOWN): # Display tapped 
pos = pygame.mouse.get_pos()
print pos
elif(event.type is MOUSEBUTTONUP): # finger released from display
pos = pygame.mouse.get_pos() # recall finger position 
print pos
# reckon which quarter of the display is the finger
x,y = pos
if y < 120:
if x < 160: # up and left
print 12
v = touch_buttons.get('12') # finds text center
if pin12 == 'off': # if off
pin12 = 'on' # sets to on
GPIO.output(12, True) # pin level high
b = '12 on' # on text
color = GREEN # Color green 
else:
pin12 = 'off'
GPIO.output(12, False)
b = '12 off'
color = RED
else: # up and right
print 16
v = touch_buttons.get('16') 
if pin16 == 'off':
pin16 = 'on'
GPIO.output(16, True)
b = '16 on'
color = GREEN
else:
pin16 = 'off'
GPIO.output(16, False)
b = '16 off'
color = RED
else:
if x < 160: # down and left
print 20
v = touch_buttons.get('20') 
if pin20 == 'off':
pin20 = 'on'
GPIO.output(20, True)
b = '20 on'
color = GREEN
else:
pin20 = 'off'
GPIO.output(20, False)
b = '20 off'
color = RED
else: # down and right 
print 21
v = touch_buttons.get('21') 
if pin21 == 'off':
pin21 = 'on'
GPIO.output(21, True)
b = '21 on'
color = GREEN
else:
pin21 = 'off'
GPIO.output(21, False)
b = '21 off'
color = RED
# draw the right display portion 
# and updates it
text_surface = font_big.render('%s'%b, True, color)
rect = text_surface.get_rect(center=v)
lcd.fill(BLACK, rect) # delete the previous text
lcd.blit(text_surface, rect) # Place the new text
pygame.display.update() # redraw the display
sleep(0.3) # waits
GPIO.cleanup()
# TFT_Rele.py.py

# Import librerie

import pygame

from pygame.locals import *

import os

from time import sleep

import RPi.GPIO as GPIO # GPIO management library

# set pin as output

GPIO.setmode(GPIO.BCM) # uses GPIO enumeration

GPIO.setup(12, GPIO.OUT) # Set pin as OUTPUT

GPIO.setup(16, GPIO.OUT)

GPIO.setup(20, GPIO.OUT)

GPIO.setup(21, GPIO.OUT)

GPIO.output(12, False) # set pins to off

GPIO.output(16, False)

GPIO.output(20, False)

GPIO.output(21, False)

# color definitions (R, G, B)

WHITE = (255,255,255)

RED = (255,0,0)

GREEN = (0,255,0)

BLACK = (0,0,0)

# system variables to define the device, the

# display and touchscreen

os.putenv('SDL_FBDEV', '/dev/fb1')

os.putenv('SDL_MOUSEDRV', 'TSLIB')

os.putenv('SDL_MOUSEDEV', '/dev/input/touchscreen')

# relays initial status

pin12='off'

pin16='off'

pin20='off'

pin21='off'

#init pygame

pygame.init()

# hydes the mouse pointer from display

pygame.mouse.set_visible(False)

lcd = pygame.display.set_mode((320, 240))

# black screen

lcd.fill(BLACK)

pygame.display.update()

# set font

font_big = pygame.font.Font(None, 50)

# dictionary Key=pin value=coordinate writing center

touch_buttons = {'12':(80,60), '16':(240,60), '20':(80,180), '21':(240,180)}

# set the initial screen status

for k,v in touch_buttons.items():

b = k + ' off' # Scritta con pin + off

text_surface = font_big.render('%s'%b, True, RED) # red text

rect = text_surface.get_rect(center=v) # centers the text

lcd.blit(text_surface, rect) # put text on the display

pygame.display.update()

# main program loop

while True:

# waiting display event

for event in pygame.event.get():

if(event.type is MOUSEBUTTONDOWN): # Display tapped

pos = pygame.mouse.get_pos()

print pos

elif(event.type is MOUSEBUTTONUP): # finger released from display

pos = pygame.mouse.get_pos() # recall finger position

print pos

# reckon which quarter of the display is the finger

x,y = pos

if y < 120:

if x < 160: # up and left

print 12

v = touch_buttons.get('12') # finds text center

if pin12 == 'off': # if off

pin12 = 'on' # sets to on

GPIO.output(12, True) # pin level high

b = '12 on' # on text

color = GREEN # Color green

else:

pin12 = 'off'

GPIO.output(12, False)

b = '12 off'

color = RED

else: # up and right

print 16

v = touch_buttons.get('16')

if pin16 == 'off':

pin16 = 'on'

GPIO.output(16, True)

b = '16 on'

color = GREEN

else:

pin16 = 'off'

GPIO.output(16, False)

b = '16 off'

color = RED

else:

if x < 160: # down and left

print 20

v = touch_buttons.get('20')

if pin20 == 'off':

pin20 = 'on'

GPIO.output(20, True)

b = '20 on'

color = GREEN

else:

pin20 = 'off'

GPIO.output(20, False)

b = '20 off'

color = RED

else: # down and right

print 21

v = touch_buttons.get('21')

if pin21 == 'off':

pin21 = 'on'

GPIO.output(21, True)

b = '21 on'

color = GREEN

else:

pin21 = 'off'

GPIO.output(21, False)

b = '21 off'

color = RED

# draw the right display portion

# and updates it

text_surface = font_big.render('%s'%b, True, color)

rect = text_surface.get_rect(center=v)

lcd.fill(BLACK, rect) # delete the previous text

lcd.blit(text_surface, rect) # Place the new text

pygame.display.update() # redraw the display

sleep(0.3) # waits

GPIO.cleanup()

 

From the store

Raspberry B+

TFT 2.8 Inch Touch hat

Starter Kit Raspberry PI

About Boris Landoni

Boris Landoni is the technical manager of Open-Electronics.org. Skilled in the GSM field, embraces the Open Source philosophy and its projects are available to the community.

4 Comments

  1. Pingback: Raspberry-pi - Alarme | Pearltrees

Leave a Reply

Your email address will not be published.