Page 1 of 1
Showing an image with gpio
Posted: Wed Mar 04, 2015 1:45 pm
by realswz
Hello guys
I've a script for showing a picture when a button connected to the gpio-inputs is pressed.
Code: Select all
#!/usr/bin/env python
import RPi.GPIO as GPIO
from PIL import Image
im=Image.open("/home/pi/Rock.png").convert("RGB")
buttonPin = 25
GPIO.setmode(GPIO.BCM)
GPIO.setup(buttonPin,GPIO.IN)
while True:
if ( GPIO.input(25) == False ):
im.show()
Unfortunately, this doesnt work. I compile it with the command "sudo chmod +x hhh.py" to make it executable. After this, I execute it with "sudo python hhh.py". Now the terminal freezes for some seconds and shows a lot of errors after this. I'm very new to python, so there are maybe some really stupid faults i made. Can anyone help me? The image is stored in the same place as the script.
These are the errors:
Code: Select all
CTraceback (most recent call last):
File "hhh.py", line 11, in <module>
im.show()
File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 1483, in show
_show(self, title=title, command=command)
File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 2123, in _show
apply(_showxv, (image,), options)
File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 2127, in _showxv
apply(ImageShow.show, (image, title), options)
File "/usr/lib/python2.7/dist-packages/PIL/ImageShow.py", line 39, in show
def show(image, title=None, **options):
KeyboardInterrupt
Re: Showing an image with gpio
Posted: Wed Mar 04, 2015 4:00 pm
by texy
Hi and welcome to the forum.
Well for one thing, you do not need to make it executable in order to use the command "sudo python hhh.py"
Secondly, are you sure that the button is connected to the pin that the software is expecting to react too?
Show us the wiring diagram of your switch and Pi.
Texy
Re: Showing an image with gpio
Posted: Wed Mar 04, 2015 4:32 pm
by elParaguayo
It looks to me as if the terminal will appear to freeze because you enter an infinite loop. Once in the loop you're constantly reading the state of the GPIO pin.
I have two comments:
1) I'd add a small sleep to the loop to free up the processor to do other things.
2) I'd also add a small sleep to the if statement to "debounce" the GPIO press - if you don't, you'll trigger multiple "im.show()" calls which your pi won't thank you for.
Also, do you get any errors when then code runs, or is it just when you press "ctrl+c" because it looks like it's frozen?
Lastly, is there any pull-up resistor on the button so that it's constantly HIGH until the button is pressed?
Re: Showing an image with gpio
Posted: Wed Mar 04, 2015 5:23 pm
by PiGraham
A few things...
Does just the code to open and display an image work?
You don't seem to have any errors reported, only 'keyboard interrupt', which was presumably you pressing Ctrl-C to exit the infinite loop.
PIL relies on a default image viewer. One option is imagemagick
Without that I get no image displayed from im.show(). After installing it I see the image in a window.
Your loop repeatedly calls show(), which is not a good idea. Call it once. One way to do that is to initialise a variable to 0, wait for the GPIO state change, then, if the variable is 0, show the image and set the variable to 1. Now the loop finds the variable is not 0 and doesn't call show() again.
In any case put a time.sleep in the loop so that your program doesn't use all the CPU resources.
Re: Showing an image with gpio
Posted: Wed Mar 04, 2015 6:25 pm
by slmaws
Don't use time.sleep as some of the guys suggest, you may miss some clicks. Use wait_for_edge function:
Code: Select all
#!/usr/bin/env python
import RPi.GPIO as GPIO
from PIL import Image
im=Image.open("/home/pi/Rock.png").convert("RGB")
buttonPin = 25
GPIO.setmode(GPIO.BCM)
GPIO.setup(buttonPin,GPIO.IN)
while True:
GPIO.wait_for_edge(buttonPin, GPIO.FALLING)
im.show()
Read more here about wait_for_edge
http://sourceforge.net/p/raspberry-gpio ... ki/Inputs/
and as @PiGraham suggests install imagemagick
Re: Showing an image with gpio
Posted: Fri Mar 13, 2015 2:27 pm
by realswz
Thanks guys, your tipps worked.
Now i have two more little questions:
1. What command do i need to display the picture in imagemagick in fullscreen (without any toolbars and things) and without the little "pan icon" window?
2. I have two pictures that should be displayed. Which command do i need to close the other picture? I tried it with os.popen('killall XXX') but i dont know what the task for imagemagick is named and i didn't find it either, i think it doesn't create any process..
Thanks guys
Re: Showing an image with gpio
Posted: Fri Mar 13, 2015 2:37 pm
by PiGraham
Re: Showing an image with gpio
Posted: Fri Mar 13, 2015 2:57 pm
by realswz
So isn't this possible with imagemagick or the default image viewer of raspbian?
pygame looks a bit more difficult than the stuff i did so far, or am i wrong?
Re: Showing an image with gpio
Posted: Fri Mar 13, 2015 3:01 pm
by gordon77
example of pygame
connect switch between GPIO pin 26 and gnd (pin 25), or change IP=26 to what you want
Set pic_names, usb_name, number of pics, width and height as required.
If the pictures are on the SD card use usb_name = "/home/pi/"
Press X for EXIT, F for FULLSCREEN, N for normal window
Code: Select all
#!/usr/bin/env python
import pygame
import sys
import time
from pygame.locals import *
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode (GPIO.BOARD)
# set GPIO output pin
IP = 26
GPIO.setup(IP,GPIO.IN)
GPIO.setup(IP,GPIO.IN,pull_up_down = GPIO.PUD_UP)
# picture display size
width = 1024
height = 768
# number of pictures
pictures = 4
# picture names
pic_names = ['screen1.jpg','screen2.jpg','screen3.jpg','screen4.jpg']
# USB stick name
usb_name = "/media/TOSHIBA/"
windowSurfaceObj = pygame.display.set_mode((width,height))
pygame.display.set_caption('Slideshow')
x= 0
while True:
imagefile = usb_name + pic_names[x]
image = pygame.image.load(imagefile)
image = pygame.transform.scale(image,(width,height))
windowSurfaceObj.blit(image,(0,0))
pygame.display.update()
if GPIO.input(IP)== False:
x +=1
if x > pictures - 1:
x = 0
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
# press N for normal screen
if event.key == K_n:
windowSurfaceObj = pygame.display.set_mode((width,height))
windowSurfaceObj.blit(image,(0,0))
pygame.display.update()
# press F for fullscreen
if event.key == K_f:
windowSurfaceObj = pygame.display.set_mode((width,height),pygame.FULLSCREEN)
windowSurfaceObj.blit(image,(0,0))
pygame.display.update()
# press X to EXIT
if event.key == K_x:
pygame.quit()
Re: Showing an image with gpio
Posted: Wed Mar 18, 2015 8:04 am
by realswz
thank you for your example. Two questions: I dont need a slideshow and i have more than one switch, for each image one button. What do i need to change to only show the image X if switch X is pressed and image Y when switch Y is pressed? And can i modify the script that it shows videos if the input is more that 3 seconds low or something like that?
thanks for your help
Re: Showing an image with gpio
Posted: Wed Mar 25, 2015 10:11 am
by realswz
I modified the script, it works now the way i want it. I just have the question if i could make it more efficient and if there are some useless lines i've written. Keep in mind that this is only a test with 2 buttons, but the final script should have 10 buttons in it. So maybe there is an easier way to do it. This is my script now:
Code: Select all
#!/usr/bin/env python
import pygame
import sys
import time
from pygame.locals import *
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode (GPIO.BCM)
# set GPIO output pins
button1 = 17
button2 = 25
GPIO.setup(button1,GPIO.IN)
GPIO.setup(button2,GPIO.IN)
# picture display size
width = 1920
height = 1080
# File names
screen1 = "/media/A2A7-1908/screen1.jpg"
screen2 = "/media/A2A7-1908/screen2.jpg"
windowSurfaceObj = pygame.display.set_mode((width,height),pygame.FULLSCREEN)
pygame.display.set_caption('Window')
while True:
if GPIO.input(button1)== False:
image = pygame.image.load(screen1)
image = pygame.transform.scale(image,(width,height))
windowSurfaceObj.blit(image,(0,0))
pygame.display.update()
if GPIO.input(button2)== False:
image = pygame.image.load(screen2)
image = pygame.transform.scale(image,(width,height))
windowSurfaceObj.blit(image,(0,0))
pygame.display.update()
for event in pygame.event.get():
if event.type == QUIT:
pygame.quit()
sys.exit()
elif event.type == KEYDOWN:
# press N for normal screen
if event.key == K_n:
windowSurfaceObj = pygame.display.set_mode((width,height))
windowSurfaceObj.blit(image,(0,0))
pygame.display.update()
# press F for fullscreen
if event.key == K_f:
windowSurfaceObj = pygame.display.set_mode((width,height),pygame.FULLSCREEN)
windowSurfaceObj.blit(image,(0,0))
pygame.display.update()
# press X to EXIT
if event.key == K_x:
pygame.quit()
and another question: what does .blit in the last few lines do? do i even need it?
the question from my post before is still actual: which command from pygame do i need to show a video, if the same input as the one for the images is pressed for 3...5 seconds? is this even possible? i just need a little hint which (two?) lines i need to do it, i can implement it myself after.
thank you guys for all your help
Re: Showing an image with gpio
Posted: Wed Mar 25, 2015 12:00 pm
by paddyg
Hi, people seem to have used pygame.movie sucessfully on RPi (google 'pygame movie raspberry pi' for some code examples)
It's a good idea to put a little sleep (0.01s say) inside your while loop so the processor doesn't go flat out.
As it stands your code will keep doing the block of code again and again while the button is pressed. You probably need to have a variable to keep track of what the state was and only do the block if it's changed. Alternatively (better) put the code in its own function and use the GPIO callback. However you will probably need to do something cleverer if you are going to cope with detecting long presses (or even multi presses), but that very subject has cropped up on this forum many times so you should be able to find ready-made code. To see if you need the blit try taking it out and see what happens.
Re: Showing an image with gpio
Posted: Wed Mar 25, 2015 2:45 pm
by realswz
Thank you for the hint about the videos and the sleep, i will try it.
I'm a little bit unexperienced at python programming, what do you mean with GPIO Callback and why is it a problem if it does the block over and over again? And with which term should i search about the long-press code? is there a technical term for it?
thanks in advance
edit: a little "problem" appeared too. Everything works perfectly fine but when i close pygame with the key (x = defined as exit key) this lines appear in the terminal:
Code: Select all
pi@raspberrypi ~ $ sudo python test2.py
Traceback (most recent call last):
File "test2.py", line 47, in <module>
for event in pygame.event.get():
pygame.error: video system not initialized
i dont know whats the problem here but it doesn't affect anything in the script..
Re: Showing an image with gpio
Posted: Wed Mar 25, 2015 2:55 pm
by gordon77
realswz wrote:
and another question: what does .blit in the last few lines do? do i even need it?
thank you guys for all your help
blit applies the image to a surface so you can then show it.
windowSurfaceObj.blit(image,(0,0)) puts your image at postion 0,0 (top left corner)
Re: Showing an image with gpio
Posted: Thu Mar 26, 2015 9:52 am
by realswz
I've created this little test script for detecting the duration of the press and then show image 1 or image 2 based on the time the button was pressed. It doesn't create any error but it still won't work. Any idea? Maybe theres something wrong with the identation, but i can't figure out what exactly. Theres nothing wrong with the pictures, they work fine in an other script.
Code: Select all
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygame
import sys
import time
from pygame.locals import *
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode (GPIO.BCM)
# set GPIO output pins
button1 = 17
button2 = 25
GPIO.setup(button1,GPIO.IN)
GPIO.setup(button2,GPIO.IN)
# picture display size
width = 1920
height = 1080
# File names
screen1 = "/media/A2A7-1908/screen1.jpg"
screen2 = "/media/A2A7-1908/screen2.jpg"
screen3 = "/media/A2A7-1908/screen3.jpg"
pygame.init()
windowSurfaceObj = pygame.display.set_mode((width,height))
pygame.display.set_caption('Window')
while True:
if GPIO.input(button1) == False:
when_pressed = time.time()
while GPIO.input(button1) == False:
time_pressed = time.time() - when_pressed
if time_pressed < 3:
image = pygame.image.load(screen1)
image = pygame.transform.scale(image,(width,height))
windowSurfaceObj.blit(image,(0,0))
pygame.display.update()
time.sleep(0.01)
if time_pressed > 3:
image = pygame.image.load(screen3)
image = pygame.transform.scale(image,(width,height))
windowSurfaceObj.blit(image,(0,0))
pygame.display.update()
time.sleep(0.01)
Re: Showing an image with gpio
Posted: Thu Mar 26, 2015 10:13 am
by PiGraham
You do have an indentation problem.
All the lower section of code should be within the while true loop.
The code never leaves the while true loop, so the later lines of code do not execute.
You can avoid repeated lines by putting the update code after and outside the if conditions.
Try this (untested)
Code: Select all
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import pygame
import sys
import time
from pygame.locals import *
import RPi.GPIO as GPIO
GPIO.setwarnings(False)
GPIO.setmode (GPIO.BCM)
# set GPIO output pins
button1 = 17
button2 = 25
GPIO.setup(button1,GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(button2,GPIO.IN, pull_up_down=GPIO.PUD_UP)
# picture display size
width = 1920
height = 1080
# File names
screen1 = "/media/A2A7-1908/screen1.jpg"
screen2 = "/media/A2A7-1908/screen2.jpg"
screen3 = "/media/A2A7-1908/screen3.jpg"
pygame.init()
windowSurfaceObj = pygame.display.set_mode((width,height))
pygame.display.set_caption('Window')
while True:
#wait for button1 to be pressed / connect to GND(, sleep for less than 100%CPU
while GPIO.input(button1) == False:
time.sleep(0.01)
#Button pressed so note the time
when_pressed = time.time()
#wait for button to be released
while GPIO.input(button1) == True:
time.sleep(0.01)
# Note time duration of press
time_pressed = time.time() - when_pressed
if time_pressed < 3: #Short press show image 1
image = pygame.image.load(screen1)
image = pygame.transform.scale(image,(width,height))
if time_pressed > 3: #Longer press show image 3
image = pygame.image.load(screen3)
image = pygame.transform.scale(image,(width,height))
windowSurfaceObj.blit(image,(0,0))
pygame.display.update()
time.sleep(0.01)
Re: Showing an image with gpio
Posted: Thu Mar 26, 2015 10:30 am
by paddyg
Though that will block the code execution in the while loops with sleeps in them and prevent the pygame event checking later (but not included in this snippet). An alternative approach would be to save the state of the GPIO to a variable and only set when_pressed if there was a change from True to False. It might then be easier to make the image change code happen when you took your finger off the button rather than when it's been on for more than 3s (and is still on) as you will find it complicated to differentiate the short press from the long press without various other flags.
Code: Select all
previous_state = True
time_pressed = -1.0
while True:
button_state = GPIO.input(button1)
if not button_state and previous_state:
when_pressed = time.time()
if button_state and not previous_state:
time_pressed = time.time() - when_pressed
if time_pressed > 3.0:
image = pygame.image.load(screen3)
elif time_pressed > 0.0:
image = pygame.image.load(screen1)
image = pygame.transform.scale(image, (width,height))
windowSurfaceObj.blit(image, (0,0))
pygame.display.update()
time_pressed = -1.0
previous_state = button_state
time.sleep(0.01)
Re: Showing an image with gpio
Posted: Thu Mar 26, 2015 11:09 am
by PiGraham
Good point Paddyg. Does the basic display require event handling? I'm not familiar with pygame so I was really just pointing to the nesting issues.
Using edge callbacks would be a better approach.
Re: Showing an image with gpio
Posted: Thu Mar 26, 2015 1:34 pm
by realswz
thank you paddyg, this code works perfectly. But now i have some questions WHY it actually does work
Actually there are two things i dont understand:
Code: Select all
previous_state = True
time_pressed = -1.0
while True:
button_state = GPIO.input(button1)
if not button_state and previous_state:
when_pressed = time.time()
if button_state and not previous_state:
time_pressed = time.time() - when_pressed
1. i understand when "when_pressed" is set. I press the button, it goes to 0 and with the not-condition its an 1. Previous_state is also 1 so it does set "when_pressed". This is ok for me. But why does it set "time_pressed"? If i take my finger off the button, the state turns to 1. But with the not-condition, previous_state is now a 0. For an and-condition both variables need to be 1, but here i have now 1 and 0. Why does it still match this if-condition and set "time_pressed?
2. why do you set previous_state = button_state at the end of the script? you've set previous_state = True at the beginning, so this variable should be true for the whole script, shouldn't it?
Re: Showing an image with gpio
Posted: Thu Mar 26, 2015 2:12 pm
by paddyg
Your questions are related. After doing the checking of the current and previous states it sets the previous state to whatever it is now, because next time round the loop that will be the previous state. previous_state is only set to True before the loop starts so the first time round there's something to compare, after that it is what it says on the tin the previous state.
Which is why taking you finger off the button triggers the second if block (so long as you had your finger on the button for the last trip round the loop) as previous_state will now be True.
As pigraham says (and I did above) it would be tidier to use callback functions (search for 'gpio add_event_detect') but if you investigate that remember to make your global variables explicit with a global statement.
PS it's supposed to be better coding (and is certainly less typing) to do 'if myflag:' rather than 'if myflag == True'
Re: Showing an image with gpio
Posted: Sun Mar 12, 2017 3:47 pm
by aks9920
[quote="gordon77"]
can you give me a code for image slideshow using pygame and gpio pins for next, previous,play/pause,escape,....
i need it for my college code.
Re: Showing an image with gpio
Posted: Sun Mar 12, 2017 4:49 pm
by PiGraham
aks9920 wrote:gordon77 wrote:
can you give me a code for image slideshow using pygame and gpio pins for next, previous,play/pause,escape,....
i need it for my college code.
Aren't YOU supposed to write the code for college?
Re: Showing an image with gpio
Posted: Mon Apr 10, 2017 10:46 am
by john.t
Is there a way to resize/scale the image resolution of your python generated image?I was able to make a python code that generates a test image.but the screen size is constant i would like to be able to resize/scale the resolution from 1920x1080 to a lower resoluton for example.Can anyone help me ?
Re: Showing an image with gpio
Posted: Mon Apr 10, 2017 11:56 am
by texy
john.t wrote:Is there a way to resize/scale the image resolution of your python generated image?I was able to make a python code that generates a test image.but the screen size is constant i would like to be able to resize/scale the resolution from 1920x1080 to a lower resoluton for example.Can anyone help me ?
Probably worth starting a new thread with that Q - explaining in more details how you are generating the initial image.
Texy