Skip navigation
1 2 Previous Next

Raspberry Pi Projects

16 Posts authored by: CharlesGantt

Halloween is one of my favorite holidays here in the US, and so much so that I spent a few years of my life thinking up and building smart Halloween props and animatronics for the haunted attraction industry. I won’t go too deep into the details of the business, but a few friends and myself founded a company a few years back with the “help” of some investors. It was my first tech startup, and like many tech companies, we had the hardware and software to revolutionize a decades stagnant industry that quite honestly did not want to change. To make a long story short, none of the original founders are part of that business anymore, with myself backing out in late 2015.

 

 

One of my duties in the company was to brainstorm and prototype new and innovative props that utilized modern technology, while remaining easy enough to use for the aging haunted house owners to be able to program. Often this was accomplished by making props that just worked once powered up, other times this involved utilizing our custom Raspberry Pi based animatronic / whole scene controller unit on the finished prop. However, during the prototyping phase, I would always develop the project using a bare Raspberry Pi or Arduino, and I loved this part about the business the most. The thrill of coming up with a concept, and then building and presenting a working prototype during our weekly all-hands meeting was exhilarating. This is why I love creating Halloween projects every year here at Element14. It gives me the perfect excuse to build some of those concepts that I never got around to prototyping when I was co-owner of the company.

 

 

One of those product ideas that I never got around to building was a smart-mirror that was fully functional while hiding a mind and body jarring jump scare that would be triggered when someone stopped in front of the mirror for more than a few seconds. So when I was asked to come up with a second Halloween project this year, I instantly thought of the smart-mirror. What I did not anticipate was the level of frustration and failure I would experience while building it. Don’t worry though, in the end, I managed to work up something that works 90% of how I wanted it to, and I am going to continue refining this project over the next couple of months, but for now, the smart mirror does work, it just lacks many of the features I wanted it to have. Before we get into the build, I would like to take a moment to talk about what failures I encountered during this project in hopes that a reader may be able to help with the javascript programming when I reboot this project in a month or two.

 

Experiencing Failure

 

As I said in the paragraph above, this project was one of the most frustrating, and stress inducing projects I have ever encountered. My issues began when building the wood frame that would house the mirror in its final form, but I am not here to rant about that, because I simply got a measurement wrong at some point in my CAD design. This was easily solved, and I only lost an hour or three rebuilding it. The real frustration kicked in shortly after deciding to use the MagicMirror2 software to power the magic mirror portion of the project.

 

 

MagicMirror2 is an amazing smart-mirror package if you are just wanting to build a feature-rich, highly functional smart-mirror. I really like this software, and it appears to be regularly updated, and has a very active community behind it. I can not recommend it enough if you are building a normal smart-mirror. The deficiencies begin to show themselves when one wants to detour from the traditional functionality that most smart-mirror builders desire. To be short, attempting to play a full-screen video, display a full-screen .GIF, or simply display a static .jpg in full screen mode on top of the MagicMirror2 display is quite difficult, if not impossible all together.

 

I spent three 12-16 hour days trying to get a video via OMX Player, HTML5, and various other raspberry-pi based video players to work when a GPIO Pin is pulled high by a PIR sensor. After I realized I was just not skilled enough in JavaScript programming to do this on my own, I asked a friend who is a great programmer for help, and six hours later we were still stumped. So I reached out via GitHub to one of the MagicMirror2 module developers, and he attempt to help me figure it out for several hours as well. In the end, the general consensus was that at the moment, without some extensive JavaScript coding, and a deep understanding of how MagicMirror2 and Node.JS work, that it was not possible in time to get this project published on time.

 

So after missing my deadline, and feeling like a complete failure, I picked myself up, tossed MagicMirror2 and all of my code into the garbage and went searching for a new approach. After a few hours of searching, I happened to come across a repository on GitHub that contained a smart-mirror program that was written in Python. This was the best possible outcome for me after the failure as Python is a language I can easily write, and understand. I really would like to make this work with the MagicMirror2 software as it is much more feature rich, and you can do some really cool stuff with Node.js, so if you would like to help me figure that out, please get in touch! Ok, enough about my failures, let's get into the actual project.

 

Parts Required

 

Hardware

Raspberry Pi 3 With NoobsRaspberry Pi 3 With Noobs
PIR SensorPIR Sensor

HT-255D Crimp ToolHT-255D Crimp Tool
Crimp ConnectorsCrimp Connectors

HDMI DisplayHDMI Display
HDMI CableHDMI Cable


3D Printing Files

 

Software

 

Setting Up Your Raspberry Pi and Downloading The Code

 

 

Before we begin installing the software packages we will need to make our spooky smart-mirror, you will need to install the latest version of Raspbian onto the SD card that will go into your Raspberry Pi. If you are using a fresh, empty SD card, then you can follow the video above to learn how to install the latest version of Raspbian to the SD card. If you already have an SD card with Raspbian installed, we can update and upgrade Raspbian from the command line. To do this remotely from the command line on your computer, connect to your Pi to your network via WiFi or a network cable, and then log in (my preferred method) via a terminal app such as Terminal, Putty, or CMDR and then enter the following commands.

 

 

sudo apt-get update

 

 

Then select “Yes” if prompted

 

When the update is finished running, its time to check to see if there is an upgrade available, and install it. To do this, run the following command. This could take a while, so sit back and watch some YouTube videos, or check out my Design Challenge Weekly Updates while you wait.

 

sudo apt-get upgrade

 

Then select “Yes” if prompted

 

Once everything is up to date, shutdown the Pi and connect a HDMI monitor, or the TV you will be using for your mirror. I did my initial development using the official Raspberry Pi 7” Touch Screen. Now restart the Pi, and access it once again from a terminal program on your computer.

 

Before any of the fun happens, we need to install my fork of the  Smart-Mirror software. To do this you will need to use Git. If you do not have Git installed, or you have never used it before, here is a helpful tutorial. The Magic Book-bag portion of the tutorial is not relevant to this project, but it does help you understand how to use Git better.

 

The Smart Mirror Code

 

Once Git is installed, and you have your SSH key saved in your Git settings, navigate to the home/pi directory again and run the following commands. This will clone my Smart-Mirror-With-Halloween-Jump-Scare repository to the Raspberry Pi.

 

cd /home/pi
git clone git@github.com:CharlesJGantt/Smart-Mirror-With-Halloween-Jump-Scare.git

 

Navigate to the folder for the repository

 

cd Smart-Mirror

 

Install the Smart-Mirror software’s dependencies (Make sure you have pip (https://pip.pypa.io/en/stable/installing/) installed before doing this.)

 

sudo pip install -r requirements.txt
sudo apt-get install python-imaging-tk

 

Select “Yes” if prompted

 

 

At the moment, the weather widget is broken due to an API change, but for what we are doing with this project at the moment, that does not matter much. With that said, you should still register a free developers account at darksky.net and enter your API key in the smartmirror.py file as pictured above. To do this, enter the following commands.

 

sudo nano smartmirror.py

 

And edit line 23 with your API key. Then exit nano with ctrl+x or cmd+x and press enter to keep the same file name.

 

Screen Orientation and Cleanup

Before we can test the Smart-Mirror install, we need to take care of some minor, but required task. The first task is to rotate the display by 90 degrees so that our smart mirror can hang in portrait orientation. To do this, enter the following commands, and edit the config file.

 

sudo nano /boot/config.txt

 

Arrow down to the bottom of the file, and add the following line of code. Then save the file by pressing ctrl+x or cmd+x and press enter to keep the same file name. If your screen's rotation is 180 degrees off after this rotation, change the number to 3 instead of 2.

 

lcd_rotate=2

 

Now we need to hide the taskbar, and the only way to do this from the command line is to edit another config file. Enter the following command to edit the necessary file.

 

sudo nano /home/pi/.config/lxpanel/LXDE-pi/panels/panel

 

In the “Global” section at the top of the file, you need to modify the following parameters:

 

autohide=0 heightwhenhidden=2

 

Replace that line with the following line

 

autohide=1 heightwhenhidden=0

 

With those small task taken care of you can now test the Smart-Mirror install by running the following command. Note that you will have to run this from the terminal app on the Pi itself for it to work properly. This is because TKinter will only open if ran natively. There are ways to run this command remotely, but I have found them to be buggy.

 

sudo python smartmirror.py

 

An error may pop up about the weather module, but ignore it, and the screen should turn black with white clock and news text appearing on the screen.

 

The Jump Scare Code

 

Ok, now that we have the Smart-Mirror running, it's time to connect the PIR sensor to the Raspberry Pi’s GPIO header. Follow the diagram below paying close attention to the Power and GND wires.

 

      • PIR Sensor VCC Pin to RPi 5V
      • PIR Sensor Data Pin to RPi GPIO5
      • PIR Sensor GND Pin to RPi GND

 

Now let's take a look at the jumpscare.py file that is inside of the Smart-Mirror directory. You might be wondering why I did not just include this code in the smartmirror.py code, and my reason is just because I expect that file to be updated soon by its creator to fix the weather API, and I also like the idea of being able to turn off the jump scare feature by killing the jumpscare process.

 

Open the jumpscare.py file in Nano.

 

sudo nano jumpscare.py

 

Starting at the top of the file we import the following libraries:

 

import RPi.GPIO as GPIO
import time
import os
import sys

from subprocess import Popen

 

 

Next we have to set which GPIO numbering schema we will be using. I always use the BCM schema. There are two different numbering schemes for the GPIO pins on the Pi.  The Broadcom chip-specific pin numbers (BCM) and P1 physical pin numbers (BOARD.

Here’s a reference showing all the pins on the P1 header, along with their special functions and both BCM and BOARD numbers:

 

GPIO.setmode(GPIO.BCM)

 

Now we need to setup the GPIO and tell the Pi which pins are what. In the first line we are telling the Pi to set GPIO pin 5 as an input, and to attach a pulldown resistor to it. The second line sets up GPIO pin 26 as an output. I left this in the code so that you could connect an LED to pin 26 to use for troubleshooting motion triggers.

 

GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(26, GPIO.OUT)

 

Before we get into the loop, we need to declare a variable called "motionDetected". We can use this variable to count motion triggers in our loop. We also need to tell the Pi where the video we want to play is located. Since you cloned this repository from my Github, the zombie.mp4 file will be in the Smart-Mirror directory.

 

motionDetected = 0
movie1 = ("/home/pi/python_programs/zombie.mp4")

 

I’m going to break the loop down line by line to better help you understand what's going on. In the line below we are defining our loop and stating that while True do this.

while True:

 

Here we are telling the Pi to watch the state of GPIO 5

 

input_state = GPIO.input(5)

 

In the next block of code we are telling the Pi that if the input state of GPIO equals True (high) then print “Motion Detected” in the terminal, increment the motionDetected variable by one, and then wait for 0.2-seconds before moving on to the next line of code.

 

if input_state == True:
        print('Motion Detected')
        motionDetected += 1
        time.sleep(0.2)

 

Finally, we finish things up with another if statement that says if motionDetected equals 1 then set GPIO pin 26 HIGH, then make sure no instance of OMXplayer is running, then open a video player with the video that was defined earlier in the code. Next we tell the code to wait for 60 seconds before continuing with the loop, resetting the motionDetected variable to 0, and set GPIO pin 26 low to turn off the debugging LED. Note that you can delay or speed up how frequent the jump scare triggers by adjusting the time.sleep(60) setting.

 

if motionDetected == 1:
        GPIO.output(26, GPIO.HIGH)
        os.system('killall omxplayer.bin')
        omxc = Popen(['omxplayer', '-b', '-o', 'local', movie1])
        player = True
        time.sleep(60)
        motionDetected = 0
        GPIO.output(26, GPIO.LOW)

 

The full code is listed below.

# This Code Triggers a video to play on
# the raspberry pi when motion is detected
# via a PIR sensor on BCM pin 5. # Written By
# Charles Gantt 2017
# http://www.themakersworkbench.com
# & http://www.youtube.com/c/themakersworkbench
# https://github.com/CharlesJGantt/Smart-Mirror-With-Halloween-Jump-Scare

import RPi.GPIO as GPIO
import time
import os
import sys

from subprocess import Popen

GPIO.setmode(GPIO.BCM)

movie1 = ("/home/pi/Smart-Mirror-With-Halloween-Jump-Scare/zombie.mp4")

GPIO.setup(5, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
GPIO.setup(26, GPIO.OUT)
motionDetected = 0

while True:
    input_state = GPIO.input(5)
    if input_state == True:
        print('Motion Detected')
        motionDetected += 1
        time.sleep(0.2)
    if motionDetected == 1:
        GPIO.output(26, GPIO.HIGH)
        os.system('killall omxplayer.bin')
        omxc = Popen(['omxplayer', '-b', '-o', 'local', movie1])
        player = True
        time.sleep(5)
        motionDetected = 0
        GPIO.output(26, GPIO.LOW)

 

With all of the code finished up, let's set both python programs to run on boot. To do this we are going to write a simple bash script that tells the Pi to run both of the python files in the background.

 

cd /home/pi/Smart-Mirror-With-Halloween-Jump-Scare
nano launcher.sh

 

Now type in this script

#!/bin/sh
# launcher.sh
# navigate to home directory, then to this directory, then execute python scripts, then back home

cd /
cd /home/pi/Smart-Mirror-With-Halloween-Jump-Scare
sudo python smartmirror.py &
sleep 10
sudo python jumpscare.py &
cd /

 

We need to make the launcher script an executable file. To do this, enter the following command.

 

chmod 755 launcher.sh

 

Since we will be using crontab to trigger this script. We need to make a directory to log any errors that may occur. This will help with troubleshooting. Enter the following commands:

 

cd
mkdir logs

 

Now lets add the script to the crontab. Add the following line to the very bottom of the crontab file.

 

@reboot sh /home/pi/bbt/launcher.sh >/home/pi/logs/cronlog 2>&1

 

Now you can reboot the Pi to see if it worked. Enter the following command to reboot the Pi.

 

sudo reboot

 

When the Pi finishes booting, you should see the GUI load, then the smart mirror window open. If you wave your hand in front of the PIR sensor, the jumpscare.py script should trigger the zombie.mp4 video, and once finished, the smart mirror screen should reappear.

 

The Smart Mirror

 

With our code finished, it’s time to make our smart mirror. This is the part of the project where my end result may differ from yours. I chose to order a new 32” LED TV from Amazon, and try my hand at creating the two way mirror from window tint film and standard plate glass. I also wanted to create a wooden frame to house the TV inside so that it had the appearance of a hand-crafted mirror. Fortunately, I have a complete, fully stocked woodworking shop here at home, and whipping up a frame was a few hour process. As I mentioned at the beginning of this project, I did get my math wrong and made the first version of the frame incorrectly, and the TV screen did not fit. I was able to correct this, but if you do not have an abundance of time-saving tools, and extra wood to work with, take time, and measure your screen’s dimensions carefully. The only advice I can really offer is to leave about 1/16” clearance around the edge of the screen to account for expansion as the steel frame of the TV as it warms up.

 

 

I am not going very in depth here about the process I used to build the frame because how you frame the mirror is arbitrary and not very relevant to getting the mirror to work. You could even just tape a 2-way mirror to the front of the TV and the effect would be the same. Some people even create these little mirrors from 15” laptop screens, or HDMI monitors. You do not have to use an actual TV. I simply used a brand new 32” TV because I will be rebuilding this mirror, with a much more refined frame that will be built from exotic hardwood. I do however plan on making a video on that build with a complete step by step guide for my YouTube channel. So if you would like to check that out, it should be out sometime towards the end of the year.

 

 

I didn’t get many photos of the glass cutting or tinting process as that was another major issue I ran into during this project. Initially I decided that I would cut my own glass, as it is something I have done in the past, and it saves a good bit of money. My mistake was thinking that the glass I bought from a big box home repair store would be of a high enough quality to actually be easy to cut with the standard score and snap method. I broke $38 worth of glass before I gave up defeated, and called a local glass shop that explained to me that the glass quality that big box home improvement stores sell is just too low quality, and it's not annealed very well giving it a harder surface that is prone to flaking in the scoring process. The higher quality glass that glass shops stock is designed to be cut with laser sharp accuracy, and to minimize errant cracks in the cutting process. They showed me how quick and easy a good, high-quality piece of glass is to cut, and $17.38 later I was on my way home with the glass.

 

 

That afternoon, I attempted to tint the glass by myself and while I came very close to succeeding, I botched the tinting process twice. This was 100% my fault, and instead of following the poorly written directions that came with the mirror tint window film, I watched a few window tinting tutorials on YouTube, and realized that by adding a little dish soap to the water I was spraying the glass and film with, the process was much easier, and provided a better result. Living in a home with four dogs, and a couple of cats as well as an attached woodworking shop did end up haunting me a bit during the tinting process though. I spent a lot of time picking specks of dust and animal hair out of the wet tint, and still managed to trap a few dust particles and hair under the tint. Since this is a Halloween prop, I am not to bothered by that. When I rebuild this into a proper smart mirror, I will order a piece of chemically tinted 2-way mirror glass to avoid these issues all together. Another advantage to chemically treated glass is that your mirror can be made from tempered safety glass which means there is a much less chance of injury if it does shatter or fall off the wall and break.

 

 

The one thing that I made that may help you along with your build is the corner brackets I designed and 3D Printed that hold the mirror and TV firmly to the frame’s bezel. These brackets take about 20-minutes to print each on a Prusa i3 MK2s at a 0.2mm resolution. If you would like to use these brackets in your project, you can download them from my Thingiverse by clicking here.

 

So without going into too much detail, here are some photos of the frame build.

 

 

 

Now that we have the frame built and it’s hanging cable attached, it's time to attach the Raspberry Pi to the back of the TV. If you have room, and a 3D Printer, you can print this handy dandy VESA mount Rasberry Pi case bottom that I found on Thingiverse. If you want to print the top piece as well, that is just fine. I only printed the bottom as I wanted my Pi to have good airflow. Unfortunately on the TV I am using, the VESA mount was only part of the rear plastic, so I ended up attaching the Pi to a single screw hole. When I rebuild the mirror, I will print a custom case with mounting points that fit the screw locations on the grey steel backing plate.

 

As you can see, it mounts to the tv with standard M4 machine screws. Then the Pi attaches to it with small 3mm screws. Then all that is required is to attach a USB cable from the Raspberry Pi 3, and the TV’s USB port.

 

 

Finally, we need to attach the PIR Sensor to the top of the frame. To do this, I found a nice and compact PIR sensor case on Thingiverse, which I remixed, and designed a small extension arm for. Download it here. This is held together with M3 machine screws and nuts. To mount it to the top of the frame, I just used more small screws like I used on the corner brackets.

 

 

To finish up the PIR sensor mounting I needed to make up a cable that would connect it to the Raspberry Pi. Using a pin and crimp kit, I made the cable about three inches longer than it needed to be to add some strain-relief and prevent the cable from putting too much tension on the pins of the Pi.

 

 

Now all that is left is to test the smart mirror and jump scare out, and to do this, I simply stood it up on my workbench. Check out the demo video above, and I hope it shows off the jump scare well enough. This was the final point of frustration for me during this project. I shot a nice video with my DSLR, and lavaliere microphone, but it appears that something is broken in my brand new camera as it will not record audio from its microphone jack. Thankfully, Canon has a spectacular warranty department, and it will be fixed in a couple of weeks. I plan on taking the smart mirror to a friend's Halloween party, and will update this post with a video of some people getting scared if that happens.

 

So, what are my final thoughts on this project? Well I can honestly say that even after all of the frustration, stress, and unfortunate events, that I am, for the most part, proud of how it turned out. There are things I wish I would have done a different way, and some features that I left off simply because of time constraints. As I mentioned earlier, I am going to continue developing this project over the coming months, and hope a few people will join me in that journey, but for now, I have a working smart mirror that also features a cool jump scare, so I will call this one a win. Albeit, a small win, but a win nonetheless. I guess that the take away from my experience on this project would be that perseverance always pays off, and as long as you refuse to give up, anything is possible. Thanks for taking the time out of your day to read this tutorial. If you would like to see me create more cool stuff like this, please leave a comment below, and hopefully I will get assigned more projects like this! I will see you on the next one, and until then, remember to Hack The World and Make Awesome!

RaspberryPySlotsBanner.jpg

 

Enter e14's 2016 Costume Contest Here!

 

Introduction

Writing the final post for a project is always tough for me because I constantly second guess myself on whether or not I could have spent more time on the project, or if I have covered everything that needs to be covered. Fortunately, I can write this post knowing that I could not have spent more time on this project, because I ran out of time two days ago. My original deadline for this project to be complete was actually two days ago, but I simply was not anywhere close to finished by the time the deadline arrived. Thankfully, the good people here at Element14 granted me 48-more hours to finish up.

 

Before we get into the main update, I want to take a moment to talk about why I got behind, and then how Murphy’s law came into effect several times over the last week. The first issue arose when some of the parts I ordered for this project did not arrive. The NeoPixelsNeoPixels, and arcade buttons did not arrive with the original parts order, and I went ahead and ordered a roll of NeoPixels from Amazon just in case they did not arrive before I needed them. I also ordered a pack of 10 arcade buttons from Amazon, but when they arrived, they did not have the micro switches attached to them, and were just the button assembly. I did manage to find two old arcade buttons in an old project parts box I had in my attic.

 

The second issue arose when I was working on mapping two GPIO pins on the Raspberry Pi 3 to keyboard inputs. I tried several different GPIO to keyboard mapping packages, and none of them worked with the Pi 3 / Raspbian Jessie. After spending a day on this, I finally tried Adafruit’s RetroGame package, and while it worked, it somehow bricked the Python install on the Pi. I ended up having to format the SD card, and start from scratch. This was not that bad though because I had all of my code saved. I reinstalled the RetroGame package, and everything worked fine this time, so I assume something was corrupted when I ran the makefile in the Retrogame install.

 

The final issue was split between Friday evening and Saturday Morning. I had been planning to design some graphics for the front of the slot machine, and then printing them on lightweight paper, but as it turns out the large format printer at my local Staples was broken. To make this matter worse, Staples is the only place locally that can print anything larger than 24-inches wide. So I woke up early Saturday morning and called several other printing locations within 30 miles, and all of them were either closed on Saturday, or they were not willing to do a single print on short notice. This forced me to come up with a solution very last minute, and you will read more about that later. So yea, that is basically how the last week of my life went, and I apologize to E14 as well as the community for this late post. Now let's get started with the actual update!

 

 

Button Play

 

 

One of the key aspects of this project is to use my left arm as the pull handle that triggers the slot machine’s roll. Since the Bfruit program uses keyboard input to control the game, I needed to map a couple of GPIO pins to work as those keyboard inputs. As I mentioned earlier, I tried several different packages that are supposed to be able to do this, but none of them worked with the Raspberry Pi 3Raspberry Pi 3 and Raspbian Jessie. I have used PiKeyed in the past, and it was the first package that I went to, but apparently there is some issue with the Debian Jessie kernel that renders it useless. Basically I could get the PiKeyed Daemon running, but it would not register any key presses from the buttons I had attached to the GPIO pins I mapped in its config file. The two other programs I used also had this same issue, and I assume that they are based off of the same code.

 

In the end I wound up using the RetroGame package from Adafruit. In hindsight I should have used this package from the start, but I was under the impression that I had to install the full RetroPie suite for it to work correctly, and I did not want all of the extra bloat that it would have added to this simple project. After talking to some people in the Adafruit forums, I realized that I could just install RetroGame and nothing else. There are a few tutorials online and at Adafruits website that covers the install, but I found them all to be a little different from each other, and some are missing key parts of the install for the latest version of the program. So to make things easier for anyone following this project at home, I am going to list my install process below, but first, I want to cover how I wired the switches to the Raspbery Pi 3’s GPIO pins.

 

Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900.png

 

The game has two key buttons for gameplay. The left arrow initiates the “spin”, and the up arrow is used to increase the “bet”. The game also uses the escape key, and the enter key, as well as the right arrow, but they are more for menu navigation, so I am not too concerned with them being broken out to physical arcade buttons. I plan on keeping a wireless keyboard in my backpack when showing off the costume at parties, so I can use it to start, and restart the game. Looking at the Raspberry Pi 3 pinout diagram above, I will map GPIO17 to the left arrow key, and GPIO22 to the up arrow key.  The ground pins located at board pin numbers nine and fourteen are used as the ground for each button. The diagram below should clarify this layout some.

 

Pi-Button-Wiring-PySlots.jpg

 

As you might have guessed, I am using the buttons to pull their respective GPIO pins down to low when pressed, and some of you might be wondering why I have not added in any pull-up resistors. The answer is that RetroGame enables the internal pull-up resistors for each pin I map in the program’s configuration file. By using the internal pull-ups I am able to reduce the components needed, and make the circuit as simple as possible.

 

 

Mapping the GPIO Pins to Keyboard Keys using RetroGame

 

retrogame-banner.jpg

 

With the buttons wired I was able to move onto installing the RetroGame package. The process is not hard, but there are a few key steps for the newer version of the program that many of the older tutorials on the internet do not have. Note: Now would be a good time to backup any code that you have not backed up previously. As I mentioned in the intro to this post, something went wrong during my initial RetroGame install, and it bricked the Python package installed on my Pi, and the only way I was able to fix things was with a fresh install of Raspbian Jessie.

 

 

Installing RetroGame to Raspbian Jessie

 

 

Most of this tutorial is copied from Adafruit’s Install RetroGame tutorial found at (https://learn.adafruit.com/super-game-pi/initial-setup) , I have amended a few things here and there to include a couple of steps unique to the new version of RetroGame.

 

Download RetroGame

Navigate to the pi's home/pi directory and download the Adafruit Retrogame repo from github.

  $ cd /home/pi/

  $ git clone git://github.com/adafruit/Adafruit-Retrogame

 

Edit The Config File

Now before we finish installing RetroGame we need to edit its configuration file to map the Pi 3’s GPIO pins to the correct keyboard strokes. Find the retrogame.cfg file in /home/pi/Adafruit-Retrogame-master and edit it using nano to configure and comment out any GPIO pins you do not want to map. Used the sample text below.

$  cd /home/pi/Adafruit-Retrogame-master

$  sudo nano retrogame.cfg

 

 

# Sample configuration file for retrogame.
# Really minimal syntax, typically two elements per line w/space delimiter:
# 1) a key name (from keyTable.h; shortened from /usr/include/linux/input.h).
# 2) a GPIO pin number; when grounded, will simulate corresponding keypress.
# Uses Broadcom pin numbers for GPIO.
# If first element is GND, the corresponding pin (or pins, multiple can be
# given) is a LOW-level output; an extra ground pin for connecting buttons.
# A '#' character indicates a comment to end-of-line.
# File can be edited "live," no need to restart retrogame!

# Here's a pin configuration for the PiGRRL 2 project:

LEFT       17  # Joypad left
# RIGHT     19  # Joypad right
UP        22  # Joypad up
# DOWN      26  # Joypad down
# LEFTCTRL  14  # 'A' button
# LEFTALT   15  # 'B' button
# Z         20  # 'X' button
# X         18  # 'Y' button
# SPACE      5  # 'Select' button
# ENTER      6  # 'Start' button
# A         12  # Left shoulder button
# S         13  # Right shoulder button
# ESC       17  # Exit ROM; PiTFT Button 1
# 1         22  # PiTFT Button 2
# 2         23  # PiTFT Button 3
# 3         27  # PiTFT Button 4


# For configurations with few buttons (e.g. Cupcade), a key can be followed
# by multiple pin numbers.  When those pins are all held for a few seconds,
# this will generate the corresponding keypress (e.g. ESC to exit ROM).
# Only ONE such combo is supported within the file though; later entries
# will override earlier.

 

 

Now save and exit using ctrl + X and then answer Y

 

Copy the config file to the /boot directory

Next we need to copy this file to the /boot directory

sudo cp retrogame.cfg /boot

 

If you are unable to copy the file to /boot because of permissions, you can drop into the root user and move it that way then exit back into the raspberry user.

$ sudo su

$  cp retrogame.cfg /boot

$  exit

 

Finishing Up

Now lets finish the Retrogame install by compliling the programs code.

$  cd /home/pi/Adafruit-Retrogame-master

$  make retrogame

 

Now move the Retrogame program to the usr/local/bin directory

$ sudo mv retrogame /usr/local/bin

 

Next, we need to set Retrogame to run at startup. To do this we need to edit the rc.local file

$  sudo nano /etc/rc.local

 

  Add the following line to the bottom of the file but above the final "exit 0" line. Do not forget the "&" at the end of the string.

/usr/local/bin/retrogame &

 

Finally we need to create a new rules file for RetroGame that will allow it to run more efficiently.

$  sudo nano /etc/udev/rules.d/10-retrogame.rules

 

And paste in the following line exactly as it is shown below.

 

SUBSYSTEM=="input", ATTRS{name}=="retrogame", ENV{ID_INPUT_KEYBOARD}="1"

Note for Pi 3 and Raspbian Jessie Users.

If you are building this project on a Raspberry Pi 3 running Raspbian Jessie, you will need to make a small change in Raspi-Config so that rc.local is called a little later in the boot stack. This is a known issue with Raspbian Jessie, and for those of us who like to use rc.local for running programs on boot, this is the best way to fix the issue.

 

To get rc.local working correctly in Raspbian Jessie Do The Following

$ sudo raspi-config

 

Then navigate to option #4 "Wait for Network at Boot" and set its option to "Yes"

 

Now reboot the Pi

$  sudo reboot

 

 

When the Pi reboots, you can test to see if our key-mapping worked by loading into Pixel and navigating to the office suite and opening a new writing document, and typing some characters with the keyboard. Then press the button connected to GPIO Pin 17 and you should see the cursor move back one space. Multiple presses should move it back even further. If this works, then you are set to go, and can move on to testing with Bfruit.

 

 

The Slot Machine Body

 

 

To be perfectly honest with everyone, I did not document the build process of the slot machine body other than a few photos here and there. This was because I knew I did not have enough time in this post to cover a 5-hour build step by step. I will share a few photos of the process though.

 

2016-10-23-17_56_50-New-notification.jpg

 

I started out by laying out all of the various cuts that were needed to get the desired shape I needed to build the face of the slot machine. Here you see me laying out where the Raspberry Pi 7-Inch Touch Screen will be located. I used a variety of different rulers, scales, and squares to build the machines body.

 

2016-10-23-18_05_31-New-notification.jpg

 

Here you can see me making the various cuts in the foam core that I laid out the machine’s face on. The reason I used foam-core was because it is very lightweight, cheap, and versatile for this kind of build. Since foam core is comprised of a piece of styrene foam that is sandwiched between two pieces of cardboard, it makes building angled 3-dimensional shapes fairly easy. In my case I needed the area where the screen sits to be recessed back into the body of the machine, and I was easily able to achieve this by making a series of “half cuts”. Half cuts are basically a cut that slices through one cardboard layer as well as the foam layer with the second layer of cardboard remaining uncut. This allows you to make very crisp, precise bends, which can be locked into place by filling the “V-Groove” that forms between the cut with hot glue and letting it set.

 

18 inches Alumicutter close up.jpg

 

You will also notice that I am using a special ruler that is designed for this kind of work. It’s called an Alumi Cutter, and is designed to keep your fingers safe, and the blade at 90-degrees when cutting foam core. I have several of these in different sizes, and can not even guess at how many times they have saved my fingers when cutting foam, fabric, and plastics with an exacto or box cutter. I highly recommend picking one up if you are going to be making a lot of straight cuts with a razor sharp knife.

 

2016-10-23-18_07_24-New-notification.jpg

 

Here is a good example of how half-cuts are so useful when working with foam core. I made a half-cut at the top of the recessed section, then flipped the foam core over, and made two half-cuts from the back. Then I made a final cut all the way through the bottom, and down each side. This allowed me to “bend” the foam core to create a 3D profile that I then locked into place with hot glue. You can also see the cutout for the touchscreen.

 

2016-10-23-18_16_50-New-notification.jpg

 

Here you can see that I mounted the two arcade buttons I scavenged from an old project. I wanted to use separate colors, but these are what I had to work with. If you are curious about what I am doing with that full sheet of foam core, I am just eyeballing the length I will need to cut the sides of this box at.

 

2016-10-23-18_17_47-New-notification.jpg

 

Once I got the sides cut and installed, I was read to mount the first layer of the front of the machine. I doubled up on this layer, as well as on the sides and top of the face because I will be cutting out slots the thickness of a single sheet to recess LED strips into the surface. A good hot glue gun is paramount to working with foam core and remaining sane. I personally like this model from Aleen’s because it has dual temperature settings, and several interchangeable tips for more precise control of the glue application process.

 

2016-10-22-14.43.jpg

 

With the basic shape of the slot machine finished, I moved on to reinforcing areas of the body that might experience wear or stress during my night party hopping. Here you can see that I have already covered most of the front face with a second sheet of foam core, and in this photo, I am readying the surface of the rest of the front with PVA glue for a second layer here as well.

 

2016-10-22-14.38.jpg

 

Here you can see the piece of foam core I cut out to reinforce the top and sides of the front face of the slot machine.

 

2016-10-21-00.161.jpg

 

When I reinforced the sides, I made them extra thick, and in doing so, they were not all the same height. To fix this problem, I took each stack out to my woodworking workshop and used my 60+ year old Rockwell jointer to true up one side.

 

2016-10-21-00.212.jpg

 

With one side now flat, straight, and square, I was able to true up the other side on my table saw. This did create a lot of fine foam dust, so if you attempt to do this yourself, wear a respirator.

 

 

Installing the Electronics

 

2016-10-21-23.35.jpg

 

With the reinforcements on, I used tape to hold everything down nice and tight while the glue dried. Surprisingly, archival-grade PVA glue dries incredibly fast. I think the total drying time was less than 10 minutes before I was able to remove the tape and move on with installing the LCD.

 

2016-10-21-23.43.jpg

 

I used more painters tape to hold the LCD in place, and then flipped the slot machine over so that I could secure the LCD to the body using hot glue.

 

2016-10-21-23.44.jpg

 

As you can see, the Raspberry Pi 7-Inch touch screen fits nice and flush when placed in a single sheet of 5mm foam core. I cut the hole out so that it would be a very tight fit on purpose, but I do recommend that you leave one edge a little wide so that there is some wiggle room in the event that you need to pull the screen back out. I also suggest when placing the screen in, you place the edge with the orange ribbon cable in first, so that they do not get pinched during the install.

 

2016-10-21-23.52.jpg

 

To hold the LCD in place, I used a generous amount of hot glue. I know what you are thinking: “That is going to be a pain to remove when the project is over.” but I have a easy solution for removing hot glue easily. You simply have to freeze it using a can of compressed air which you turn upside down. The glue becomes very brittle and it simply pops right off.

 

2016-10-22-00.17.jpg

 

With the screen in place, it was time to start adding in the rest of the hardware. Since I plan on reusing this hardware in a desktop arcade style slot machine, I chose to just glue in an old small breadboardsmall breadboard, and wire everything up temporarily. Here you can see that I have added in the Arduino nanoArduino nano, a barrel jack, and a 600uF 60V capacitor to balance out the input power for the NeoPixels as Adafruit suggest.

 

2016-10-22-00.27.jpg

 

Now we need to wire up the arcade switches, and to do that I crimped some female spade terminals onto the ends of some wire, and wired the switch into Normally Open mode. I really appreciate the higher quality arcade buttons that use these removable micro switches, as they make wiring things up very easy.

 

2016-10-22-00.47.jpg

 

I soldered common female dupont jumper wires to the other end of the switch wires and then connected them to their respective pins on the Raspberry Pi. See the button wiring schematic earlier in this post for more information on where those wires go.

 

finalschempyslots.jpg

 

Here is a diagram of the final circuit for the complete whole project.

 

2016-10-22-00.00.jpg

 

I know someone was wondering what the blue wire that was tied around the Pi 3’s standoffs was, and the answer is that it is a simple safety cable. While I am sure the hot glue will hold the screen in place just fine, a little insurance never hurt anyone.

 

 

Installing the NeoPixel Strip

 

2016-10-22-15.29.jpg

 

Now that the internal electronics are installed and hooked up, I needed to move onto installing the NeoPixel Strips on the external face of the slot machine. Early on I decided to recess the NeoPixels into the face of the machine, and the easiest way to do this is to make two parallel half-cuts in the foam core that is slightly wider than the LED strips. In my case, the strips were 1cm wide. Once the cuts have been made, you can simply pull out the thin strip you created, and you are left with a 5mm deep slot to place the LED strips in.

 

2016-10-22-15.35.jpg

 

One important thing to remember is that the dimensions your LED stips have to be spaces will be determined by where the solder points are on the end of each strip. It’s hard to see, but you can see that the last LED on the strip is about another strip’s width from the end where the solder points are. This allowed me to make the next cuts with the top stip overlapping the unplaced strip by about 1cm. This makes wiring the strips together very easy, and in my case, it worked out perfectly for the spacing that I needed for symmetry.

 

2016-10-22-15.06.jpg

 

With all of the slots cut out for the NeoPixel strips to recess into, it was time to begin wiring up the strips. Since NeoPixels need a 5V, Data, and GND line, I am using three of the wires from 4-Conductor RGB LED wiring. I buy this stuff on Ebay in 200’ quantities whenever I need a few feet. It’s cheaper than any other 4-conductor wire on the market. I do not have a nice pin crimper, so I just solder the male header pins straight onto the wires.

 

2016-10-22-15.10.jpg

 

Once the header pins have been soldered on, I use a pair of flush cutters to split them apart. If the pins will be located close to to other components or pins, I will sometimes heat shrink them at the connection, but in this case it was not needed.

 

2016-10-22-14.58.jpg

 

Next I needed to solder the wires to the actual NeoPixel strip and that is pretty straight forward. One tip I can offer would be to not keep the heat on each pad for very long. I have soldered hundreds of these strips over the last few years, and have seen many joint failures from the pad lifting due to too much prolonged heat. I like to pre-tin the pad, and the wires, then use as little heat as possible to make the connection.

 

2016-10-22-15.00.jpg

 

One other quick tip I can offer is to use the grid lines on a cutting mat to quickly and easily cut heat shrink tubing to precise inch long sizes. On most cutting mats here in the US, the grid is based on 1-inch divisions.

 

2016-10-22-15.02.jpg

 

One lesson I learned after installing hundreds of LED strips in different haunted houses is that their weakest point is where the solder connection is. It does not take very much stress at all to rip a solder pad from the strip. To alleviate this, I add two heat shrink tubes to the wire, shrinking one overtop of the other.

 

2016-10-22-15.03.jpg

 

Then I slide a third heat shrink tube over the LED strip by about ½-inch. This creates a very nice stress relief, and protects the solder points from shorting out. It does use a little more heat shrink, but it is worth it in the end.

 

2016-10-22-17.22.jpg

 

One of the most tedious parts of this project was soldering up the NeoPixel strips into squares. To get the angle right, and ensure proper spacing between strips, I used tape to affix them to a scrap piece of foam core, then soldered short wires from point to point. Note that I do have these two strips positioned incorrectly. I have the Digital Out pins on each strip facing each other. The bottom, horizontal strip, should be flipped around so that the Digital In pin can be connected to the Digital Out pin.

 

2016-10-22-16.39.jpg

 

Once each corner joint was complete, I potted the corner using hot glue. This acts as a strain relief, and helps keep the corner square.

 

2016-10-22-18.47.jpg

 

With all of the NeoPixel strips built it was as simple as removing their adhesive tape’s backing and pushing them into place.

 

finalschempyslots.jpg

Now connect the NeoPixel strips to the Arduino like so.

 

2016-10-22-19.16.jpg

 

A quick test using the Rainbow Chase function showed that they are all working. Both strips run from the same pin, so the animation is the same, but I have the direction they chase in reversed by the way I mounted the smaller square.

 

 

Building the Slot Machine Arm Sleeve

 

2016-10-23-21_40_38-New-notification.jpg

 

You might remember from my first post that I purchased a few yards of this shiney silver metallic stretch fabric with the intention of using it as a sleeve on my left arm. This combined with the tilt sensor, and a cheap halloween childrens flashlight will create the pull arm for the slot machine. I will be the first to admit that sewing fabric together is not one of my strong abilities, much less sewing it so that it conformed to my arm. So I enlisted the help of my girlfriend who is a professional fiber artist, and general all around maker. Using her sewing machine, and seamstress skills, she quickly had the sleeve crafted, and there was enough material left over for her to make jokes about sewing me a pair of short shorts together….

 

IMG_9630.jpg

 

I did not get many photos of her sewing the sleeve together because I was busy working on the rest of the project, but here it is in all of its glory. The sleeve fits over my arm quite well, and the pumpkin flashlight is fastened into place. The sleeve will go on my arm before I put a black t-shirt on, thus hiding its open end. So let's look at how I built the electronics into this piece.

 

2016-10-21-22.38.jpg

 

As I mentioned earlier, I will be using a simple tilt switch to control the spin of the slots wheels. If you are unfamiliar, a tilt switch consist of a plastic tube that is encased in a metal housing. Inside the tube is a small steel ball. Then the tilt switch is tilted down, the ball makes contact with two contacts, and completes the circuit. Installing the tilt switch was as simple as soldering two wires to its leads, and adding heat shrink.

 

2016-10-21-23.15.jpg

 

On the other end of the wires I soldered on two Dupont female jumper ends. These will plug directly into the Raspberry Pi 3’s GPIO Pins.

 

2016-10-21-22.17.jpg

 

The pumpkin flashlight originally came with a very dim incandescent christmas light bulb, and was powered by two AA batteries. All of that had to come out, and I added an 8mm NeoPixel LED so that the pumpkin could still light up. I did have to drill the hole out, and I just happened to have a 7mm drill bit laying around. I was able to wiggle it a little in the hole and that widened things enough for the 8mm LED to fit snugly inside.

 

2016-10-21-23.04.jpg

 

I forgot to take photos of the 8mm NeoPixel being wired up, but I did remember to take a photo of it hot glued into place.

 

2016-10-21-23.24.jpg

 

On the other end of the Pixel wires, I added three more DuPont female jumper ends so they could be plugged into the breadboard using some spare male header pins I had laying around.

 

Finishing Up

IMG_9634.jpg

 

I absolutely ran out of time to install the Bluetooth speaker the way I wanted to, so I simply hot glued a stack of foam core together, then glued it to the front panel from behind. This gave me a ledge to place the speaker. A rough hole was then cut out, to allow the sound to pass through. Don’t worry though, I covered this ugly hole up with something.

 

IMG_9635.jpg

 

One of the final parts of the build was to fabricate a solution that would easily hang the slot machine from my shoulders. A good friend of mine is a professional cos-player, and he suggested that I build a shoulder harness out of PVC pipe, and that is exactly what I did. This used about 5-feet of PVC, 2 elbows, and two caps. I mounted each arm to the slot machine by building two stacks of foam core, then drilling a ⅞-inch hole in each with a Forstner bit. I then hot glued them into the holes. This setup is surprisingly comfortable, even with both battery packs inside the slot machine, and it holds the machine at the perfect height for people to play while I am walking around.

 

IMG_9641.jpg

 

Here is a quick shot of how I am powering the Raspberry Pi, the Touch Screen, and the Arduino Nano / Neo Pixels. The striped red USB cable powers the screen, via a 2.4A port on a battery bank, while the black USB cable powers the Raspberry Pi 3 from a 2.4A port on a second battery bank. The solid red USB cable provides 5V 1.5A to the breadboard which powers the Arduino Nano, and the NeoPixels.

 

IMG_9640.jpg

 

This is the two power banks I am using to power the costume. The KMASHI is a 16,000mAh 2.4A / 1.5A battery bank while the Royal is a 10,000mAh 2.4A battery bank. I picked both up from Amazon, and I think I spent $15 on the KMASHI, and $10 on the Royal.

 

IMG_9636.jpg

 

 

Finally we have a shot of the front of the slot machine after some decorations have been added. I originally planned on designing custom graphics for the machine, but as I mentioned at the beginning of this post, ran into printing issues. So I did the next best thing, and wrapped it in silver wrapping paper, and printed some logos that I then mounted to foam core and cut out. Both of these are glued to the slot machine body with 1cm standoffs behind. I am using the Halloween Pi logo to cover the ugly hole I cut for the speaker.

 

Running The Bfruit Program

 

Now that everything is buttoned up and connected, we can run the Bfruit Python script. There are two ways to quickly do this, but before you run the scrip, you will need to enable the built-in Bluetooth by clicking on it in the top navigation bar in PIXEL. Then to pair with the Bluetooth Speaker, you will need to right click on the audio icon, and select the speaker you want to pair with. If you do not want the games audio to play, then you can ignore this step.

 

Running the program via CMD

If you are remotely connected to the Raspberry Pi via SSH, then you can simply navigate to the Bfruit directory and then use the following command to run the program on the Pi and the script will run in full screen mode on the touchscreen.

 

$ cd /home/pi/Desktop/bfruit-0.1.2

$ sudo python bfruit.py

 

Running the program from inside the PIXEL GUI

If you are not remotely connected to the Raspberry Pi 3 via SSH and want to run the program, you will need to take the following steps to use IDLE to run the script.

 

nIXUAwx.jpg

Locate the bfruit folder in the directory you saved it to. I placed mine on the desktop for ease of access.

 

eZm5qLH.jpg

Then double click on the bfruit.py scrip, and the program will open in IDLE.

 

u5s4wLL.jpg

Once the script is open in IDLE, you can make any edits to the code that you wish, then navigate to the Run menu at the top of IDLE, and click on the Run Module option that is available. This will run the Python script. Unfortunately I was unable to take a screen shot of this as there is a bug in the built in PIXEL's built in screen shot utility that prevents screen shots of open menus.

 

wdFsM5p.jpg

 

When the Python script first runs, a quick warning window will pop up letting us know that GPIO37 is already in use, but you can ignore this, and it will not affect our program at all.

 

t327RiY.jpg

 

When bfruit loads, it will open in a windowed screen. You will need to navigate to its settings menu and select the full screen option so that it takes up the entire touchscreen.

 

FmtDDdD.jpg

 

Once you have selected the full screen option, simply select the back to main menu option to return to the main menu. From there, select new game, and enjoy the fun! I apologize for no screen shot of the actual game itself which is due to another bug that prevents PIXEL's built-in screen shot utility from taking screen shots if a Python Program is running in full screen mode. I have reported these bugs to the developers to see if they can be fixed.

 

 

 

All in all, I am quite happy with how the hardware turned out for this project, and a little disappointed with my execution of the theming. I would have looked so much better with the graphics I wanted to print, but honestly it is what it is, and being able to improvise on the fly is what being a maker is all about. If I would have had two more weeks to build this, I may have scrapped the whole foam core idea and built the whole thing from wood, but I can sit back and play the what-if game all night. In the end, it was a fun project, and my friends are already excited for me to wear it to their Halloween parties. Note that the video above was created after being awake for 39-hours straight. I will be replacing it with a better video in the coming days.

 

I want to take a moment to answer a few questions that I have gotten via comments, and messages.

 

Q:  Will you provide an image of the OS so that anyone could replicate this project without having to modify code, and use the terminal to install packages?

A:  No image will be made of this project. I feel that creating an image of any of my tutorial projects causes them to lose some of their educational value. If you follow this tutorial, and download the bfruit program from its original source, then modify it's python code using my code examples, you can have this project up and running in just a few hours.

 

Q: Are there design files available for the slot machine costume?

A: No. Design files were not produced because I built the slot machine body on the fly. I had a general idea of how I wanted it to look, and I simply built it using the plans that were inside my head.

 

Q: Why are the modified slot machine icons not available in the GitHub repo for this project?

A: The images I used for the slot machine's spinner wheels belong to different companies, and while I am sure they would not mind me using them in this project, I am sure they would not like me sharing them with the world on my GitHub. It's more of a "I don't want to get an angry email" kind of thing. If you want to create your own icons for your version of this project, you simply need to resize the images you would like to use to 128px X 128px, and make them a transparent .PNG file.

 

Q: If you were to build this project again, what would be the one thing you did differently?

A: I would definitely add more architectural features to the slot machine body, and then wrap the entire thing in custom designed graphics.

 

Q: When I try to run the bfruit.py program, it seems to be missing a lot of different files.

A: You have to download the original Bfruit program files from the source forge link that I posted in part two of this project. I also have the required files in a zip file on my Github.

 

 

I want to thank Element14, Raspberry Pi, and all of the staff at Element14 who gave me the opportunity to build this project. If you have not yet read the first two parts to this project, then head over to the links below to get caught up! That is going to wrap up this project for me. I will post an updated video with some footage of people playing the game at some of the parties I will be attending, but do not look for those until after Halloween. Thanks for taking the time to read this project, and I will see you on my next post! Until then remember to Hack The World, and Make Awesome!

 

Check Out The Full Project!

  1. Raspberry PySlots: The Costume - Introduction
  2. Raspberry PySlots: The Costume - Hardware, Software, and Pretty Lights!
  3. Raspberry PySlots: The Costume - The Slot Machine, NeoPixels, Pull Arm, And Finishing Things Up

RaspberryPySlotsBanner.jpg

 

Enter e14's 2016 Costume Contest Here!

The Raspberry Pi Hardware

 

Pi3-Touchscreen.jpg

 

As I mentioned in the first post, I will be using a Raspberry Pi 3Raspberry Pi 3, and the Raspberry Pi 7-inch touchscreenRaspberry Pi 7-inch touchscreen. So before I can get started with developing the program and lighting effects, I need to get the Raspberry Pi 3, and the touchscreen mated together. I won't walk you through the process on how to set this up though as there are many of these tutorials here on Element14 already such as this one from my friend Enrico Miglino (balearicdynamics), plus it’s as simple as connecting the ribbon cable, and then screwing the Raspberry Pi to the touchscreen’s controller board when you are using a Pi 3 and the latest version of Raspbian.

 

Pi3-Touchscreen-assembled.jpg

 

With the Pi and the Touchscreen now assembled, I just needed to get the latest version of Raspbian burnt onto a SD card, and then the screen would automatically work when I boot the Pi up for the first time. I took this as an opportunity to create a video for my YouTube channel on how to burn Raspbian to an SD card. I have wanted to do a series on Raspberry Pi Basics for a while now, and this project gave me the push I needed to get started on that. Check out the video below, and let me know what you think!

 

 

The Slot Machine Software

 

If you have followed any of my projects over the years, you will know that I try to make the software side of things as easy as possible. This usually results in searching out open source code that I can modify to fit my needs. That is no different from this project, and I was lucky enough to find a fully functional slot machine program that is written in Python, and developed for use on low-power linux machines.

 

The program I am using is called Bfruit and was written by Balázs Nagy and Ferenc Nagy. Bfruit is licensed under the GNU General Public License version 2.0 (GPLv2). I have uploaded a forked version of this program to my Git Hub, so that I as well as others can continue to develop this program for use on the Raspberry Pi platform.

 

Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900.png

 

In my initial testing, the Bfruit program ran very sluggish on a Raspberry Pi 2 Model BRaspberry Pi 2 Model B, and I was a little disappointed as it ran flawlessly in a Debian-based VM on my Windows 10 workstation. Thankfully, when I installed it on a Raspberry Pi 3, the program ran just as fast as it did in the VM. So with things running correctly, I jumped into the Bfruit.py program and modified the code to set a GPIO Pin on the Raspberry Pi to High when the system detected a WIN from the slots roll. For reference, I have posted a pinout diagram for the Raspberry Pi 3 above.  I have listed my changes to the Bfruit.py program below, I have also uploaded this as a change log to my GitHub Repo.

 

Line 29: Imported the RPi.GPIO library

import RPi.GPIO as GPIO ## Import GPIO library\

 

Line 35: Set the GPIO Mode to BOARD

GPIO.setmode(GPIO.BOARD) ## Use board pin numbering

 

Line 36: Set GPIO Pin 37 as an output

GPIO.setup(37, GPIO.OUT) ## Setup GPIO Pin 37 to OUT

 

Lines 606-611: Created two functions to set GPIO Pin 37 HIGH and LOW and included some debugging text

def ledOn (self):
   GPIO.output(37,True) ## Set GPIO pin 7 HIGH
   print "LedOn"

def ledOff (self):
   GPIO.output(37,False) ## Set GPIO pin 7 LOW
   print "LedOff"

 

Line 604: Called the ledON fuction after a win was detected in the Winner function

self.ledOn()

 

Line 320: Called the ledOFF function in the Main Loop’s “key down” section.

self.ledOff()

 

To better explain what each of these changes to the code does, a short line by linedescription of what each change does.

 

  • Line 27: GPIO.setup(37, GPIO.OUT) - This line tells Python to include the RPi.GPIO library when executed so that the program can control the Raspberry Pi’s GPIO Pins.
  • Line 35: GPIO.setmode(GPIO.BOARD) - This tells Python that the program will be using the BOARD pin numbering schema instead of the BCM schema.
  • Line 36: GPIO.setup(37, GPIO.OUT) - This sets GPIO Pin 37 as an output.
  • Line 606: This creates a function called ledOn.
  • Line 607: This sets GPIO pin 37 to HIGH.
  • Line 608: This prints LedOn in the terminal for debugging purposes.
  • Line 609: This creates a function called ledOff.
  • Line 610: This sets the GPIO pin 37 to LOW.
  • Line 611: This prints LedOff in the terminal for debugging purposes.
  • Line 604: This calls the ledOn function when a win is detected by the program. This triggers the interrupt on the Arduino, which triggers the winner lighting function.
  • Line 320: This calls the ledOff function when the key press that spins the wheels is detected. This allows the Winner LED animation  on the Arduino to reset so that it can be triggered again if another win is detected.

 

The full code is below. It’s over 800 lines, so it may be a little long if you are reading this on a mobile device.

 

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
# Written by Balázs Nagy <nxbalazs@gmail.com>
# Design by Ferenc Nagy <nferencfx@gmail.com>
# Project web site: http://bfruit.sf.net

#This code was modified on Oct 11 2016 by Charles Gantt
#For the Raspberry PySlots Halloween Costume.
#Find all three parts of the the project build log at http://bit.ly/RPiSlots

import pygame
from pygame.locals import *
from random import randrange
import sys
from sys import argv
from getopt import getopt, GetoptError
import RPi.GPIO as GPIO ## Import GPIO library
import time
import os

VERSION = "0.1.2"

GPIO.setmode(GPIO.BOARD) ## Use board pin numbering
GPIO.setup(37, GPIO.OUT) ## Setup GPIO Pin 37 to OUT

# main menu###########################
class Menu:
    def __init__(self):
        self.screen = screen
        self.maincolor = [0, 0, 0]
        self.white = [255, 255, 255]
        self.bsound = pygame.mixer.Sound("data/sounds/CLICK10A.WAV")
        self.background = pygame.image.load("data/menubg/menubg.png")
        self.backgroundadded = pygame.image.load("data/menubg/added.png")
        self.sav = pygame.image.load("data/menubg/sav.png")
        self.highscore = (pygame.image.load("data/menubg/highscore.png"))
        self.menu = ["  New Game  ", "  Settings  ", "  High score  ", "  Exit to Linux "]
        self.menubg = []
        self.menubg.append(pygame.image.load("data/menubg/al.png").convert())
        self.menubg.append(pygame.image.load("data/menubg/ci.png").convert())
        self.menubg.append(pygame.image.load("data/menubg/he.png").convert())
        self.menubg.append(pygame.image.load("data/menubg/na.png").convert())
        self.menubg.append(pygame.image.load("data/menubg/di.png").convert())
        self.menuall = ""
        self.selectedmenu = 0
        self.mid = []
        # get menu width
        self.menuid()
        # all menu in one:
        self.listmenuall()
        # mainloop
        sz = 0
        szam = 0
        szamlalo = 0
        self.showhs = False # show hs in menu
        while True:
            for self.event in pygame.event.get():
                if self.selectedmenu == 2:
                    self.showhs = True
                else:
                    self.showhs = False
                if self.event.type == pygame.QUIT:
                    exit()
                if self.event.type == pygame.KEYDOWN:
                    self.bsound.play()
                    if self.event.key == pygame.K_LEFT:
                        if self.selectedmenu == 0:
                            self.selectedmenu = len(self.menu)-1
                        else:
                            self.selectedmenu = self.selectedmenu-1
                    elif self.event.key == pygame.K_RIGHT:
                        if self.selectedmenu == len(self.menu)-1:
                            self.selectedmenu = 0
                        else:
                            self.selectedmenu = self.selectedmenu+1
                    elif self.event.key == pygame.K_RETURN:
                        if self.selectedmenu == 0:
                            plc = Game()
                        elif self.selectedmenu == 1:
                            plc = Settings()
                        elif self.selectedmenu == 2:
                            self.selectedmenu = 2 # 
                        else:
                            exit()
                    if self.event.key == pygame.K_ESCAPE:
                        exit()
            # 1st layer: background color
            self.screen.fill(self.maincolor)
            self.bg = self.menubg[szam]
            self.bg.set_alpha(sz)
            self.screen.blit(self.bg, (0, 0))
            self.screen.blit(self.backgroundadded, (0, 0))
            # 2nd layer: menus
            self.crt_menu()
            # 3rd layer: transparent image
            self.screen.blit(self.background, (0, 0))
            
            font = pygame.font.Font("data/LiberationSans-Regular.ttf", 15)
            text_surface = font.render("Balazs Nagy - BFruit - "+VERSION , True, self.white)
            self.screen.blit(text_surface, (3, 460))
            
            if self.showhs == True:
                self.screen.blit(self.sav, (0, 60))
                self.screen.blit(self.sav, (0, 120))
                self.screen.blit(self.highscore, (50, 60))
                font=pygame.font.Font("data/LiberationSans-Regular.ttf", 25)
                text_surface = font.render(scr, True, self.white)
                self.screen.blit(text_surface, (295, 110))
            
            szamlalo = szamlalo + 4
            
            if szamlalo < 245:
                sz = sz + 4
            if szamlalo > 244:
                sz = sz - 4
                
            if szamlalo > 490:
                sz = 0
                szamlalo = 0
                if szam == len(self.menubg)-1:
                    szam = 0
                else:
                    szam = szam + 1
            
            
            pygame.display.update()
             
            
    def menuid(self):
        for n in self.menu:
            font = pygame.font.Font("data/LiberationSans-Regular.ttf", 25)
            text_surface = font.render(n, True, self.white)
            self.mid.append(text_surface.get_width())
            
    def listmenuall(self):
        for n in self.menu:
            self.menuall = self.menuall+n
            
    def crt_menu(self):
        nmb = 0
        xpos = 0
        while nmb <= self.selectedmenu:
            xpos = xpos-self.mid[nmb]
            nmb = nmb+1
        xpos = xpos+self.mid[self.selectedmenu]/2
        # draw menus on screen
        font = pygame.font.Font("data/LiberationSans-Regular.ttf", 25)
        text_surface = font.render(self.menuall, True, self.white)
        self.screen.blit(text_surface, (320+xpos, 15))

# Settings menu################################
class Settings:
    def __init__(self):
        self.screen = screen
        self.maincolor = [0, 0, 0]
        self.white = [255, 255, 255]
        self.bsound = pygame.mixer.Sound("data/sounds/CLICK10A.WAV")
        self.background = pygame.image.load("data/menubg/menubg.png")
        self.backgroundadded = pygame.image.load("data/menubg/added.png")
        self.sav = pygame.image.load("data/menubg/sav.png")
        self.menu = ["  Fullscreen  ", "  Back to main  "]
        self.menubg = []
        self.menubg.append(pygame.image.load("data/menubg/al.png").convert())
        self.menubg.append(pygame.image.load("data/menubg/ci.png").convert())
        self.menubg.append(pygame.image.load("data/menubg/he.png").convert())
        self.menubg.append(pygame.image.load("data/menubg/na.png").convert())
        self.menubg.append(pygame.image.load("data/menubg/di.png").convert())
        self.menuall = ""
        self.selectedmenu = 0
        self.mid = []
        # get menu width
        self.menuid()
        # all menu in one:
        self.listmenuall()
        # mainloop
        sz = 0
        szam = 0
        szamlalo = 0
        while True:
            for self.event in pygame.event.get():
                if self.event.type == pygame.QUIT:
                    exit()
                if self.event.type == pygame.KEYDOWN:
                    self.bsound.play()
                    if self.event.key == pygame.K_LEFT:
                        if self.selectedmenu == 0:
                            self.selectedmenu = len(self.menu)-1
                        else:
                            self.selectedmenu = self.selectedmenu-1
                    elif self.event.key == pygame.K_RIGHT:
                        if self.selectedmenu == len(self.menu)-1:
                            self.selectedmenu = 0
                        else:
                            self.selectedmenu = self.selectedmenu+1
                    elif self.event.key == pygame.K_RETURN:
                        if self.selectedmenu == 0:
                            pygame.display.toggle_fullscreen()
                        else:
                            plc = Menu()
            # 1st layer: background color
            self.screen.fill(self.maincolor)
            self.bg = self.menubg[szam]
            self.bg.set_alpha(sz)
            self.screen.blit(self.bg, (0, 0))
            self.screen.blit(self.backgroundadded, (0, 0))
            # 2nd layer: menus
            self.crt_menu()
            # 3rd layer: transparent image
            self.screen.blit(self.background, (0, 0))
            
            font = pygame.font.Font("data/LiberationSans-Regular.ttf", 15)
            text_surface = font.render("Balazs Nagy - BFruit - "+VERSION , True, self.white)
            self.screen.blit(text_surface, (3, 460))
            
            szamlalo = szamlalo + 4
            
            if szamlalo < 245:
                sz = sz + 4
            if szamlalo > 244:
                sz = sz - 4
                
            if szamlalo > 490:
                sz = 0
                szamlalo = 0
                if szam == len(self.menubg)-1:
                    szam = 0
                else:
                    szam = szam + 1
            
            
            pygame.display.update()
            
    def menuid(self):
        for n in self.menu:
            font = pygame.font.Font("data/LiberationSans-Regular.ttf", 25)
            text_surface = font.render(n, True, self.white)
            self.mid.append(text_surface.get_width())
            
    def listmenuall(self):
        for n in self.menu:
            self.menuall = self.menuall+n
            
    def crt_menu(self):
        nmb = 0
        xpos = 0
        while nmb <= self.selectedmenu:
            xpos = xpos-self.mid[nmb]
            nmb = nmb+1
        xpos = xpos+self.mid[self.selectedmenu]/2
        # draw menus on screen
        font = pygame.font.Font("data/LiberationSans-Regular.ttf", 25)
        text_surface = font.render(self.menuall, True, self.white)
        self.screen.blit(text_surface, (320+xpos, 15))

# the game###########################
class Game:
    def __init__(self):
        self.mut = 0
        self.wins = [0, 0, 0, 0, 0]
        self.keys = 1
        self.credit = 20
        self.bet = 1
        self.lastwin = 0
        self.show = []
        
        self.screen = screen
        
        self.bsound = pygame.mixer.Sound("data/sounds/CLICK10A.WAV")
        self.rasound = pygame.mixer.Sound("data/sounds/film_projector.wav")
        self.rbsound = pygame.mixer.Sound("data/sounds/film_projector.wav")
        self.rcsound = pygame.mixer.Sound("data/sounds/film_projector.wav")
        self.bgsound = pygame.mixer.Sound("data/sounds/background001.wav")
        self.beepsound = pygame.mixer.Sound("data/sounds/beep.wav")
        self.background = pygame.image.load("data/img/bg.png")
        self.rlayer = pygame.image.load("data/img/rlayer.png")
        self.windowlayer = pygame.image.load("data/img/windowlayer.png")
        self.imgone = pygame.image.load("data/img/1.png")
        self.imgtwo = pygame.image.load("data/img/2.png")
        self.imgthree = pygame.image.load("data/img/3.png")
        self.imgfour = pygame.image.load("data/img/4.png")
        self.imgfive = pygame.image.load("data/img/5.png")
        self.imgsix = pygame.image.load("data/img/6.png")
        self.imgseven = pygame.image.load("data/img/7.png")
        self.imgeight = pygame.image.load("data/img/8.png")
        
        img = []
        img.append(self.imgone)
        img.append(self.imgtwo)
        img.append(self.imgthree)
        img.append(self.imgfour)
        img.append(self.imgfive)
        img.append(self.imgsix)
        img.append(self.imgseven)
        img.append(self.imgeight)
        
        self.bgsound.play(loops=-1)
        
        # mainloop
        while True:
            self.screen.fill([0, 0, 0])
            self.screen.blit(self.background, (0, 0))
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.bgsound.stop()
                    exit()
                    
                if event.type == pygame.KEYDOWN:
                    self.ledOff()
                    self.bsound.play()
                    if event.key == pygame.K_LEFT and self.keys == 1:
                        if self.credit > 0:
                            if self.credit - self.bet < 0:
                                self.bet = self.credit
                            self.credit = self.credit - self.bet
                            self.randi()
                            self.check()
                            self.roll(img)
                            self.screen.blit(self.background, (0, 0))
                            self.drawl()
                            self.winner()
                        elif self.credit == 0 and self.bet == 0:
                            self.bgsound.stop()
                            plc = Menu()
                            
                    if self.credit > 0:
                        if event.key == pygame.K_UP and self.keys == 1:
                            if self.credit - self.bet - 1 >= 0:
                                self.bet = self.bet + 1
                            else:
                                self.bet = 1
                            if self.bet == 11:
                                self.bet = 1
                            
                    else:
                        self.bet = 0
                            
                            
                    if event.key == pygame.K_F1:
                        if self.keys == 1:
                            self.keys = 0
                            self.menu = "h"
                        elif self.keys == 0:
                            self.keys = 1
                            self.menu = "n"
                            
                    if event.key == pygame.K_RETURN:
                        self.keys = 0
                        self.menu = "e"
                      
                    if event.key == pygame.K_ESCAPE and self.keys == 1:
                        self.bgsound.stop()
                        plc = Menu()
                            
            self.draw_side()
            
            if self.mut == 1:
                self.drawl()
                self.check()
                self.wins = [0, 0, 0, 0, 0]
            
            if self.credit == 0 and self.bet == 0:
                font = pygame.font.Font("data/LiberationSans-Regular.ttf", 55)
                text_surface = font.render("Game Over", True, [255, 0, 0])
                self.screen.blit(text_surface, (70, 190))
            
            self.screen.blit(self.rlayer, (37, 48))
            self.screen.blit(self.windowlayer, (0, 0))
            
            if self.keys == 0 and self.menu == "h":
                self.helpmenu()
            if self.keys == 0 and self.menu == "e":
                self.endthegame(scr)
            
            pygame.display.update()
    
    def roll(self, img):
        szam = 0
        
        
        # toll time
        rolla = randrange(5, 14)
        rollb = randrange(rolla+1, rolla+5)
        rollc = randrange(rollb+1, rollb+5)
        
        # a column
        rollaf = []
        rollaf.append(img[int(self.show[0])-1])
        rollaf.append(img[int(self.show[1])-1])
        rollaf.append(img[int(self.show[2])-1])
        while szam <= rolla-3:
            rollaf.append(img[randrange(0, 8)])
            szam = szam + 1
        self.rasound.play()
        rollaf.append(img[int(self.showold[0])-1])
        rollaf.append(img[int(self.showold[1])-1])
        rollaf.append(img[int(self.showold[2])-1])
        
            
        szam = 0
        
        # b column
        rollbf = []
        rollbf.append(img[int(self.show[3])-1])
        rollbf.append(img[int(self.show[4])-1])
        rollbf.append(img[int(self.show[5])-1])
        while szam <= rollb-3:
            rollbf.append(img[randrange(0, 8)])
            szam = szam +1
        self.rbsound.play()
        rollbf.append(img[int(self.showold[3])-1])
        rollbf.append(img[int(self.showold[4])-1])
        rollbf.append(img[int(self.showold[5])-1])
            
        szam = 0
        
        # c column
        rollcf = []
        rollcf.append(img[int(self.show[6])-1])
        rollcf.append(img[int(self.show[7])-1])
        rollcf.append(img[int(self.show[8])-1])
        while szam <= rollc-3:
            rollcf.append(img[randrange(0, 8)])
            szam = szam +1
        self.rcsound.play()
        rollcf.append(img[int(self.showold[6])-1])
        rollcf.append(img[int(self.showold[7])-1])
        rollcf.append(img[int(self.showold[8])-1])
        
        szama = len(rollaf)-1
        szamb = len(rollbf)-1
        szamc = len(rollcf)-1
        
        while szamc > 2:
            self.screen.fill([0, 0, 0])
            self.screen.blit(self.background, (0, 0))
            
            if szama > 2:
                self.screen.blit(rollaf[len(rollaf)-3], (36, 46))
                self.screen.blit(rollaf[len(rollaf)-2], (36, 174))
                self.screen.blit(rollaf[len(rollaf)-1], (36, 302))
                szama = szama - 1
                del(rollaf[len(rollaf)-1])
            else:
                self.screen.blit(rollaf[len(rollaf)-3], (36, 46))
                self.screen.blit(rollaf[len(rollaf)-2], (36, 174))
                self.screen.blit(rollaf[len(rollaf)-1], (36, 302))
                self.rasound.stop()
                
            if szamb > 2:
                self.screen.blit(rollbf[len(rollbf)-3], (165, 46))
                self.screen.blit(rollbf[len(rollbf)-2], (165, 174))
                self.screen.blit(rollbf[len(rollbf)-1], (165, 302))
                szamb = szamb - 1
                del(rollbf[len(rollbf)-1])
            else:
                self.screen.blit(rollbf[len(rollbf)-3], (165, 46))
                self.screen.blit(rollbf[len(rollbf)-2], (165, 174))
                self.screen.blit(rollbf[len(rollbf)-1], (165, 302))
                self.rbsound.stop()
                
            if szamc > 2:
                self.screen.blit(rollcf[len(rollcf)-3], (295, 46))
                self.screen.blit(rollcf[len(rollcf)-2], (295, 174))
                self.screen.blit(rollcf[len(rollcf)-1], (295, 302))
                szamc = szamc - 1
                del(rollcf[len(rollcf)-1])
            else:
                self.screen.blit(rollcf[len(rollcf)-3], (295, 46))
                self.screen.blit(rollcf[len(rollcf)-2], (295, 174))
                self.screen.blit(rollcf[len(rollcf)-1], (295, 302))
            
            self.draw_side()
            self.screen.blit(self.rlayer, (37, 48))
            self.screen.blit(self.windowlayer, (0, 0))
            pygame.display.update()
            rollc = rollc - 1
        self.rcsound.stop()
    
    def draw_side(self):
        #animation
        digifont = pygame.font.Font("data/DIGITAL2.ttf",24)
        text_surface = digifont.render("88888888888", True, [60, 0, 0])
        self.screen.blit(text_surface, (470, 50))
        
        text_surface = digifont.render("F1 FOR HELP", True, [255, 0, 0])
        self.screen.blit(text_surface, (470, 50))
        
        font = pygame.font.Font("data/LiberationSans-Regular.ttf", 15)
        text_surface = font.render("Bet:", True, [230, 255, 255])
        self.screen.blit(text_surface, (500, 185))
        # multip
        digifont = pygame.font.Font("data/DIGITAL2.ttf",24)
        text_surface = digifont.render("88", True, [60, 0, 0])
        self.screen.blit(text_surface, (500, 210))
        text_surface = digifont.render(str(self.bet), True, [255, 0, 0])
        self.screen.blit(text_surface, (500, 210))
        
        font = pygame.font.Font("data/LiberationSans-Regular.ttf", 15)
        text_surface = font.render("Winner Paid:", True, [230, 255, 255])
        self.screen.blit(text_surface, (500, 255))
        # last win
        digifont = pygame.font.Font("data/DIGITAL2.ttf",24)
        text_surface = digifont.render("888", True, [60, 0, 0])
        self.screen.blit(text_surface, (500, 280))
        text_surface = digifont.render(str(self.lastwin), True, [255, 0, 0])
        self.screen.blit(text_surface, (500, 280))
        
        font = pygame.font.Font("data/LiberationSans-Regular.ttf", 15)
        text_surface = font.render("Credit:", True, [230, 255, 255])
        self.screen.blit(text_surface, (500, 325))
        # startsum
        digifont = pygame.font.Font("data/DIGITAL2.ttf",24)
        text_surface = digifont.render("888888", True, [60, 0, 0])
        self.screen.blit(text_surface, (500, 350))
        text_surface = digifont.render(str(self.credit), True, [255, 0, 0])
        self.screen.blit(text_surface, (500, 350))
    
    def drawl(self):        
        self.screen.blit(pygame.image.load("data/img/"+str(self.show[0])+".png"), (36, 46))
        self.screen.blit(pygame.image.load("data/img/"+str(self.show[1])+".png"), (36, 174))
        self.screen.blit(pygame.image.load("data/img/"+str(self.show[2])+".png"), (36, 302))
        self.screen.blit(pygame.image.load("data/img/"+str(self.show[3])+".png"), (165, 46))
        self.screen.blit(pygame.image.load("data/img/"+str(self.show[4])+".png"), (165, 174))
        self.screen.blit(pygame.image.load("data/img/"+str(self.show[5])+".png"), (165, 302))
        self.screen.blit(pygame.image.load("data/img/"+str(self.show[6])+".png"), (295, 46))
        self.screen.blit(pygame.image.load("data/img/"+str(self.show[7])+".png"), (295, 174))
        self.screen.blit(pygame.image.load("data/img/"+str(self.show[8])+".png"), (295, 302))

    # random images
    def randi(self):
        self.showold = []
        if len(self.show) > 1:
            self.showold = self.show
        else:
            self.showold = ["8", "8", "8", "8", "8", "8", "8", "8", "8"]
        self.mut = 1
        ran = {}
        ran[0] = randrange(1, 335)
        ran[1] = randrange(1, 335)
        ran[2] = randrange(1, 335)
        ran[3] = randrange(1, 335)
        ran[4] = randrange(1, 335)
        ran[5] = randrange(1, 335)
        ran[6] = randrange(1, 335)
        ran[7] = randrange(1, 335)
        ran[8] = randrange(1, 335)
        self.show = []
        for n in ran:
            if 1 <= ran[n] <= 5:
                self.show.append("8")
            if 6 <= ran[n] <= 15:
                self.show.append("7")
            if 16 <= ran[n] <= 30:
                self.show.append("6")
            if 31 <= ran[n] <= 50:
                self.show.append("5")
            if 51 <= ran[n] <= 120:
                self.show.append("4")
            if 121 <= ran[n] <= 180:
                self.show.append("3")
            if 181 <= ran[n] <= 253:
                self.show.append("2")
            if 254 <= ran[n] <= 334:
                self.show.append("1")
                
    def check(self):
        if self.show[0] == self.show[3] == self.show[6]:
            pygame.draw.line(self.screen, [246, 226, 0], (36, 111), (423, 111), 8)
            self.wins[0] = self.show[0]
        if self.show[1] == self.show[4] == self.show[7]:
            pygame.draw.line(self.screen, [246, 226, 0], (36, 239), (423, 239), 8)
            self.wins[1] = self.show[1]
        if self.show[2] == self.show[5] == self.show[8]:
            pygame.draw.line(self.screen, [246, 226, 0], (36, 367), (423, 367), 8)
            self.wins[2] = self.show[2]
        if self.show[0] == self.show[4] == self.show[8]:
            pygame.draw.line(self.screen, [246, 226, 0], (37, 47), (422, 433), 8)
            self.wins[3] = self.show[0]
        if self.show[2] == self.show[4] == self.show[6]:
            pygame.draw.line(self.screen, [246, 226, 0], (37, 432), (422, 47), 8)
            self.wins[4] = self.show[2]
            
    def winner(self):
        self.lastwin = 0
        for n in self.wins:
            winsu = self.bet*int(n)
            winsum = winsu + self.bet
            if winsum > self.bet:
                self.credit = self.credit + winsum
                self.lastwin = self.lastwin + winsum
                self.beepsound.play()
                self.ledOn()

    def ledOn (self):
        GPIO.output(37,True) ## Turn on GPIO pin 7
        print "LedOn"
    def ledOff (self):
        GPIO.output(37,False) ## Turn on GPIO pin 7
        print "LedOff"

    def helpmenu(self):
        pygame.draw.line(self.screen, [176, 176, 176], (50, 250), (590, 250), 400)
        font = pygame.font.Font("data/LiberationSans-Regular.ttf", 15)
        text_surface = font.render("How to play:", True, [255, 255, 255])
        self.screen.blit(text_surface, (60, 60))
        text_surface = font.render("New spin: left arrow", True, [255, 255, 255])
        self.screen.blit(text_surface, (60, 80))
        text_surface = font.render("Raise bet: arrow up", True, [255, 255, 255])
        self.screen.blit(text_surface, (60, 100))
        text_surface = font.render("To end game to high score press Enter", True, [255, 255, 255])
        self.screen.blit(text_surface, (60, 120))
        text_surface = font.render("To close this as game over help press F1", True, [255, 255, 255])
        self.screen.blit(text_surface, (60, 160))
        
    def endthegame(self, scr):
        scrb = int(scr)
        pygame.draw.line(self.screen, [176, 176, 176], (50, 250), (590, 250), 400)
        if self.credit > scrb:
            font = pygame.font.Font("data/LiberationSans-Regular.ttf", 15)
            text_surface = font.render("You have a new high score!!!", True, [255, 255, 255])
            self.screen.blit(text_surface, (60, 60))
            text_surface = font.render("Old high score: "+scr, True, [255, 255, 255])
            self.screen.blit(text_surface, (60, 80))
            text_surface = font.render("New high score: "+str(self.credit), True, [255, 255, 255])
            self.screen.blit(text_surface, (60, 100))
            self.writehs(myhsfile)
        else:
            font = pygame.font.Font("data/LiberationSans-Regular.ttf", 15)
            text_surface = font.render("You ended the game, but you don't have a new high score...", True, [255, 255, 255])
            self.screen.blit(text_surface, (60, 60))
        for event in pygame.event.get():
            if event.type == pygame.KEYDOWN:
                self.bgsound.stop()
                plc = Menu()
    
    def writehs(self, myhsfile):
        writef = open(myhsfile, "w")
        writef.write(str(self.credit))
        writef.close()
        

def help():
    print "BFruit help:"
    print "Options:"
    print "-h, --help        display this help message"
    print "-v, --version     display game version"
    print "Contact: nxbalazs@gmail.com"

if __name__ == "__main__":
    try:
        long = ["help", "version"]
        opts = getopt(argv[1:], "hv", long)[0]
    except GetoptError:
        help()
        exit()
    for opt, arg in opts:
        if opt in ("-h", "--help"):
            help()
            exit()
        if opt in ("-v", "--version"):
            print "BFruit - version: "+ VERSION
            exit()
            

    # .settings:
    homedir = os.path.expanduser("~")
    if homedir[0] == "/":
        mydir = homedir+"/.bfruit"
        myhsfile = mydir+"/hs"
    else:
        mydir = homedir+"\Application Data\.bfruit"
        myhsfile = mydir+"\hs"
    if os.path.exists(mydir) == False:
        os.mkdir(mydir)
    if os.path.exists(myhsfile) == False:
        open(myhsfile, "w").close()
    hsf = open(myhsfile, "r+")
    scr = hsf.readline() # high score
    hsf.close()
    if scr == "":
        scr = "1"

    # pygame init, set display
    pygame.init()
    screen = pygame.display.set_mode([640, 480], 0, 24)
    pygame.display.set_caption("BFruit")
    pygame.mouse.set_visible(False)
    
    # intro
    border = pygame.image.load("data/intro/border.png").convert()
    point = pygame.image.load("data/intro/point.png").convert()
    sun = pygame.image.load("data/intro/sun.png").convert()
    
    szam = 0
    while szam < 256:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            if event.type == pygame.KEYDOWN:
                plc = Menu()
        screen.fill([0, 0, 0])
        border.set_alpha(szam)
        point.set_alpha(szam)
        screen.blit(border, (160, 120))
        screen.blit(point, (185, 150))
        screen.blit(point, (185, 180))
        screen.blit(point, (185, 210))
        screen.blit(point, (185, 240))
        screen.blit(point, (185, 270))
        screen.blit(point, (215, 150))
        screen.blit(point, (215, 180))
        screen.blit(point, (215, 210))
        screen.blit(point, (215, 240))
        screen.blit(point, (215, 270))
        screen.blit(point, (245, 150))
        screen.blit(point, (245, 180))
        screen.blit(point, (245, 210))
        screen.blit(point, (245, 240))
        screen.blit(point, (245, 270))
        screen.blit(point, (275, 150))
        screen.blit(point, (275, 180))
        screen.blit(point, (275, 210))
        screen.blit(point, (275, 240))
        screen.blit(point, (275, 270))
        screen.blit(point, (305, 150))
        screen.blit(point, (305, 180))
        screen.blit(point, (305, 210))
        screen.blit(point, (305, 240))
        screen.blit(point, (305, 270))
        screen.blit(point, (335, 150))
        screen.blit(point, (335, 180))
        screen.blit(point, (335, 210))
        screen.blit(point, (335, 240))
        screen.blit(point, (335, 270))
        screen.blit(point, (365, 150))
        screen.blit(point, (365, 180))
        screen.blit(point, (365, 210))
        screen.blit(point, (365, 240))
        screen.blit(point, (365, 270))
        screen.blit(point, (395, 150))
        screen.blit(point, (395, 180))
        screen.blit(point, (395, 210))
        screen.blit(point, (395, 240))
        screen.blit(point, (395, 270))
        screen.blit(point, (425, 150))
        screen.blit(point, (425, 180))
        screen.blit(point, (425, 210))
        screen.blit(point, (425, 240))
        screen.blit(point, (425, 270))
        szam = szam + 4
        pygame.display.update()
    
    starttime = time.clock()
    
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                exit()
            if event.type == pygame.KEYDOWN:
                plc = Menu()
                
        screen.blit(border, (160, 120))
        
        screen.blit(point, (185, 150))
        screen.blit(point, (185, 180))
        screen.blit(point, (185, 210))
        screen.blit(point, (185, 240))
        if time.clock() - starttime < 1:
            screen.blit(point, (185, 270))
        if time.clock() - starttime < 1.2:
            screen.blit(point, (215, 150))
        screen.blit(point, (215, 180))
        if time.clock() - starttime < 1.15:
            screen.blit(point, (215, 210))
        if time.clock() - starttime < 1.2:
            screen.blit(point, (215, 240))
        if time.clock() - starttime < 1.23:
            screen.blit(point, (215, 270))
        if time.clock() - starttime < 1.18:
            screen.blit(point, (245, 150))
        if time.clock() - starttime < 1.2:
            screen.blit(point, (245, 180))
        screen.blit(point, (245, 210))
        if time.clock() - starttime < 1.43:
            screen.blit(point, (245, 240))
        if time.clock() - starttime < 1.5:
            screen.blit(point, (245, 270))
        screen.blit(point, (275, 150))
        screen.blit(point, (275, 180))
        screen.blit(point, (275, 210))
        screen.blit(point, (275, 240))
        if time.clock() - starttime < 1.22:
            screen.blit(point, (275, 270))
        if time.clock() - starttime < 1.41:
            screen.blit(point, (305, 150))
        if time.clock() - starttime < 1.34:
            screen.blit(point, (305, 180))
        if time.clock() - starttime < 1.4:
            screen.blit(point, (305, 210))
        if time.clock() - starttime < 1.36:
            screen.blit(point, (305, 240))
        if time.clock() - starttime < 1.1:
            screen.blit(point, (305, 270))
        screen.blit(point, (335, 150))
        screen.blit(point, (335, 180))
        screen.blit(point, (335, 210))
        screen.blit(point, (335, 240))
        screen.blit(point, (335, 270))
        screen.blit(point, (365, 150))
        if time.clock() - starttime < 1.13:
            screen.blit(point, (365, 180))
        screen.blit(point, (365, 210))
        if time.clock() - starttime < 1.4:
            screen.blit(point, (365, 240))
        screen.blit(point, (365, 270))
        screen.blit(point, (395, 150))
        if time.clock() - starttime < 1.31:
            screen.blit(point, (395, 180))
        screen.blit(point, (395, 210))
        if time.clock() - starttime < 1.25:
            screen.blit(point, (395, 240))
        screen.blit(point, (395, 270))
        if time.clock() - starttime < 1.43:
            screen.blit(point, (425, 150))
        screen.blit(point, (425, 180))
        if time.clock() - starttime < 2.0:
            screen.blit(point, (425, 210))
        screen.blit(point, (425, 240))
        if time.clock() - starttime < 2.4:
            screen.blit(point, (425, 270))
            
        if time.clock() - starttime > 3:
            font = pygame.font.Font("data/LiberationSans-Regular.ttf", 25)
            text_surface = font.render("nXBalazs" , True, [255, 255, 255])
            screen.blit(text_surface, (190, 273))
        if time.clock() - starttime > 3.5:
            font = pygame.font.Font("data/LiberationSans-Regular.ttf", 25)
            text_surface = font.render("games" , True, [255, 255, 255])
            screen.blit(text_surface, (280, 310))
        if 5 > time.clock() - starttime > 4:
            szamsun = 0
            while szamsun < 100:
                sun.set_alpha(szamsun)
                screen.blit(sun, (0, 0))
                szamsun = szamsun + 1
                pygame.display.update()
        if time.clock() - starttime > 5:
            plc = Menu()
    
    
    
        pygame.display.update()

 

 

Lighting Effects Pt. 1

 

LED Animation Designs

 

I have always been a self-proclaimed LED junkie. From as early as I can remember in my maker adventures, I have been fascinated with LEDs, and when the first NeoPixelNeoPixel / WS2811 and WS2812 strips hit the market, my life all but changed. No longer did I have to design complex circuitry and coding to manipulate RGB LED’s, I could use a single data line, and two power lines to control as many of these LEDs as I desired. For this project I knew I had to incorporate NeoPixels into the design somewhere, and my solution was to use them for both advertising the game to possible players, and to indicate when a player has won on a spin.

 

1506-00.jpg

 

My initial plan was to have a single animation running from a separate controller that would serve as the slot machine costume’s “ambient” lighting animation, and then have a separate strip of NeoPixels run an animation when someone wins, and I developed two separate scripts for these animations. I was able to combine these into a single script after coming up with an entirely new approach to how I control the NeoPixels, more on that in a bit though. Let’s look at both scripts and see how they work.

 

Ambient Chase Code

I named the first animation Ambient Chase because that is basically what it is. I modified some code I found in an example animation for the FastLED library that let me create a traditional theater chase animation that cycled through a rainbow effect of 256 different colors. If you have worked with Adafruit’s NeoPixel library, or the FastLED library (my preferred choice) then you know how short these  type of scripts can be. Below is an snippet of just the Ambient Chase code, and below that is the full Arduino-ready script to run this code.

 

Ambient Chase Function Snippet

//Theatre Chase Sytle Crawling Lights With Rainbow Effect
void theaterChaseRainbow(uint8_t wait) {
  uint16_t i,j,q;
  for (j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (q=0; q < 3; q++) {
      for (i=0; i+q < NUM_LEDS; i=i+3) {
        leds[i+q].setHue((i+j) % 255);    //turn every third pixel on
      }
      FastLED.show(); //Update all LEDs
      delay(55);  // controls the speed of the chase
      for (i=0; i+q < NUM_LEDS; i=i+3) {
        leds[i+q] = 0;        //turn every third pixel off
      }
    }
  }
}

 

Full Ambient Chase Code

#include "FastLED.h"

// How many leds in your strip?
#define NUM_LEDS 22
#define DATA_PIN 6
#define SLOW 250
#define MEDIUM 75

CRGB leds[NUM_LEDS];
void setup() {

  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
}

void loop(){
    theaterChaseRainbow(50);
}

//Theatre Chase Sytle Crawling Lights With Rainbow Effect
void theaterChaseRainbow(uint8_t wait) {
  uint16_t i,j,q;
  for (j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (q=0; q < 3; q++) {
      for (i=0; i+q < NUM_LEDS; i=i+3) {
        leds[i+q].setHue((i+j) % 255);    //turn every third pixel on
      }
      FastLED.show(); //Update all LEDs
      delay(55);  // controls the speed of the chase
      for (i=0; i+q < NUM_LEDS; i=i+3) {
        leds[i+q] = 0;        //turn every third pixel off
      }
    }
  }
}

 

White Strobe Code

The second animation I had to have in this project was something that could alert players when they won on a spin. I tried several different things including a Rainbow Color Wipe (too slow), a reverse ambient chase (not evident enough), a color flipflop from blue to green (just did not look right), as well as a few others. After several different animations, I settled on a simple white strobe. I chose this for a few different reasons, the first being that it is instantly recognizable as a WIN, and the second being that it was very easy to code, and control the length. The problem with some of the other animations I tried out were their length. For a color wipe, at a decent speed that looked good, the entire animation took more than thirty seconds. The strobe animation takes less than five seconds to complete. Below is an snippet of just the White Strobe code, and below that is the full Arduino-ready script to run this code.

 

White Strobe Function Snippet

void whitestrobe(int NUM_OF_CYCLES) {
  // Turn the LED on, then pause
  for (int j=0; j<NUM_OF_CYCLES; j++) {  
  fill_solid( &(leds[0]), NUM_LEDS /*number of leds*/, CRGB::White);
  FastLED.show();
  delay(20);
  // Now turn the LED off, then pause
  fill_solid( &(leds[0]), NUM_LEDS /*number of leds*/, CRGB::Black);
  FastLED.show();
  delay(50);
  }
}

 

Full White Strobe Code

#include "FastLED.h"

// How many leds in your strip?
#define NUM_LEDS 22
#define DATA_PIN 6
#define SLOW 250
#define MEDIUM 75

CRGB leds[NUM_LEDS];

void setup() {

  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

}

void loop(){
    whitestrobe(20);
}


void whitestrobe(int NUM_OF_CYCLES) {
  // Turn the LED on, then pause
  for (int j=0; j<NUM_OF_CYCLES; j++) {  
  fill_solid( &(leds[0]), NUM_LEDS /*number of leds*/, CRGB::White);
  FastLED.show();
  delay(20);
  // Now turn the LED off, then pause
  fill_solid( &(leds[0]), NUM_LEDS /*number of leds*/, CRGB::Black);
  FastLED.show();
  delay(50);
  }
}

 

 

Slight Issues With Raspberry Pi and NeoPixels

 

Almost every project I have ever built has had some form of an issue arise during its development phase, and as it turns out, this project is no different. In my initial planning phase for this project, I wanted to control the NeoPixel LEDs directly from the Raspberry Pi 3 itself. Unfortunately I forgot about the Pi’s audio channel being routed through pin 12 which is also the PWM pin on the Pi’s GPIO pins. This is a problem because the NeoPixel library for the Raspberry Pi uses this pin to send data to the WS2811 microcontroller that is embedded inside each NeoPixel LED. While I am not sure if this is an issue with just the audio jack, or if it affects the Bluetooth audio output as well, I have decided to control the NeoPixels with an Arduino Nano. This not only alleviates the issue with the PWM pin / Audio channel, it allows me more control over the NeoPixels, as well as being able to run several LED animations from a single source.

 

IMG_9605.jpg

 

Since I will be using an Arduino Nano to control the NeoPixel Strips, I have to have a way to trigger the different LED animations from the Raspberry Pi. There are several methods to do this, and after much consideration I have decided to have the slot machine software trigger the LEDs by setting a GPIO Pin on the Raspberry Pi to High. This high signal will carry over to a GPIO pin on the Arduino Nano, which will then run a predetermined LED animation. Those of you who read my Foginator 2000 project from last Halloween will remember that this is how I controlled the NeoPixels then as well. The only difference this time is that I will be using an external interrupt on the Arduino’s Digital Pin 3, which will trigger on the rising edge of the signal going high and then tell the Arduino to break from its currently running function, and to run another. If you want to know more about how interrupts work on the Arduino, Jeremy Blum (sciguy14) made an excellent video on them for Element14 a while back.

 

 

After talking to several engineer friends, this method seems to be the correct way to handle this situation after all. The Raspberry Pi is not really well suited to control devices that need real-time control. This is because Raspbian is a multitasking operating system, and thus real-time control is not possible. Since the WS2812B LEDs on the NeoPixel Strip require a very precise and timed signal, controlling them from a Raspberry Pi is hackery at best (not that hackery is a bad thing). As I mentioned, there is a NeoPixel library for the Raspberry Pi, and it converts a PWM signal into something that the WS2812B-based NeoPixels can use, but with this, you lose functionality of the Audio port, as it runs through the PWM pin. So naturally, the best way to add NeoPixels to a Raspberry Pi project, is to offload their control to a separate microcontroller. Below is a diagram of how I connected the Raspberry Pi to the Arduino Nano.

 

NeoPixel-Wiring-Diagram.jpg

 

With the circuit figured out, I created a small test board with some NeoPixel scraps I had laying around. I connected two breadboards together, and used one to lay out a square that is connected together as one strip, and another two independent strips. I also added in a female barrel jack pigtail so that I could provide proper power to the strips without overloading the Arduino Nano.

 

NeoPixel-Demo-Board.jpg

 

With the development setup built I was able to successfully able to combine the two Arduino scripts into a single script that allowed me to run the Ambient Chase animation when the game is powered up, and then quickly switch to the White Strobe animation when a win is detected. To do this, I attached an external interrupt to the Arduino Nano’s digital Pin 3, which is where the Atmega 328’s interrupt 1 is connected. Then all three NeoPixel strips were connected to the Arduino Nano’s digital pin 6. The full code is below.

 

Raspberry PySlots NeoPixel Code for Arduino

#include "FastLED.h"

#define NUM_LEDS 22
#define DATA_PIN 6
#define CLOCK_PIN 13
#define SLOW 250
#define MEDIUM 75

CRGB leds[NUM_LEDS];

void setup() {

  pinMode(3,INPUT);
  pinMode(3,LOW);
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);

  attachInterrupt (1,react,RISING);
}


void loop(){
    theaterChaseRainbow(50);
}

void react () {
  whitestrobe(20); // run the strobe function 
}

void whitestrobe(int NUM_OF_CYCLES) {
  // Turn the LED on, then pause
  for (int j=0; j<NUM_OF_CYCLES; j++) {  
  fill_solid( &(leds[0]), NUM_LEDS /*number of leds*/, CRGB::White);
  FastLED.show();
  delay(20);
  // Now turn the LED off, then pause
  fill_solid( &(leds[0]), NUM_LEDS /*number of leds*/, CRGB::Black);
  FastLED.show();
  delay(50);
  }
}

  //Theatre Chase Sytle Crawling Lights With Rainbow Effect
void theaterChaseRainbow(uint8_t wait) {
  uint16_t i,j,q;
  for (j=0; j < 256; j++) {     // cycle all 256 colors in the wheel
    for (q=0; q < 3; q++) {
      for (i=0; i+q < NUM_LEDS; i=i+3) {
        leds[i+q].setHue((i+j) % 255);    //turn every third pixel on
      }
      FastLED.show(); //Update all LEDs
      delay(55);  // controls the speed of the chase
      for (i=0; i+q < NUM_LEDS; i=i+3) {
        leds[i+q] = 0;        //turn every third pixel off
      }
    }
  }
}

 

 

 

In the video above you can see a demo of what I have working so far. During normal game play, the Arduino runs the Ambient Chase Function, then when a win is registered by the software, the Raspberry Pi triggers the White Strobe Function. I still need to work on the code to allow me to trigger the spin via a Tilt Switch, but that will have to wait until the next post. I simply ran out of time to figure out how to map a keyboard press to a GPIO Input Pin using PyGame, so if anyone has any suggestions there, please leave them in the comments. That is going to wrap up this post. I have one more post before the project is finished, so check back next week for the grand finale! Until then, Hack the World, and Make Awesome!

 

Check Out The Full Project!

  1. Raspberry PySlots: The Costume - Introduction
  2. Raspberry PySlots: The Costume - Hardware, Software, and Pretty Lights!
  3. Raspberry PySlots: The Costume - The Slot Machine, NeoPixels, Pull Arm, And Finishing Things Up

RaspberryPySlotsBanner.jpg

 

Enter e14's 2016 Costume Contest Here!

 

There are only a few holidays here in the US that I actually participate in, with Halloween being my favorite by far. Many of you reading this might remember my two projects from last year, Foginator2000 and Trick or Trivia. They were both fun projects to build, and I learned a lot over the two months it took to build them. This year Element14 has asked me to build another project for Halloween, specifically a costume. Over the past week I have spent a lot of time trying to come up with concepts that I can easily complete in three weeks, and I will be the first to admit that this was actually a lot tougher than it sounds, but I finally settled on something that I think will be pretty fun.

 

When Element14 first contacted me about doing this project, I actually tried to talk them into letting me build another Halloween prop this year instead of a costume. Building Halloween props is well within my comfort zone, and I even once co-owned a business that did just that, but this year they were firmly set on the idea of a costume based around the Raspberry Pi 3. I wanted to build this crazy spooky demon costume, but there was just not enough time or budget to pull it off, so I settled on something more comical: a walking, talking, digital slot machine.

 

I know what you are thinking, “This guy has to be the lamest costume builder ever,” and I would tend to agree with you, but before you break out the pitchforks and torches take a moment to hear me out. The purpose of this project is to showcase the Raspberry Pi 3, and its capabilities even in a mobile environment. I chose this idea because it will allow me to not only show off the Pi 3, but would give me the chance to use a Raspberry Pi 7-inch Touch Screen in another project. Finally, the major deciding factor was the fact that I basically have two weeks to get everything finished as shipping the hardware to me would take a full week. Additionally, I was able to find an open source slot machine game that was written in Python that would be easy to modify.

 

IMG_9123.jpg

 

Before we dive deeper into the concept of the project, let's take a few minutes and talk about the hardware that I have selected for this project. Below you will find the full bill of materials broken down into two sections. The first section is all of the hardware that can be purchased from Element14 / Newark.com, and the second list is all of the materials that I had to purchase separately. I will provide links to any items on the second list that can be purchased from Amazon.

 

Newark Part No.

Notes

Qty

Description

77Y652077Y6520

Raspberry Pi 3

1

RASPBERRY PI 3

77Y653477Y6534

SD Card

1

16GB NOOBS MICRO SD CARD

49Y171249Y1712

Touch Screen

1

Raspberry Pi 7-Inch Touchscreen

26Y844626Y8446

NeoPixel Strip

1

NeoPixel Strip 60 LED/meter 4 Meters

13T927513T9275

Arduino Nano

1

Arduino Nano 3.0

66W7510

Arcade Button

1

ADAFRUIT  Massive Arcade Button with LED - 100mm Blue

27T269227T2692

Tilt Switch

1

COMUS  CW1300-1  TILT/MOTION SENSOR

 

 

Amazon Product No.

Notes

Qty

Description

B00MBAZJUI

Bluetooth Speaker

1

Neon BTS220-37 Ultra-Portable Bluetooth Wireless Speaker

B007ZFXDLG

Felt Topper Hat
1Black Felt Top Magician Costume Hat

B00JP8MZGK

Power Bank
1KMASHI 15000mAh External Battery Power Bank

B015RLUAV0

Hookup Wire

1TronicsPros 4 Pin 4 Color 20m RGB Extension Cable

B005GYHQL6

Fabric

1Silver Metallic Stretch Spandex Fabric
B01KZFLSBOUSB Cables16-foot Amoner Micro USB Cable 3-pack

 

 

The Raspberry Pi 3 will serve as the brains of the costume, and will control all of the slot machine functions, the sound, and some of the lighting effects. However, the majority of the lighting effects will be controlled by an Arduino Nano. I made the decision to control the majority of the lighting effects with an Arduino simply because it is actually rather difficult (in my experience) to control more than one string of neopixel LEDs at a time with the Raspberry Pi, and as I wanted both an always on lighting scheme and an event triggered on a win in the slots, this was the best decision.

 

pyslotneo.jpg

 

Audio will be handled via a cheap Bluetooth speaker that I will cannibalize to make it fit somewhere on the costume. I am not yet sure if the speaker will be visible or hidden just yet. The speaker I picked up to cannibalize also features an auxiliary port, so if for some reason I can not get the Bluetooth connection to work, I can just plug in a 3.5mm audio cable and the audio will still be available.

 

IMG_9125.jpg

 

My left arm will serve as the pull handle that triggers the slot machine’s “spin,” and will utilize either a simple tilt switch, or a more complex accelerometer. I am not sure which I will use just yet, as it all comes down to reliability and repeatability. To sort of dress the costume up a little more, I have selected a shiny silver fabric to sew into a sleeve, which will conceal my arm, hand, and the tilt switch. (You can see a close up of this fabric below.) When someone wants to spin the slots, they simply have to pull my arm down. I am still toying with the idea on how to dress this up a little more to make it look more like a traditional pull lever, but I am not sure yet. Does anyone have any thoughts? The tophat is a sort of bonus project, that I will build if time allows. I plan on brightening it up with several strips of NeoPixels.

 

IMG_9126.jpg

 

As you can see, the fabric is about as shiny as fabric can get, and to top it off, it’s quite stretchy. I actually searched two hobby stores before visiting a fabric store where I found this. The most shocking thing I learned in that adventure is that fabric, especially specialty fabric, can be quite expensive. I got lucky and found this shiny fabric on sale for $15.00/yard, down from its regular price of $25/yard, and I had a 20% off my purchase coupon. So I think I paid about $12 for the yard I needed. I purchased this specific fabric at Joann Fabrics and it's SKU is 400106656512 if you would like to use the same fabric. Alternatively, I have linked to a similar spandex fabric in the Amazon list above, and it is actually a bit cheaper per yard.

 

IMG_9124.jpg

 

The rest of the costume will be built out of foam core project board that I picked up at the local dollar store for $0.89 per sheet. I am not sure how many sheets it will take right now, but I have 15 on hand. The plan is to build something similar to the mockup you see above this paragraph. I will be recessing the LED strips into the foam core’s first layer, then covering everything with custom designed artwork that I will have printed at staples. My thoughts behind this is that the light will diffuse into the paper some, and will make the bright 5050 LED modules less harsh. As of right now, I am still deciding on the best way to mount this facade to my body, but a friend who cosplays semi-professionally said that a shoulder rig made from PVC pipe will be my best bet, so if I go that route, I will update the BOM to reflect the additional parts.

 

pIsCREEN.jpg

 

The screen where all the action takes place will be an official Raspberry Pi 7-inch Touch Screen, which will be flush mounted with the surface of the foam board facade. I am not sure if I will have time to build any touch screen functionality into the slots program, but it may still be possible if time allows. Since the Pi Touch Screens feature a very thin bezel, and are quite wide, this makes mounting the screen with some 3M VHB tape very quick and easy. I wish the foundation would release a 10-inch or 12-inch screen, as a larger screen would have been ideal for this project, but I think the 7-inch will work out ok. I do have plans to continue this project in the coming months, but in a different direction, so I may pick up a cheap 19" HDMI TV or Monitor for that. The one thing I do like about this screen is that it is so easy to work with. I have used a few on several different projects both personally, and in my past haunted attraction automation business, and for projects like this, it is perfect as far as ease of use goes.

 

pyslots_Bfruit.jpg

 

 

As far as the software side of things goes, I will be building the slot-machine almost completely in Python. As I mentioned earlier, I am under a time crunch to get this completed before Halloween, and I knew that there would not be enough time to develop a slot-machine program from scratch, and luckily I found an open source slots program written in Python on Source Forge called BFruit. While it is not the most glamorous, or efficient slot-machine program out there, it will be very easy for me to modify to add lighting even triggers, and such. The best part is that since it is licensed under the GPL V2 licence, I am able to modify the code, and upload my own version as long as I credit the original creator. This means that once finished, you, the community, will be able to continue where I left off, and code in new and exciting features. Since the program is written in Python and not a compiled language, I am able to easily swap out the images too. I already have most of the new images figured out, but I wanted to let the community pick the last image. So leave me a comment below, and I will pick a few of the best, and then create a poll that you can vote on and place it in the next update.

 

 

PYSLOT_POWERBANK.jpg

 

Now you have to be asking yourself how in the world am I going to be able to power a Raspberry Pi 3, 7-inch Touchscreen, and all of these power hungry Neopixels? The answer is actually quite simple. I will be using a high-capacity USB power banks that is capable of 2A of output at 5V each on at least one port. I will also create a USB pigtail to add power to the Neopixels, but if this single power bank is not enough, I have two more on hand to help out. I plan on wearing a backpack when taking the costume to a party, and that is why I ordered the 6-foot long USB cables. I should have about two feet to spare, giving me enough room to twist some without the cable getting tight. All in all, by my estimate, the project will consume about three amps, which is what this power bank is capable of producing. If this proved to be true, this single power bank should have enough power for two or more hours of use. This is plenty of time to show the costume off at a Halloween Party, or for trick or treating. If that turns out not to be the case, I have two more that I can utilize.

 

Thanks for taking the time to read this post. I will have two more posts with updates on this project, with things wrapping up before Halloween. At the time of this article's publication I am still awaiting on several components to the project, and I expect some to not arrive until late next week, so I would estimate my next update to go live sometime around the 14th of October, with the final update coming a week later. So stay tuned for the hardware portion of the build next! Until then, I will continue to post my weekly Design Challenge summaries (just project summaries until the next Design Challenge kicks off). As always, remember to Hack The World, and Make Awesome!

 

Check Out The Full Project!

  1. Raspberry PySlots: The Costume - Introduction
  2. Raspberry PySlots: The Costume - Hardware, Software, and Pretty Lights!
  3. Raspberry PySlots: The Costume - The Slot Machine, NeoPixels, Pull Arm, And Finishing Things Up

Trick-or-Trivia-Banner-006.jpg

 

Welcome back to the Trick or Trivia Blog. In this installment, I will show off how I built the candy dispenser that will set beside the tombstone. Unfortunately this part of the project did not turn out as I had planned because I could not find the type of bowls I was looking for. I did managed to cobble something together that works, and I will be able to build a better version for next Halloween.

 

My original idea was to use faux concrete flower urns that typically can be found beside tombstones. I got the idea from some flower vases I saw at the local Hobby Lobby back in July, but was unable to find them again at any store I visited. So I improvised and bought two cheap Halloween Candy bowls, and hacked them into something that would work. While this is not the most refined solution, it worked well in the end.

 

The Hardware and Tools Needed

 

 

Below you will see a list of the hardware and tools used to build the candy dish that catches the dispensed candy.

 

  • Two large bowls of similar size
  • 15-20 Sticks of Hot Glue
  • Hot Glue Gun
  • 6”x6” Square of Plywood
  • Knife or Scribe
  • Shims Made from Scrap Cardboard.

 

 

Installing The Touchscreen

 

Before we get started on the candy dispenser, I wanted to quickly show you how I installed the touch screen into the Tombstone. I spent a lot of time mulling over how to mount the screen, and after several different mockups, I decided on just using hot glue to secure it. Unfortunately during the time I moved to my new home, and the time I began working on this (a week later) I found that the Raspberry Pi Screen had cracked after a heavy box had been stacked on top of the box the screen was wrapped up in. So I had to order a new screen and wait on it to arrive.

 

TorT-006-(1).jpg

You might remember that when I carved out the tombstone, I left a square patch near the top, fairly blank. This is the place where I cutting out the recess for the screen.

 

TorT-006-(2).jpg

To get started I transferred the screen’s metal housing dimensions to a piece of scrap cardboard. I then cut out the waste cardboard, and checked the screen for fitment.

 

TorT-006-(4).jpg

As you can see, the screen fit perfectly inside the template.

 

TorT-006-(3).jpg

The next step is to cover the flat part on the tombstone with painters tape. This will give us somewhere to trace out the rectangle we need to remove.

 

TorT-006-(5).jpg

After eyeballing the placement, I traced the rectangle onto the painters tape. I tried to keep this as centered as possible, but in the end it was off a little, but no big deal as it is a 100+ year old digital tombstone!

 

TorT-006-(6).jpg

Next I use a razor knife to trim the excess tape away. This gives me a clean line to follow when cutting out the foam.

 

TorT-006-(7).jpg

Using a cheap box cutter I was able to remove the foam rectangle with little trouble. If I had to do this again, I would have used a jig saw to cut this out as the cut would have been easier.

 

TorT-006-(8).jpg

Finally, a shot from the back showing how I used hot glue to secure the screen in. I am withholding the shot of the screen installed from the front until the next installment of this series.

 

 

Building the Candy Dispensing System.

 

 

The heart and soul of this project was the touch screen, but we can not forget the reward that we owe the children who visit us on Halloween night. When I originally prototyped the candy dispensing system, I had a plan in mind that would utilize a faux flower urn and smaller candle dish to hide the dispenser. The Dispenser was planned around that urn, and its dimensions. Unfortunately I was unable to find that style flower urn for sale when the time came to buy it despite several being on the shelves of Hobby lobby just days before. I would not let that stop me though, and I improvised with two large candy bowls from the dollar store.

 

TorT-006-(9).jpg

To get started, I needed to find a suitable piece of scrap wood. Fortunately I found this piece of ⅜” thick hardboard laying around from an old cheap book shelf we had planned to throw away. I cut a suitable sized piece off and heated up my glue gun.

 

TorT-006-(10).jpg

While the glue gun was heating, I mocked the dispenser hopper up, and found some scrap foam to use as a shim to set it at an angle. You can use cardboard or even dry hot glue to raise the back of the hopper up.

 

TorT-006-(11).jpg

With the angle set, I used a knife to trace an outline of the foam so I could remove the paper covering. I did this because I know from past experiences that hot glue does not stick to this surface very well.

 

TorT-006-(12).jpg

Then I simply cut through the black paper layer, and used my knife to rough it up a little for better glue adhesion.

 

TorT-006-(13).jpg

I then added hot glue to the roughed up surface. The glue sticks I am using are considered “High Temp” meaning they melt around 350f, and honestly they were a little too hot for the foam I used, but they are all I had. In retrospect, I should have used “Low Temp” glue sticks.

 

TorT-006-(14).jpg

I then placed the foam on top of the glue. One of the bad things about using “High Temp” glue sticks is that you will get burnt instantly if any squeezes out the sides and comes in contact with your finger. This is much less of an issue with “Low Temp” glue sticks. I buy these sticks by the 25lb box, so I have an abundance of them.

 

TorT-006-(15).jpg

Next I glued the smaller foam strip down. This part was tricky as the high temp sticks are hot enough to melt this foam. I let the glue gun cool down some before applying any glue.

 

TorT-006-(17).jpg

For the next part, I managed to find a low temp glue stick in my Girlfriend’s craft room. I knew I would melt the foam with the high temp sticks. I should have removed the black paper here as well but I got into a rush and forgot to cut it out until it was too late.

 

TorT-006-(18).jpg

Finally I glued everything down and held pressure on it until the glue cooled. It looks very messy here, but I did clean it up a bit.

 

TorT-006-(19).jpg

With the hopper secured in place, I was able to mock up the servo placement. It took a few tries, but I finally managed to get the edge of the board trimmed down enough so that the plunger was able to travel enough to eject the candy.

 

TorT-006-(20).jpg

With the optimal placement found, I used my used my knife to carve out a hole that the servo could fit inside. Then I used hot glue to secure things.

 

TorT-006-(30).jpg

With the candy dispenser assembly completed I moved on to modifying two bowls. Basically I cut a relief into the bottom of the black bowl, and a similar relief into a side on top of the other bowl. I then used about 20 glue sticks to secure everything together.

 

TorT-006-(21).jpg

I am not going into much detail on this bowl design on purpose as I feel that the odds of someone finding similar bowls is slim to none, and there is surely a better way to do this. Here you can see that I have placed the glue about one inch up on the purple bowl and let it “flow” onto the black bowl about an inch as well. I did the same on the inside.

 

TorT-006-(25).jpg

Here you can see how I layered the glue on the inside of the two bowls.

 

TorT-006-(26).jpg

One more shot of the inside. You can almost make out the candy hopper.

 

TorT-006-(30).jpg

And a final shot of the bowls pared together. You can see the hopper in the big bowl, and the candy feeds into the smaller bowl. Both of these will be perched on a stand beside the tombstone and the black bowl will have a jack-o-lantern cover as to hide the dispenser.

 

That is going to wrap this installment of Project: Trick or Trivia. Check back in a few days for the next installment, where we bring everything together, and demo the system working. Until then, remember to Hack The World, and Make Awesome!

Foginator-Banner-007.jpg

 

Welcome back to Project: Foginator 20000! In this installment we are going begin wrapping the build up by moving everything from  the breadboard, to a prototyping PCB, and then placing it all into an enclosure. Then we will wrap everything up with a demonstration of the final code. There will be one more installment after this one, which will include actual data from Halloween night. I will also finalize the bill of materials in the final post as well.

 

 

The Parts

 

The only special parts we are using tonight is a piece of prototyping board, and a project enclosure. You will need something to cut holes into the project box. I used a dremel multitool with a cutoff wheel, drill bits, and some hand files to accomplish this. You will also need a hot glue gun, to secure the PCBs and the motion sensor.

 

MCM Part No.

Notes

Qty

Manufacturer / Description

21-16075

Prototyping Board

1

Circuit Board - 750 Holes

21-15178

Project Enclosure

1

ABS Case Gray - 5-5/8" x 3-1/8" x 1-3/16"

 

 

 

The Build

 

20151022_141353.jpg

 

To get started let’s look at how the project box is laid out internally. Idealy, a 5” thick box would be used so that the Raspberry PI and Sense Hat could be placed in the enclosure as well. Unfortunately I was unable to find one large enough at Newark or MCM Electronics. So we are going to use this enclosure that is just large enough to house the rest of the electronics.

 

20151022_141435.jpg

 

The inside of the project enclosure has several standoffs on one side, and just the enclosures screw standoffs on the other. I am going to use the clean side as the bottom of the box since none of my boards will align with the mounting standoffs on the other side.

 

20151022_141932.jpg

 

This is the main portion of what we need to move to a prototyping PCB. The Arduino Nano, a pulldown resistor, and the LED cable connections.

 

20151022_142047.jpg

 

I am again using a Protostack protoboard as I have several laying around. You can use any prototyping board you would like though. I chose to only solder the pins that I was using as well as the 5V and GND pins.

 

20151022_143613.jpg

 

Here you can see that I used jumper wires to connect the GND and 5V lines on the Arduino Nano to the GND and VCC rails on the prototyping board. That is why I love these little boards from Prototstack. They are laid out like a breadboard, with five of the holes connected, and the power rails encircling everything.

 

20151022_144936.jpg

 

With the power connections made, I soldered in the Neopixel strip. I am not a fan of the microphone cable I used for the connection when soldering to these boards. Their holes are designed for smaller through hole pins, but with a little finesse it fits well. You will notice that I did not solder in the Neopixel ring. I think I killed it on accident, as I could not get it to light up at all.

 

20151022_190944.jpg

 

Here you can see the basic layout . Notice I notched both the Arduino protoboard and the 5V power supply board. I forgot to take pics of this process, but I used a hacksaw blade to cut them. A dremel would work too but it produces a lot of glass fiber dust that is very bad to breath. The relay sits on the right, and the PIR sensor will be placed in the top cover through a hole.

 

20151022_210930.jpg

 

This enclosure needs several holes for the wiring to exit. Here you can see some of them laid out. I used a dremel tool, a drill and drill bit, and some hand files to create and clean up these holes.

 

20151022_211726.jpg

 

Here’s the hole roughed out for the PIR sensor. It is important to get the sensor mounting flush with the top of the case for space concerns inside.

 

20151022_211726.jpg

 

Once everything is fitting nice and tight, I used hot glue to secure the PIR sensor to the case. Note that I hot glued the jumper wires to the pins as well. This prevents them from pulling loose later.

 

20151022_212703.jpg

 

Here you can see everything glued into place, and the power wire ran to the power supply. Not pictured is the dobs of glue that I used to hold all the wires that exit the case in place.

 

20151022_215504.jpg

 

While it is not the most discrete motion sensing project enclosure ever made, it sure does look good once everything is closed up nice and tight.

 

20151022_215757.jpg

 

Thinking ahead in case I ever wanted to reprogram the Arduino, I cut a slot that would allow me to plug in a USB cable. I made the slot oversize as the USB cables I like to keep handy, have a bit of a thicker encasement around the tip.

 

20151022_215820.jpg

 

Unfortunately I was unable to fit the Raspberry Pi and Sense Hat inside this project enclosure as I had planned. I needed to keep the stack close to the peripheral boards, so I simply hot glued it to the back of the enclosure.

 

20151022_220103.jpg

 

And a final shot of everything connected and ready to go! Note that the Raspberry Pi has been reoriented in this image. I forgot about the audio cable, and the original way I mounted it would not allow for it to be plugged in and the enclosure still be able to sit upright.

 

20151023_123342.jpg

 

Due to a lack of time, I simply chose to mount the project enclosure on top of the fog machine using some velcro and hot glue. While this is not ideal, it does work quite well.

 

20151030_162624.jpg

 

Looking at it from the back, you can see how starved for space this project is. Note the speaker. I found that for small things, blue tape on the fog machine’s surface helps hold the hot glue better.

 

20151030_162637.jpg

 

Looking at the back you can see how I mounted the audio amplifier and the fog machine remote switch. Again, blue tape came in handy here to help the hot glue stick better.

 

20151030_162722.jpg

 

The Final Code

 

 

I have merged all of the code together and added in some print lines that help troubleshooting any issues. To record the data, you will need to sign up for an Initial State account, and then generate a new API key for your account. You can download this code from its Github Repository which can be found here.

 

 

__author__ = 'Charles Gantt'
# This code is part of the Foginator 2000 project developed for the Halloween15 Raspberry Pi Project event at Element14.com and can be found at http://bit.ly/foginator2000


import RPi.GPIO as GPIO
import time
import sys
from sense_hat import SenseHat
from ISStreamer.Streamer import Streamer


logger = Streamer(bucket_name="Foginator2000_Data_10/23/2015", access_key="zLahwAUqKbNKv6YvuT5JuO58EiUOavDa")


sense = SenseHat()
sense.clear()
sensing = True
fog_Armed = True




GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(17, GPIO.IN)
GPIO.setup(21, GPIO.OUT)


O = (0, 255, 0) # Green
X = (0, 0, 0) # Black


creeper_pixels = [
    O, O, O, O, O, O, O, O,
    O, O, O, O, O, O, O, O,
    O, X, X, O, O, X, X, O,
    O, X, X, O, O, X, X, O,
    O, O, O, X, X, O, O, O,
    O, O, X, X, X, X, O, O,
    O, O, X, X, X, X, O, O,
    O, O, X, O, O, X, O, O
]


black_pixels = [
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X
]


var = 0


def is_integration():
  while sensing == True:
        print "IS Start"
        temp = sense.get_temperature()
        temp = round(temp, 1)
        logger.log("Teperature C",temp)
        print "T1"
        humidity = sense.get_humidity()
        humidity = round(humidity, 1)
        logger.log("Humidity :",humidity)
        print "H1"
        pressure = sense.get_pressure()
        pressure = round(pressure, 1)
        logger.log("Pressure:",pressure)
        print "P1"
        logger.log("Trick Or Treat Event #",var)
        print "ToT Event Logged"
        sense.set_pixels(creeper_pixels)
        time.sleep(2)
        sense.set_pixels(black_pixels)
        sense.clear()
        print "IS Done"
        break


def fire_fog():
    while fog_Armed == True:
        print "Trick or Treat Event Sensed"
        print "Lights Start"
        GPIO.output(21,True)
        time.sleep(2)
        print "Relay Triggered"
        GPIO.output(4,True)
        time.sleep(10)
        print "Relay Disabled"
        GPIO.output(4,False)
        time.sleep(20)
        print "Lights Disabled"
        GPIO.output(21,False)
        is_integration()
        print "Trick or Treat Event Finished"
        time.sleep(10)
        print "Watching For Motion"
        break


while True:
    time.sleep(3)
    if GPIO.input(17)==True:
        var = var +1
        print ("var =", var)
        print "Motion Detected"
        fire_fog()
        

 

This code has been modified to run continuously while always looking for a motion trigger. To make this code run when you plug the Raspberry Pi in, you will need to set the python script to run on startup via the cron tab.

 

 

The Data

 

 

To recap, we are using the Sense Hat to record a few environmental data points including air temperature, humidity and air pressure. The Raspberry Pi then pushes that data to a remote server at Initial State, which then processes it, and displays it in nice graphs, and other visualizations. I have also added a fourth metric called “Trick or Treat Event” that simply increments by one every time a motion event is detected.  As you can see in the image below, everything seems to be working perfectly. You can check out the full stream here.

 

2015-10-30-02_08_07-New-notification.jpg

 

In the video below, you can see me walking into the room, and the sensor tripping when the fog fires. If I have some free time on Halloween before the Trick or Treaters arrive, I am going to add in another meter or so of Neopixel strips to increase the illumination.

 

 

That is going to wrap up this installment. I will be back in just a few days with a complete wrap up of this whole project and the results from Halloween night!

 

 

Win this Kit and Build-A-Long

 

  1. Project Introduction
  2. Fog Controller Hardware and Test
  3. Environment Sensing Coding & Testing
  4. Ambient Audio Hardware and Coding
  5. Lighting Coding and Testing
  6. Final Assembly and Testing

Trick-or-Trivia-Banner005.jpg

 

Welcome back to the Trick or Trivia Blog. In this installment, I am going to lightly document the process I used to build the faux tombstone that will be used to hold the Raspberry Pi 7-inch touchscreen. My original plan was to buy a 5-foot tall Frankenstein statue, or some other tall halloween figure. Unfortunately I was unable to find anything locally that fit within my budget of $100 for this segment. After talking to a few friends, and watching several videos on YouTube, I decided to just build my tombstone from 1-inch thick construction foam insulation.

 

During the planning of this project, I realized I needed to make the tombstone thicker than 1-inch as the foam is quite weak. This led me to search for 2-inch thick foam, and while it exist, it seems to not be sold anywhere in South Carolina. In the end, I wish I would have been able to find the 2-inch thick foam as gluing the sheets together proved to take a lot longer than I anticipated. However, the end result was still quite amazing, and I find myself still wondering how I managed to pull off such a realistic looking tombstone.

 

 

The Hardware and Tools Needed

 

20151015_134523_HDR.jpg

 

Below you will see a list of the hardware and tools used to build the tombstone that we will use to hold our 7-inch touchscreen. All of these tools and materials can be purchased at your local home improvement store, and most can even be found online. The only thing that is brand specific is the Glidden Gripper primer that is used as a glue. This primer / sealer is what many foam tombstone builders use to glue their models together as it is cheap, dries without exposure to air, and it carves easily.

 

    • Glidden Gripper Primer / Sealer (Used as glue to glue the foam together.
    • Stone Grey Latex Paint
    • Black Latex Paint
    • 2oz acrylic craft paint White
    • 2oz acrylic craft paint OD Green
    • 2oz acrylic craft paint  Desert Tan
    • Acrylic Caulking
    • Great Stuff Foam In A Can
    • 1-inch Closed Cell Insulation Foam sheet. 4’x8’
    • Xacto  / Hobby Knife
    • Jigsaw with 2” 32TPI blade or 32TPI Hacksaw blade
    • 2x 2-inch Chip Brushes
    • Old Soldering Iron or Wood Burning Iron Kit
    • Popsicle Sticks or Wooden BBQ Skewers
    • 5-inch Prop Skull
    • 1-meter straight-edge
    • Curve Ruler
    • Compass / Circle Ruler
    • Fine Point Sharpie
    • Acetone / Acetone-based fingernail polish remover
    • Hot Glue Gun
    • Stanley Sureform Foam Shaping Rasp

 

 

The Design

 

ToTRender.jpg

 

I chose to go with a mix between a traditional tombstone, and something you might find in a classic B-grade horror flick. After quickly scratching out a general outline on a piece of paper, I sat down in Sketchup and modeled what the tombstone would look like. As you can see, it borrows from traditional, gothic, and horror-movie tombstone designs. The overall height is about 5.5-feet, and places the touchscreen at a height that most children can easily access it.

 

ToTlayout.jpg

 

This design fits entirely from one 4’x8’x1” sheet of pink / green / blue insulation foam from any big-box home improvement store. I do suggest gluing the two main tombstone pieces together before hand and cutting them out once they are dry.

 

ToTDem.jpg

 

You can download the Sketchup design file for this project which includes 3D models of the finished tombstone, layouts with dimensions, etc, from here. Use this file to get the dimensions you will need for each piece. I simply printed out each design on a normal sheet of paper, and used them to layout each part onto the foam.

 

 

The Build

 

 

IMG_9829.jpg

 

I like to start all of my projects by laying out any tools, components and materials neatly so that I can quickly and easily access them when needed.

 

IMG_9831.jpg

 

With all of the tools and materials laid out, I decided that the easiest thing to do would be to cut the large foam sheet into halves, and then half one of the halves again. This would give me two 2-foot by 4-foot pieces which I could then glue together and set aside while the glue dries.

 

IMG_9836.jpg

 

I do not have a photo of the actual glue application process as it was fairly warm outside, and the Glidden Gripper was drying almost instantly. The basic method I used is exactly the same as you would use when painting a wall. Use a small roller brush to apply a very liberal coat of the Gripper onto one side of one of the sheets of foam. Then place the other sheet on top of the freshly “painted” surface. Align things so that at least two edges align at a right angle.

 

IMG_9837.jpg

 

I knew I would need a way to index the two sheets of foam together, and after searching for toothpicks for about half an hour, I found some craft sticks that would work just fine if I cut a point onto them with my hobby knife. Place one of these sticks in each corner of the foam sheets, and push down until you are sure that both layers have been penetrated.

 

Now set the laminated foam sheets to the side, placing heavy objects on top of them. This will help apply enough pressure so that the sheets get a good bond when the Glidden Gripper dries. I used two drink coolers filled with water, which applied about 200lbs of pressure.

 

20151015_140540_HDR.jpg

 

With the two large pieces drying, let’s move onto cutting out the base of the tombstone. We will need to glue it together as well. As I mentioned earlier, I printed out the design files for each element of this build, and I used a yardstick to transfer the dimensions over.

 

IMG_9843.jpg

 

It is important to remember to pull your measurements from one of the factory-square edges. This will ensure that everything aligns nice and square in the end.

 

IMG_9842.jpg

 

Here you can see one of the major issues with construction insulation foam. It’s built on a tongue and groove design that greatly speeds up installation, and improves its efficiency. This groove is problematic if you plan on using the full 4-foot dimensions of the sheet though. I simply chose to place this piece facing the back so that it is not seen.

 

20151015_155821_HDR.jpg

 

With all of the pieces cut out, I dry-stacked them to test for proper fit. As you can see, the foam warped a little, but since this is supposed to be a 100+ year old tombstone, I am ok with the less-than-perfect look. Before I glue things up though, I need to rough the edges up a little so that they look like they have been exposed to the elements for the last century.

 

20151015_161632_HDR.jpg

 

To rough the edges I used the Stanely Shureform Foam Rasp. I practiced on a scrap piece of foam and found a stroke that would not rip the foam, but shave it. After about 10-minutes I was quite pleased with the results.

 

20151015_162340_HDR.jpg

 

Now it’s time to glue the base layers together. Again using a liberal coating of Glidden Gripper, I  coated each layer, then stacked them together using sharpened popsicle sticks to hold the alignment. Just like the two larger pieces, place this to the side and stack something heavy on top to ensure a proper bond while the glue dries.

 

20151015_165649_HDR.jpg

 

With the base out of the way, it’s time to get to work on the cross that will adorn the top of the tombstone. I began transferring the design over, and used a curve ruler to get the clean lines the base of the cross calls for.

 

20151015_171943_HDR.jpg

 

As you can see, I goofed my layout a little, but caught the mistake before cutting anything out. Remember to measure once, and cut twice! I used the blue ruler off to the right to draw the circle. I bought it on amazon years ago, and this was the first time I ever used it. I like it because it allows you to quickly draw a circle of any size up to 12” diameter.

 

20151015_175600_HDR.jpg

 

I used a hacksaw blade and hobby knife to cut the cross out. In hindsight I should have used my jigsaw as it would have turned this 25-minute task into a three-minute job. Here you can see that I have already roughed the edges with the rasp, and shaped the cross a little. Now it’s time to add some faux cracks and surface blemishes.

 

20151015_181411_HDR.jpg

 

Using a wood-burning tool, and the rasp, I added several cracks and surface blemishes to the cross. This was actually pretty fun, and I was able to really add some fine detail with the conical tip on the wood-burning tool. The surface blemishes were created by pressing the rasp into the surface and twisting it from side to side while pushing up or down at the same time.

 

20151015_181959_HDR.jpg

 

I started painting the cross with the stone grey paint. The surface blemishes along with the cracks proved to make this process a little more difficult as the paint had to be “pushed” into the small crevices. I found that the best method was to sort of stab the paintbrush into the cracks, and “wiggle” it on the surface blemishes.

 

20151015_183747_HDR.jpg

 

With the cross painted, I sat it aside and let it dry for about 12 hours before applying a second coat. One thing to be aware of is that latex paint will not dry if the humidity is too high, and if any dew falls on the paint before it dries, the paint will stay wet.

 

I let the cross, the base, and the main tombstone body dry overnight, and well into the next day. I would estimate that things dried for about 14 hours, and unfortunately the Glidden Gripper had not fully dried by the time I got around to laying out the tombstone body. In hindsight, I would much prefer using something like a non-solvent based contact cement to glue the two sheets together. Glidden Gripper is pretty common for gluing foam together, but in general, you should wait about 48-72 hours before it is fully cured.

 

I was highly frustrated at this point and I forgot to take photos of the tombstone’s layout on the uncut laminated foam sheet. I used the same method to lay it out as I did everything else. I also cut it out using a jigsaw this time as two sheets proved to be a little too difficult to cut with a hacksaw blade by hand.

 

20151016_184737_HDR.jpg

 

I then lined the edges with blue painters tape, masking off between 1.5 and 2-inches. This was part of a failed experiment to use acetone to melt a significant portion of the surface which would create a relief cut look. As I later found out, new insulation foam like this is coated in a solvent-resistive film that prevents things like construction adhesives, spray-paint and other solvent laced things from eating it away. The big blank spot at the top is where the LCD will mount.

 

20151016_193110_HDR.jpg

 

Again being frustrated, I failed to take photos of the next process. I decided to use my plunge router to remove the first ¼-inch of the surface where I wanted the acetone to etch away. Unfortunately, even pure acetone had a hard time etching the majority of the surface, but I did notice that large puddles would eat away portions of the foam, leaving these cool craters behind. So with this new found knowledge I dripped puddles of acetone onto the surface and used the rasp to speed up the chemical reaction by etching where I wanted the craters. As you can see, it gave the tombstone a really cool, aged look. I did make sure to hose the tombstone down to help nullify any remaining acetone residue that might have been hiding.

 

20151017_132633_HDR.jpg

 

The next morning I set up the wood burning tool again and began creating more faux cracks into the surface of the tombstone. I also took the tool and used it to define the line between the letters, edges, and LCD mounting spot. This made the inside portion really stand out. While it’s not pictured here, I also used the rasp to create more surface blemishes to tie in the tombstone body to the cross.

 

Before I get to the next part, I want to show you how I prepped the small 5-inch prop skull to be mounted onto the tombstone.

 

20151012_142410_HDR.jpg

 

The skull was purchased at Target for about $3, and was the perfect size for a tombstone of this size. I wanted a foam skull, but unfortunately almost every skull you find in the USA is blow-molded.

 

20151012_142824_HDR.jpg

 

Since I needed a way to firmly attach the skull to the tombstone, I decided to fill it with Great Stuff foam in a can. To allow the foam to expand (it expands by 3-4 times the volume used) I cut the back of the skull off, and then created a 1.5” dam with masking tape. This would ensure that the foam rose high enough above the cut line that I could get a good flat cut later on.

 

20151012_142836_HDR.jpg

 

Since the skulls jaw is moveable, I taped it shut in the event that the great stuff foam glued it into place.

 

20151012_143013_HDR.jpg

 

I then taped the skull to the railing on my homes back deck. This allowed me to use both hands when filling it with foam. In hindsight I should have wrapped this rail in plastic from a trash bag or something. I got lucky and no foam dripped off, but it could have turned into a disaster. Great Stuff literally sticks to anything and everything, and is almost impossible to remove.

 

20151013_173651_HDR.jpg

 

Here you can see the foam expanded. I only filled the skull about half way with the wet foam, and once dry, it was significantly larger in volume. I mistakenly thought that it was fully cured here, and cut the top off at the tape line.

 

20151013_173814_HDR.jpg

 

What I did not know was that the foam inside that had not been exposed to air was still liquid. After I took this photo I laid the skull in a box and to my surprise it had expanded more overnight and the foam had squirted out of any crack it could find. This process repeated itself three times. I later found out that I could have layered in wet paper towel strips every inch or so of foam. this would allow moisture to wick in and help cure the foam faster.

 

2015-10-21-19_38_35-New-notification.jpg

 

With the foam skull finally cured, I traced its outline onto the tombstone, and used my router to “hog out” the material by about ¾-inch deep.

 

2015-10-21-19_39_10-New-notification.jpg

 

Then I used a low-temp hot glue gun to secure the skull to the tombstone. I used this method because when I tried a few other glues, they did not seem to stick well to the Great Stuff foam as it was very porous. Hot glue worked great, and dried almost instantly.

 

2015-10-21-19_39_51-New-notification.jpg

 

With the skull recessed about ¾-inch into the surface of the tombstone, I used a latex / silicone blend caulking to seal the edges and give it a nice transition to make it appear as if it is part of the stone.

 

2015-10-21-19_40_38-New-notification.jpg

 

With the skull in place, I could finally begin painting the whole tombstone. Just like the cross, painting in the cracks and surface blemishes proved to be a tough task. I spent two hours making sure that everything was properly coated, and that no pink from the foam was showing.

 

20151017_154342_HDR.jpg

 

I apologize for not getting any good shots of the painting process, but it was getting late and I was in a hurry to beat the fast-setting sun. The image above was taken after two coats had been applied, and let dry for about 24 hours.

 

20151015_184813_HDR.jpg

 

Now it’s time to paint the base. Much like the tombstone and cross, getting paint into this rough surface was challenging, but after about an hour and two coats later, I managed to get everything covered.

 

20151015_185617_HDR.jpg

 

One important thing to mention is that when painting rough surfaces like this, it is paramount that you rotate the piece and check it from every angle. Even after two coats, I still found a few tiny pink spots that I missed.

 

20151018_144133.jpg

 

Once again, I do not have any photos of the finishing process. I took about 30 photos of the dry and wet brushing techniques my Girlfriend and myself used to detail the tombstone, but for some reason I lost all 30 of them and four videos I had recorded as well. There are dozens of videos on YouTube and thousands of tutorials on the web that detail these techniques though, so if you are interested in these processes, search for “dry brush technique” and “wet brushing” or “paint washing technique” on YouTube.

 

Building this tombstone took way more time than I thought it would. All in all, I think I have about 14 hours into its design and construction, and about $140 in materials, tools, and other things I bought for it. While my budget was only $100, I feel that $140 is a fair number since I got some tools, and enough paint to do another 1-2 of these. The biggest thing is the time it took be to build it. Including the waiting times for things like glue and paint to dry, the project took about 4.5 days to complete, which put me way behind on its posting schedule.

 

That is going to wrap this installment of Project: Trick or Trivia. Check back in a few days for the next installment, where we finally mate the screen to the tombstone, and permanently mount the candy dispenser mechanism. Until then, remember to Hack The World, and Make Awesome!

 

Win this Kit and Build-A-Long

 

  1. Project Introduction

  2. Building The Trivia Interface

  3. Interfacing Ambient and Triggered Audio Events
  4. Building The Candy Dispenser & Servo Coding
  5. Carve Foam Tombstone
  6. October 24th -  Assembly and Testing
  7. October 28th - Project Wrap-up

Foginator-Banner-005.jpg

 

Welcome to installment #005 of Project: Foginator 2000, part of the 2015 Raspberry Pi Halloween Project series here at Element14. In this week's episode I am going to demonstrate how to get Neopixel (WS2812B) LED modules working with the Raspberry Pi 2. Unfortunately as you will see, this is an almost impossible task as the previously working library is only compatible with Raspberry Pi versions up to the Model B+.

 

Below is a table containing the parts you will need for this segment of the project. In addition to these parts you will need to connect the Raspberry Pi to the internet either via a wifi dongle, or a wired Ethernet connection. You will also need three colors of stranded hook-up wire, a soldering station, solder, and some 0.100 male header pins.

 

Newark Part No.

Notes

Qty

Manufacturer / Description

38Y646738Y6467

RPi

1

RASPBERRY PI 2, MODEL B

38Y647038Y6470

SD Card

1

RASPBERRY PI 8GB NOOBS MICRO SD CARD

44W493244W4932

PSU

1

USB PORT POWER SUPPLY 5V, 1A

06W104906W1049

USB Cable

1

USB A PLUG TO MICRO USB B PLUG

53W628553W6285

WiFi Dongle

1

USB WIFI MODULE

26Y845826Y8458

Fog Coloring Rings

1

NEOPIXEL RING - 16 X WS2812

26Y846026Y8460

Mood LEDs

1

NEOPIXEL DIGITAL RGB 1M 144LED BLACK

34C109234C1092

PSU Vreg

1

LM7805 LINEAR VOLTAGE REGULATOR, 5V, TO-220-3

58K379658K3796

PSU LED Resistor

1

METAL FILM RESISTOR, 1KOHM, 250mW, 1%

17F216517F2165

PSU Filter Cap

1

CERAMIC CAPACITOR 0.1UF, 50V, X7R, 20%

69K794969K7949

PSU Filter Cap

1

ELECTROLYTIC CAPACITOR 47UF, 50V, 20%

69K790769K7907

PSU Filter Cap

1

ELECTROLYTIC CAPACITOR 100UF, 50V, 20%

14N941814N9418

PSU LED

1

LED, RED, T-1 3/4 (5MM), 2.8MCD, 650NM

49Y756949Y7569RPi Sense Hat1Raspberry Pi Sense HAT
13T927513T9275Arduino Nano1Arduino Nano V3
38K032838K032810k Resistor1Multicomp 10k Resistor

 

 

The Theory

 

 

1138-00.jpg

Neopixel’s are the brand name for the popular WS2812B individually addressable RGB LED modules, and are marketed and sold by Adafruit here at Element14. You can find WS2812B strips, rings, sticks, and individual modules on various electronic retail outlets as well, but for the purpose of this project, I will be using genuine Neopixel strips and rings from Adafruit.

 

The NeoPixel line is the latest advance in the quest for a simple, scalable and affordable full-color LED. Red, green and blue LEDs are integrated alongside a driver chip into a tiny surface-mount package controlled through a single wire. They can be used individually, chained into longer strings or assembled into still more interesting form-factors.

 

leds_neo-closeup.jpg

As you can see, each Neopixel contains a small microcontroller built into each LED module, with control wires emanating to each LED die. Neopixels use a single-wire protocol making them easy to integrate into any project without consuming valuable GPIO resources. Neopixels pass data along to the next module in-line, and can be individually controlled in single module,strip and matrix form factors.

 

Unfortunately, Neopixels require very strict timings, and this causes a lot of headache when attempting to control them from something like a Raspberry Pi, as it’s GPIO pins are software based, and not hardware based like those of an Arduino. Raspberry Pi models up to the B+ were able to skirt around this limitation thanks to the excellent rpi_ws281x library created by Jeremy Garff, but as I recently found out, the library does not seem to function on the new Raspberry Pi 2 boards.

 

I spent a good portion of last week looking for a solution to this problem, and to be honest, I came up with nothing. This caused me to freak out a little bit, and Neopixels play a very large role in this project. After much deliberation, and consultation with some friends here at Element14, I decided to abandon my quest to get Neopixels working with the Raspberry Pi 2. Instead of directly controlling them with the Pi, I decided to go a much easier route, by controlling them with an Arduino Nano, which will be triggered by the Raspberry Pi.

 

As many of you may already know, Adafruit has an excellent guide to getting Neopixels up and running on an Arduino, and even wrote their own library. (Albeit it is a modified version of the pre-existing fastLED library.) To keep things simple and easy to understand for those of you following along at home, I stuck with the Adafruit Neopixel Library despite being more familiar with the fastLED library. If you are looking for more code examples for driving WS2812B modules, give fastLED a try.

 

neopixel_stick_circuit.png

As I briefly mentioned earlier, Neopixels utilize a single-wire data format, meaning they only require a single data wire regardless if your strip has one module or one thousand modules. The only other connections required are 5V and GND connections. It is very important to remember that with each “pixel” you get three LEDs that are being driven. This means that Neopixel strips, and rings can draw a large amount of current. I find that on a standard Arduino board, only about 60 Neopixels can be driven before browning out the board, and that number diminishes by half, if the strip is set to display white at full brightness.

 

For this reason, I recommend driving your Neopixels with a separate power source such as a 5V 1A regulated source, or a 5V 2A wall transformer. You can also power the strip with a 4x AA battery box. Adafruit also recommends filtering the power input with a large capacitor, and limiting the current on the data line with a resistor. I find that this is usually not needed, but it will prevent a pixel from dying in the event you accidentally plug the strip in while the system is powered up.

 

 

Wiring the Neopixels, Arduino Nano, and Raspberry Pi

 

 

fog2000schem2.jpg

Wiring up the Neopixels to the Arduino is fairly straightforward,and is as simple as following the diagram above. Note that I have connected the data-in line from both the Neopixel Ring and the Neopixel strip to the Arduino Nano’s digital pin 6. This allows me to drive both Neopixel devices with the same code. Also note that I have connected a 4X AA battery pack in the image for illustration purposes. As you will see later, I am using an LM805 VReg-based power supply in the physical application.

 

Connecting the Raspberry Pi to the Arduino is simple as well. Connect the Raspberry Pi’s GPIO Pin 21 to the Arduino Nano’s Digital Pin 8. Then connect one of the Raspberry Pi’s GND pins to the shared GND circuit between the Neopixels and Arduino Nano. It is very important that all of the ground’s in this circuit are connected together. Finally, a 10k Ohm resistor needs to be connected as a pulldown resistor on the Arduino’s Digital Pin 8. This will prevent any false triggers from happening.

 

Raspberry-Pi-Sense-HAT.jpg

Since we are using the Raspberry Pi Sense Hat with our Raspberry Pi, we need to make some slight modifications to the Sense Hat before we can connect any jumper wires to the GPIO headers. As you can see in the image above, the header pins that come with the sense hat do not protrude past the black plastic bar on top of the sense hat.

 

20151001_153828_HDR.jpg

Unfortunately figuring out how to get around this issue is not something that has been widely discussed anywhere on the internet. However, I did manage to find a post on the Astro Pi forums that mentioned buying some extra-long header pins from Adafruit. This is one of the reasons this post has been delayed for so long. As you can see in the image above, the extra-long pins from Adafruit are about 5mm longer than the ones that ship with the Sense Hat.

 

20151001_153743_HDR.jpg

The first step in installing the new header pins is to gently pry the Sense Hat off of its existing header pins. The Sense Hat was designed with this in mind, and prying the existing header pin strip out is easy when done slowly and carefully with a small flat-blade screw driver. Once removed, you can simply slide the longer header pins into place.

 

20151001_153931_HDR.jpg

Now you are ready to hook up everything as per the instructions above. In the image below you can see how I have everything laid out. Note that for this portion of the project to work, you need to have followed all of the previous installment’s instructions as well.

 

20151013_225331_HDR.jpg

It looks like a bit of a mess, but with everything laid out and taped down, I could easily troubleshoot any issues that arose.

 

20151013_225352_HDR.jpg

Here you can see the connections made to the Raspberry Pi. Note that I have removed some of the plastic connectors from some of the jumper wires. The header pins only stick about 5mm above the surface of the black plastic bar, and some of my jumpers were having issues keeping a secure connection.

 

20151013_225342_HDR.jpg

Here is a shot of how I have the Arduino Nano connected to the breadboard and wired up. Note that the grey wire is connected to the neopixel strip, and the twisted yellow, red, and black wires are connected to the neopixel ring. In this image, you can also see the LM7805-based 5V power supply I built. More on that later.

 

20151013_225347_HDR.jpg

Finally, a shot of the NeoPixel ring wired up. Note that these rings do not come pre-wired, and you will need to solder wires to it.

 

 

 

Building a 5V Regulated Power Supply

 

 

This is the same PSU that I built for my Trick or Trivia Halloween Candy Dispenser #004 - Building The Candy Dispenser & Servo Coding project, so I have re-used its images below. To build this PSU you will need the following components, as well as a soldering iron, flush cutters, and a 12-30V DC power source.

 

58K382758K3827

Resistors

1

METAL FILM RESISTOR, 220 OHM, 250mW, 1%

10M846410M8464

General Purpose Diode

1

1N40011N4001 Rectifier Diode 50 V 1 A

34C109234C1092

PSU Vreg

1

7805 LINEAR VOLTAGE REGULATOR, 5V, TO-220-3

17F216517F2165

PSU Filter Cap

1

CERAMIC CAPACITOR 0.1UF, 50V, X7R, 20%

69K790769K7907

PSU Filter Cap

1

ELECTROLYTIC CAPACITOR 100UF, 50V, 20%,

14N941814N9418

PSU LED

1

RED, T-1 3/4 (5MM)

49Y171249Y17127-Inch Touch Screen1Raspberry Pi 7" Touch Screen Display
66H746266H7462Strip Board1VECTOR ELECTRONICS-8022-PCB, Tracks(Strip Board)
21M490921M4909Screw Terminal2MOLEX-39543-0002-TERMINAL BLOCK

 

 

TrickOrTrivia_004 (1).jpg

 

A 5V regulated power supply circuit is quite simple to build thanks to the fairly common LM7805 voltage regulator, and requires just five components to get up and running. A 100uF capacitor, two 0.1pF ceramic capacitors, a 1N004 diode, and the LM7805 regulator. I am adding two screw terminals, and an indicator LED to the mix. I want to design a pcb for this, but for now a piece of protoboard will work just fine.

 

FZBN31NHH2VMX7Q.bmp

 

Following the schematic above, build the power supply and solder in each component. The protoboard I am using is different from the one listed above as I have a big supply of these from Protostack.com, so I just used one of mine.

 

TrickOrTrivia_004 (2).jpg

 

With all of the components soldered together, I made the necessary jumps from each component to the next. I lucked out with the Protostack board as it has integrated power and ground rails. This cut down on the number of jumps I needed to make.

 

TrickOrTrivia_004 (3).jpg

 

With everything soldered up, I trimmed the board down to reduce its size, and connected a 12v 1amp power source. The red LED lit up and I confirmed 5V out with a multimeter.

 

TrickOrTrivia_004 (4).jpg

 

 

The Neopixel Code

 

 

With everything connected, load the Arduino IDE and make sure the Adafruit Neopixel Library is installed. Refer to Adafruit’s Neopixel Uber Guide if you need help installing the library. Additionally, I won’t be going over the Arduino sketch that will drive the Neopixels in great detail as Adafruit does a good job at that in the code’s comments.

 

To keep things simple, I am using a modified version of Adafruits Strand Test example. I have added some custom code that looks for a high signal on the Arduino Nano’s digital pin 8, and included an else statement that tells the neopixels to turn off if no high signal is present. As always, you can find all of the code used in the Foginator 2000 project at its Github Repository.

 

 

/* This code is adapted from the StrandTest example from Adafruit's Neopixel library. Please visit adafruit.com to download the neopixel library in order to use this code. https://learn.adafruit.com/adafruit-neopixel-uberguide/arduino-library */

#include <Adafruit_NeoPixel.h>

#define PIN 6

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//  NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//  NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//  NEO_GRB    Pixels are wired for GRB bitstream (most NeoPixel products)
//  NEO_RGB    Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(60, PIN, NEO_GRB + NEO_KHZ800);

// IMPORTANT: To reduce NeoPixel burnout risk, add 1000 uF capacitor across
// pixel power leads, add 300 - 500 Ohm resistor on first pixel's data input
// and minimize distance between Arduino and first pixel.  Avoid connecting
// on a live circuit...if you must, connect GND first.

int rasPin = 8; // defines digital pin 8 as rasPin
int val = 0; // creates an integer called val, and assigns it a value of 0.

void setup() {
  strip.begin(); // Initialize the pixel strip
  strip.show(); // Initialize all pixels to 'off'
  pinMode(rasPin, INPUT); // sets rasPin to an Input pin
  }

void loop() {
val = digitalRead(rasPin); // tells the arduino to take a reading on rasPin and store the value in the val integer we declared earlier.

if (val == HIGH) // says if val is equal to 1, run the following code
{
  delay(1000); // wait one second
  rainbowCycle(30); // run the rainbowCycle function
  }
  else // tells the arduino that if val equals anything other than 1 (high) to run the following code.
  {
  colorWipe(strip.Color(0,0,0), 100); // sets each pixel to black (off) one by one via the colorWipe function
    }
}

// This function makes a rainbow equally distributed throughout the strip
void rainbowCycle(uint8_t wait) {
  uint16_t i, j;

  for(j=0; j<256*5; j++) { // 5 cycles of all colors on wheel
    for(i=0; i< strip.numPixels(); i++) {
      strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
    }
    strip.show();
    delay(wait);
  }
}

// This function fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
  for(uint16_t i=0; i<strip.numPixels(); i++) {
      strip.setPixelColor(i, c);
      strip.show();
      delay(wait);
  }
}

//This code generates a color-wheel value generator.
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
  if(WheelPos < 85) {
  return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
  WheelPos -= 85;
  return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
  WheelPos -= 170;
  return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}



 

 

Now upload the above code to the Arduino. If you have an error, check that the Neopixel library is properly installed, and that your Arduino is connected to the correct com-port.

 

 

Python Code To Trigger Arduino Via Raspberry Pi

 

 

Making an Arduino do something based on a trigger from a Raspberry Pi is quite simple, and only requires a few lines of code. Since we are looking for a high-input on the Arduino, we simply need to tell the Raspberry Pi to set one of its GPIO pins as an output when we want the Arduino to do something. In our case, we want the Neopixels to light up when the motion sensor is tripped. This will allow us to illuminate the fog that was triggered by the motion sensor as well.

 

Below you will find the code. I have not broken it down as it is simply just a few lines that set GPIO Pin 27 to an output when the motion sensor is tripped.

 

import RPi.GPIO as GPIO
import time
import sys

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(17, GPIO.IN)
GPIO.setup(21, GPIO.OUT)

def fire_fog():
    GPIO.output(21,True)
    time.sleep(2)
    GPIO.output(4,True)
    time.sleep(10)
    GPIO.output(4,False)
    time.sleep(20)
    GPIO.output(21,False)
    GPIO.cleanup()
    sys.exit()

while 1:
    time.sleep(3)
    if GPIO.input(17)==True:
        fire_fog()



 

 

Testing The Code

 

 

Power the Raspberry Pi, Arduino, and Neopixel power supply up, and then connect to the Raspberry Pi via SSH with a terminal like Putty, or Terminal if you are using a Mac. Using the Nano text editor, create a new file called foginator_ledfx_demo.py using the command below.

 

nano foginator_ledfx_demo.py

 

Now paste the Python code from the previous section above, and then save and exit the Nano text editor. If everything is hooked up correctly, and the code has been copied and pasted correctly, you can run the command below to see the neopixels light up.

 

sudo python foginator_ledfx_demo.py

 

You will have to wait for a few seconds, then move your hand over the motion sensor. The program will wait about two seconds, and then trigger the relay which fires the fog. At the same time, the Raspberry Pi will send a high signal to the Arduino which will trigger the NeoPixel strip and ring. Check out the video below to see it in action.

 

 

So that wraps up part five of the Foginator2000 project. This was a really fun but frustrating portion of the project for me as I lost a lot of time trying to sort out the Neopixel / Raspberry Pi 2 incompatibility issues. In the end, everything worked out well, but I was forced to add another part to the project’s bill of materials. Recently, a newly acquired friend of mine, who just happens to be a EE, told me that being an engineer means that you spend more than half your time problem solving. After this portion of the project, I am highly inclined to believe him.Tune in in just a few days for my next installment on the Foginator2000 project. Until then remember to Hack The World and Make Awesome!

 

Win this Kit and Build-A-Long


  1. Project Introduction
  2. Fog Controller Hardware and Test
  3. Environment Sensing Coding & Testing
  4. Ambient Audio Hardware and Coding
  5. Lighting Coding and Testing
  6. October 16th -  Final Assembly and Testing
  7. October 23th - Project Wrap-up

Trick-or-Trivia-Banner004.jpg

 

Welcome back to the Trick or Trivia Blog. In this installment, I am going to cover the candy dispensing mechanical assembly, as well as the coding to get the servo up and running on the Raspberry Pi 2. Up until now, all of the parts needed to build this project were able to be purchased from Newark.com or MCM Electronics, but this portion will require a 3D printer or some handy inguinuity and minor skills with wood working equipment. I have included both the printable .STL files as well as the sketchup design files so that anyone following along at home can recreate, improve, or modify things to fit their needs.

 

When I came up with the concept of the Trick or Trivia candy dispenser, I spent hours trying to figure out the best way to autonomously dispense Halloween candy one piece at a time, and mocked up a few designs in sketchup. After a lot of thought, I came to the conclusion that the candy needed to be very compact and pretty uniform and consistent in size.  It was also important that the candy be very tightly wrapped as loose packaging caused jams. I finally settled on Starburst candies as they fit all of the requirements. Starburst were actually my second choice, with Now & Later candies being my first. Unfortunately I could not find any of them locally, and know that Starburst are found throughout the US and abroad. Let’s get into the meat of things, and talk about the hardware needed for this project.

 

 

The Hardware

 

 

Below you will see a list of the hardware used to build out the candy dispenser portion of this project. In addition to these components, you will need the following tools: a soldering iron, solder, flush cutters, wire strippers, 12-inches or more of 3-conductor wire, 16 Gauge Galvanized Steel Wire (found at hobby stores), and a bag of Starburst candies.

 

Newark.com


Newark Part No.

Notes

Qty

Manufacturer / Description

38Y646738Y6467

RPi

1

RASPBERRY PI 2, MODEL B,

38Y647038Y6470

SD Card

1

RASPBERRY PI 8GB NOOBS MICRO SD CARD

44W493244W4932

PSU

1

POWER SUPPLY 5V, 1A

06W104906W1049

USB Cable

1

USB A PLUG TO MICRO USB B PLUG

53W628553W6285

WiFi Dongle

1

ADAFRUIT USB WIFI MODULE

58K382758K3827

Resistors

1

METAL FILM RESISTOR, 220 OHM, 250mW, 1%

10M846410M8464

General Purpose Diode

1

1N40011N4001 Rectifier Diode 50 V 1 A

34C109234C1092

PSU Vreg

1

7805 LINEAR VOLTAGE REGULATOR, 5V, TO-220-3

17F216517F2165

PSU Filter Cap

1

CERAMIC CAPACITOR 0.1UF, 50V, X7R, 20%

69K790769K7907

PSU Filter Cap

1

ELECTROLYTIC CAPACITOR 100UF, 50V, 20%,

14N941814N9418

PSU LED

1

RED, T-1 3/4 (5MM)

49Y171249Y17127-Inch Touch Screen1Raspberry Pi 7" Touch Screen Display
66H746266H7462Strip Board1VECTOR ELECTRONICS-8022-PCB, Tracks(Strip Board)
21M490921M4909Screw Terminal2MOLEX-39543-0002-TERMINAL BLOCK

 

MCM Electronics

 

MCM Part No.

Notes

Qty

Manufacturer / Description

28-17450

Servo

1

Micro Servo

 

 

3D Printing The Candy Dispenser Assembly

 

 

I chose to 3D print the parts for the candy dispenser simply because I have a few 3D Printers at my disposal at home, and could quickly design everything in Sketchup. If you do not have a 3D printer, you could easily build this assembly from wood or even foam core. The most important thing to remember is to leave enough clearance on all moving parts to negate any candy size anomalies.

 

Download all of the .STL files and the Sketchup design file from Thingiverse.com.

 

To keep this blog at a somewhat reasonable length, I am not going to post any images of the parts being 3D printed but as you can see from the image below, they print well at a 0.25mm layer height.  I used Voltivo Excelfil PLA Filament as the printing medium as PLA is more food-safe than ABS. Since the candy is wrapped in wax-coated paper, PLA is fine to make the dispenser out of.

 

TrickOrTrivia_004 (6).jpg

 

I mocked up the candy dispenser on a scrap box from a previous Newark order, and used hot glue to temporarily stick everything together. This was a very important step as I realized that the plunger tube was about 2mm taller than the magazine was despite being exactly the same in the sketchup file. I printed the tube again and the second try was perfect. I suspect a slicing error to be the cause of the first tubes difference. I apologize for the low-quality image, I simply got so wrapped up in getting this to work, that I forgot to take one, and had to use a screen cap from a video of everything working.

 

TrickOrTrivia_004-(7).jpg

 

In the image above you can see that I have the servo mounted to the back of the box, with the push-rod made from the 16 gauge wire pushing the plunger into the tube. It took a little trial and error to get the length right, and to get the servo’s horn placed just right, so that it would push candy out and not bind on the return stroke.

 

TrickOrTrivia_004-(8).jpg

 

With everything lined up and secure, I tested the dispenser for over an hour until I was confident that everything would work fine. I then super glued the plunger tube to the candy magazine using a thick, gel-like super glue. If this were ABS plastic I would have solvent-welded it together using acetone instead.

 

TrickOrTrivia_004-(9).jpg

 

I then glued the steel rod into the plunger block using hot glue. I chose hot glue as it is easier to remove if I need to change its length.

 

TrickOrTrivia_004 (5).jpg

 

With the easy part done, it was time to move on to getting the code for the servo working.

 

 

Wiring and Coding the Servo.

 

 

When designing the original kit for this project I listed a normal-sized hobby servo as I thought it’s extra power would be needed, but as it turns out, a smaller 9g servo works much better. This is due to the fact that the candy sometimes binds in the tube if it’s wrapper is coming loose, and when it binds, the bigger servo will actually bend the steel push rod. The 9g servo simply stalls out, preventing the rod from bending.

 

The servo I am using is a small 9g metal-gear servo from Hobby King’s Turnigy line, but the one listed in the parts list at the top of this post will work just as good. I also had issues trying to drive the original Tower Pro servo from the Raspberry Pi 2, even with a 6-volt, 5-amp power supply hooked to it. The smaller 9G servos worked just fine with the 5V power supply we will build later in this post.

 

The PIGPIO Library

 

To drive the servo and retain audio output I chose to install the pigpio library. Installing it is as easy as entering the following commands into the terminal one by one.

 

wget abyz.co.uk/rpi/pigpio/pigpio.zip

unzip pigpio.zip

cd PIGPIO

make

sudo make install

 

Then restart the Raspberry Pi with the following command.

 

sudo reboot

 

Once the Pi is back up and running, we need to start the pigpio module using the following command.

 

sudo pigpiod

 

This command will need to be ran every time the Raspberry Pi reboots. I simply added it to the crontab, just like we did with the command that plays the ambient audio on boot. In the event you need to stop the pigpio module, simply run the commands below. To find out more about what the pigpio module can do, check out its info-page.

 

sudo killall pigpiod

 

Servo Control Code

 

I chose the pigpio module because it not only allows the user to utilize all of the Raspberry Pi’s GPIO pins as PWM pins, but because it does not block audio like some of the other servo control solutions do. An added bonus is how easy it is to program servo control using Python with this library. Below is a breakdown of the servo code, followed by the full TrickOrTrivia code with the servo control integrated.  As always, you can find the full code for this project at its Github repo.

 

First we need to import the time and pigpio libraries.

 

import time
import pigpio
























 

Next we need to define which GPIO pin is connected to the servo.

 

servos = 4 #GPIO number
























 

Now we need to initialize the pigpio library

 

pi = pigpio.pi()
























 

This next block of code is the function that makes the candy dispenser’s plunger move back and forth to dispense three pieces of candy upon a correct answer. We are telling the servo to move hard right with a pulsewidth of 2500, and then move a little more than 90 degrees left with a pulsewidth of 1300. We wait 0.5 seconds between each move. When finished, we turn the servo off by setting a pulse width of 0, and telling the pigpio module to stop. Finally we break out of this function.

 

def correct_servo ():
        while True:
            pi.set_servo_pulsewidth(servos, 2500)
            time.sleep(.5)


            pi.set_servo_pulsewidth(servos, 1300)
            time.sleep(.5)


            pi.set_servo_pulsewidth(servos, 2500)
            time.sleep(.5)


            pi.set_servo_pulsewidth(servos, 1300)
            time.sleep(.5)


            pi.set_servo_pulsewidth(servos, 2500)
            time.sleep(.5)


            pi.set_servo_pulsewidth(servos, 1300)
            time.sleep(.5)


            pi.set_servo_pulsewidth(servos, 0);
            pi.stop()
            break
























 

The same code works for the incorrect answer, but only dispenses a single piece of candy.

 

def incorrect_servo ():
    while True:
        pi.set_servo_pulsewidth(servos, 2500)
        time.sleep(.5)


        pi.set_servo_pulsewidth(servos, 1300)
        time.sleep(.5)


        pi.set_servo_pulsewidth(servos, 0);
        pi.stop()
        break
























 

In the full code below, you will see that I call each of these functions in the Blink_LED functions.

 

from Tkinter import *
import RPi.GPIO as GPIO
import time
import sys
import pygame
import pigpio

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.OUT)
GPIO.setup(19, GPIO.OUT)

servos = 4 #GPIO number
pi = pigpio.pi()

state = True

correct_audio_path = '/home/pi/Desktop/audio/correct.mp3'
incorrect_audio_path = '/home/pi/Desktop/audio/incorrect.mp3'

def correct_servo ():
        while True:
            pi.set_servo_pulsewidth(servos, 2500)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 1300)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 2500)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 1300)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 2500)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 1300)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 0);
            pi.stop()
            break

