Trybotics Logo

Christmas Wreath 2.0 Raspberry Pi / Arduino "Selfie / Photobooth"

DESCRIPTION

This is my festive craft for 2015 and builds on my 2014 Arduino based Christmas Tune Playing Christmas Wreath. I got into playing with the Raspberry PI this year and liked the aspects of running on linux and the various options I had with Linux and Python (or other programming) languages.

Last year's wreath simply used a PIR motion sensor to detect movement and then played a recorded greeting in an "elfish" voice and played a random Christmas song. This year I decided to make a photo booth type greeting complete with a touch screen interface, camera, and remote printer.

When the interface isn't presenting a "Selfie" or as I call it "Elfie" taking option I use a screensaver package to loop through festive Christmas graphics.

Description:

Raspberry PI 2 - $60 (Canakit from Amazon)

Raspberry PI Camera - $23 on Amazon

8 Gig SD card configured with Raspbian Jessie

Powered USB Hub - $10

Waveshare 800x600 Raspberry PI Touchscreen - $60

Raspberry Pi 2 Banana Pi LCD Display 7inch HDMI LCD (B) Capacitive Touch Screen

Polaroid Pogo - Polaroid CZA-10011B PoGo Instant Mobile Thermal Printer - $57

Bluetooth Dongle for Raspberry PI - $10

Inateck USB Bluetooth 4.0 Low Energy Micro Adapter USB Wireless Bluetooth Dongle, Compatible with Windows XP/ Vista/ 7/ 8/ 8.1, Support A2DP Bluetooth

Foam board - $3 for 2 (30x30) boards

PIR Sensor - $9

Christmas Wrapping Paper

Assorted Wire / Electrical Tape

