Skip navigation
2016

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

Hello,

it is full of people here that are making home automation things in their spare time or as a hobby.

I am also doing this and want to make the project bigger.

It is called - webcontrol.link and it is a web application that is controlling raspberry pi connected to internet ant registered in the website of course, which has RF433/868mhz/2.4ghz modules.

The idea is to make one universal computer - raspberry pi with the modules and one software that everybody can use easily, and the programming language to be easily updated.

Till now it is working with 433 sender/receiver but i want to find better ones with antena..

The app is working with MQTT with publish/subscribe method and on the PI - it is python.

There is a logic for automatic update, so once the software is installed, it can be automatically updated at any time.

 

If somebody want to do something more than a hobby and it is interesting, you are welcome to join me.

There are many products in the market, why not to build our own:)

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

I’ve had a Unicorn pHAT sitting in a box for a while, but I finally used it in a simple project. Because it has four rows of LEDs, I thought it would be ideal to make a binary clock from.

 

 

A script fetches the time, converts it to binary and lights up the matching pixels on the LED matrix. Because the matrix has RGB LEDs, any colour can be used

 

You can find the full post and code on my blog: Binary Clock – Frederick Vandenbosch

See Part 1 of the project here.

See Part 2 of the project here.

See Part 3 of the project here.

 

 

 

The Wireless Charging and Portable Raspberry Pi for under $10 dollars – in all its glory.

It charges.

It’s portable.

It ain’t pretty…

 

The concept works. But, technically it was sorted out in 2009 when the first Palm Pre came out. I, in fact, had a Palm Pre back then. Since then, Palm and WebOS has ingrained itself into me like the love of a childhood cartoon show. For all its flaws, you love it like nothing else.

It isn’t surprising I immediately went to the old Palm phones immediately when I started this project. (Fun fact: I started this project 3 years ago! It’s been on the back burned for a long time.)

 

This was a short build, despite the 3 year gap in development. I originally was going to make a wireless and portable Pi B+. Then it was a 2. Now a 3.

Luckily, power demands and mounting footprints stayed the same.

 

Although wireless charging, inductive charging technology has advanced a bit more since the palm days, I found the prices of such “Qi” charger kits to be a little high for my taste. But, since Palm/webOS phones are nearly gone… I figured it was the perfect time to pick up a bunch of the accessories.

 

In the end, I have what I wanted. It can stay off the charger for around 1hr with the single Palm Pre/Pixi battery. It charges and stays on and useable at all times. Super-happy success!

 

Here is what I bought for this project:

1 Palm external battery charger with extra battery

1 Palm Pixi Inductive charging back cover

1 Palm Touchstone wireless charger base kit

I bought all 3, with more accessories, as a group on eBay for $5.00 with free shipping.

Sources I used were Amazon and eBay. I also bought a HP Pre 3, the last webOS phone, just for fun. I am currently using it on the service “Ting.”

 

1 surface mount relay (pulled from electronic surplus)

1 Voltage boost regulator (Bought in a pack of 10, so $2 each)

Bits of breadboard (surplus)

Project wire (surplus)

Raspberry Pi 3

Adafruit GPIO 2.8” Touchscreen

3D printed parts (Printed on my printer for cents in material)

 

So… to add wireless charging and portability to a Raspberry Pi with a touchscreen… was below $10.

I win! Yay! …

But no one is keeping score…. Hmm

 

Problems I experienced in the build:

  1. I didn’t quite realize the size of some of the components I used. The breadboard (pieces) in particular were very large and made fitting all together look terrible.
  2. Likewise, the project wire I used were not able to be tucked, neatly, into the housing. So, wires spill out everywhere.
  3. Ultimately, the screen I used was way too small to do anything with it. Using a 5” screen would be way nicer.
  4. Using a cellphone battery is a big issue. On a lot of batteries there are 3, 4 or more contacts. They aren’t simple +5V and GND. No, some are thermal sensor contacts, among other uses. In this case, I had 3 contacts. The 3rd contact is a for a thermistor for internal battery temperature sensing. To charge the battery, and use it for power, I had to “trick” the battery into working. When the system in placed on the Palm Touchstone charger base, the relay is powered… connecting the thermal sensor contact to the battery’s negative. This was the BRUTE FORCE way I chose to make the battery charge when it was on the base. When you take it off, the relay would turn off, it would disconnect the thermal contact. Which was the only way I could force the battery to supply power to the Pi when off the base. If I left the thermal and battery neg connected, the battery wouldn’t supply power to the Pi when off the charger base, in other words.
  5. The battery charger needed 5V to charge. But then, it would only output the typical Lithium 3.7V to the Pi. I added the voltage boost circuit to then bump up the 3.V back to 5V. I either need to boost or buck a voltage no matter what I did. I just found it annoying, to be honest. The Pi should have a voltage regulator onboard, in my opinion. Take any voltage and use it.

 

If I continue to refine this project:

  1. Taking all the additional components and make a small PCB for them.
  2. Use modern wireless charger components. Which would affect the first refinement. With this, a much larger battery. The Palm Pre was 1125mAh, I would make the new one close to 5000mAh.
  3. Use a bigger screen, and in turn, a larger 3D printed case.

 

 

Wireless Pi Schematic.PNG

Schematic, block, diagram.

 

wireless portable pi parts.jpg

All the parts used in the project's build. Note: I soldered the power pins to the bottom of the Raspberry Pi GPIO. Why? The screen was covering up the pins.

 

wireless portable pi working.jpg

One of the first tests. The Raspberry Pi is on and booted to the OS. The whole system is running off the battery.

 

wireless portable pi stacked up.jpg

The whole Wireless&Portable Raspberry Pi, charging, on the base. Yikes... that is one ugly mess. But it works!

 

 

See more of my project here:

Drinkmotizer, drink mixing robot

Project Goldie, my favorite - I animated the opening!

Pi Ball, a spherical and interactive Raspberry Pi case

Scary Door, Halloween #1

Scary Porch, Halloween #2

New Years’ Eve Countdown timer and Fireworks launcher

Raspberry Pi Arcade

Filter Blog

By date: By tag: