Friday, December 2, 2016

Manage animatronic props from a wireless tablet, Part 2

Step 2:  Install a suitable web server and server-side application framework

(continued from Part 1)

Rather than Apache I went with NGINX for the web server.  Since I want to develop the web application in Python 3, I selected Django.  In order to work with Django, NGINX needs uWSGI.  I also want to use PostgreSQL as the database.

sudo apt-get install nginx

sudo apt-get install uwsgi
sudo apt-get install python3
sudo apt-get install python3-rpi.gpio
sudo apt-get install uwsgi-plugin-python3
sudo apt-get install python3-django

sudo apt-get install postgresql
sudo apt-get install python3-psycopg2

Breakdown of our "stack":

  1. NGINX is the web server
  2. uWSGI is the interface between the web server and the web application framework
  3. Django is the web application framework
  4. Python is the application programming language
  5. PostgreSQL is the database
Throughout this article I may talk about "editing a file" and I may or may not tell you how to do this.  I prefer to use the nano editor.  The syntax is nano followed by the path & filename.  If you are not root you will need to add the sudo command in front.

NGINX configuration

Since users will connect from a tablet such as an iPad, once they connect to the Raspberry Pi in wifi access point mode we want to redirect all traffic to the application.

Since many of the bookmark URLs in Safari (such as Google, Apple, etc.) start with https we need to configure NGINX to allow https over port 443 in addition to regular http over port 80.

First we generate a self-signed SSL certificate.

You'll need to read up on how to configure an NGINX site.  Here's how I configured mine:

