Introduction
As I have said before part of the point of this blog is so I have a record of how I did things and this definitely fits into that category. If others find it useful, that is a bonus.
I have had a small 2.4″ TFT with touch sitting around for ages. I looked at using it when it arrived, but compling a kernel put me right off. So this week the notion took me to try again and I discovered it was actually very easy with newer versions of Raspbian.
[Edit 16 Dec 17] I had made an error in the table below putting both clocks on GPIO08. I have had some PCBs made up to simplify the connection – the error blew the TFT I was using sadly.
Sources
There are a couple of key sources I used and in places I have blatantly plagiarized them (they are that good) so as to bring it all together, and in case the source disappears (it happens).
- Wiring and OS tasks
- tslib info
- fbTFT info
- getting started with pygame
- More on pygame
- Fixing Coordinates on Jessie
Background
The background detail, found in the first reference, is interesting. It seems the old notro type method is being phased out in preference for overlays. Worth reading.
Wiring
I was fortunate in that my board was very similar to the board in reference 1 so I could use those mappings for my wiring. If you have a different board then head over there and it is explained how to work out the wiring for your specific overlay.
Panel Pin | Function name
|
GPIO | Pin No. |
T_IRQ | Panel Touch Interrupt | GPIO25 | 22 |
T_DO | Touch Data Out | GPIO09 | 21 |
T_DIN | Touch Data In | GPIO10 | 19 |
T_CS | Touch Chip Select SPI_CE1_N | GPIO07 | 26 |
T_CLK | Touch Clock | GPIO11 | 23 |
SDO (MISO) | TFT Data Out SPI_MISO | GPIO09 | 21 |
LED | Backlight | GPIO18– see note | 12 |
SCK | TFT Clock SPI_CLK | GPIO11 | 23 |
SDI (MOSI) | TFT Data In SPI_MOSI | GPIO10 | 19 |
D/C | TFT Data / Command | GPIO24 | 18 |
RESET | Reset | GPIO23 | 16 |
CS | TFT Chip Select SPI_CE0_N | GPIO08 | 24 |
GND | Ground | GND | |
VCC | 3V3 supply |
+3V3 |
I did the wiring using a breadboard as a couple of the pins need the same GPIO pin. Not pretty but functional!
Note the original sources comment on wiring up the LED Backlight. For now I have just connected to the 3.3V.
Setting up the OS
As an aside, although I did this initially on a clean install of Raspbian Jessie, I then moved to DietPi. The main reason for this is that you can create a configuration file for such things as WiFi SSID & Password and a fixed IP address. I could then do everything headless from the go.
The OS changes themselves are simplicity itself.
Edit the file /boot/config.txt (on DietPi you need to edit /DietPi/config.txt) and include the following lines;
1 2 3 4 5 6 7 |
# TFT display and touch panel #dtoverlay=rpi-display,rotate=0,speed=10000000,xohms=100,debug=4 dtoverlay=rpi-display dtparam=rotate=0 dtparam=speed=10000000 dtparam=xohms=100 dtparam=debug=4 |
And reboot the Pi. That’s it. If it is OK, the screen will light up during boot, then go blank.
Next step is to check and calibrate the touchscreen. I deviate a bit from my main source as there were 2 extra packages to install (references 2 & 3).
1 |
sudo apt-get install tsconf tslib libts-bin |
I found I needed to do the calibration before I did the test so (remembering to change the event number and fb if necessary);
1 |
sudo TSLIB_FBDEVICE=/dev/fb1 TSLIB_TSDEVICE=/dev/input/event0 ts_calibrate |
and then
1 |
sudo TSLIB_FBDEVICE=/dev/fb1 TSLIB_TSDEVICE=/dev/input/event0 ts_test |
If all is well, you can drag the cross hairs or draw in the screen.
You now need to check the touch input. to do this;
1 |
sudo apt-get install xinput evtest |
and then run evtest If you are running headless, the touch input is likely to be event0, if you are not, again head over to the first reference and see how to interpret the contents of /dev/events/
The AdaFruit tutorial on this has some instructions for creating a udev rule to map the touch screen events to a fixed point. I have not managed to get this to work and I suspect it is because I am using overlays.
pygame and TSLIB problems with Jessie
I won’t bore you with how I got here, suffice to say I realised that the coordinates of the touch input were not correctly reported by the OS to pygame. After a bit of digging I found reference 6. In summary, to fix the issue create and run the following script;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#!/bin/bash #enable wheezy package sources echo "deb http://archive.raspbian.org/raspbian wheezy main " > /etc/apt/sources.list.d/wheezy.list #set stable as default package source (currently jessie) echo "APT::Default-release \"stable\"; " > /etc/apt/apt.conf.d/10defaultRelease #set the priority for libsdl from wheezy higher then the jessie package echo "Package: libsdl1.2debian Pin: release n=jessie Pin-Priority: -10 Package: libsdl1.2debian Pin: release n=wheezy Pin-Priority: 900 " > /etc/apt/preferences.d/libsdl #install apt-get update apt-get -y --force-yes install libsdl1.2debian/wheezy |
This fixed the coordinates for me.
Python and TFT
The aim of all this is to have a small touchscreen that I can use to provide simple control of my heating and hot water – basically a boost function. I’ll blog about that when I get a bit further. In the meantime, the following code will test out the touch responses.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#!/usr/bin/python import os import locale import logging as log import pygame from time import * # Tell the RPi to use the TFT screen and that it's a touchscreen device os.putenv('SDL_VIDEODRIVER', 'fbcon') os.putenv('SDL_FBDEV' , '/dev/fb1') os.putenv('SDL_MOUSEDRV' , 'TSLIB') os.putenv('SDL_MOUSEDEV' , '/dev/input/event0') class test(): def __init__(self): pygame.init() self.screen = pygame.display.set_mode((320, 240)) def main_loop(self): while True: event = pygame.event.wait() if event.type == pygame.MOUSEBUTTONDOWN: log.debug("MOUSEBUTTONDOWN:{}".format(pygame.mouse.get_pos())) pygame.event.clear() if __name__ == "__main__": log.basicConfig(filename="/tmp/log",level=log.DEBUG) main_window = test() main_window.main_loop() |
Edit 5 June 2017
I have now sorted out some more useful code to display buttons which you will find here.
HTH
by