├── README.md ├── diagram.png ├── logo.png └── main.py /README.md: -------------------------------------------------------------------------------- 1 | # Using Kivy with the official Raspberry Pi Touch Display 2 | 3 | [![Demo video](http://img.youtube.com/vi/Eah3Zq18OyM/0.jpg)](http://www.youtube.com/watch?v=Eah3Zq18OyM) 4 | 5 | The guide below and example code will get you started setting up the Raspberry Pi touch display and getting Kivy working with it. [Kivy](http://kivy.org/) is an "open source Python library for rapid development of applications 6 | that make use of innovative user interfaces, such as multi-touch apps." 7 | 8 | This guide assumes you have a fresh install of Raspbian (the 2015-05-05 Wheezy release or the 2015-09-24 Jessie release), an Internet connection, and the display is connected and working. It also assumes that you're already familiar with Raspberry Pi enough to get yourself to the command line. You can run this code locally or via SSH. 9 | 10 | **Note:** I don't recommend executing these steps with the desktop envioronment running. It may slow down the set up process and cause problems with running Kivy apps. If you're set up to boot to into the desktop enviroment on Raspbian Jessie, click the Raspberry Menu → Preferences → Raspberry Pi Configuration. Change the Boot setting from Desktop to CLI and then reboot. 11 | 12 | The command line is where you'll start: 13 | 14 | 1. Update your software. This is required with the 2015-05-05 Raspbian image in order to get touch working. This step will take a few minutes: 15 | 16 | pi@raspberrypi ~ $ sudo apt-get update && sudo apt-get -y upgrade 17 | 18 | 2. Reboot (this is not required, but might be a good idea if you're working from an older version of Raspbian): 19 | 20 | pi@raspberrypi ~ $ sudo reboot 21 | 22 | 3. Back on the command line, check that touch input works by trying it in X11: 23 | 24 | pi@raspberrypi ~ $ startx 25 | 26 | 4. If touch works, exit out of X11 and go back to the command line. 27 | 5. The next few steps will install Kivy. These instructions are based on the [Kivy User’s Guide](http://kivy.org/docs/installation/installation-rpi.html). Firstly, open the APT sources list: 28 | 29 | pi@raspberrypi ~ $ sudo nano /etc/apt/sources.list 30 | 31 | 6. At the end of file, add the APT sources for Gstreamer: 32 | 33 | deb http://vontaene.de/raspbian-updates/ . main 34 | 35 | 7. Type `Control+X` to exit nano. Then press `Y` and `Enter` to save the file. You'll be back on the command line. 36 | 37 | 8. Download and add the GPG key for the Gstreamer sources: 38 | 39 | pi@raspberrypi ~ $ gpg --keyserver pgp.mit.edu --recv-keys 0C667A3E 40 | pi@raspberrypi ~ $ gpg -a --export 0C667A3E | sudo apt-key add - 41 | 42 | 9. Install the dependencies: 43 | 44 | pi@raspberrypi ~ $ sudo apt-get update 45 | pi@raspberrypi ~ $ sudo apt-get -y install pkg-config libgl1-mesa-dev libgles2-mesa-dev \ 46 | python-pygame python-setuptools libgstreamer1.0-dev git-core \ 47 | gstreamer1.0-plugins-{bad,base,good,ugly} \ 48 | gstreamer1.0-{omx,alsa} python-dev 49 | 50 | 10. Install pip from source, as the version that is in the Raspbian apt repository is too old. You can ignore any messages about `InsecurePlatformWarning`: 51 | 52 | pi@raspberrypi ~ $ wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py 53 | pi@raspberrypi ~ $ sudo python get-pip.py 54 | 55 | 11. Install [Cython](http://cython.org/), [Pygments](http://pygments.org/), and [docutils](https://pypi.python.org/pypi/docutils). The Pygments and docutils packages are not actually required for Kivy, but the example code you'll execute uses them. This step will take a few minutes: 56 | 57 | pi@raspberrypi ~ $ sudo pip install cython pygments docutils 58 | 59 | 12. Download Kivy and install it globally (this step will take quite a few minutes): 60 | 61 | pi@raspberrypi ~ $ git clone https://github.com/kivy/kivy 62 | pi@raspberrypi ~ $ cd kivy 63 | pi@raspberrypi ~/kivy $ python setup.py build 64 | pi@raspberrypi ~/kivy $ sudo python setup.py install 65 | 66 | 13. To enable touch, you'll need to make a modification to the default Kivy configuration file. To create that file, first run an example: 67 | 68 | pi@raspberrypi ~/kivy $ python ~/kivy/examples/demo/pictures/main.py 69 | 70 | 13. Quit the example with `Ctrl+C` and then open the newly-created `config.ini` file for editing: 71 | 72 | pi@raspberrypi ~/kivy $ nano ~/.kivy/config.ini 73 | 74 | 14. Go into the `[input]` section, remove the lines that are in there and put in: 75 | 76 | mouse = mouse 77 | mtdev_%(name)s = probesysfs,provider=mtdev 78 | hid_%(name)s = probesysfs,provider=hidinput 79 | 80 | 15. Launch the multi touch pictures demo. Tap, drag, pinch, and rotate should all work like a dream: 81 | 82 | pi@raspberrypi ~/kivy $ python ~/kivy/examples/demo/pictures/main.py 83 | 84 | 16. Type `Control+C` to exit the pictures demo. 85 | 86 | 17. Launch the UI showcase. This shows you all the different UI elements that Kivy makes available to you: 87 | 88 | pi@raspberrypi ~/kivy $ python ~/kivy/examples/demo/showcase/main.py 89 | 90 | 18. If you'd like, explore the other examples in `~/kivy/examples/`. 91 | 92 | 19. To try Kivy and GPIO together, download this repo to your Raspberry Pi if you haven't already: 93 | 94 | pi@raspberrypi ~/kivy $ cd ~ 95 | pi@raspberrypi ~ $ git clone https://github.com/mrichardson23/rpi-kivy-screen.git 96 | 97 | 20. The example uses BCM GPIO pins 17 as a piezo buzzer, 27 and 10 as LEDs, and 22 as a button (with internal pullups set HIGH, so connect one leg of the button to 22 and the other to ground.) 98 | 99 | ![Wiring Diagram](https://github.com/mrichardson23/rpi-kivy-screen/blob/master/diagram.png) 100 | 101 | 21. First try to run the example as root (in versions of Raspbian before Jessie, root access is required for the GPIO library): 102 | 103 | pi@raspberrypi ~ $ cd rpi-kivy-screen/ 104 | pi@raspberrypi ~/rpi-kivy-screen $ sudo python main.py 105 | 106 | 22. As you'll see, touch doesn't work. To fix this, you need to make the same change to `config.ini` you made before, but to the root account's config file. Exit (`Control+C`) and copy over your home directory's Kivy configuration file to overwrite the root account's: 107 | 108 | pi@raspberrypi ~/rpi-kivy-screen $ sudo cp ~/.kivy/config.ini /root/.kivy/config.ini 109 | 110 | 23. Run the example again and you'll be able to control the LED and buzzer. You'll also be able to see the state of the physical button! 111 | 112 | pi@raspberrypi ~/rpi-kivy-screen $ sudo python main.py 113 | 114 | Even though root access isn't required for Python GPIO starting with the Jessie version of Raspbian, it may be helpful to copy the `config.ini` file anyway in case you decide to have the root user execute your project immediately after boot up. 115 | -------------------------------------------------------------------------------- /diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrichardson23/rpi-kivy-screen/179a5c8478cfdb492e673ec5f705ddfbd71e1c66/diagram.png -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrichardson23/rpi-kivy-screen/179a5c8478cfdb492e673ec5f705ddfbd71e1c66/logo.png -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import kivy 2 | kivy.require('1.0.6') # replace with your current kivy version ! 3 | 4 | from kivy.app import App 5 | from kivy.uix.button import Button 6 | from kivy.uix.togglebutton import ToggleButton 7 | from kivy.uix.gridlayout import GridLayout 8 | from kivy.uix.image import Image 9 | from kivy.uix.slider import Slider 10 | from kivy.clock import Clock 11 | from kivy.graphics import Color, Rectangle 12 | 13 | import RPi.GPIO as GPIO 14 | 15 | #for now, use a global for blink speed (better implementation TBD): 16 | speed = 1.0 17 | 18 | # Set up GPIO: 19 | beepPin = 17 20 | ledPin = 27 21 | buttonPin = 22 22 | flashLedPin = 10 23 | GPIO.setmode(GPIO.BCM) 24 | GPIO.setup(beepPin, GPIO.OUT) 25 | GPIO.output(beepPin, GPIO.LOW) 26 | GPIO.setup(ledPin, GPIO.OUT) 27 | GPIO.output(ledPin, GPIO.LOW) 28 | GPIO.setup(flashLedPin, GPIO.OUT) 29 | GPIO.output(flashLedPin, GPIO.LOW) 30 | GPIO.setup(buttonPin, GPIO.IN, pull_up_down=GPIO.PUD_UP) 31 | 32 | # Define some helper functions: 33 | 34 | # This callback will be bound to the LED toggle and Beep button: 35 | def press_callback(obj): 36 | print("Button pressed,", obj.text) 37 | if obj.text == 'BEEP!': 38 | # turn on the beeper: 39 | GPIO.output(beepPin, GPIO.HIGH) 40 | # schedule it to turn off: 41 | Clock.schedule_once(buzzer_off, .1) 42 | if obj.text == 'LED': 43 | if obj.state == "down": 44 | print ("button on") 45 | GPIO.output(ledPin, GPIO.HIGH) 46 | else: 47 | print ("button off") 48 | GPIO.output(ledPin, GPIO.LOW) 49 | 50 | def buzzer_off(dt): 51 | GPIO.output(beepPin, GPIO.LOW) 52 | 53 | # Toggle the flashing LED according to the speed global 54 | # This will need better implementation 55 | def flash(dt): 56 | global speed 57 | GPIO.output(flashLedPin, not GPIO.input(flashLedPin)) 58 | Clock.schedule_once(flash, 1.0/speed) 59 | 60 | # This is called when the slider is updated: 61 | def update_speed(obj, value): 62 | global speed 63 | print("Updating speed to:" + str(obj.value)) 64 | speed = obj.value 65 | 66 | # Modify the Button Class to update according to GPIO input: 67 | class InputButton(Button): 68 | def update(self, dt): 69 | if GPIO.input(buttonPin) == True: 70 | self.state = 'normal' 71 | else: 72 | self.state = 'down' 73 | 74 | class MyApp(App): 75 | 76 | def build(self): 77 | # Set up the layout: 78 | layout = GridLayout(cols=5, spacing=30, padding=30, row_default_height=150) 79 | 80 | # Make the background gray: 81 | with layout.canvas.before: 82 | Color(.2,.2,.2,1) 83 | self.rect = Rectangle(size=(800,600), pos=layout.pos) 84 | 85 | # Instantiate the first UI object (the GPIO input indicator): 86 | inputDisplay = InputButton(text="Input") 87 | 88 | # Schedule the update of the state of the GPIO input button: 89 | Clock.schedule_interval(inputDisplay.update, 1.0/10.0) 90 | 91 | # Create the rest of the UI objects (and bind them to callbacks, if necessary): 92 | outputControl = ToggleButton(text="LED") 93 | outputControl.bind(on_press=press_callback) 94 | beepButton = Button(text="BEEP!") 95 | beepButton.bind(on_press=press_callback) 96 | wimg = Image(source='logo.png') 97 | speedSlider = Slider(orientation='vertical', min=1, max=30, value=speed) 98 | speedSlider.bind(on_touch_down=update_speed, on_touch_move=update_speed) 99 | 100 | # Add the UI elements to the layout: 101 | layout.add_widget(wimg) 102 | layout.add_widget(inputDisplay) 103 | layout.add_widget(outputControl) 104 | layout.add_widget(beepButton) 105 | layout.add_widget(speedSlider) 106 | 107 | # Start flashing the LED 108 | Clock.schedule_once(flash, 1.0/speed) 109 | 110 | return layout 111 | 112 | if __name__ == '__main__': 113 | MyApp().run() 114 | --------------------------------------------------------------------------------