def incorrect_servo ():
    while True:
        pi.set_servo_pulsewidth(servos, 2500)
        time.sleep(.5)
        pi.set_servo_pulsewidth(servos, 1300)
        time.sleep(.5)
        pi.set_servo_pulsewidth(servos, 0);
        pi.stop()
        break

def blink_led():
    # endless loop, on/off for 1 second
    while True:
        GPIO.output(26,True)
        pygame.mixer.init()
        pygame.mixer.music.load(correct_audio_path)
        pygame.mixer.music.set_volume(1.0)
        pygame.mixer.music.play(5)
        time.sleep(10)
        correct_servo()
        GPIO.output(26,False)
        GPIO.cleanup()
        pygame.quit()
        sys.exit()

def blink_led_2():
    # endless loop, on/off for 1 second
    while True:
        GPIO.output(19, True)
        pygame.mixer.init()
        pygame.mixer.music.load(incorrect_audio_path)
        pygame.mixer.music.set_volume(1.0)
        pygame.mixer.music.play(5)
        time.sleep(10)
        incorrect_servo()
        GPIO.output(19,False)
        GPIO.cleanup()
        pygame.quit()
        sys.exit()

root = Tk()
root.overrideredirect(True)
root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))
root.focus_set()  # <-- move focus to this widget
root.configure(background='black')

label_1 = Label(root, text="Welcome to Trick or Trivia", font=("Helvetica", 36), bg="black", fg="white")
label_1.grid(columnspan=6,padx=(100, 10))
label_2 = Label(root, text="Answer the question for candy!", font=("Helvetica", 28), bg="black", fg="red")
label_2.grid(columnspan=6, pady=5, padx=(100, 10))
label_3 = Label(root, text="Casper is a friendly ____!", font=("Helvetica", 32), bg="black", fg="green")
label_3.grid(columnspan=6, pady=5, padx=(100, 10))
button_1 = Button(root, text="Ghost", font=("Helvetica", 36), command=blink_led)
button_1.grid(row=4, column=2, pady=5, padx=(100, 10))
button_2 = Button(root, text="Ghast", font=("Helvetica", 36), command=blink_led_2)
button_2.grid(row=4, column=4, sticky=W, padx=(100, 10))
button_3 = Button(root, text="Ghoul", font=("Helvetica", 36), command=blink_led_2)
button_3.grid(row=5, column=2, pady=5, padx=(100, 10))
button_4 = Button(root, text="Gremlin", font=("Helvetica", 36), command=blink_led_2)
button_4.grid(row=5, column=4, sticky=W, padx=(100, 10))
label_4 = Label(root, text="Correct Answer = 3 Pieces", font=("Helvetica", 20), bg="black", fg="green")
label_4.grid(columnspan=6, padx=(100, 10))
label_5 = Label(root, text="Incorrect Answer = 1 Piece", font=("Helvetica", 20), bg="black", fg="red")
label_5.grid(columnspan=6, padx=(100, 10))

root.mainloop()
























 

 

Building a 5V Regulated Power Supply

 

 

The 9g servo we are using requires a 5V power source, and while the Raspberry Pi is capable of powering it for free movement, the servo could pull 2-3 amps if it binds up. The Pi is not capable of sourcing this much current through its GPIO, and it could cause damage to the Pi. So we are going to build a quick and simple regulated 5V power supply. This power supply will not supply 2-3 amps, but can sustain 1-amp without a heatsink.

 

To build this PSU you will need the following components, as well as a soldering iron, flush cutters, and a 12-30V DC power source.

 

58K382758K3827

Resistors

1

METAL FILM RESISTOR, 220 OHM, 250mW, 1%

10M846410M8464

General Purpose Diode

1

1N40011N4001 Rectifier Diode 50 V 1 A

34C109234C1092

PSU Vreg

1

7805 LINEAR VOLTAGE REGULATOR, 5V, TO-220-3

17F216517F2165

PSU Filter Cap

1

CERAMIC CAPACITOR 0.1UF, 50V, X7R, 20%

69K790769K7907

PSU Filter Cap

1

ELECTROLYTIC CAPACITOR 100UF, 50V, 20%,

14N941814N9418

PSU LED

1

RED, T-1 3/4 (5MM)

49Y171249Y17127-Inch Touch Screen1Raspberry Pi 7" Touch Screen Display
66H746266H7462Strip Board1VECTOR ELECTRONICS-8022-PCB, Tracks(Strip Board)
21M490921M4909Screw Terminal2MOLEX-39543-0002-TERMINAL BLOCK

 

 

