Using the Rasp Pi to make Halloween really spooky

The Ghost Program

The entire Halloween ghost program is found on the FTP site [2]. As is typically the case with Java imports, it defines the class containing the main() method. All of the data needed by the LEDs for creating the eyes and the mouth are found in the two-dimensional array eye[][]. The task of calculating values for display is simple but nonetheless time intensive.

Listing 5 shows the crucial section, which defines an input port for the PIR sensor. You should attach an event listener to this port by means of an anonymous class of type GpioPinListenerDigital(). In this class, you overwrite the method handleGpioPinDigitalStateChangeEvent() with your own code.

Listing 5

Define PIR Input Port

01 final static File soundFile = new File("gost.wav");
02 static AudioInputStream audioIn=null;
03 static Clip clip=null;
05 public static void main(String args[])throws Exception {
06   final GpioController gpio = GpioFactory.getInstance();
07   final GpioPinDigitalInput pir = gpio.provisionDigitalInputPin(RaspiPin.GPIO_00,PinPullResistance.PULL_DOWN);
09   audioIn = AudioSystem.getAudioInputStream(soundFile);
10   clip = AudioSystem.getClip();
13   pir.addListener(new GpioPinListenerDigital() {
14     @Override
15     public void handleGpioPinDigitalStateChangeEvent(GpioPinDigitalStateChangeEvent event) {
16       if((event.getState()==PinState.HIGH) && !running) {
17         running=true;
18         System.out.println("wake up");
19         eyeOpen();
20         slp(1000);
21         gost.clip.setFramePosition(0);
22         gost.clip.start();
23         spuk();
24         spuk();
25         spuk();
26         eyeClose();
27         eyeInit();
28         slp(60000);
29         gost.clip.stop();
30         running=false;
31       }
32     }
33   });
35   int fd = Spi.wiringPiSPISetup(SPI_CHANNEL, 1000000);
37   if (fd <= -1) {System.out.println("Can't init SPI");return;}
39   initBuffer();
40   eyeInit();
41   SoftPwm.softPwmCreate( 1, 0, 100 );
42   SoftPwm.softPwmCreate( 2, 0, 100 );
43   SoftPwm.softPwmWrite( 1, 20 );
44   SoftPwm.softPwmWrite( 2, 10 );
45   SoftPwm.softPwmWrite( 1, 0 );
46   SoftPwm.softPwmWrite( 2, 0 );
47   slp(1000*60*60*10);// the program remains active for 10 hours
48 } //main

The first thing to do is to check that the pin is set to HIGH. This prevents the ghost from continuing to shriek when the sensor switches off. The computer should not execute the method more than once, so the script sets the running variable to prevent this from happening. The methods that follow are named so that it is self-evident what you should do.

The program plays the WAV file asynchronously. It therefore continues to run as soon as playback begins and does not wait for the audio file to come to an end. This occurs because it calls the spuk() method three times in succession. The time needed for these three calls corresponds almost exactly to the playback time for the WAV file.

As a result, everything important happens in this section. The slp() method involves a wrapper for the Java method Thread.sleep(), which hides the bothersome try/catch. At the end of the handleGpioPinDigitalStateChangeEvent() method, you can recognize the call to slp(). It prevents the ghost from shrieking on and on. The predefined length of time during which the ghost should shriek can be adapted as needed.

The main() method contains the steps for initializing the hardware. Listing 6 shows another important section in the code, which is the copyBufferToLed() method. This transmits the local buffer, found in the buffer[][] variables, by way of the SPI bus to the LED module. All of the methods responsible for the animation, like eyeClose(), only work initially on the local buffer.

Listing 6

Transmit Local Buffer

01 public static void copyBufferToLed(){
02   byte packet[] = new byte[MODULES*2];
03   for (int row = 0; row <= 7; row++) {
04     for (int col = 0; col < MODULES; col++) {
05       packet[0+(2*col)] = (byte)(row+1);
06       packet[1+(2*col)] = (byte) buffer[col][row];
07       Spi.wiringPiSPIDataRW(0, packet, MODULES * 2);
08     }
09   }
10 }

The servomotors are controlled with the SoftPwm methods from the Pi4J library. This works surprisingly well. If you would like to have more exact control over the servos, it pays to review the ServoBlaster project.

Last but not least, a series of methods are responsible for initializing the SPI devices. You should study the data sheet for the MAX7219 [9] before working with it. Then, you transfer the program to the Rasp Pi (e.g., using SFTP). Next, the program is compiled on the Rasp Pi and then booted (Listing 7). Now nothing is in the way of the ghost scaring those who venture near.

Listing 7

Compile and Boot Program

$ pi4j -c
+ javac -classpath '.:classes:*:classes:/opt/pi4j/lib/*' -d .
$ pi4j -r gost
+ sudo java -classpath '.:classes:*:classes:/opt/pi4j/lib/*' gost


This project once again shows what the Rasp Pi is capable of doing. The program proves that the Pi4J library provides elegant access to the hardware. The software presented in this article is just one example of how a ghost like the one described here can be created. It can be adapted and expanded as desired. For example, the ghost could howl more gruesomely or be integrated into its environment. It is relatively unlikely, however, that you can have the ghost open the door for trick or treaters and hand out candy. Nonetheless, Halloween visitors should enjoy this Halloween Rasp Pi creation.

Buy Raspberry Pi Geek

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content