Christmas Krans 2.0 Raspberry Pi / Arduino "Selfie / Photobooth" (3 / 6 steg)
Steg 3: Skriva Python program
Jag började programmera genom att fokusera på att få en enkel interaktiva touch skärm system med mestadels Tkinter objekt för att skapa en python GUI. All kod ingår att ha en kiosk stil photobooth. Koden ingår i en zip-fil i detta instructable. Efter att ha kört detta i flera dagar har jag haft några små ändringar som jag har rättats i ladda upp zip-filen och i dessa exempel.
Projektet består av tre huvudsakliga program:
- christmas_motion.py - detta är vad jag starta upp när PI börjar, den övervakar rörelsesensorn och när rörelse detekteras kontrollerar om det finns en fil som är bara där när den viktigaste "christmas_wreath_2.0.py" programmet körs. Om filen är det gör det inte något, om det inte är då rörelse programmet drar igång huvudprogrammet "christmas_wreath_2.0.py"
- Huvudåtgärder:
- Monitor Motion
- Sparka igång christmas_wreath_2.0.py
- Stäng screensaver "feh"
- Huvudåtgärder:
- christmas_wreath_2.0.py - detta är huvudprogrammet, det gör fyra saker:
- Be besökaren till din dörr om de vill ta en "Elfie" bild
- Ta / återta bilder
- Skriv ut
- Avsluta
- christmas_nowprinting.py - används för att Visa animerade GIF-bilder av en skrivare. Eftersom skrivaren är bluetooth tar utskriftsjobbet cirka två minuter för att slutföra. Efter detta görs filen att förhindra rörelse programmet från sparka igång en ny "Ta Elfie" program (christmas_wreat_2.0.py"tas bort och vår process återupptas.
Kod:
christmas_motion.py
importera RPi.GPIO som GPIO
Importera tid
importera os
underprocess importera Popen
importera os.path
GPIO.setmode (GPIO. BCM)
PIR_PIN = 7
GPIO.setup (PIR_PIN, GPIO. I) en
def MOTION(PIR_PIN):
skriva ut "Motion upptäckta!"
#try:
# os.system("killall-9 feh")
# Öppna en fil i skrivläge
om os.path.exists("/home/pi/Documents/pythonprograms/christmas_wreath_placeholder.txt"):
Logfile = öppna ("motionlog.txt", "rw +")
skriva ut "namnet på filen:", logfile.name
str1 = time.strftime("%Y%m%d-%H%M%S")
str2 = "\n"
str3 = str1 + str2
# Skriva en rad i slutet av filen.
logfile.Seek (0, 2)
linje = logfile.write (str3)
# Nära öppnade filen
logfile.Close()
annat:
PROC = Popen (["python /home/pi/Documents/pythonprograms/christmas_wreath_2.0.py"], shell = True, stdin = ingen, stdout = ingen, stderr = ingen, close_fds = True)
Time.Sleep(3)
OS.system ("killall -9 feh")
skriver du ut "PIR modul (CTRL + C för att avsluta)"
Time.Sleep(10)
skriva ut "Redo"
PROC = Popen (["python /home/pi/Documents/pythonprograms/christmas_wreath_2.0.py"], shell = True, stdin = ingen, stdout = ingen, stderr = ingen, close_fds = True)
om os.path.exists("/home/pi/Documents/pythonprograms/christmas_wreath_placeholder.txt"):
OS.Remove("/Home/PI/Documents/pythonprograms/christmas_wreath_placeholder.txt")
försök:
GPIO.add_event_detect (PIR_PIN, GPIO. STIGANDE, återuppringning = rörelse)
medan 1:
Time.Sleep(100)
Förutom KeyboardInterrupt:
skriva ut "Avsluta"
GPIO.cleanup()
christmas_wreath_2.0.py
#! / usr/bin/env python
importera os
från att importera sömn
importera tkFont
från Tkinter import *
importera Tkinter som tk
från ImageWin importera Dib, HWND
importera bild från PIL
importera ImageTk från PIL
underprocess importera Popen
importera shutil
importera os.path
Importera tid
#from SimpleCV import bild
importera picamera
klass App:
def __init__ (själv, master):
Self.Counter = 0
im = Image.open("/home/pi/Pictures/christmasbg1.jpg")
storlek = im.resize ((340, 240),Image.ANTIALIAS)
tkimage = ImageTk.PhotoImage(resized)
MyVar = etikett (ram, bild = tkimage, bg = "black"
text = "" sammansatt = tk. BOTTEN, font = btnFont, fg = "vit")
MyVar.image = tkimage
MyVar.Grid(Row=1,Column=0,Sticky=N+S+E+W)
## märker, inte använda button.pack och button.grid omväxlande - grid tvingar knappar i kolumnen/raden platser anger du
## pack kan tkinter systemet att bestämma vad som skulle fungera bäst
Self.button1 = knappen (ram, lättnad = platt, bg = "red", activebackground = "vit", förgrunden = "silver",
text = "Nej tack, \n god jul", font = btnFont,
Command=Self.quit_pressed)
Self.button1.Grid(Row=1,Column=1,Sticky=N+S+E+W)
#self.button1.pack(fill=BOTH,expand=1)
Self.button2 = knappen (ram, lättnad = platt, bg = "grön", activebackground = "red", förgrunden = "silver",
text = "Ta 'Elfie'?", font = btnFont,
Command=Self.pi_picture)
Self.button2.Grid(Row=0,Column=0,Sticky=N+S+E+W)
#self.button2.pack(fill=BOTH,expand=1)
#SHOW ELFIE KNAPP - TOM TILLS ELFIE TAGIT
Self.Button4 = knappen (ram, lättnad = platt, bg = "grön", activebackground = "red", förgrunden = "silver",
Font = btnFont, state = inaktiverad,
Command=Self.show_elfie)
Self.Button4.Grid(Row=0,Column=1,Sticky=N+S+E+W)
#self.button4.pack(fill=BOTH,expand=1)
def show_elfie(self):
im = Image.open("/home/pi/Documents/pythonprograms/imagetest2.jpg")
storlek = im.resize ((340, 240),Image.ANTIALIAS)
tkimage = ImageTk.PhotoImage(resized)
MyVar = etikett (ram, bild = tkimage, bg = "red",
text = "Din Elfie Preview", sammansatta = tk. BOTTEN, font = btnFont, fg = "vit")
MyVar.image = tkimage
Self.Button4["text"] = "Skriv ut Elfie? \nClick"Ta Elfie"att åter ta"
MyVar.Grid(Row=1,Column=0,Sticky=N+S+E+W)
def create_window(self):
Self.Counter + = 1
t = Toplevel()
Center(t)
t.title ("bild här")
MSG = meddelande (t, text = "Sätta bild här")
MSG.Pack()
t.wm_title ("fönster #%s" % self.counter)
im = Image.open("/home/pi/Pictures/christmasbg1.jpg")
#tkroot = Tk()
tkimage = ImageTk.PhotoImage(im)
RAM = RAM (relief = platt, bg = "grön")
Frame.pack_propagate(0)
Frame.Pack (fylla = båda, expandera = 1)
Frame.rowconfigure((0,1),Weight=1)
Frame.columnconfigure((0,1),Weight=1)
Label(Frame,image=tkimage).Pack()
knappen = knappen (ram, text = "Stäng", command=t.destroy)
Button.Pack()
def quit_pressed(self):
PROC = Popen (["feh -Y - x - q -D 5 -B svart -F -Ö - ö - r /home/pi/Pictures"], skal = True, stdin = ingen, stdout = ingen, stderr = ingen, close_fds = True)
Sleep(2)
OS.Remove("christmas_wreath_placeholder.txt")
#os.system ("feh -Y - x - q -D 5 -B svart -F -Ö - ö - r /home/aaron/Pictures")
Quit() #This kommer att döda själva ansökan, inte ramen själv.
def pi_picture(self):
med picamera. PiCamera() som kamera:
Camera.resolution=(1920,1080)
#camera.exposure_mode="backlight"
#camera.awb_mode="shade"
Camera.start_preview()
Sleep(4)
globala filepath
filepath = "/ home/pi/dokument/pythonprograms/wreathpics /"
globala filenamestring
filenamestring=Time.strftime("%Y%m%d-%H%M%S")
globala arkivera
arkivera = ".jpg"
globala filefullname
filefullname = filepath + filenamestring + arkivera
Camera.Capture(filefullname)
Camera.stop_preview()
#sleep(2)
im = Image.open(filefullname)
storlek = im.resize ((340, 240),Image.ANTIALIAS)
tkimage = ImageTk.PhotoImage(resized)
MyVar = etikett (ram, bild = tkimage, bg = "red",
text = "Elfie Preview", sammansatta = tk. BOTTEN, font = btnFont, fg = "vit")
MyVar.image = tkimage
Self.button2["text"] = "Åter ta Elfie?"
Self.Button4["text"] = "Skriv ut Elfie?"
Self.Button4["State"]= "normal"
Self.Button4["Command"] = self.print_elfie
MyVar.Grid(Row=1,Column=0,Sticky=N+S+E+W)
def print_elfie(self):
#setup Skriv ut grejer
destdir = "/ home/pi/dokument/pythonprograms/wreathpics/utskrifter /"
målsökväg = destdir + filenamestring + arkivera
shutil.copy2(filefullname,destpath)
obexftpstr = "sudo obexftp -b 00:04:48:10:0B:21--kanal 1 -p"
obexftpfull = obexftpstr + filefullname
skriva ut obexftpfull
PROC = Popen ([obexftpfull], shell = True, stdin = ingen, stdout = ingen, stderr = ingen, close_fds = True)
PROC = Popen (["python christmas_nowprinting.py"], shell = True, stdin = ingen, stdout = ingen, stderr = ingen, close_fds = True)
Sleep(1)
#os.system ("feh -Y - x - q -D 5 -B svart -F -Ö - ö - r /home/aaron/Pictures")
Quit() #This kommer att döda själva ansökan, inte ramen själv.
klass ImageView(Frame):
def __init__(self,master,**options):
Frame.__init__(Self,Master,**Options)
Self.DIB = ingen
Self.BIND("",Self._expose)
def setimage(self,image):
Self.config(BG="")
Self.DIB = Dib(image)
Self.event_generate("")
def _expose(self,event):
om self.dib:
Self.DIB.Expose(HWDN(Self.winfo_id()))
def center(win):
"""
centrerar en tkinter fönster
: param win: roten eller Toplevel fönster att centrera
"""
Win.update_idletasks()
bredd = win.winfo_width()
frm_width = win.winfo_rootx() - win.winfo_x()
win_width = bredd + 2 * frm_width
höjd = win.winfo_height()
titlebar_height = win.winfo_rooty() - win.winfo_y()
win_height = höjd + titlebar_height + frm_width
x = win.winfo_screenwidth() / / 2 - win_width / / 2
y = win.winfo_screenheight() / / 2 - win_height / / 2
Win.Geometry ('{} x {} + {} + {}'.format (bredd, höjd, x, y))
Win.deiconify()
def close_after():
PROC = Popen (["feh -Y - x - q -D 5 -B svart -F -Ö - ö - r /home/pi/Pictures"], skal = True, stdin = ingen, stdout = ingen, stderr = ingen, close_fds = True)
Sleep(2)
OS.Remove("christmas_wreath_placeholder.txt")
#os.system ("feh -Y - x - q -D 5 -B svart -F -Ö - ö - r /home/aaron/Pictures")
Quit() #This kommer att döda själva ansökan, inte ramen själv.
#this är huvudprogrammet
rot = Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
# Använd nästa rad om du också vill bli av med namnlisten att köra en full skärm app
root.overrideredirect(1)
root.Geometry("%DX%d+0+0" % (w, h))
root.config(BG="Black",padx=10,Pady=10)
#root.rowconfigure((0,1),weight=1)
#root.columnconfigure((0,1),weight=1)
#put ramen här göra det globalt tillgänglig till sub rutiner
RAM = RAM (relief = platt, bg = "mörkgrön", bd = "0")
Frame.rowconfigure((0,1),Weight=1)
Frame.columnconfigure((0,1),Weight=1)
Frame.pack_propagate(0)
Frame.Pack (fylla = båda, expandera = 1)
btnFont = tkFont.Font(family='Times',size=32,weight='bold')
om inte os.path.exists("christmas_wreath_placeholder.txt"):
Open("christmas_wreath_placeholder.txt","w")
root.after (300000, close_after) #call slutade efter 5 minuter oavsett vad
app = App(root)
root.mainloop()
#os.system ("pkill - x feh")
#exit()
christmas_nowprinting.py
från Tkinter import *
importera bild, ImageTk från PIL
underprocess importera Popen
importera os.path
klass MyLabel(Label):
def __init__ (själv, master, filnamn):
im = Image.open(filename)
SEQ =]
försök:
medan 1:
SEQ.append(im.Copy())
im.Seek(len(SEQ)) # hoppa till nästa bildruta
utom EOFError:
passera # vi är klara
försök:
Self.Delay = im.info['duration']
Förutom KeyError:
Self.Delay = 100
först = seq[0].convert('RGBA')
Self.frames = [ImageTk.PhotoImage(first)]
Label.__init__ (själv, master, image=self.frames[0])
Temp = seq [0]
för bild i seq [1:]:
Temp.paste(Image)
ram = temp.convert('RGBA')
Self.frames.append(ImageTk.PhotoImage(frame))
Self.idx = 0
Self.Cancel = self.after (self.delay, self.play)
def play(self):
Self.config(Image=Self.frames[Self.idx])
Self.idx + = 1
om self.idx == len(self.frames):
Self.idx = 0
Self.Cancel = self.after (self.delay, self.play)
rot = Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.overrideredirect(1)
root.Geometry("%DX%d+0+0" % (w, h))
root.config(BG="darkgreen",padx=10,Pady=10)
anim = MyLabel (rot, "/ home/pi/Documents/pythonprograms/nowprinting.gif")
anim.Pack()
def stop_it():
anim.after_cancel(anim.Cancel)
#Button (root, text = "stoppa", command=stop_it).pack()
root.after (107000, lambda: os.remove("christmas_wreath_placeholder.txt"))
root.after (109000, lambda: Popen (["feh -Y - x - q -D 5 -B svart -F -Ö - ö - r /home/pi/Pictures"], skal = True, stdin = ingen, stdout = ingen, stderr = ingen, close_fds = True))
root.after (110000, lambda: root.destroy()) #destroy widget efter 20seconds
root.mainloop()
Att få PI till AutoStart i Tkinter baserade Python app med användarsessionen
Det är en munsbit men i grund och botten du kan inte bara köra denna tkinter beroende python app från kommandoraden i konsolen endast miljö, måste du vara i en x-windows eller LXDE session, alias, en normal Linux desktop - inte telnet eller SSH eftersom detta är en GUI app. För att göra detta på en raspberry PI finns det en specifik autostart-fil som du redigera som exekverar GUI eller icke-GUI apps efter skrivbordet är laddad. Det bästa jag kan jämföra med att är mappen windows "Start".
Redigera följande fil:
/Home/PI/.config/lxsession/LXDE-PI/Autostart
Du kan göra detta via en kommandorad sessionen genom att skriva:
sudo nano /home/pi/.config/lxsession/LXDE-pi/autostart
Tillsätt sedan skriptet att sparka igång programmet längst ned i filen, jag använde en SH script för att sparka igång min christmas_motion.py fil. Här är vad den autostart filen ser ut:
--profil LXDE-pi < br >--skrivbordet--profil LXDE-pi
-ingen-splash < br > < br > ${HOME}/.config/lxsession/LXDE-pi/autokey.sh /home/pi/Documents/pythonprograms/christmas_launcher.sh
Notera sista raden punkter till min Launcher fil (christmas_launcher.sh) -min launcher fil ser ut så här:
#! / bin/sh < br > #christmas_launcher.sh < br > #navigate till katalogen < br > cd /
CD /home/pi/Documents/pythonprograms
sudo python christmas_motion.py
CD /
Filen launcher ser till att jag kör den christmas_motion.py använder SUDO / root-privilegier så att GPIO begär i python kod har rätt behörighet att komma åt GPIO stiften, annars standard "PI" användaren har inte tillräcklig behörighet för att komma åt motion sensor stiften.
Jag försökte lansera christmas_motion.py direkt från autostart-fil men det resulterade i en konstig oändlig loop av sparka igång samma app om och om igen så jag tog tillbaka till min standard SH script som har arbetat varje gång.