TrickOrTrivia_004 (1).jpg

 

A 5V regulated power supply circuit is quite simple to build thanks to the fairly common LM7805 voltage regulator, and requires just five components to get up and running. A 100uF capacitor, two 0.1pF ceramic capacitors, a 1N004 diode, and the LM7805 regulator. I am adding two screw terminals, and an indicator LED to the mix. I want to design a pcb for this, but for now a piece of protoboard will work just fine.

 

FZBN31NHH2VMX7Q.bmp

 

Following the schematic above, build the power supply and solder in each component. The protoboard I am using is different from the one listed above as I have a big supply of these from Protostack.com, so I just used one of mine.

 

TrickOrTrivia_004 (2).jpg

 

With all of the components soldered together, I made the necessary jumps from each component to the next. I lucked out with the Protostack board as it has integrated power and ground rails. This cut down on the number of jumps I needed to make.

 

TrickOrTrivia_004 (3).jpg

 

With everything soldered up, I trimmed the board down to reduce its size, and connected a 12v 1amp power source. The red LED lit up and I confirmed 5V out with a multimeter.

 

TrickOrTrivia_004 (4).jpg

 

With the power supply built and working, we can move on to testing our servo!

 

 

Testing the Servo

 

TrickOrTrivia_004-(10).jpg

 

Connect the servo to the power supply as shown. Then connect the servos signal wire to the Raspberry Pi’s GPIO Pin 4 using the BCM schema. You also need to connect the power supply’s ground to the Raspberry Pi’s ground. You can see that I have done that here with the GND rail on a breadboard I am using to power the mock-up’s LEDs.

 

To test the servo, let’s create a new test script with Python. Using the Nano text editor create a new file within the Trivia Scripts directory using the following commands.

 

cd /home/pi/Desktop/TriviaScrips

nano servo_test.py

 

Now paste the following code into the file you just created. Then exit out of the file, saving the changes.

 

import time
import pigpio
import sys

servos = 4 #GPIO number

pi = pigpio.pi()
#pulsewidth can only set between 500-2500

def correct_servo ():
        while True:
            pi.set_servo_pulsewidth(servos, 2500)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 1300)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 2500)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 1300)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 2500)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 1300)
            time.sleep(.5)
            pi.set_servo_pulsewidth(servos, 0);
            pi.stop()
            break


def incorrect_servo ():
    while True:
        pi.set_servo_pulsewidth(servos, 2500)
        time.sleep(.5)
        pi.set_servo_pulsewidth(servos, 1300)
        time.sleep(.5)
        pi.set_servo_pulsewidth(servos, 0);
        pi.stop()
        break

correct_servo()
incorrect_servo()
sys.exit






 

To run the script, use the following command.

 

sudo python servo_test.py

 

The servo should move back and forth a few times before finishing up, and the script terminating. If it worked, copy the full foginator code that I posted earlier in this post, and edit the foginator2000.py script. Delete the existing code and paste the new code into it. Save and exit. Now you should be able to run the Foginator2000.py script and when you select the correct answer, three pieces of candy will be ejected from the magazine like in the video below.

 

 

I apologize for this post being so late, but as you might know, South Carolina got hit by a pretty massive rainstorm over the last few days. That has seriously hindered my ability to work on anything, but we are back to blue skies now. I hope you enjoyed this installment of my Trick or Trivia project, and I hope that you learned a thing or two about the Raspberry Pi and servos. That is going to wrap this installment of Project: Trick or Trivia. Check back in a few days for the next installment. Until then, remember to Hack The World, and Make Awesome!

 

Win this Kit and Build-A-Long

 

  1. Project Introduction

  2. Building The Trivia Interface

  3. Interfacing Ambient and Triggered Audio Events
  4. Building The Candy Dispenser & Servo Coding
  5. Carve Foam Tombstone
  6. October 24th -  Assembly and Testing
  7. October 28th - Project Wrap-up

Foginator-Banner-004.jpg

 

With the month of October almost here, I have kicked these Halloween projects into high-gear. I previously said that update number four would be all about lighting, but since I just finished the audio portion of Project Trick or Trivia, I thought this would be a good time to tackle the audio portion of Foginator2000. Since Trick or Trivia will be playing triggered audio events based on the buttons, I did not want to muddy the dynamic sound-stage with too much audio. So Foginator 2000 will only be playing ambient audio. I may go back and add in a single triggered event with some sort of greeting that would play either when the fog triggers, or right after it finishes. In this update, I am going to show you how I managed to get the audio portion of this project up and running.

 

If you follow my Trick or Trivia project, you will find that much of this installment is the same. This is because the audio needs for both projects are quite similar, and I did not feel the need to reinvent the wheel for this update. With that said, I had originally planned on running the background / ambient audio from within the same python script that the main program was in, but I slowly realized that this was not needed. After several hours of experimentation with the audio on project Trick or Trivia, I decided that the best route to take for always-on, ambient audio was to create a separate python script that would play the ambient audio loop when the Raspberry PiRaspberry Pi booted up.

 

The Hardware

 

Below you will see a list of the hardware used to build out the audio portion of this project. In addition to these components, you will need the following tools: a soldering iron, solder, flush cutters, wire strippers, 3-10 feet of 2-pair cable, and a 6-inch or longer 3.5mm to 3.5mm audio extension cable.

 

Newark.com


Newark Part No.

Notes

Qty

Manufacturer / Description

38Y646738Y6467

RPi

1

RASPBERRY PI 2, MODEL B,

38Y647038Y6470

SD Card

1

RASPBERRY PI 8GB NOOBS MICRO SD CARD

44W493244W4932

PSU

1

POWER SUPPLY 5V, 1A

06W104906W1049

USB Cable

1

USB A PLUG TO MICRO USB B PLUG

53W628553W6285

WiFi Dongle

1

ADAFRUIT USB WIFI MODULE

40P118440P1184

Speaker

1

VISATON SPEAKER, 20 kHz, 8OHM, 4W

49Y171249Y17127-Inch Touch Screen1Raspberry Pi 7" Touch Screen Display

 

MCM Electronics

 

MCM Part No.

Notes

Qty

Manufacturer / Description

28-12812

Audio Amp

1

Audio Amplifier Kit 2 X 5W RMS

 

 

Building the Velman 2x5W Amplifier

 

 

One of the major things that I have learned from being in the Haunted Attraction industry is that lighting and sound are two of the biggest “make it or break it” features of a successful prop. When I was putting together the kit for this project, I knew I wanted audio to be a big part of the project. The Raspberry Pi makes it quite easy to add audio to a project, but unfortunately, unless your project makes use of earbuds, you will need to add an amplifier to the project to drive more powerful speakers.

 

20150928_203121_HDR.jpg

 

For this project, I chose the Velleman 2x5W Amplifier kit from MCM Electronics. This kit is designed for even the most novice maker to be able to assemble, and it’s quite powerful for its small size. I also chose to use a single small three-inch, eight-Ohm speaker from Visatoneight-Ohm speaker from Visaton. This speakers is a little undersized for this project and this amp, but it works just fine as long as you do not max out the amp’s volume control.

 

20150928_203803_HDR.jpg

 

The kit is very straight forward, does not include any confusing, hard-to-identify parts, nor does it utilize any SMD parts that would make it hard to solder. The toughest part to solder in the whole kit is the power indicator LED, as you need to bend it at a very specific point if you want to follow the build instructions 100% word-for-word. I built this entire board in less than 10 minutes.

 

20150928_205244_HDR.jpg

 

I sort of went off script and soldered up several of the amp’s components at once. If you follow the directions, you will solder each type of component step by step. This was way to slow for me, and I have hand soldered so many SMD boards in the past few months, that I can solder a through-hole board like this with my eyes closed.

 

20150928_210327_HDR.jpg

 

I finished up the board with a second round of soldering. This time I soldered the IC, and other large / heavy components. When soldering terminal blocks, ICs, and other components that are hard to keep in place, or that have several leads, I like to solder one of the leads on an end of the component first. This lets me lock the component in place, then I can use my fingers to re-align the part while re-heating that single solder joint.

 

20150928_210334_HDR.jpg

 

It’s hard to see in this photo, but I set the potentiometer all the way to the left, then placed the knob on it with the indicator dot down in the bottom left corner. This will place the dot almost perfectly opposite this position when the volume is turned to max.

 

20150928_210340_HDR.jpg

 

The one thing I always say about soldering is that flux is your friend. Velleman must know this as well because they coated the entire bottom of the PCB in a very sticky resin-based flux. I still used my flux pen on a per-joint basis as I like flux on the component leads I am soldering as well.

 

20150928_212852_HDR.jpg

 

Wiring up the speaker is pretty straight forward as Visaton was kind enough to mark the leads with + and - symbols to identify its leads. For those wondering, the + lead is almost always the larger of the two leads. Rumor has it, that this was adopted as common practice first in the automotive industry back in the 1970s. You will note that I used some spare two-conductor, shielded microphone wire. You can use any two-conductor wire you have, just pay attention to the polarity. The speaker will work even if it’s reversed, but the best sound quality comes from a properly wired speaker.

 

20150928_213444_HDR.jpg

 

Connect the other end of the speaker wire to the amp while paying attention to the polarity. You can also connect the power cable to the screw terminals to the left at this point. The amp requires a 6-14v 1A DC power source. You can power this with an old 9v or 12v wall-adapter, or even a 9-volt battery, but the battery will struggle to output enough current to keep the amp at full capacty.

 

 

The Ambient Audio Code

 

 

To start off let's quickly cover the background / ambient audio working and how I set it up to begin when the Raspberry Pi Boots. Below is the Python script that I wrote to play the mp3 file I selected as the ambient source. I have broken out each section, and commented on what it does. You can download this code used in this tutorial at the Github repository for this project. The audio files are available for download from here. If you do not want to modify the code, create a folder in the Desktop directory called “audio” and move all three of the mp3 files into it.

 

 

To get started we need to import the pygame library. I know a lot of you would have liked to see me use OMXplayer, but there were some things I could not get to work as they should, and I just chose to use something I was familiar with instead.

 

import pygame







 

Next we need to define the path to the ambient.mp3 file, and give it a name.

 

audio_path = '/home/pi/Desktop/audio/ambient.mp3'







 

Now we need to set a variable to True

 

var = True







 

Now we need to write a while-loop to play our mp3 file, and set it to only play if var is equal to True.

 

while var ==True:







 

Now we need to initialize PyGame.

 

    pygame.mixer.init()







 

Then we need to load the MP3 file we want to play.

 

    pygame.mixer.music.load(audio_path)







 

Now we need to set the pygame player’s volume. The range is between 0.0 and 1.0 so a setting of 0.5 would be half way.

 

    pygame.mixer.music.set_volume(1.0)







 

Finally we need to tell pygame to play the MP3 file, and set it to loop five times.

 

    pygame.mixer.music.play(5)







 

The full code is pasted below. Alternatively you can download this code used in this tutorial at the Github repository for this project. The audio files are available for download from here. If you do not want to modify the code, create a folder in the Desktop directory called “audio” and move all three of the mp3 files into it.

 

import pygame

audio_path = '/home/pi/Desktop/audio/ambient.mp3'

var = True

while var ==True:
    pygame.mixer.init()
    pygame.mixer.music.load(audio_path)
    pygame.mixer.music.set_volume(1.0)
    pygame.mixer.music.play(5)







 

 

Navigate to the project files folder adn then open a new file called ambient.py using the Nano text editor by entering the following command

 

sudo nano ambient.py

 

Then copy and paste the code above into the file. Save and exit, and then use the following command to test the pi.

 

sudo python ambient.py

 

You should hear the ambient.mp3 file begin to play if you have the amplifier / speaker combo we just built hooked up via a 3.5mm to 3.5mm audio cable from the amp to the Raspberry Pi. To get this python script to run on boot, we need to add it to the Raspberry Pi’s crontab. Enter the following command in the terminal to create a new crontab entry.

 

sudo crontab -e

 

Now paste the following line at the bottom of the crontab.

 

@reboot sudo python /home/pi/Desktop/Foginator2000/ambient.py







 

then save and exit out of the file. Reboot the Raspberry Pi using the command below. When the Pi reboots, you should hear the ambient.py file playing after you login.

 

sudo reboot

 

If the audio is quite low despite the amplifier’s volume being maxed out, you will need to turn the Raspberry Pi’s volume up. This is as simple as entering the small command found below, into the terminal.

 

amixer cset numid=1 -- 400

 

The range of amixer’s volume is -10200 and +400 in centi-dB units. Since we are using an external amplifier, we can set the Raspberry Pi’s volume to its max setting at +400, and adjust the volume on the amp accordingly. Once you have the volume set, you should be able to reboot the Pi, and the ambient audio will begin playing when you log in. I did not shoot a video of this for this installment, but if you check out the video below from my Trick or Trivia project, you will get the idea of whats going on with the ambient audio.

 

 

Well that is going to wrap up this weeks installment of the Foginator2000 project. Check back in a few days for the next update where I cover how to get Individually Addressable RGB LEDsIndividually Addressable RGB LEDs working with the Raspberry Pi, and how they will be incorporated into this project! If you have not checked it out yet, head over to my other Halloween 2015 Raspberry Pi project, Trick or Trivia, that makes use of the new 7-inch Touchscreen LCD from Raspberry Pi.7-inch Touchscreen LCD from Raspberry Pi.

 

Win this Kit and Build-A-Long


  1. Project Introduction
  2. Fog Controller Hardware and Test
  3. Environment Sensing Coding & Testing
  4. Ambient Audio Hardware and Coding
  5. Lighting Coding and Testing
  6. October 16th -  Final Assembly and Testing
  7. October 23th - Project Wrap-up

Trick-or-Trivia-Banner003.jpg

 

Welcome back to the Trick or Trivia Blog. In this installment, I am going to show you how I managed to get the audio portion of this project up and running. I hit a slight bump in the road shortly after setting down to figure all of this out. I had planned on having several different layers of sound playing at once, but have only managed to get a background and foreground set of layers working together, and I think that will be enough.

 

I had originally planned on running the background / ambient audio from within the same python script that the main program was in, but I slowly realized that this was not only a bad idea, but it simply might not work with the way I plan on randomizing questions. I will confess that I spent more than a few hours trying to get the ambient audio working in a subprocess, and several other parallel processing methods, but failed miserably, and decided to run the ambient audio another way. I decided to take the easy route, and just write a separate python script that would allow me to play the ambient audio loop when the Raspberry PiRaspberry Pi booted up. By removing this process from my main TrickOrTrivia.py script, I was able to move on to getting the audio working with the buttons. Before we get into how I did that, let’s take a quick look at the hardware that is used in this installment of Trick Or Trivia.

 