server {
listen 80;
listen 443 ssl;
if ($scheme = https) {return 302 http://$server_addr/prophome.html;}
server_name localhost;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
access_log /var/log/nginx/asp.access.log;
error_log /var/log/nginx/asp.error.log;
location / {
     root /var/www/asp;
     index prophome.html;
     error_page 404 302 http://$server_addr/prophome.html;
location /app {
     include         /etc/nginx/uwsgi_params;
     uwsgi_pass      unix:/var/uwsgi/propos.sock;
     uwsgi_param     UWSGI_SCHEME $scheme;
     uwsgi_param     SERVER_SOFTWARE nginx/$nginx_version;
The scheme and error_page lines redirect the user's browser to the application page prophome.html which is just a basic "Hello World" html file we create for initial testing. 

Eventually prophome.html will be changed to the real application page.

This makes connecting simple; the user just clicks any icon in their Safari bookmarks and does not have to remember any special URL to access the application.

uWSGI configuration

In /usr/share/nginx/propos/ create a test program:
def application(environ, start_response):
     start_response('200 OK', [('Content-Type', 'text/html')])
     return [b"<h1 style="color: blue;">Hello There!</h1>"]
The b after return[ is required in Python3. Without it you will not get a response.

In /etc/uwsgi/apps-available, create an ini file for the application.

sudo nano /etc/uwsgi/apps-available/propos.ini

The file should look like this:

module = wsgi:application
chdir = /usr/share/nginx/propos/
python-path = /usr/share/nginx/propos
socket = /var/uwsgi/propos.sock
chown-socket = www-data
chmod-socket = 666
enable-threads = true
master = true
plugins-dir = /usr/lib/uwsgi/plugins
plugin = python34,http
uid = www-data
gid = www-data
vacuum = true
die-on-term = true
manage-script-name = true
Create a symbolic link for this file in ../apps-enabled:

sudo ln -s /etc/uwsgi/apps-available/propos.ini /etc/uwsgi/apps-enabled/propos.ini

Then restart uwsgi:

sudo service uwsgi restart

Then you might as well restart NGINX:

sudo service nginx restart

NGINX communicates with uWSGI over a unix socket which is specified in both config files (/var/uwsgi/propos.sock) - you may need to create the directory and/or adjust the permissions.

If you go to http://(pi address)/app you should see the test output:

Hello There!

If you see that, uWSGI is working correctly.  We will be reconfiguring propos.ini to work with a Django project in the next section.

Django configuration

Create a new Django project.  In this example I will use /home/pi/propos.

cd /home/pi
(do not create a propos directory in /home/pi, django admin will do that for you automatically)

django-admin startproject propos

Django will create the propos directory containing and a propos subdirectory containing other .py files.

Reconfigure uWSGI to point to this Django application:

sudo nano /etc/uwsgi/apps-available/propos.ini

Edit the file to look like this:

chdir = /home/pi/propos/
module = propos.wsgi:application
socket = /var/uwsgi/propos.sock
chown-socket = www-data
chmod-socket = 666
enable-threads = true
master = true
plugins-dir = /usr/lib/uwsgi/plugins
plugin = python34,http
uid = www-data
gid = www-data
vacuum = true
die-on-term = true
manage-script-name = true
Restart uWSGI:

sudo service uwsgi restart

After the service fully restarts If you go to http://(pi address)/app you should see something like this:

If you see that then uWSGI and Django are working correctly!

Thursday, November 10, 2016

Manage animatronic props from a wireless tablet, Part 1

Moving up to a Raspberry Pi from the Arduino provides several benefits.  The Pi is basically a computer which allows us to do a whole lot more.  We have more choices in programming languages, the ability to play high quality video and audio files, and with the Pi 3's integrated wireless network interface we can even turn the Pi into an access point and configure the prop via an iPad (or other wireless tablet) using a web interface.

Project Steps
  1. Configure a Pi 3 as a wireless access point that redirects all URLs to its own IP address and advertise a prop name over the network
  2. Install a suitable web server and server-side application framework (such as Python or Mono)
  3. Develop a prop control program that allows users to "program" prop logic using a web browser.  Pi GPIO pins can be referred to by name, On or Off can be defined as High or Low, video playback, audio playback, delays, if/then, looping, etc.  Optionally provide a way to change the wifi channel via the web interface, change the operating mode from access point to join an existing wifi network, and change other network settings
  4. Research audio/video capabilities (crossfading, looping, transition from static image to video on trigger, etc.)
  5. Interface 5v relay boards with Pi 3.3v GPIO
  6. Interface an audio amplifier board over i2c
  7. Build optoisolated triggers for Insteon, motion and IR beam-break sensors

Step 1:  Configure a Pi 3 as a wireless access point that redirects all URLs to its own IP address and advertise a prop name over the network

Update the Pi:

sudo apt-get update
sudo apt-get upgrade

Change the keyboard configuration to US (the Pi defaults to a UK configuration):

sudo dpkg-reconfigure keyboard-configuration

Comment out these lines in /etc/rsyslog.conf:

#       news.err;\
#       *.=debug;*.=info;\
#       *.=notice;*.=warn       |/dev/xconsole

Set the timezone of the Pi.  Run the next command from the console rather than over SSH:

sudo dpkg-reconfigure tzdata

Older Pi kernel versions defaulted power management to on which in conjunction with another setting may result in the integrated wifi interface going to sleep - most inconvenient when trying to manage the prop over wifi!

The apt-get update and upgrade steps performed above should upgrade the kernel.  You can check your kernel version by issuing the following command:

sudo uname -a

As of this writing my kernel version is 4.4.34-v7+ #930 SMP.

You can check the power save mode of the wifi interface using the following command:

sudo iw wlan0 get power_save

If it says power save mode is On then you can try adding this line to /etc/network/interfaces after the wlan0 section:

post-up iw wlan0 set power_save off

Then reboot and check the power save mode of the interface again to confirm it is now off.  If you ever see this mode change back to On make sure you have the proper power supply for the Pi 3.  I believe it needs to be at least 2.5 amps.  Also try searching the internet to solutions for the power management issue and try different solutions until it is resolved.  Following the above steps resolved the issue for me.  Moving on...

Set the hostname of the prop to "NewProp"

Configure the DHCP client to register as "NewProp":
  1. Edit /etc/dhcp/dhclient.conf
  2. Comment out with # any uncommented send host-name lines
  3. Add the line send host-name "NewProp";
  4. CTRL-X followed by Y and Enter to save & exit nano editor.
You need to select a static IP address for the prop.  I used for the first prop.  The next prop will use and so on.

I was able to successfully complete this step by following the instructions in these articles:
  • In /etc/hostapd/hostapd.conf, "driver=nl80211", the character after the n is an L not a 1.
  • Change all occurrences of 172.24.1 to 10.10.1
  • In /etc/hostapd/hostapd.conf change "ssid=Pi3-AP" to "ssid=NewProp"
  • Change "address=/#/" to "address=/#/"

After all the configuration changes have been made, run sudo reboot to reboot the Pi.

On the iPad, the wifi network shows up:
After connecting this is the IP info I got:

Running Fing on the iPad shows the Pi on the network under the specified hostname:

However, for the rest of the project we need to switch the Raspberry Pi 3 back to connecting to an existing wifi network so it has internet access to install packages and we can SSH to it from another computer.  The instructions for that are at:

You can use Fing on the iPad to determine what IP address it got from your home DHCP server (router):

Then you can use an SSH client (such as Putty) from any computer on your home wifi network to connect to the Pi to continue installation and configuration.

If SSH is not enabled on the Pi run sudo raspi-config and go to Advanced Options.  You should find SSH there.

I'll post additional Parts as I complete each project step.

Wednesday, October 19, 2016

Trashcan Monster, Part 2

Moving to 1/2" tubing and fittings definitely sped up the prop.  I think as a general rule of thumb you should go up a size or two on the fittings and tubing.  Even though the cylinder, valve and accumulator all have 1/4" NPT connections, look at the difference between these two fittings:

Two push-to-connect fittings with 1/4" NPT threads.
Left: 1/4" O.D. tubing.  Right: 1/2" O.D. tubing.
Even though these two fittings both screw into a component that has 1/4" NPTF connectors, the orifice on the right is twice as big, allowing greater air flow.

Initially I thought the Automation Direct NITRA valve was not performing to its specs, but it turned out the 1/4" tubing and fittings were choking the air flow.  1/2" tubing and fittings fixed the problem.

The prop uses my standard pneumatic design where each prop has its own accumulator tank to buffer air from the main supply line so as to not affect other props.

I like to use Insteon dual-band relay switches to trigger my props which allows me to use either a wireless remote control or a battery-powered Insteon motion sensor to trigger each prop.

The Insteon relay originally turned a 120VAC relay on and off.  The relay's normally-open contacts were connected to one of the Arduino's analog inputs through a pull-down resistor.  While testing the control box I discovered the Arduino was resetting every time the relay shut off, so I suspect the relay coil was discharging a spike which was affecting the AC to DC power supply.  I'm sure I could have fixed this with a diode or capacitor or something but I didn't want to deal with it and set off in search for another way for the Arduino to tell if the Insteon relay was turned on.

One technique would be to use a photodiode sensor aimed at a small light turned off and on by the Insteon relay.  I used a similar method in my Big Blue Clear-Com Call Light project. 

Another technique would be to use some kind of AC voltage or current sensor.  Since a current sensor would require a load - which could have been a light anyway, I searched for a voltage sensor.  Several articles on the internet mentioned the "zmpt101b" and I discovered it is sold on Amazon.

This AC voltage sensor board is a little tricky to use - while no AC voltage is applied the initial reading is stable, but when AC voltage is present the analog input reading sweeps from plus to minus around 60 from the initial reading.  This means that the reading crosses through the "off" value even when "on" which can lead to a trigger loop.  Code was needed to watch this reading and wait for it to stop sweeping to determine that it was truly "off."

Update:  After finishing the prop and writing this post, I discovered a couple of even smaller components to translate Insteon commands into an Arduino trigger:  A High Voltage Phototransistor Optocoupler ($0.49) and the INSTEON 2443-222 Micro On/Off Module ($40), which is apparently Dual-Band.  Again, next prop...

I've also come to realize that the sound quality of the ELK-120 board is not great.  Research into the specifications of its ISD 4004 chip showed it uses an audio sampling rate of 8khz.  Compare that to the 44.1khz rate of a regular audio CD.  Turns out it would have been cheaper to use a Raspberry Pi and a 20w amplifier board than the Arduino Leonardo, 4 channels of relay board and an ELK-120.  Not only cheaper, but better sound quality, and I'd save around 11 square inches of space which would let me use a smaller enclosure for all the electronics.  I'll do that on the next prop.

This video shows the control box internals.

This video shows the completed prop in operation.

I posted a parts list with pricing on Google Docs.

Monday, October 17, 2016

Halloween Yard Haunt Sound System

I have always had sound for my yard haunts.  Even going back to my childhood I had a basic system - a Halloween record playing through an outdoor speaker.  Over the years it has evolved. 
  • Early 1980s - record player and outdoor speaker
  • Late 1980s - two cassette decks crossfaded using a small Radio Shack mixer and several outdoor speakers.  There were different cassettes for each "scene" that the people would walk through and as they transitioned I would crossfade to the next cassette then change the cassette in the other player.
  • 2005 - A boombox playing a CD that loops and a digital recorder playing back through amplified speakers.
  • 2007 - Sound Cue System running on a laptop connected to a multichannel USB sound card, a couple of stereo consumer audio receivers and several 8 ohm speakers.
  • 2012 - 5 hour, 13-channel recording playing from an Alesis HD24 through a Crown 8-channel 70v amplifier and a 70v transformer on each speaker.

I've seen articles about using radios tuned to a weak FM transmitter, wireless speakers (which need power run to them anyway) or small self-contained sound systems with their own playback and amplifier components.

I still feel that the components used outside in the haunt should be inexpensive and easy to replace if stolen or damaged by weather.  So since 2012 I've been pretty happy with a centralized system. 

I use 70-volt constant-voltage wherever I can.  There are still a couple of channels that drive 8-ohm speakers over heavy cable to reduce loss, but all the 70-volt stuff runs over cheap 18-gauge lampcord.  Any 8-ohm speaker can be converted to use 70-volt by adding a transformer of the appropriate wattage.

This $13 70-volt transformer
is available from Amazon.

To compare standard 8-ohm mode against 70-volt, check out this chart:

Power available to system in watts using 18-gauge cable
 100 feet500 feet
70-volt / constant-voltage95.0878.63
8-ohm / constant-current74.3630.93

70-volt systems are far more efficient.

I purchase the sound effects from - once you own the sound effects you can legally use them in a public performance. 

Nero has a couple of free software utilities that were very useful when putting together the soundtrack.

Nero SoundTrax - great for layering sound effects
Nero WaveEditor - great for preparing individual sound effects

Once the individual tracks are completed they are played in a continuous loop while recording to the Alesis HD24.  I bought the HD24 on eBay years ago.  They are probably even cheaper now.

Recording the soundtrack

On the HD24 you can arm individual tracks separately so you can make one pass with the first set, move on to the next set, and so on.  I figured the longest Halloween night could ever run is five hours, so the "song" on the HD24 is that long.

The Alesis HD24

I felt the mix on a couple of the scenes would be best tweaked on site rather than premixed, so I kept those as separate channels and fed them through a Gentner AP800 mixer.  I hacked the Gentner using an Arduino to make a remote mix control.

The Gentner AP800 can be found on eBay for around $25

The output of the Gentner and the other channels from the HD24 connect to a Crown CTs-8200 8-channel amplifier. 

The Crown CTs-8200 can be found on eBay for around $400. 
That's $50 per channel!

Each pair of outputs on the Crown can be set to run in 70-volt or standard 8-ohm mode.

I found it handy to keep track of the patch and levels to make future setups easy.
System Configuration Record
How the sounds are used:
  1. Crickets - there are three speakers on the left channel and three speakers on the right channel, hid at ground level in ivy and bushes.
  2. Regular & Spooky Wind - balanced via the Gentner, there are three speakers on the left channel and three speakers on the right channel set along the edge of the roofline all across the front of the property.
  3. Tree Critters - one speaker per channel, hidden up in trees at the far left and right of the yard haunt.  The tracks cycle through things like bats, owls, birds, and other spooky sounds with a bit of silence in between each one.  They also alternate which side they play on.
  4. Zombie Scene - a story in sound about two zombies.  The speaker for this has a 12" woofer for good bass and is hidden at the rear of the scene area.
  5. Atrium Wind & Music - balanced via the Gentner, there are one to two speakers on the roof facing the atrium area.  The wind in here is different because it is an enclosed space.
The system fits into a 19" rolling rack: