I have recently gotten the Adafruit 2.8" TFT Touchscreen I've got it all set up and working correctly. All of my touchscreen calibration went well and appears to be functioning correctly.

I am now trying to write a program using pygame that will output somethings to the touchscreen and allow inputs via the touchscreen. This is functioning well if I run startx and then launch my script. However I'd like to be able to start my script directly from the console without the need for startx

This question got me most of the way there, the screen is now getting drawn to properly. It does seem to accept touch inputs the x/y coordinates are off. The answer provided on this question was to put this:

os.environ["SDL_FBDEV"] = "/dev/fb1"

in my script before calling pygame.init()

Using pygame if I leave the mouse turned on I can see that it does not follow my stylus as I touch various points on the screen. It appears that the x and y axis are flipped. If I move my stylus side to side the mouse cursor moves up and down, if I move up and down the cursor goes side to side.

However if I do startx first, and then launch my python script the mouse/touchscreen functions perfectly with all of the events getting sent to the correct coordinates.

What do I need to do in order to get my touch events to work properly inside of pygame with a script launched from console rather than inside of x?

Going back through the touchscreen setup procedures (which I admittedly did not fully understand while I was doing them) I've noticed they had me create a file: /etc/X11/xorg.conf.d/99-calibration.conf

and put this into it:

Section "InputClass"
    Identifier "calibration"
    MatchProduct "stmpe-ts"
    Option "Calibration" "3800 200 200 3800"
    Option "SwapAxes" "1"

I assume the "SwapAxes" "1" is what is allowing the touch screen to work properly when I launch my script from x.

I just need to know how to "apply" this config file when I am running from the console rather than via x.


I've also noticed if I run the ts_test program (from console rather than X) the touch screen functions correctly. So there must be some way to allow it to work without X being launched.


4 Answers 4


I was able to get calibrated touch screen coordinates with the following set of environment variables set before initialising PyGame:

os.environ['SDL_VIDEODRIVER'] = 'fbcon'
os.environ["SDL_FBDEV"] = "/dev/fb1"
os.environ["SDL_MOUSEDEV"] = "/dev/input/touchscreen"
os.environ["SDL_MOUSEDRV"] = "TSLIB"

You may need a different path for SDL_MOUSEDEV, depending on how you've set up the touch screen device. The example above matches the one in the Adafruit guide.


If calibration shows the right coordinates, but pygame does not, then the most common cause is the SDL library version needs to be updated to 1.2. This is what bit me for a while as well with the same touchscreen, where outside of pygame it was perfect but I kept getting absolutely horrible values from mouse._get_pos() even with all the proper device environment.

PiTFT Pygame Tips describes the procedure, which was originally posted by a user in the Adafruit forums and includes the following update scripts (in case the link is ever down):


#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

apt-get update
apt-get -y --force-yes install libsdl1.2debian/wheezy

Create that script in a file, chmod +x that_file, and then run sudo that_file.

Now re-run your pygame script and coordinates from the touchscreen should be happy once again.

  • This no longer just works. But you can get it going by changing the echo "APT::Default-release \"stable\"; to echo "APT::Default-release \"wheezy\";
    – fret
    Commented Nov 26, 2017 at 20:32
  • This no longer just works, even with echo "APT::Default-release \"wheezy\";. The repository has been taken down Commented Jul 23, 2021 at 9:13

Also don't forget to recalibrate the touchscreen. Manually worked the best for me. See the Adafruit site here

sudo TSLIB_FBDEVICE=/dev/fb1 TSLIB_TSDEVICE=/dev/input/touchscreen ts_calibrate

I had this same problem with a 10 inch TSTP Touchscreen. I ended up reading the data directly from the USB interface which turned out to be completely accurate and correct. Something is wrong in either pygame or SDL, and it breaks a lot of touchscreens unless you run in X11. I documented how I solved this at https://stackoverflow.com/a/71827823/571608 (If linking to SO is not preferred please let me know)

Short summary if your touch is a USB device: Find out where your touch device file is, read it with the linux command "xxd", analyze where the touch coordinates are in the bytestream, then in your python script struct to parse the binary data into X/Y integers. You can then either feed those in as mouse or joystick events (I used JOYBUTTONDOWN in order to be able to distinguish between my correct coordinates and the incorrect ones coming from the mouse device), or you can just handle things directly.

YMMV of course, and depending on the touchscreen you may actually experience calibration issues. But at least in my case, calibration was never an issue and this solved my problem.

I can now run my pygame program at full speed on a raspi without the significant memory and CPU overhead of X11, while using half the CPU time.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.