The Hardware

 

Below you will see a list of the hardware used to build out the audio portion of this project. In addition to these components, you will need the following tools: a soldering iron, solder, flush cutters, wire strippers, 3-10 feet of 2-pair cable, and a 6-inch or longer 3.5mm to 3.5mm audio extension cable.

 

Newark.com


Newark Part No.

Notes

Qty

Manufacturer / Description

38Y646738Y6467

RPi

1

RASPBERRY PI 2, MODEL B,

38Y647038Y6470

SD Card

1

RASPBERRY PI 8GB NOOBS MICRO SD CARD

44W493244W4932

PSU

1

POWER SUPPLY 5V, 1A

06W104906W1049

USB Cable

1

USB A PLUG TO MICRO USB B PLUG

53W628553W6285

WiFi Dongle

1

ADAFRUIT USB WIFI MODULE

40P118440P1184

Speaker

1

VISATON SPEAKER, 20 kHz, 8OHM, 4W

49Y171249Y17127-Inch Touch Screen1Raspberry Pi 7" Touch Screen Display

 

MCM Electronics

 

MCM Part No.

Notes

Qty

Manufacturer / Description

28-12812

Audio Amp

1

Audio Amplifier Kit 2 X 5W RMS

 

 

Building the Velman 2x5W Amplifier

 

 

One of the major things that I have learned from being in the Haunted Attraction industry is that lighting and sound are two of the biggest “make it or break it” features of a successful prop. When I was putting together the kit for this project, I knew I wanted audio to be a big part of the project. The Raspberry Pi makes it quite easy to add audio to a project, but unfortunately, unless your project makes use of earbuds, you will need to add an amplifier to the project to drive more powerful speakers.

 

20150928_203121_HDR.jpg

 

For this project, I chose the Velleman 2x5W Amplifier kit from MCM Electronics. This kit is designed for even the most novice maker to be able to assemble, and it’s quite powerful for its small size. I also chose to use a single small three-inch, eight-Ohm speaker from Visatoneight-Ohm speaker from Visaton. This speakers is a little undersized for this project and this amp, but it works just fine as long as you do not max out the amp’s volume control.

 

20150928_203803_HDR.jpg

 

The kit is very straight forward, does not include any confusing, hard-to-identify parts, nor does it utilize any SMD parts that would make it hard to solder. The toughest part to solder in the whole kit is the power indicator LED, as you need to bend it at a very specific point if you want to follow the build instructions 100% word-for-word. I built this entire board in less than 10 minutes.

 

20150928_205244_HDR.jpg

 

I sort of went off script and soldered up several of the amp’s components at once. If you follow the directions, you will solder each type of component step by step. This was way to slow for me, and I have hand soldered so many SMD boards in the past few months, that I can solder a through-hole board like this with my eyes closed.

 

20150928_210327_HDR.jpg

 

I finished up the board with a second round of soldering. This time I soldered the IC, and other large / heavy components. When soldering terminal blocks, ICs, and other components that are hard to keep in place, or that have several leads, I like to solder one of the leads on an end of the component first. This lets me lock the component in place, then I can use my fingers to re-align the part while re-heating that single solder joint.

 

20150928_210334_HDR.jpg

 

It’s hard to see in this photo, but I set the potentiometer all the way to the left, then placed the knob on it with the indicator dot down in the bottom left corner. This will place the dot almost perfectly opposite this position when the volume is turned to max.

 

20150928_210340_HDR.jpg

 

The one thing I always say about soldering is that flux is your friend. Velleman must know this as well because they coated the entire bottom of the PCB in a very sticky resin-based flux. I still used my flux pen on a per-joint basis as I like flux on the component leads I am soldering as well.

 

20150928_212852_HDR.jpg

 

Wiring up the speaker is pretty straight forward as Visaton was kind enough to mark the leads with + and - symbols to identify its leads. For those wondering, the + lead is almost always the larger of the two leads. Rumor has it, that this was adopted as common practice first in the automotive industry back in the 1970s. You will note that I used some spare two-conductor, shielded microphone wire. You can use any two-conductor wire you have, just pay attention to the polarity. The speaker will work even if it’s reversed, but the best sound quality comes from a properly wired speaker.

 

20150928_213444_HDR.jpg

 

Connect the other end of the speaker wire to the amp while paying attention to the polarity. You can also connect the power cable to the screw terminals to the left at this point. The amp requires a 6-14v 1A DC power source. You can power this with an old 9v or 12v wall-adapter, or even a 9-volt battery, but the battery will struggle to output enough current to keep the amp at full capacty.

 

 

The Ambient Audio Code

 

 

To start off let's quickly cover the background / ambient audio working and how I set it up to begin when the Raspberry Pi Boots. Below is the Python script that I wrote to play the mp3 file I selected as the ambient source. I have broken out each section, and commented on what it does.

 

 

To get started we need to import the pygame library. I know a lot of you would have liked to see me use OMXplayer, but there were some things I could not get to work as they should, and I just chose to use something I was familiar with instead.

 

import pygame





 

Next we need to define the path to the ambient.mp3 file, and give it a name.

 

audio_path = '/home/pi/Desktop/audio/ambient.mp3'





 

Now we need to set a variable to True

 

var = True





 

Now we need to write a while-loop to play our mp3 file, and set it to only play if var is equal to True.

 

while var ==True:





 

Now we need to initialize PyGame.

 

    pygame.mixer.init()





 

Then we need to load the MP3 file we want to play.

 

    pygame.mixer.music.load(audio_path)





 

Now we need to set the pygame player’s volume. The range is between 0.0 and 1.0 so a setting of 0.5 would be half way.

 

    pygame.mixer.music.set_volume(1.0)





 

Finally we need to tell pygame to play the MP3 file, and set it to loop five times.

 

    pygame.mixer.music.play(5)





 

The full code is pasted below. Alternatively you can download this code used in this tutorial at the Github repository for this project. The audio files are available for download from here. If you do not want to modify the code, create a folder in the Desktop directory called “audio” and move all three of the mp3 files into it.

 

import pygame

audio_path = '/home/pi/Desktop/audio/ambient.mp3'

var = True

while var ==True:
    pygame.mixer.init()
    pygame.mixer.music.load(audio_path)
    pygame.mixer.music.set_volume(1.0)
    pygame.mixer.music.play(5)





 

 

Navigate to the Open a new file called ambient.py using the Nano text editor by entering the following command

 

sudo nano ambient.py

 

Then copy and paste the code above into the file. Save and exit, and then use the following command to test the pi.

 

sudo python ambient.py

 

You should hear the ambient.mp3 file begin to play if you have the amplifier / speaker combo we just built hooked up via a 3.5mm to 3.5mm audio cable from the amp to the Raspberry Pi. To get this python script to run on boot, we need to add it to the Raspberry Pi’s crontab. Enter the following command in the terminal to create a new crontab entry.

 

sudo crontab -e

 

Now paste the following line at the bottom of the crontab.

 

@reboot sudo python /home/pi/Desktop/TriviaScrips/ambient.py





 

then save and exit out of the file. Reboot the Raspberry Pi using the command below. When the Pi reboots, you should hear the ambient.py file playing after you login.

 

sudo reboot

 

If the audio is quite low despite the amplifier’s volume being maxed out, you will need to turn the Raspberry Pi’s volume up. This is as simple as entering the small command found below, into the terminal.

 

amixer cset numid=1 -- 400

 

The range of amixer’s volume is -10200 and +400 in centi-dB units. Since we are using an external amplifier, we can set the Raspberry Pi’s volume to its max setting at +400, and adjust the volume on the amp accordingly.

 

 

Correct and Incorrect Answer Audio

 

 

I plan on changing out the audio files used for the correct and incorrect answer triggers, but for now the two that are in the download will work just fine. I wish I had time to get the Correct and Incorrect audio recorded and mastered, but I have not had time to sit down and hook up my recording gear.

 

The first thing we need to do is open the TrickorTrivia.py script and make some modifications. This script is the same as the one we used in the last installment of this tutorial, but has a new name. With that said, I am not going to go over every single line of code. Just the few bits and pieces we need to add.

 

The first thing we need to do is import the pygame library.

 

import pygame





 

Now we need to define two audio paths and give them names.

 

correct_audio_path = '/home/pi/Desktop/audio/correct.mp3'
incorrect_audio_path = '/home/pi/Desktop/audio/incorrect.mp3'





 

Finally we need to edit the blink_led functions, to make the LED illuminate once when the correct and incorrect answers are selected. We also need to add in a few lines to play the correct and incorrect answer audio files. For a more precise breakdown of this audio code, see the ambient code written earlier in this post.

 

def blink_led():
    # endless loop, on/off for 1 second
    while True:
        GPIO.output(26,True)
        pygame.mixer.init()
        pygame.mixer.music.load(correct_audio_path)
        pygame.mixer.music.set_volume(1.0)
        pygame.mixer.music.play(5)
        time.sleep(10)
        GPIO.output(26,False)
        GPIO.cleanup()
        pygame.quit()
        sys.exit()





 

def blink_led_2():
    # endless loop, on/off for 1 second
    while True:
        GPIO.output(19, True)
        pygame.mixer.init()
        pygame.mixer.music.load(incorrect_audio_path)
        pygame.mixer.music.set_volume(1.0)
        pygame.mixer.music.play(5)
        time.sleep(10)
        GPIO.output(19,False)
        GPIO.cleanup()
        pygame.quit()
        sys.exit()





 

That’s all that we have to modify in this script to get the audio files playing when a button is pressed. When the correct answer is chosen, the green LED will illuminate, the correct.mp3 file will play, and when done, the LED will turn off and the script will exit. The same goes for the incorrect answer. The red LED will illuminate, the incorrect.mp3 file will play, and then when finished the LED will turn off and the script will exit. Below is the full code.

 

To test if the code works, enter the Desktop GUI by typing the following command:

 

startx

 

Then open LXterminal, and navigate to the TrickorTrivia.py script.

 

cd /home/pi/Desktop/TriviaScrips

 

Then run the TrickorTrivia.py scrip with the following command:

 

sudo python TrickorTrivia.py

 

This should open the trivia interface and when you select the answer, the corresponding LED should light up and audio file play.

 

 

I really wish I could have gotten the ambient audio working on a sub-process, but it will work just fine the way I set it up by running on boot via crontab. I will admit that the speaker is a little underpowered, and I am not utilizing the Amp to its full potential. This is an easy fix, if you have an old set of small bookshelf speakers laying around. That is going to wrap this installment of Project: Trick or Trivia. Check back in a few days for the next installment. Until then, remember to Hack The World, and Make Awesome!

 

 

Win this Kit and Build-A-Long

 

  1. Project Introduction

  2. Building The Trivia Interface

  3. Interfacing Ambient and Triggered Audio Events
  4. Building The Candy Dispenser & Servo Coding
  5. Carve Foam Tombstone
  6. October 24th -  Assembly and Testing
  7. October 28th - Project Wrap-up

Foginator-Banner-003.jpg

 

Welcome to installment #003 of Project: Foginator 2000 part of the 2015 Raspberry Pi Halloween Project series here at Element14. In this week's episode I am going to cover the basics of getting the Raspberry Pi Sense HatRaspberry Pi Sense Hat up and running, and a very light tutorial on how to push this data to the cloud in order to record and analyze the data. The cool thing about this is that we can simply save all of our acquired data to the cloud, and access it from anywhere!

 

The Hardware

 

Below is a table containing the parts you will need for this segment of the project. In addition to these parts you will need to connect the Raspberry Pi to the internet either via a wifi dongle, or a wired Ethernet connection.

 

Newark Part No.

Notes

Qty

Manufacturer / Description

38Y646738Y6467

RPi

1

RASPBERRY PI 2, MODEL B

38Y647038Y6470

SD Card

1

RASPBERRY PI 8GB NOOBS MICRO SD CARD

44W493244W4932

PSU

1

USB PORT POWER SUPPLY 5V, 1A

06W104906W1049

USB Cable

1

USB A PLUG TO MICRO USB B PLUG

53W628553W6285

WiFi Dongle

1

USB WIFI MODULE

49Y756949Y7569RPi Sense Hat1Raspberry Pi Sense HAT

 

 

The Theory

 

 

The idea behind this part of the project is to log environmental data from the immediate area surrounding the fog machine. Using the Raspberry Pi Sense Hat we will measure and log temperature, humidity, and barometric pressure, and then push it up to the cloud. We will trigger this data logging even every time the fog machine trips, and will record the entire event as a “Trick-Or-Treat Event.” Then we will be able to export the data as a CSV file and analyze what temperatures, humidity levels, and barometric pressure levels correlated with spikes in Trick-Or-Treat events.

 

For the purpose of this blog post, we will be simply figuring out how to read the data from the Sense Hat with our Raspberry Pi. Once we have that figured out we can move on to learning how to push that data to the cloud.

 

 

The Sense Hat

rpisensehat.jpg

 

The new Raspberry Pi Sense Hat was released a few weeks ago, and to be quite honest, I had planned this project out before it was released, and I was quite confused as to what this Hat actually did. The Sense HAT is an add-on board for Raspberry Pi, made especially for the Astro Pi mission that will be performed on the International Space Station in December 2015.

 

 

The Sense HAT has an 8×8 RGB LED matrix, a five-button joystick and includes the following sensors:

  • Gyroscope
  • Accelerometer
  • Magnetometer
  • Temperature
  • Barometric pressure
  • Humidity

To make things simple, the Raspberry Pi Foundation has created Python library providing easy access to everything on the board. You can find that library here.

 

 

Installing Astro Pi / Sense Hat

 

 

Raspberry-Pi-Sense-HAT.jpg

To get started you need to connect the Sense Hat to a Raspberry Pi 2 by placing it on the GPIO Pins. Note the orientation of the board in the image above.

 

Now we need to install the Raspberry PI Sense Hat library package into Raspbian. So SSH into the Raspberry Pi, or open the terminal if you are using your Pi with a Monitor such as the new Raspberry Pi 7-Inch Touch Screen. If you are following along at home, and building your own Foginator, your Raspbian install should already be updated, but just incase run the following commands in the terminal.

 

sudo apt-get update

sudo apt-get upgrade -y

 

 

Then run the following command which will download the necessary package to get the Sense Hat up and running. This process should take less than five minutes on a Raspberry Pi 2, but it could take longer. Do unplug your Raspberry Pi during this process.

 

sudo apt-get install sense-hat

 

Then to finish up the process you need to restart the Raspberry Pi. To do this, run the following command.

 

sudo reboot

 

Once the Pi has had time to reboot, reconnect via SSH or re-open the terminal.

 

 

Testing AstroPi and The Sense Hat

 

2015-09-23-23_48_42-Start.jpg

 

Let’s create a quick Python script to test that everything was installed and connected correctly. Using the Nano text editor, create a new file named sense_test.py. You can do this with the command below.

 

sudo nano sense_test.py

 

Now copy and paste the script below. This script basically tells the sense hat to scroll the words “Hello World” across the Hat’s LED matrix. When you have the code pasted, exit out of nano while keeping the same file name.

 

from sense_hat import SenseHat
sense = SenseHat()
sense.show_message("Hello World")
































 

Now enter the command below to run the script we just created.

 

sudo nano sense_test.py

 

Now you should see Hello World scroll across the LED matrix. If this works, you are ready to move onto the next step. If not, something went wrong with your install of Astro Pi. Go back over the steps to make sure everything is installed and written correctly.

 

 

Acquiring Data From The Sense Hat

 

temp-test-Start.jpg

 

Following some excellent tutorials on the RaspberryPi.org website, I was able to quickly get data from the temperature, air pressure, and humidity sensors. Surprisingly, this is possible with only a handful of lines of Python code. Below is a breakdown of the code and what each line / section does.

 

First need to import the sense_hat library, the time library, and the system library.

 

from sense_hat import SenseHat
import time
import sys





























 

Now we need to initialize the sense hat, and clear its matrix.

 

sense = SenseHat()
sense.clear()





























 

Now we need to set a variable named var, and give it a value of 30. This is used to close the program after it loops for 30 cycles.

 

var = 30





























 

Now we need to create our while loop, and set it to run if var is greater than 0.

 

while var > 0:





























 

The first data we want to import is the ambient temperature. The Sense Hat library makes this super simple, and all we have to do is tell the program to get the temperature. The default output is in degrees celsius, and is extended to several places after the decimal.

 

  temp = sense.get_temperature()





























 

To round that number to a more friendly tenth of a degree, we can simply tell the program to round the temperature output to the first decimal place.

 

  temp = round(temp, 1)





























 

Now we can print our temperature to the terminal. To do this we simply write a print command, and write some text to explain what this output is so that other people can understand what they are reading.

 

  print("Teperature C",temp)





























 

The same methods apply to the humidity and pressure readings as well, so I won’t list each of them out line by line.

 

  humidity = sense.get_humidity()
  humidity = round(humidity, 1)
  print("Humidity :",humidity)





























 

  pressure = sense.get_pressure()
  pressure = round(pressure, 1)
  print("Pressure:",pressure)





























 

Now we need to tell the program to wait for one second before continuing on. This slows down the rate at which the data is read and output. You can slow this rate down by increasing the number after the time.sleep command, or you can speed it up by decreasing the number.

 

  time.sleep(1)





























 

Now we need to tell the program to decrease the var variable by one.

 

  var = var -1





























 

With our var variable decreased by one, we need to check to see if it has reached 0 yet. If it has, we can tell the program to exit. This allows us to poll data for as long as we want, and not have the loop constantly running. Basically the while loop will run over and over until the var variable has decreased to 0.

 

  if var == 0:
    sys.exit()





























 

Putting It All Together

 

Below is the full code we just wrote, without any comments. Nano into the sense_test.py file and delete all of the code that is in it. Then copy and paste the code below, and save the file.

 

from sense_hat import SenseHat
import time
import sys

sense = SenseHat()
sense.clear()

var = 30

while var > 0:
  temp = sense.get_temperature()
  temp = round(temp, 1)
  print("Teperature C",temp)
  humidity = sense.get_humidity()
  humidity = round(humidity, 1)
  print("Humidity :",humidity)
  pressure = sense.get_pressure()
  pressure = round(pressure, 1)
  print("Pressure:",pressure)
  time.sleep(1)
  var = var -1
  if var == 0:
    sys.exit()





























 

Now run the program we just wrote with the following command:

 

sudo python sense_test.py

 

You should see each data set we are looking for, temperature, humidity, and pressure being displayed in the terminal. The Raspberry Pi will poll and display the data for 30-seconds / loops if you stuck with the 1-second delay we wrote into the while statement. With that working, lets move on to getting this data into the cloud.

 

 

Pushing The Data To The Cloud / Internet Of Things

 

 

initial_state_data_foginator.jpg

A while back I received an email from a company called Initial State who wanted me to try out their new cloud-based data visualization solution that is geared towards makers, and programmers alike. Unfortunately I forgot all about Initial State due to some life events taking me away from making things for a few months. I had not thought about Initial State for months until I was writing up one of my Design Challenge Summaries, and wrote about Rick Reynolds’ (RWReynolds) project, Vertically Oriented Modular System. In a comment, Rick mentioned that he  used Initial State to record and log the data from his project, and I decided to use it for mine as well.

 

You will need to go to InitialState.com and signup for a free account. I have a pro-account, but that is because I plan on using it in a lot of my future projects, but the free account should suffice for most.

 

2015-09-24 00_46_17-Start.jpg

I won’t go into the whole process of installing Initial State’s logger onto your Raspberry Pi, as Initial State has an excellent video tutorial on how to do exactly that. They also have a very comprehensive written tutorial on the subject as well. You can find the video below, it’s about an hour long, for the full tutorial, but the first 20 minutes should give you a good understanding of how to make this work.

 

 

Now let’s modify our code to enable it to begin sending data to the InitialState Cloud. So this by using the Nano text editor to edit the sense_test.py script.

 

This time around we need to import the InitialState Streamer library as well.

 

from sense_hat import SenseHat
import time
import sys
from ISStreamer.Streamer import Streamer




















 

Now we need to set up the InitialState Logger, name the bucket for this project, and then enter your access key. Chage the code below to include your key.

 

logger = Streamer(bucket_name="Sense Hat Environment Stream", access_key="YOUR_KEY_HERE")




















 

Our Setup stays the same

 

sense = SenseHat()
sense.clear()
var = 30




















 

Now everywhere we told the program to print the output of a sensor, we need to change that to tell the program to log and send that data to the InitialState bucket we created earlier in the code. Everywhere you wrote “print” before, change it to logger.log.

 

while var > 0:
  temp = sense.get_temperature()
  temp = round(temp, 1)
  logger.log("Teperature C",temp)
  humidity = sense.get_humidity()
  humidity = round(humidity, 1)
  logger.log("Humidity :",humidity)
  pressure = sense.get_pressure()
  pressure = round(pressure, 1)
  logger.log("Pressure:",pressure)
  var = var -1
  time.sleep(30)
  if var == 0:
    sys.exit()




















 

Bringing It All Together

 

The full code is below.

 

from sense_hat import SenseHat
import time
import sys
from ISStreamer.Streamer import Streamer


logger = Streamer(bucket_name="Sense Hat Environment Stream", access_key="zLahwAUqKbNKv6YvuT5JuO58EiUOavDa")


sense = SenseHat()
sense.clear()
var = 30


while var > 0:
  temp = sense.get_temperature()
  temp = round(temp, 1)
  logger.log("Teperature C",temp)
  humidity = sense.get_humidity()
  humidity = round(humidity, 1)
  logger.log("Humidity :",humidity)
  pressure = sense.get_pressure()
  pressure = round(pressure, 1)
  logger.log("Pressure:",pressure)
  var = var -1
  time.sleep(30)
  if var == 0:
    sys.exit()




















 

With the script edited and saved, run it using the command below.

 

sudo python sense_test.py

 

Now you can go to your InitialState account and click on the bucket you just created to see the data. Remember that IntialState free accounts have a very limited amount of events you can stream each month. Each data point is one event. So running this script in its current configuration would create three events per second for thirty seconds, totaling out at 90 events each time its ran.

 

2015-09-24 01_01_32-Start.jpg

I wanted to set this up to read data for several days, and I am one of those kinds of people who need a visual indicator to tell me that things are working as they should. So I once again modified the code to not only run the loop for several days, but also tossed in a few lines that would display a creeper head from MineCraft on the LED matrix at the end of every data collection cycle. If you are interested, that code is below. I won’t go into how I did it, but you can learn more at this link from the Raspberry Pi Foundation.

 

Code With Creeper Head Appearing On LED Matrix

from sense_hat import SenseHat
import time
import sys
from ISStreamer.Streamer import Streamer


logger = Streamer(bucket_name="Sense Hat Environment Stream", access_key="zLahwAUqKbNKv6YvuT5JuO58EiUOavDa")


sense = SenseHat()
sense.clear()
var = 14400


O = (0, 255, 0) # Green
X = (0, 0, 0) # Black


creeper_pixels = [
    O, O, O, O, O, O, O, O,
    O, O, O, O, O, O, O, O,
    O, X, X, O, O, X, X, O,
    O, X, X, O, O, X, X, O,
    O, O, O, X, X, O, O, O,
    O, O, X, X, X, X, O, O,
    O, O, X, X, X, X, O, O,
    O, O, X, O, O, X, O, O
]


black_pixels = [
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X,
    X, X, X, X, X, X, X, X
]


while var > 0:
  temp = sense.get_temperature()
  temp = round(temp, 1)
  logger.log("Teperature C",temp)
  humidity = sense.get_humidity()
  humidity = round(humidity, 1)
  logger.log("Humidity :",humidity)
  pressure = sense.get_pressure()
  pressure = round(pressure, 1)
  logger.log("Pressure:",pressure)
  var = var -1
  logger.log("Seconds Until Script Exit",var)
  sense.set_pixels(creeper_pixels)
  time.sleep(5)
  sense.set_pixels(black_pixels)
  time.sleep(25)
  sense.clear()
  if var == 0:
    sys.exit()

















 

Run this code by using the command below. Note the “&” on the end. This tells the Raspberry Pi to run the script in the background and return the command prompt in the terminal. This allows you to continue developing on your Pi while the script runs. Also note that this means that if the Pi loses power, or you reboot it, the script will stop and you will need to re-run it. You can get around this by setting the script to run on startup. A good tutorial on how to do this can be found at the following instructable. Additionally, you can download all of the code used in this project from it's Github repo.

 

initial_state_data_foginator3.jpg

 

If you would like to see the data in real time, that my Raspberry Pi / Sense Hat combo is generating, visit the following link or click the image above.

 

 

So that wraps up part 3 of the Foginator2000 project. This was a really fun portion of the project for me as I got to learn how easy it is to push data to InitialState, as well as how easy it is to use the Raspberry Pi Sense Hat. Hats off to the AstroPi team, and the Raspberry Pi Foundation for creating such a feature-rich and easy to use Pi Hat. Tune in in just a few days for my next installment on the Foginator2000 project. Until then remember to Hack The World and Make Awesome!

 

Win this Kit and Build-A-Long


  1. Project Introduction
  2. Fog Controller Hardware and Test
  3. Environment Sensing Coding & Testing
  4. Ambient Audio Hardware and Coding
  5. Lighting Coding and Testing
  6. October 16th -  Final Assembly and Testing
  7. October 23th - Project Wrap-up

Foginator-Banner-002.jpg

 

Welcome to installment #002 of my Foginator 2000 Halloween Project here at Element14. In this week's episode I am going to cover the basics of automating an ADJ VFI1300 1300W Fog MachineADJ VFI1300 1300W Fog Machine via a Raspberry PiRaspberry Pi and a Parallax PIR Motion SensorParallax PIR Motion Sensor. The process is fairly simple, and only involves a handful of lines of Python code, so even the code-beginner should easily be able to get this working.

 

20150916_212859_HDR.jpg

 

Below is a table containing the parts you will need for this project. In addition to these parts you will need a drill, drill bit, soldering iron, stranded hook up wire, and some female to female jumper wires.

 

Newark Part No.

Notes

Qty

Manufacturer / Description

38Y646738Y6467

RPi

1

RASPBERRY PI 2, MODEL B

38Y647038Y6470

SD Card

1

RASPBERRY PI 8GB NOOBS MICRO SD CARD

44W493244W4932

PSU

1

USB PORT POWER SUPPLY 5V, 1A

06W104906W1049

USB Cable

1

USB A PLUG TO MICRO USB B PLUG

53W628553W6285

WiFi Dongle

1

USB WIFI MODULE

 

 

 

MCM Part No.

Notes

Qty

Manufacturer / Description

83-14732

Relay Module

1

TinkerKit Relay Module

555-19400

Fog Machine

1

Fog Machine Hurricane 901

28-17976

Parallax PIR Sensor

1

PIR Infared Measurement Sensor Module

 

 

The Theory

 

 

The fog machine will trigger when trick-or-treaters trip its motion sensor. Throughout this project we will call this a “trick-or-treat event,” or “T&T Event” for short. So when the T&T event happens, the fog machine to fire off and begin fogging out the immediate area. To do this we need to first take a look at how a fog machine works, and methods to trigger a fog-machine based on motion detection. First we will take a quick look at how a fog machine works.

 

fog-machine-diagram1.jpg

In the image above you can see how the basic operations of a standard fog machine works. Fog liquid is pumped from a reservoir into a heater block, which flashes to a vapor and exits out of a nozzle due to the pressure created by the expanding gasses. Everything is controlled from a central control interface, and depending on the quality and brand, this could be nothing more than a few passive components all the way up to a full scale MCU-based controller.

 

On most fog machines with manual remotes, a small LED indicator is present that illuminates when the heater block has reached optimal temperature. On the ADJ 1300W that we are using, this LED, as well as the push button are powered by low voltage, but on many fog machines, these components can be powered by mains voltage. Exercise extreme caution and high voltage safety when modifying any fog machine.

 

So in theory we should be able to use a relay to trigger the fog machine using the wires that go to the push button. As an added bonus we should be able to use the signal from the “ready” led to tell the Raspberry Pi that the fog machine is armed and ready to spray fog. If your fog machine uses high-voltage for its LED, then this will not work, and you will have to design a rectifying solution. So the bulk of this blog post will be showing you how to modify the manual remote control for the ADJ VFI1300 1300W Fog Machine, this method may work on other ADJ fog machine products, but I am not sure. Remember that this will most certainly void your warranty, and you are assuming all risk associated with modifying a product to perform in a way it was not designed to do from the factory. I take on no responsibility if anything should go wrong.

 

 

The Schematic

 

 

Fog-Control-Schematic.jpg

As you can see in the image above, my plan is to utilize the TinkerKit relay module as a sort of “smart” switch to fire the fog machine. The PIR-based motion sensor will be used to sense motion which will tell the Raspberry Pi 2 to trigger the relay. I am using seven of the Raspberry Pi 2’s GPIO pins including both of its 5-volt pins, two of its ground pins, and three actual I/O pins.

 

Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900.png

 

Using the Raspberry Pi 2 GPIO Pinout reference above, you can see that the three I/O pins I am using are (BCM schema)

  • Raspberry Pi GPIO4 to TinkerKit Relay Module
  • Raspberry Pi GPIO17 to Parallax PIR Motion Sensor
  • Raspberry Pi GPIO27 to Fog Machine Remote “Ready” Indicator LED (used in a later project update)

 

With our schematic planned out, let’s begin the build by modifying the ADJ VFI1300 1300W Fog Machine’s manual remote control. Again, if you are modifying any fog machine’s remote control other than the exact model that I am using in this tutorial, beware that it could utilize mains voltage instead of low voltage. Proceed with caution.

 

 

Modifying The Remote

 

 

20150916_222341_HDR.jpg

Here we can see the manual remote that came with the ADJ VFI1300 1300W Fog Machine. Notice the “Output” button and the “Ready” LED. These are the objects we will be hacking some wiring to in order to connect them to our Raspberry Pi and TinkerKit relay module.

 

20150916_222411_HDR.jpg

Opening the remote up is quite simple and only requires the removal of four phillips head screws. Save the screws as we will be putting this back together when the modifications are complete.

 

20150916_223556_HDR.jpg

Once the back has been removed you will see a bundle of wires attached to two leads of the momentary push button and the “ready” indicator LED. To fire the fog machine one simply needs to close the “trigger” circuit by pressing the button. This means that we can easily modify this to utilize a relay to trigger the fog machine. Additionally we can use the low-voltage signal from the indicator LED to tell the Raspberry Pi that the fog machine is armed and ready to fire.

 

