Pumpkin Pi

Pumpkin Pi

 I really like Halloween and year after year I find new ways to really get into the halloween spirit.  Some people bake cookies and others put on haunted houses. Me, I like tech.  This year I created a talking pumpkin with motion detection and addressable LEDs that light up with audio peaks.

 At first I wanted to use a raspberry pi pico for this because I have been trying to work more with microcontrollers.  I knew it would be tough and I had only come up with the idea for this about 2 weeks before Halloween.  I would need to reconstruct some audio circuitry and somehow get extra storage onto a pico since it can only hold 2mb.  I would have to wire up and configure the code to be able to read directly from an sd card or something.  There is such a method to do that, but it required lots of configuring on the pico and I knew I would probably screw it up, and it would just take too long to properly implement.  

So I decided to just use a normal raspberry pi.  

 This would make things much easier because it already had audio output via the 3.5mm audio jack and it used an sd card to store the os.  On hand I only had a raspberry pi 2 (Raspberry Pis are still hard to get.)  It is pretty old at this point but this little Pi would be enough, barely (More on this later.)  

 My initial idea was to just write a simple python script that would wait for detection on a motion detector and if it read motion, then it would play an audio file and blink the LEDs.  I thought this script would be really simple, so I just wrote it directly on the pi itself through ssh and with vim as my editor.  I started with the 'pumpkin.py' file.

 I looked online for the easiest way to play a wav file through the pi and the consensus was to just use 'pygame'.  Pygame is a nice little python library for making games and it has a neat and nice little 'mixer' object that I can use.  You just load it up, init it, load a wav file and play it.  It's awesome and easy.

  I was getting an error at first saying that some 'libsdl2-mixer-2.0-0" was not found.  This had an easy solution of just installing the missing lib with 'sudo apt install libsdl2-mixer-2.0-0' and all was well.

 I wired up a 3.5mm cable to a tiny mono amp from Adafruit that I had.  Then I wired the output to a tiny 20hm speaker.  These speakers are really good for replacing bad gameboy color speakers.  It worked great and sounded nice and loud.  With the audio taken care of, it's time to blink the LEDs.  

Yes, messy flux I know, sorry

 I realized I still had some addressable LEDs on hand from an earlier project.  These would be way cooler to use than normal LEDs.  I wanted to use the neopixel library from Adafruit because I have used it before on the pico and it was easy.   This time there were many issues.  

 Apparently the neopixel library messes with the pi's audio for some reason.  I really don't understand it but when I tried to use the library, the audio would go crazy and get all fucked up.  I didn't spend too much time trying to debug and fix the issue because this issue actually gave me a really good excuse to use the pi pico.

 My new plan was to have the raspberry pi 2 communicate with the pi pico via serial uart.  First I had to setup the pi2b for serial uart.  To do this I followed this tutorial: https://medium.com/geekculture/serial-connection-between-raspberry-pi-and-raspberry-pico-d6c0ba97c7dc

 You have to go into the raspi-config and set the serial up in there.  I wired up gpio 0 (rx) of the pico to gpio14 (pin 8 tx uart) on the raspberry pi 2, looked up the code, wrote it and wow it just worked.  

 The only thing I had to fiddle with was the serial port.  The tutorial I followed online told me to use '/dev/ttys0' port but the actual port to use is the '/dev/ttyama0'. It was something about using uart0 vs uart1.  Probably my error.  Once that was fixed it worked beautifully.  

Serial object in Pumpkin.py

 If the raspberry pi 2 detected motion, it wrote '1' to the serial port and if the pico read a '1', it would blink the neopixel LED's.  Awesome.  But now I want more.  The LED blinking was lifeless and robotic.  I wanted the LED's to brighten and blink to audio peaks of the wav file.  

 Doing a spectrum analyzation on the wave form of the file during runtime would be waaayy to resource intensive.  The raspberry pi 2 was already old and struggling to keep up.  Especially since the sample rate of my audio files was about 44k.  I could use a smaller sample rate but then it sounds like poopie.  The solution that I went with was to predetermine the timings of the audio peaks and write that data to a json file.  So I wrote a new python script, 'WavSpectrum.py' to do the work.

 First I would search an AudioFiles directory and grab all the '.wav' files within it. Next I would run each one through a simple algorithm that would take note of the elapsed time from the start if the tested amplitude value at that time was over a threshold variable.  To avoid grabbing a bunch of samples that were like less than a millisecond apart, I wrote the algorithm to only grab times that were at least 0.18 seconds apart.  If the previous recorded time had a difference of 0.18s or more with the argued time, then it would allow another time stamp entry.  I am not doing a good job of explaining it in text so here is some code lol.  

From WavSpectrum.py

 Now I have a nice neat json file with time stamps of when the LEDs should blink.  A little math expression of the current time - StartTime gives me an amount to wait in the while loop before sending a blink command from the rpi2 to the pico through uart.  I ran the wavspectrum.py file on the pi itself but since its a pi2 and a slow shitty algorithm that I wrote, it took forever.  I recommend running the python script on a desktop pc and then just transferring the json file it spits out.  

Pumpkin.py writing '1' to the uart serial buffer (GPIO 14, Physical Pin 8)
main.py file on the Pico, reads a '1' from the uart serial buffer (GPIO 0)

 The result of my trash little algorithm is actually pretty good in my opinion haha. The LEDs blink at moments you would expect.  Now I just gota carve a pumpkin and throw all this hardware inside of it.  

I chose a white pumpkin.
Ye, I pretty much just threw everything in there.

 I 3d printed some brackets and stuff but, yeah I just tossed it in.  You probably don't wana do what I did because it did get moist in there from the pumpkin and did give me some issues.  Here is a crappy schematic I drew to show you how it was roughly wired up.  

I was getting this weird error with alsa mixer.  "ALSA lib pcm.c:8545:(snd_pcm_recover) underrun occurred".  According to the internet its from too slow of a pi but I dunno, maybe it was from moisture.  Restarting the python script fixes it.  Or maybe the PIR sensor was sending too many motion events too fast for the pi2 to handle or something.  Also the LEDs were kinda bright so I put a diffuser (a paper towel in my case) to knock it down a bit.  

 I powered the 2 pi boards separate because I was worried about amp draw, and actually might have been the reason why I was getting that alsa underrun error, but I really don't know.  The usb power bank I used had an output of 5v 2amp.  The pico was powered by recycled lipos with a little charge board and the pi2b was powered by a generic usb power bank.

I got a github link for ya this time:

GitHub - OgreBeast/Pumpkin-Pi: Blinking talking pumpkin thingie I made.
Blinking talking pumpkin thingie I made. Contribute to OgreBeast/Pumpkin-Pi development by creating an account on GitHub.

Can see the full code there and all the hardware I used.  The formatting on the scripts isn't great because I just kinda quickly threw all the code together using vim.  

Damn this was a long ass post shit.  Anyway, here are the results.

Happy Halloween, if you made it this far then thank you for reading and checking out this dumb project haha.