Christmas Wreath 1.0 see (https://www.instructables.com/id/Christmas-Greeting-Wreath-Arduino-and-MP3/)

Description:

Configure Raspberry PI with Raspbian "Jessie" Version

This version should have Python "Idle" installed with Python 2.7 which is what was used in the programming. I had ZERO experience with Python before starting this effort and had no opinion on the use of different versions of Python. I'm sure real programmers will have a multitude of reasons why Python 3.x should have been used but I am able to do everything I need to do for this application.

Install Linux Components

Install FEH Screensaver App for rotating between festive holiday pictures

sudo apt-get install feh

Install Python Tkinter Components

sudo apt-get install python python-tk idle python-pmw python-imaging 
sudo apt-get install python-pip

Install ImageTK for Python

sudo apt-get install python-imaging-tk 

Enable the PI camera http://thepihut.com/blogs/raspberry-pi-tutorials/...

Install PI-camera app

sudo apt-get install python-picamera

Enable BlueTooth

(GETTING BLUETOOTH TO WORK STUNK!!!!)

sudo apt-get install bluez 
sudo apt-get install obexftp 
sudo apt-get install ussp-push 
sudo apt-get install blueman

Configure BlueMan Bluetooth on the PI in Linux

  • Restart PI
  • Open Bluetooth icon in raspberry PI
  • Add devices
  • Search for polaroid (see: http://mattrichardson.com/Raspberry-Pi-Wireless-Photo-Printing/)
  • Put in 6000 for password
  • Send file to test print
    • send file via obexFTP
    • sudo obexftp -b 00:04:48:10:0B:21 --channel 1 -p /home/pi/Documents/pythonprograms/imagetest2.jpg
    • (Change the above mac address to what you found when searching for the Polaroid in blueman - change the path to your image to the appropriate path)

Various Useful Websites Referenced to Get the Above Going

Pi-Camera Docs: https://picamera.readthedocs.org/en/release-1.10/i...

Tkinter tutorials: https://www.daniweb.com/programming/software-devel...

Tkinter info at Effbot:http://effbot.org/tkinterbook/button.htm

Linux / Bluetooth:https://www.garron.me/en/go2linux/how-transfer-fil...

Description:

I started the programming out by focusing on getting a simple interactive touch screen system using mostly Tkinter objects to create a python GUI. All of the code is included to have a kiosk style photobooth. The code is included in a zip file in this instructable. After running this for several days I have had a few little changes that I've rectified in the upload zip file and in these examples.

The project consists of three main programs:

  • christmas_motion.py - This is what I start up when the PI starts, it monitors the motion sensor and when motion is detected it checks if a file exists that is only there when the main "christmas_wreath_2.0.py" program is running. If the file is there it doesn't do anything, if it isn't then the motion program kicks off the main program "christmas_wreath_2.0.py"
    • Main Actions:
      • Monitor Motion
      • Kick off christmas_wreath_2.0.py
      • Close the screensaver "feh"
  • christmas_wreath_2.0.py - This is the main program, it does four things:
    • Ask the visitor to your doorstep if they want to take an "Elfie" picture
    • Take / Retake pictures
    • Print
    • Quit
  • christmas_nowprinting.py - this is used for displaying an animated GIF of a printer. Since the printer is bluetooth the print job takes about two minutes to complete. After this is done the file preventing the motion program from kicking off a new "Take Elfie" program(christmas_wreat_2.0.py" is deleted and our process resumes.

Code:

christmas_motion.py

import RPi.GPIO as GPIO
import time import os from subprocess import Popen import os.path

GPIO.setmode(GPIO.BCM) PIR_PIN = 7 GPIO.setup(PIR_PIN, GPIO.IN)a

def MOTION(PIR_PIN): print "Motion Detected!" #try: # os.system("killall -9 feh") # Open a file in write mode if os.path.exists("/home/pi/Documents/pythonprograms/christmas_wreath_placeholder.txt"): logfile=open("motionlog.txt", "rw+") print "Name of the file: ", logfile.name

str1 = time.strftime("%Y%m%d-%H%M%S") str2 = "\n" str3 = str1+str2 # Write a line at the end of the file. logfile.seek(0, 2) line = logfile.write( str3 )

# Close opend file logfile.close() else: proc = Popen(["python /home/pi/Documents/pythonprograms/christmas_wreath_2.0.py"], shell=True, stdin=None, stdout=None, stderr=None, close_fds=True) time.sleep(3) os.system("killall -9 feh")

print "PIR Module Test (CTRL+C to exit)" time.sleep(10) print "Ready" proc = Popen(["python /home/pi/Documents/pythonprograms/christmas_wreath_2.0.py"], shell=True, stdin=None, stdout=None, stderr=None, close_fds=True)

if os.path.exists("/home/pi/Documents/pythonprograms/christmas_wreath_placeholder.txt"): os.remove("/home/pi/Documents/pythonprograms/christmas_wreath_placeholder.txt")

try: GPIO.add_event_detect(PIR_PIN, GPIO.RISING, callback=MOTION) while 1: time.sleep(100) except KeyboardInterrupt: print "Quit" GPIO.cleanup()


christmas_wreath_2.0.py

#!/usr/bin/env python

import os

from time import sleep import tkFont from Tkinter import * import Tkinter as tk from ImageWin import Dib,HWND from PIL import Image from PIL import ImageTk from subprocess import Popen import shutil import os.path

import time

#from SimpleCV import Image

import picamera

class App: def __init__(self, master):

self.counter = 0

im = Image.open("/home/pi/Pictures/christmasbg1.jpg") resized = im.resize((340, 240),Image.ANTIALIAS) tkimage = ImageTk.PhotoImage(resized) myvar=Label(frame,image = tkimage,bg="black", text="", compound=tk.BOTTOM, font=btnFont, fg='white') myvar.image = tkimage myvar.grid(row=1,column=0,sticky=N+S+E+W)

## notice, don't use button.pack and button.grid interchangeably - grid forces buttons into the column/row locations you specify ## pack allows the tkinter system to determine what should work best self.button1 = Button(frame,relief=FLAT,bg="red",activebackground="white",foreground="silver", text="No Thanks,\n Merry Christmas", 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 = Button(frame,relief=FLAT,bg="green",activebackground="red",foreground="silver", text="Take '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 BUTTON - BLANK UNTIL ELFIE TAKEN self.button4 = Button(frame,relief=FLAT,bg="green",activebackground="red",foreground="silver", font=btnFont, state=DISABLED, 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") resized = im.resize((340, 240),Image.ANTIALIAS) tkimage = ImageTk.PhotoImage(resized) myvar=Label(frame,image = tkimage,bg="red", text="Your Elfie Preview", compound=tk.BOTTOM, font=btnFont, fg='white') myvar.image = tkimage self.button4["text"] = "Print Elfie?\nClick 'Take Elfie' to re-take" myvar.grid(row=1,column=0,sticky=N+S+E+W)

def create_window(self): self.counter += 1 t = Toplevel() center(t) t.title("Picture Here") msg = Message(t,text="Put Picture Here") msg.pack() t.wm_title("Window #%s" % self.counter) im = Image.open("/home/pi/Pictures/christmasbg1.jpg") #tkroot = Tk() tkimage = ImageTk.PhotoImage(im) frame = Frame(relief=FLAT, bg='green') frame.pack_propagate(0) frame.pack(fill=BOTH, expand=1) frame.rowconfigure((0,1),weight=1) frame.columnconfigure((0,1),weight=1) Label(frame,image=tkimage).pack() button = Button(frame,text="Dismiss", command=t.destroy) button.pack()

def quit_pressed(self): proc = Popen(["feh -Y -x -q -D 5 -B black -F -Z -z -r /home/pi/Pictures"], shell=True, stdin=None, stdout=None, stderr=None, close_fds=True) sleep(2) os.remove("christmas_wreath_placeholder.txt") #os.system("feh -Y -x -q -D 5 -B black -F -Z -z -r /home/aaron/Pictures") quit() #This will kill the application itself, not the self frame.

def pi_picture(self): with picamera.PiCamera() as camera: camera.resolution=(1920,1080) #camera.exposure_mode="backlight" #camera.awb_mode="shade" camera.start_preview() sleep(4) global filepath filepath="/home/pi/Documents/pythonprograms/wreathpics/" global filenamestring filenamestring=time.strftime("%Y%m%d-%H%M%S") global filext filext=".jpg" global filefullname filefullname=filepath+filenamestring+filext camera.capture(filefullname) camera.stop_preview() #sleep(2) im = Image.open(filefullname) resized = im.resize((340, 240),Image.ANTIALIAS) tkimage = ImageTk.PhotoImage(resized) myvar=Label(frame,image = tkimage,bg="red", text="Elfie Preview", compound=tk.BOTTOM, font=btnFont, fg='white') myvar.image = tkimage self.button2["text"] = "Re-Take Elfie?" self.button4["text"] = "Print 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 print stuff destdir="/home/pi/Documents/pythonprograms/wreathpics/prints/" destpath=destdir+filenamestring+filext shutil.copy2(filefullname,destpath) obexftpstr="sudo obexftp -b 00:04:48:10:0B:21 --channel 1 -p " obexftpfull=obexftpstr+filefullname print obexftpfull proc = Popen([obexftpfull], shell=True, stdin=None, stdout=None, stderr=None, close_fds=True) proc = Popen(["python christmas_nowprinting.py"], shell=True, stdin=None, stdout=None, stderr=None, close_fds=True) sleep(1) #os.system("feh -Y -x -q -D 5 -B black -F -Z -z -r /home/aaron/Pictures") quit() #This will kill the application itself, not the self frame.

class ImageView(Frame): def __init__(self,master,**options): Frame.__init__(self,master,**options) self.dib = None self.bind("",self._expose)

def setimage(self,image): self.config(bg="") self.dib = Dib(image) self.event_generate("")

def _expose(self,event): if self.dib: self.dib.expose(HWDN(self.winfo_id()))

def center(win): """ centers a tkinter window :param win: the root or Toplevel window to center """ win.update_idletasks() width = win.winfo_width() frm_width = win.winfo_rootx() - win.winfo_x() win_width = width + 2 * frm_width height = win.winfo_height() titlebar_height = win.winfo_rooty() - win.winfo_y() win_height = height + titlebar_height + frm_width x = win.winfo_screenwidth() // 2 - win_width // 2 y = win.winfo_screenheight() // 2 - win_height // 2 win.geometry('{}x{}+{}+{}'.format(width, height, x, y)) win.deiconify()

def close_after(): proc = Popen(["feh -Y -x -q -D 5 -B black -F -Z -z -r /home/pi/Pictures"], shell=True, stdin=None, stdout=None, stderr=None, close_fds=True) sleep(2) os.remove("christmas_wreath_placeholder.txt") #os.system("feh -Y -x -q -D 5 -B black -F -Z -z -r /home/aaron/Pictures") quit() #This will kill the application itself, not the self frame.

#this is the main program root = Tk()

w, h = root.winfo_screenwidth(), root.winfo_screenheight() # use the next line if you also want to get rid of the titlebar to run a full screen 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 the frame here to make it globally available to the sub routines frame = Frame(relief=FLAT, bg='darkgreen', bd="0") frame.rowconfigure((0,1),weight=1) frame.columnconfigure((0,1),weight=1) frame.pack_propagate(0) frame.pack(fill=BOTH, expand=1)

btnFont = tkFont.Font(family='Times',size=32,weight='bold')

if not os.path.exists("christmas_wreath_placeholder.txt"): open("christmas_wreath_placeholder.txt","w")

root.after(300000, close_after) #call quit after 5 minutes no matter what

app = App(root) root.mainloop()

#os.system("pkill -x feh")

#exit()

christmas_nowprinting.py

from Tkinter import *
from PIL import Image, ImageTk from subprocess import Popen import os.path

class MyLabel(Label): def __init__(self, master, filename): im = Image.open(filename) seq = [] try: while 1: seq.append(im.copy()) im.seek(len(seq)) # skip to next frame except EOFError: pass # we're done

try: self.delay = im.info['duration'] except KeyError: self.delay = 100

first = seq[0].convert('RGBA') self.frames = [ImageTk.PhotoImage(first)]

Label.__init__(self, master, image=self.frames[0])

temp = seq[0] for image in seq[1:]: temp.paste(image) frame = 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 if self.idx == len(self.frames): self.idx = 0 self.cancel = self.after(self.delay, self.play)

root = 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(root, "/home/pi/Documents/pythonprograms/nowprinting.gif") anim.pack()

def stop_it(): anim.after_cancel(anim.cancel)

#Button(root, text='stop', 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 black -F -Z -z -r /home/pi/Pictures"], shell=True, stdin=None, stdout=None, stderr=None, close_fds=True)) root.after(110000,lambda: root.destroy()) #destroy the widget after 20seconds

root.mainloop()

Getting the PI to AutoStart the Tkinter based Python app with the User Session

That's a mouthful but basically you can't just run this tkinter dependent python app from the command line in a console only environment, you need to be in an x-windows or LXDE session, aka, a normal Linux desktop - NOT telnet or SSH since this is a GUI app. To do this on a raspberry PI there is a specific autostart file that you edit which executes GUI OR non-GUI apps AFTER the desktop is loaded. The best I can compare this to is the windows "startup" folder.

Edit the following file:

/home/pi/.config/lxsession/LXDE-pi/autostart

You can do this via a command line session by typing:

sudo nano /home/pi/.config/lxsession/LXDE-pi/autostart

Then add your script to kick off your program at the bottom of the file, I used a SH script to kick off my christmas_motion.py file. Here's what the autostart file looks like:

@lxpanel --profile LXDE-pi<br>@pcmanfm --desktop --profile LXDE-pi 
@xscreensaver -no-splash <br>@sh ${HOME}/.config/lxsession/LXDE-pi/autokey.sh <br>@sh /home/pi/Documents/pythonprograms/christmas_launcher.sh

NOTE the last line points to my Launcher file (christmas_launcher.sh) - my launcher file looks like this:

#!/bin/sh<br>#christmas_launcher.sh <br>#navigate to directory<br>cd /
cd /home/pi/Documents/pythonprograms
sudo python christmas_motion.py
cd /

The launcher file makes sure that I run the christmas_motion.py using SUDO / root privileges so that the GPIO requests in the python code have the correct level of permissions to access the GPIO pins, otherwise the standard "PI" user does not have adequate permissions to access the motion sensor pins.

I tried launching the christmas_motion.py directly from the autostart file but it resulted in a weird infinite loop of kicking off the same app over and over again so I resorted back to my standard SH script which has worked every time.

Attachments

Description:

Create the Box and Mounting for the Camera and Screen
3 More Images

Building the Foam Box

I created the mounting for the PI, Camera, and Printer out of simple craft foam board. It was very easy to work with and cost practically nothing so when I cut twice and measured once, whoops "measure twice and cut once" it didn't cost me much to start over. I simply measured the interior of the wreath and started from there. I outlined the screen and made a mount for the screen which was free floating, pictured in the third and fourth pictures. The free floating screen holder allowed me to move it around in the "box top" to get the correct placement in the view port.

I used brown packing tape which has very tacky and holds to the foam board very well, plus it lies flat vs something like duct tape or masking type that would either have texture or not be tacky enough to keep the box stiff.

Mounting the Wreath

I cut a piece of plywood that I could prop above some of the steel rods on the wreath and wired the wood to the rods to secure it. I then put velcro on the plywood cross bars so I could "set" the box on that, those are pictured in the last picture. Every wreath will probably be different so good luck!

Description:

When a visitor walks up to your door the PIR sensor from last year's wreath picks up first and greets the visitor with an "Elfish" high pitched "Welcome to the Jones', Merry Christmas" and begins to play a random Christmas MP3 song. The motion sensor hooked to the raspberry PI then picks up and presents the screens (christmas_wreath_2.0.py) for taking an Elfie picture.

You can "Take Elfie" or quit by touching "No Thanks, Merry Christmas"

A preview takes over the entire screen(not pictured above) where you have about 3-5 seconds (easily configurable in code) and then a picture is taken

The Picture is loaded into the lower left of the screen and you can either click "Re-take Elfie", "Print Elfie", or Quit again.

If you click "Re-take" the process re-takes a picture and loads the new preview.

If you click "Print Elfie" the "Now Printing" animation takes over so you know something is happening since the bluetooth printer takes about 2 minutes to receive a standard 5mp photo coming out of the PI camera, then the photo prints out and the app quits until the next movement is detected.

Description:

We put the wreath through its paces with a bunch of 4-17 year olds at a family Christmas Part and it held up pretty well. They were able to intuitively use the system and took a boatload of "Elfies". One participant managed to be in almost every Elfie picture, they loved it so much.

We also bought a bunch of kistchy props for making the Elfies more festive and fun and have stuck them in the wreath for easy access and storage for visitors.

Some enhancements I'd like to make later:

  • Make the christmas_motion.py more intelligent to take low res pictures of any motion in order to double as a security camera
  • Auto sync the saved files to a cloud service, NOTE - all printed "Elfies" are saved in a special directory since presumably these are the pick of the litter by your visitors.
  • Allow an option to send pictures to a visitors phone or email address
  • Add a bright LED / flash type system for night pictures -Already done which allows for perfect night pictures and filling in shadows during the bright daylight where the backlight causes whitebalance and exposure issues with the PI - Camera.
  • Enhance the PI camera coding to better handle different lighting situations (note it is pretty smart at that already) but this could include:
    • Time of day based intelligence
    • Photo resistor integration to check light levels
    • Logic to handle back lighting


YOU MIGHT ALSO LIKE