20150916_225217_HDR.jpg

Before we can solder in the wiring, we need to make room to place our three binding post. Since this case is tapered, you need to drill the holes just above the ADJ logo as seen in the image above. Make sure that you space the holes so that all three binding post will fit, and their mounting hardware does not get obstructed by the adjacent binding post’s hardware.

 

20150916_225648_HDR.jpg

As it turns out, the plastic used in the casing for the remote is quite cheap, and very brittle. I used a brand new, very sharp drill bit to drill a pilot hole, and then a larger one that was just as sharp, and the plastic fractured and flaked in a few places. If this were a proper glass-filled ABS or Nylon case this would not have happened.

 

20150916_230341_HDR.jpg

Take notice of how close the nuts are that fasten the binding post to the case. I failed to account for the proper spacing when laying out where to drill the holes, and somehow I got lucky enough that everything just barely fit. I would suggest that you add a dab of CA glue, hot glue or some other adhesive to these nuts as they tend to back off the threads after some time passes.

 

20150916_230351_HDR.jpg

As you can tell, I am not using the binding post I listed in the parts list for this post. I forgot to order the correct ones when I designed the kit, and am using some I found in my scrap parts box. The ugly green binding post was painted with craft acrylic paint from a local hobby store. It did not adhere as well as I wanted, but it serves its purpose of identifying the post as being different.

 

20150916_231709_HDR.jpg

Hacking the switch to work with our relay is super simple. You simply need to solder one of the switches leads to either the red or black binding post, and then solder the other switch lead to the other binding post. While you are in here, solder a wire from the anode side of the LED to the other binding post.

 

20150916_231808_HDR.jpg

I messed up and accidentally heated the heat shrink on the LED wire with my soldering iron which caused it to no longer slide over the LED’s lead. Instead of cutting it off and adding a new piece in, I simply chose to wrap it in 3M Super 33 Electrical Tape.

 

20150917_000450_HDR.jpg

Now simply screw the bottom of the case back on, and then cut three 24” lengths (or longer depending on your needs) of the stranded hook-up wire. I chose to use red, black, and yellow. For a cleaner look, I chucked the wires up in my cordless drill, and twisted them together. I lost a few inches in length because of this, but it looks much cleaner and is easier to manage. Connect the three wires to the binding post as shown in the image above. Red to red, black to black, and yellow to yellow.

 

 

Connecting The PIR Motion Sensor

 

 

Pir-Schematic.jpg

Connecting the Parallax PIR sensor to the Raspberry Pi is quite easy as well, and only requires a few lines of code to test its functionality. To start you will need to connect the PIR sensor to the Raspberry Pi as per the diagram above, following the pinouts below.

 

  • PIR “Out” Pin  to Raspberry Pi GPIO17
  • PIR “VCC” Pin to Raspberry Pi 5V Pin
  • PIR “GND” Pin to Raspberry Pi GND Pin

 

20150916_213334_HDR.jpg

With those connected, you will need to boot up your Raspberry Pi 2 with the NOOBS SD Card installed, or any SD Card with Raspbian installed on it. It is also advisable to update your version of Raspbian to the latest. If you need to learn how to do this, I briefly cover it in part two of my other Halloween Project, Trick or Trivia.

 

The Code

 

With everything updated, and the SSH connection still open, type the following command to create a python file for testing the PIR sensor

 

sudo nano test-pir.py


This will create the file and open it in the nano text editor. Before we paste the python code in, lets take a look at it step by step and what each step does.

 

We need to import the Raspberry Pi GPIO library, the time library, and the system library. So python can execute our code.

 

import RPi.GPIO as GPIO
import time
import sys


































 

Now we need to set up our GPIO pin. Note that we are using the BCM schema to run our code. For those of you who do not know, the Raspberry PI’s GPIO pins can be configured two different ways, GPIO.board and GPIO.bcm.  When setting the GPIO pins mode, you are telling it what numbering scheme your code will be adhering too. Unfortunately the pin numbering between each of the different modes changes on various models and revisions of the Raspberry PI. So if you are not running a Model B+ or Raspberry Pi 2, you will need to search the internet for the proper pinouts for the mode you select.

 

Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900.png

 

The GPIO.BOARD option specifies that you are referring to the pins by the number of the pin the the plug - i.e the numbers printed on the board (e.g. P1) and in the middle of the diagram above.

 

The GPIO.BCM option means that you are referring to the pins by the "Broadcom SOC channel" number, these are the numbers after "GPIO" in the green rectangles around the outside of the diagram above.

 

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(17, GPIO.IN)

























 

Now we can build a function to test our code. We will call the function fire_fog. The code below it basically says to set GPIO 4 to True (high) for three seconds (triggering the fog machine, then set it to False (stop firing fog), then the code cleans up the GPIO Pins, and exits the script.

 

def fire_fog():
    GPIO.output(4,True)
    time.sleep(3)
    GPIO.output(4,False)
    GPIO.cleanup()
    sys.exit()
   

























 

Now we need to tell the to wait for a high signal on GPIO17 (movement detected by the PIR sensor), and to run the fire_fog function if that high signal is present. I put this in a “while” statement so that it would loop over and over until motion is detected. There are better ways to do this, but I am still brushing up on my python.

 

while 1:
    time.sleep(3)
    if GPIO.input(17)==True:
        fire_fog()

























 

Now past the following lines of code into the file. You can also download this code from it's GitHub Repo. If you are using a terminal such as putty, you can simply copy this code and right click in the terminal to paste it.

 

import RPi.GPIO as GPIO
import time
import sys

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.OUT)
GPIO.setup(17, GPIO.IN)

def fire_fog():
    GPIO.output(4,True)
    time.sleep(3)
    GPIO.output(4,False)
    GPIO.cleanup()
    sys.exit()

while 1:
    time.sleep(3)
    if GPIO.input(17)==True:
        fire_fog()

























 

Now save and exit out of the nano text editor. If everything is connected correctly, and the code is correct, we can move onto connecting the TinkerKit relay module to the Raspberry Pi and test our PIR sensor out.

 

 

Connecting And Testing The Relay

 

 

Fog-Control-Schematic.jpg

Now connect the relay as shown in the schematic above, and the pinout below. Only make the Raspberry Pi to Relay connection at this time.


  • Tinkerkit Relay + Pin to Raspberry Pi 5V Pin
  • Tinkerkit Relay Signal Pin (Middle) to Raspberry Pi GPIO4
  • Tinkerkit Relay - Pin to Raspberry Pi GND Pin

 

20150916_213438_HDR.jpg

With everything connected, we can now test the PIR and Relay systems. From the terminal, enter the following command:

 

 

sudo python test-pir.py


20150916_213558_HDR.jpg

 

 

The script will wait a few seconds before looking for motion, so wait a few seconds, and then wave your hand in-front of the sensor. It will illuminate, indicating that motion was detected. If you do not hear the relay click on, then wait a few more seconds and try again. If the click does not happen after waiting for 15 seconds, then check the code again. If the code is working, you will hear the relay click on for three seconds and then click off.

 

 

Bringing It All Together

 

 

Relay-Pins.jpg

Now connect the red and black wires to the “Comm” (Common) and “NO” (Normally Open) contacts on the relay. Don’t worry about the “ready” (Yellow) wire for the moment. We will revisit it in another post.

 

20150917_000506_HDR.jpg

If you have not filled the fog machine with fog juice yet, now would be the time to do so. (I recommend Hog Fog as it is super clean, thick, low-lying, and have used it personally many times!)  With everything connected you can connect the remote’s cable to the fog machine, and then connect the fog machine to the mains supply. Switch the fog machine on, and wait for about 5 minutes for the green light to come on. The run the script again from the terminal.

 

sudo python test-pir.py

 

If everything is correct, then the PIR sensor should begin looking for motion three seconds after the script has been triggered. These three seconds allow for you to get out of the way when setting the Foginator2000.

 

 

That is going to end it for this installment of Project: Foginator2000! Tune in next week for installment 3, in which I work on the environment sensing coding & testing aspect of the project. If you have not yet seen my other Halloween project for 2015 here at Element14, head over to Trick or Trivia: A trivia-based Halloween Candy Dispenser - Part 001. Until next time, remember to Hack The World and Make Awesome!

 

Win this Kit and Build-A-Long


  1. Project Introduction
  2. Fog Controller Hardware and Test
  3. Environment Sensing Coding & Testing
  4. Ambient Audio Hardware and Coding
  5. Lighting Coding and Testing
  6. October 16th -  Final Assembly and Testing
  7. October 23th - Project Wrap-up

Trick-or-Trivia-Banner-002.jpg

 

Hello everyone! It’s been a week and I have been working hard at designing and writing the trivia interface for this project, and I am proud to say that after an absence of more than five years from Python, I was successful in getting a decent looking GUI built. Unfortunately I have yet to figure out how I will be randomizing the questions that the device ask trick-or-treaters, but that is something I can work on later in the project. So let’s jump in and take a look at how I created the trivia interface.

 

In my first post, I mentioned that I had planned on using the Drupal CMS to build the trivia interface. After some conversation with another Drupal developer, I came to the conclusion that using a PHP-based framework and building a database was way overkill when I wanted to just display a few questions on a screen. So I decided to just write the whole trivia interface in Python, a language I have not touched in more than five years. Unfortunately my entire Python experience was in the command line, and I had never tried writing a GUI before.

 

TrickOrTriviaScreen.jpg

 

After some research I found out that it is extremely easy to create a simple, low-level user interface in Python by using a GUI library named Tkinter. For those of you who have never heard of Tkinter (like me), it’s Python's de-facto standard GUI (Graphical User Interface) package. It is a thin object-oriented layer on top of Tcl/Tk. Using Tkinter I was easily able to create a nice full-screen application that would clearly present the question and its answer buttons to the user.

 

 

Installing The Raspberry Pi 7-InchTouch Screen

 

 

TrickOrTrivia_002 (5).jpg

Before I show you the interface and the code that created it, let’s take a look at what we will be displaying the code on. Element14 sent me the brand new Raspberry Pi 7-inch touch-screen LCDRaspberry Pi 7-inch touch-screen LCD to use in this project, and after spending a couple of weeks with this screen, all I can say is WOW. I have used several different screens with the Raspberry PiRaspberry Pi, and Beaglebone BlackBeaglebone Black boards, and none has been as easy as this screen was to use.

 

 

TrickOrTrivia_002 (1).jpg

Getting the Raspberry Pi 7-inch Touch Screen up and running is as simple as connecting the large ribbon cable to the back of the driver board, and then securing the driver board to the screen with the provided hardware.

 

 

TrickOrTrivia_002 (2).jpg

With the driver board mounted to the LCD screen, connect the smaller ribbon cable to the driver board. I found it was easier to do it this way since I have larger fingers.

 

 

TrickOrTrivia_002 (3).jpg

With thetwo LCD ribbon cables connected, mount the Raspberry Pi to the stand-offs, and then connect the DSI cable to both boards.

 

 

TrickOrTrivia_002 (4).jpg

Now connect the two power jumper wires to both boards as shown in the above image. You will also want to insert the SD card into the Raspberry Pi. If you are running the latest version of raspbian, you can now plug a 5V 2A power source into the LCD screen’s driver board. If you do not have a 5V 2A power source, you can remove the power wires that connect the two boards, and then connect a single 5V 1A power source to the Raspberry Pi and One to the LCD screen’s driver board.

 

You will have to connect your Raspberry Pi to video source via the HDMI port for this process, or SSH into the Pi if you know it’s IP address. If you are using the NOOBs SD card that comes with the kit for this tutorial, you will have to update to the latest Raspbian, as the one installed on it is out of date.

 

To see which version of Raspbian your Pi is running, use the following command in the terminal:

 

uname -a

 

Which should return something that looks like this.

 

 

Linux raspberrypi 4.1.6-v7+ #810 SMP PREEMPT Tue Aug 18 15:32:12 BST 2015 armv7l GNU/Linux

 

 

If your version of Raspbian is out of date, run the following commands in the terminal:

 

sudo apt-get update

 

Then

 

sudo apt-get upgrade -y

 

 

With the update and upgrades ran, you can now restart your Raspberry Pi, and the LCD screen should now work and display the login screen.

 

TrickOrTrivia_002-(6).jpg

 

 

Enter the desktop GUI by typing the following command after logging in.

 

startx

 

 

 

 

TrickOrTrivia_002 (6).jpg

 

Now that you are on the desktop, let’s look at how I built the trivia GUI.

 

 

GUI Build UsingTkinter

 

tkinter-logo.png

As I mentioned above, I decided to write my own GUI instead of using a heavy framework like Drupal to create a simple quiz interface. I looked at a few options and finally decided on a GUI solution that was already built into Python called Tkinter. I chose this because it was very lightweight which would save loading times, and because it seemed very simple to use.

 

The Knowledge

 

One of the biggest sellers for me on Tkinter was the sheer amount of documentation that is available online. New Mexico Tech has a great Tkinter reference on their website which was very helpful when troubleshooting, but the best resource I found was a series of Videos on YouTube from a user named TheNewBoston. I would highly recommend heading to his channel and watching his tutorial series on using Tkinter.

 

 

TheNewBoston's first Tkinter Tutorial

 

 

I ended up watching the entire series, but if you only have time to watch a few, everything up to video six will give you the knowledge needed to complete this project. Watch the videos if you are following along at home, and check out my code below which I have broken out to better explain what each section does.

 

The Code

 

We need to import Tkinter, the Raspberry Pi GPIO as GPIO, Time, and system libraries.

 

from Tkinter import *
import RPi.GPIO as GPIO
import time
import sys
































 

 

Here we set up the GPIO pins. For the purpose of this tutorial I turn GPIO warnings to off. Then we need to set the GPIO Pinout to the BCM layout. Finally we need to define two output pins that will turn on a pair of LEDs.

 

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.OUT)
GPIO.setup(19, GPIO.OUT)
































 

 

For those of you who do not know, the Raspberry PI’s GPIO sins can be configured two different ways, GPIO.board and GPIO.bcm.  When setting the GPIO pins mode, you are telling it what numbering scheme your code will be adhering too. Unfortunately the pin numbering between each of the different modes changes on various models and revisions of the Raspberry PI. So if you are not running a Model B+ or Raspberry Pi 2, you will need to search the internet for the proper pinouts for the mode you select.

 

  • The GPIO.BOARD option specifies that you are referring to the pins by the number of the pin the the plug - i.e the numbers printed on the board (e.g. P1) and in the middle of the diagram below.
  • The GPIO.BCM option means that you are referring to the pins by the "Broadcom SOC channel" number, these are the numbers after "GPIO" in the green rectangles around the outside of the diagram below.

Raspberry-Pi-GPIO-Layout-Model-B-Plus-rotated-2700x900.png

Raspberry Pi B+ and Raspberry Pi 2 GPIO Pinout.

 

 

We need to set the state to True

 

state = True





























 

 

This section defines a function called blink_led. At the end of this script I add a sys.exit line that is executed three seconds after I turn off the GPIO pin for the last time. This exits out of the quiz script, allowing us to reset for the next trick-or-treater.

 

def blink_led():
# endless loop, on/off for 1 second
    while True:
        GPIO.output(26,True)
        time.sleep(1)
        GPIO.output(26,False)
        time.sleep(1)
        GPIO.output(26,True)
        time.sleep(1)
        GPIO.output(26,False)
        time.sleep(1)
        GPIO.output(26,True)
        time.sleep(1)
        GPIO.output(26,False)
        time.sleep(1)
        GPIO.cleanup()
        time.sleep(3)
        sys.exit()





























 

 

This section sets up another function that blinks the same pattern, but this time we name the function blink_led_2.

 

def blink_led_2():
# endless loop, on/off for 1 second
    while True:
        GPIO.output(19, True)
        time.sleep(1)
        GPIO.output(19, False)
        time.sleep(1)
        GPIO.output(19, True)
        time.sleep(1)
        GPIO.output(19, False)
        time.sleep(1)
        GPIO.output(19, True)
        time.sleep(1)
        GPIO.output(19, False)
        time.sleep(1)
        GPIO.cleanup()
        time.sleep(3)
        sys.exit()





























 

 

Now we need to set up Tkinter. The first thing we need to do is set up a basic box that will hold the elements of our GUI. We do this by telling the program that root=Tk().

 

root = Tk()





























 

 

Now we need to set the window to not have a border, title, or any of the normal minimize, maximize, and close buttons.

 

root.overrideredirect(True)





























 

 

This line tells the program to set the window to full screen and auto size it to the screens resolution.

 

root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))





























 

 

Now we need to tell the program to set the focused window to this one.

 

root.focus_set()





























 

 

We also need to set the window’s background to black.

 

root.configure(background='black')





























 

 

With the basic GUI window setup we can move on to setting up the elements that will appear in the z. This consist of three labels on top that span three rows of a grid, followed by two answer buttons on the next row spaced apart by two columns, and another row with two buttons and the same spacing below it. Finally we need to add two more labels to the bottom that describe what the rewards are for correct and incorrect answers. You will see that I have styled the elements inline with basic styling options, and placed the elements using Tkinter's .grid Geometry Manager.

 

 

Setting up the Labels.

 

 

In each of these three labels you can see that I have placed them in the root box, and included font, font size, background color, and foreground color attributes. and the set each of the labels to display using the .grid method followed by some placement style and padding attributes.

 

 

label_1 = Label(root, text="Welcome to Trick or Trivia", font=("Helvetica", 36), bg="black", fg="white")
label_1.grid(columnspan=6,padx=(100, 10))
label_2 = Label(root, text="Answer the question for candy!", font=("Helvetica", 28), bg="black", fg="red")
label_2.grid(columnspan=6, pady=5, padx=(100, 10))
label_3 = Label(root, text="Casper is a friendly ____!", font=("Helvetica", 32), bg="black", fg="green")
label_3.grid(columnspan=6, pady=5, padx=(100, 10))





























 

 

Setting up the Buttons

 

Just like the Label elements, I defined the buttons by placing them into the root window, adding text, and including attributes for font type and font size. Here is a reference (http://effbot.org/tkinterbook/button.htm). What makes the buttons special is the “command” attribute I included at the end of the button setup line. This calls the function it names, which in our case is one of the two blink_led functions we wrote earlier. Finally I displayed the button using the .grid method with some styling attributes.

 

button_1 = Button(root, text="Ghost", font=("Helvetica", 36), command=blink_led)
button_1.grid(row=4, column=2, pady=5, padx=(100, 10))
button_2 = Button(root, text="Ghast", font=("Helvetica", 36), command=blink_led_2)
button_2.grid(row=4, column=4, sticky=W, padx=(100, 10))
button_3 = Button(root, text="Ghoul", font=("Helvetica", 36), command=blink_led_2)
button_3.grid(row=5, column=2, pady=5, padx=(100, 10))
button_4 = Button(root, text="Gremlin", font=("Helvetica", 36), command=blink_led_2)
button_4.grid(row=5, column=4, sticky=W, padx=(100, 10))





























 

 

Finally I added two more labels with the same styling and placement attributes as before.

 

label_4 = Label(root, text="Correct Answer = 3 Pieces", font=("Helvetica", 20), bg="black", fg="green")
label_4.grid(columnspan=6, padx=(100, 10))
label_5 = Label(root, text="Incorrect Answer = 1 Piece", font=("Helvetica", 20), bg="black", fg="red")
label_5.grid(columnspan=6, padx=(100, 10))





























 

 

Finally we need to tell the program to stay in the event loop until we close the window.

 

root.mainloop()





























 

 

Putting It All Together

 

Here is what the code looks like as a whole. You can download this code from my Github repo for this project or by clicking here.

 

 

from Tkinter import *
import RPi.GPIO as GPIO
import time
import sys


GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(26, GPIO.OUT)
GPIO.setup(19, GPIO.OUT)


state = True


def blink_led():
# endless loop, on/off for 1 second
    while True:
        GPIO.output(26,True)
        time.sleep(1)
        GPIO.output(26,False)
        time.sleep(1)
        GPIO.output(26,True)
        time.sleep(1)
        GPIO.output(26,False)
        time.sleep(1)
        GPIO.output(26,True)
        time.sleep(1)
        GPIO.output(26,False)
        time.sleep(1)
        GPIO.cleanup()
        time.sleep(3)
        sys.exit()


def blink_led_2():
# endless loop, on/off for 1 second
    while True:
        GPIO.output(19, True)
        time.sleep(1)
        GPIO.output(19, False)
        time.sleep(1)
        GPIO.output(19, True)
        time.sleep(1)
        GPIO.output(19, False)
        time.sleep(1)
        GPIO.output(19, True)
        time.sleep(1)
        GPIO.output(19, False)
        time.sleep(1)
        GPIO.cleanup()
        time.sleep(3)
        sys.exit()


root = Tk()
root.overrideredirect(True)
root.geometry("{0}x{1}+0+0".format(root.winfo_screenwidth(), root.winfo_screenheight()))
root.focus_set()  # <-- move focus to this widget
root.configure(background='black')
root.config(cursor="none")


label_1 = Label(root, text="Welcome to Trick or Trivia", font=("Helvetica", 36), bg="black", fg="white")
label_1.grid(columnspan=6,padx=(100, 10))
label_2 = Label(root, text="Answer the question for candy!", font=("Helvetica", 28), bg="black", fg="red")
label_2.grid(columnspan=6, pady=5, padx=(100, 10))


label_3 = Label(root, text="Casper is a friendly ____!", font=("Helvetica", 32), bg="black", fg="green")
label_3.grid(columnspan=6, pady=5, padx=(100, 10))


button_1 = Button(root, text="Ghost", font=("Helvetica", 36), command=blink_led)
button_1.grid(row=4, column=2, pady=5, padx=(100, 10))


button_2 = Button(root, text="Ghast", font=("Helvetica", 36), command=blink_led_2)
button_2.grid(row=4, column=4, sticky=W, padx=(100, 10))


button_3 = Button(root, text="Ghoul", font=("Helvetica", 36), command=blink_led_2)
button_3.grid(row=5, column=2, pady=5, padx=(100, 10))


button_4 = Button(root, text="Gremlin", font=("Helvetica", 36), command=blink_led_2)
button_4.grid(row=5, column=4, sticky=W, padx=(100, 10))


label_4 = Label(root, text="Correct Answer = 3 Pieces", font=("Helvetica", 20), bg="black", fg="green")
label_4.grid(columnspan=6, padx=(100, 10))


label_5 = Label(root, text="Incorrect Answer = 1 Piece", font=("Helvetica", 20), bg="black", fg="red")
label_5.grid(columnspan=6, padx=(100, 10))




root.mainloop()





























 

Copy and paste this code into a new file on your Raspberry Pi’s desktop, or from the command line enter the following commands.

 

cd Desktop

sudo nano TrickorTriviaQuiz.py

 

 

 

 

Then right click to paste the copied code into the new file, and exit nano.

 

 

Setting up the LEDs

 

TrickOrTrivia_002-(8).jpg

 

Follow the diagram above and wire up your LEDs to GPIO pins 19 and 26 . Since the Pi’s GPIO pins output a 3.3v signal, you do not need resistors if you are using a single red, green LEDs.

 

 

Running the program

 

TrickOrTriviaScreen.jpg

 

Now from the desktop, open the terminal (if you were not in the GUI or pasting the code remotely. With the terminal open, navigate to the desktop directory and enter the following command to run your new quiz program.

 

sudo nano TrickorTrivia.py

 

The trivia screen should pop up like in the video below. If you select a correct answer, then the green LED will illuminate and flash three times. If an incorrect answer is selected, then the red LED will illuminate and flash three times.

 

 

The LEDs used in this tutorial are just for troubleshooting purposes, and are not part of the kit. You can use any LEDs you have laying around, or two of the red 10mm LEDs included in the kit. In a future update, I will show you how to write a function that rotates a servo via the GPIO pins and we will replace the blink_led calls with this. For now this proves that the quiz script works, and that we are okay moving forward with the next step in the project. Check back next week for another update, and until then, Hack the World and Make Awesome!

 

 

Win this Kit and Build-A-Long

 

  1. Project Introduction

  2. Building The Trivia Interface

  3. Interfacing Ambient and Triggered Audio Events
  4. Building The Candy Dispenser & Servo Coding
  5. Carve Foam Tombstone
  6. October 24th -  Assembly and Testing
  7. October 28th - Project Wrap-up

foginator001jpg.jpg


Halloween has always been one of my favorite holidays, so much so that I founded a business that makes professional-grade props and controllers for Haunted Houses. This naturally led to Element14 asking me to create a couple of projects that were easy enough for the community to follow along and replicate the project at home. For my second project, I am going to be creating a automated Fog Machine controller that utilizes a Raspberry Pi, and the new Sense Hat.

The Concept


foginator-Flow-Chart.jpg


The basis of this project is to utilize the all new Sense Hat from the Raspberry Pi Foundation to work in conjunction with the Raspberry Pi and a Relay to activate a fog machine when guest trigger a motion sensor. For those of you who might not follow new Raspberry Pi products as myself, the Sense Hat features an array of environment sensors that relay data back to the Raspberry Pi. To be honest, I struggled to figure out how I would tie the Sense Hat back into this project, and after a few conversations with friends I think I have come up with an idea.


I am going to utilize the Sense HatSense Hat to log data about the environmental conditions on Halloween Night and use the fog machine triggers to log what I will call a “Trick or Treat” event. When the night is over, I will compile the data and try to determine if swings in temperature, humidity, or air pressure correlates to a rise or fall in trick or treat events.


senshat.jpg


I will also utilize a few more of the Raspberry Pi’s GPIO pins to trigger some special effects lighting (NeoPixels), and will play an array of spooky ambient sounds, halloween-themed music, and (if time allows) audio events when the fog machine is triggered. One final bonus feature will be to integrate some form of remote notification when a trick or treat event occurs.

This project will progress a little faster than my Trick or Trivia Candy Dispenser project, mostly because I am building both at the same time. I purposely kept this project a little more simple for this reason. You will also note that I have chosen to use an off-the-shelf relay module this time instead of building my own as I will be doing in my other project. This is both in the spirit of saving some time, but as well to illustrate that there is alternative solutions that are ok to use as well.


The Hardware



Newark Part No.

Notes

Qty

Manufacturer / Description

38Y646738Y6467

RPi

1

RASPBERRY PI 2, MODEL B

38Y647038Y6470

SD Card

1

RASPBERRY PI 8GB NOOBS MICRO SD CARD

44W493244W4932

PSU

1

USB PORT POWER SUPPLY 5V, 1A

06W104906W1049

USB Cable

1

USB A PLUG TO MICRO USB B PLUG

53W628553W6285

WiFi Dongle

1

USB WIFI MODULE

18J555818J5558

Home Pir Sensor

1

PIR MOTION SENSOR

40P118440P1184

Speaker

1

SPEAKER, 20 kHz, 8OHM, 4W

26Y845826Y8458

Fog Coloring Rings

1

NEOPIXEL RING - 16 X WS2812

26Y851226Y8512

Ambient LEDs

1

NEOPIXEL 8MM THROUGH HOLE LED

26Y852826Y8528

AMbient LEDs

1

NEOPIXEL 5MM THROUGH HOLE LED

26Y846026Y8460

Mood LEDs

1

NEOPIXEL DIGITAL RGB 1M 144LED BLACK

34C109234C1092

PSU Vreg

1

LM7805 LINEAR VOLTAGE REGULATOR, 5V, TO-220-3

58K379658K3796

PSU LED Resistor

1

METAL FILM RESISTOR, 1KOHM, 250mW, 1%

17F216517F2165

PSU Filter Cap

1

CERAMIC CAPACITOR 0.1UF, 50V, X7R, 20%

69K794969K7949

PSU Filter Cap

1

ELECTROLYTIC CAPACITOR 47UF, 50V, 20%

69K790769K7907

PSU Filter Cap

1

ELECTROLYTIC CAPACITOR 100UF, 50V, 20%

14N941814N9418

PSU LED

1

LED, RED, T-1 3/4 (5MM), 2.8MCD, 650NM

49Y756949Y7569RPi Sense Hat1Raspberry Pi Sense HAT




MCM Part No.

Notes

Qty

Manufacturer / Description

83-14732

Relay Module

1

TinkerKit Relay Module

555-19400

Fog Machine

1

Fog Machine Hurricane 901

28-12812

Audio Amp

1

Audio Amplifier Kit 2 X 5W RMS

83-15748

Logic Level Converter

1

8 Channel Logic Level Converter

21-15178

Project Enclosure

1

ABS Case Gray - 5-5/8" x 3-1/8" x 1-3/16"



As you can see, in this project I am using a fairly high-end fog-machine. Any fog machine will work as long as it has a wired remote. You can use a $19.99 200W fog machine from a party store, or a $699 fog machine from a professional event supply shop as long as it has a wired remote with a push button. Additionally, you will need to purchase some form of water-based fog juice. There are hundreds of brands out there, and all will work just fine, but some of the more professional brands like Froggy’s Fog will have better results. You could even make your own fog juice and I will include a recipe for that in a later blog post.


The ADJ 1300w Fog Machine In Action. Video courtesy ADJ Lighting.


In addition to the parts listed above, you will need a few yards of 3-conductor wire (4-wire phone cable works well), or 100 feet or more of single conductor wire that will need to be paired up for the NeoPixel and Audio components. Finally, you will need a 3.5mm audio extension cable, an ethernet patch cable, or a wifi router. A soldering iron will also be needed to assemble parts of the kit. Having some heat shrink tubing, electrical tape, zip ties, and a hot glue gun on hand would be advised as well.

If you have any questions, suggestions, or comments in general, please feel free to leave them below, or by sending me a private message here at Element14. If anyone chooses to follow along at home and build their own Trick or Trivia Candy Dispenser, please post photos, and even blog post if you can as I am very excited to see your work!

I will be posting an update every Friday with the project wrapping up on October 16th. I have taken the liberty of laying out each of the weekly milestones below.


Win this Kit and Build-A-Long


  1. Project Introduction
  2. Fog Controller Hardware and Test
  3. Environment Sensing Coding & Testing
  4. Ambient Audio Hardware and Coding
  5. Lighting Coding and Testing
  6. October 16th -  Final Assembly and Testing
  7. October 23th - Project Wrap-up

Filter Blog

By date: By tag: