(Anything with Bluetooth or line out cable, anyway).
You know what I’m talking about, right? Billy Bass was a ridiculous, but genius wall-mounted fish that danced and sang a few songs. It was stupid, it was hilarious. People laughed their butts’ off for about 10 minutes then took the batteries out forever. UNTIL some genius hacked his Billy Bass so its’ mouth would move when he asked his Amazon Echo a question. Now he had his very own animated weatherman-weatherfish thing… Whatever you want to call it. The internet loved it…and my wife loved it. She asked me to make her one every single time that video popped up on Facebook for the next year or two so I finally decided to help my stepson make her one for Christmas.
There was a tutorial out there by James Bulpin that provided some great information, but I felt there had to be a simpler way. In the end, All I used was an Arduino Uno R3 and the audio amplifier out of some crappy computer speakers I had in a box. (And a couple jacks for power and audio in). *Note that I used an Arduino, but a Raspberry Pi would work just as well except you’d have to use an external analog to digital converter – Arduino has that built-in**
How Billy Bass works:
(There are a couple versions, and I think what I got on eBay is the original so what I found differs just a bit from other tutorial/breakdown pages) Once you take a bunch of screws out of the back panel, it pops right off. The back half just has the battery box and an on-off switch for the motion detector. The front half has the rubber fish, motors and gearboxes, a button and motion detector (either of which will make the fish sing and dance, but I immediately cut the wires to the button and motion detector to get them out of my way). The batteries add up to 6 volts but a quick test proved that Billy likes 5V off a power supply just fine – very convenient to replace the batteries with a micro-USB jack and power with a phone charger cube.
Everything is controlled by a microchip on the control board (It’s on a little circuit board soldered to the big circuit board, under a back blop) – it is programmed with the songs and dance moves. Most everything else on the board seems to be amplifiers for the audio and motors.
You can easily see three pairs of wires coming from the motors going to the control board – a pair for mouth, head, and tail. This is where I realized my board is different – James found an H-Bridge to drive the single head/tail motor while I have a pair of wires for each the head and the tail motors (in addition to the mouth). Looking closer at his picture, it’s obvious that everything is different… different enough that I have to wonder if my Billy Bass has the same h-bridge to reverse a single head/tail motor or two separate motors with separate driver circuits. This is a gift and I wanted to be careful not to damage the motor/gear assembly, so instead of taking the gearboxes off/apart I set about following every transistor backward from the motors and drawing my own circuit diagram…but only briefly before realizing that I don’t have to.
Regardless of what motor and driver scheme the different versions used, the microcontroller simply uses one of its pins as an output for each movement function, and one more for audio output. This would be typical of anything I’ve ever built or hacked.
James had concluded the motor outputs are analog but I have my doubts. I didn’t take an oscilloscope to it, but I see no reason the manufacturer would bother for such a simple skit, plus James had a problem with audible whining while trying to PWM less than 100%. No matter to me, really – even if the chip outputs a PWM or other analog signal, I could simply determine which pins were the outputs for which motor and what voltage I need to fully drive the transistors, then inject my own digital signal right there to make the mouth open and head lift. I shouldn’t even need a current limiting transistor because the existing circuit would already have one. This method would save me an Arduino motor shield or some other motor driver circuit, and some code to manage the PWM signals.
I made my test probe with an old adjustable bench supply I made as a kid, set to 2.5 volts for the first pass. I guessed that should be safe enough and I could always bump it up if I got no response from the motors, but if I started higher than the original circuit was designed to handle bad things would likely happen. For this test I put a milliamp meter and a 2.2k ohm resistor inline, connected the ground to the battery negative on Billy Bass, and set about testing each pin. In less than a minute, I had a drawing for which leads off the microblop were for which motor – easy peasy. As a bonus win, I found I could remove the resistor and bump test probe voltage up to 5 volts and still draw barely 5-7ma to fully drive the motors. This meant I could definitely connect the Arduino output pins directly to the output of the original chip with no extra interface at all except a wire.
I. Love. Simple.
What we need to happen now:
We need to take an audio line-out cable from Alexa and constantly read it as an analog input to our Arduino, which will convert it to a digital value from 0-1024. When our code decides Alexa is speaking, the Arduino outputs to our motors to move the head and mouth. I wanted to use the original Billy Bass speaker so I also need to Alexa audio signal to get to an amplifier and to the speaker. This proved slightly more troublesome than I’d hoped. Just slightly – we’ll get to that below. So….
Step One – Read the Audio Signals:
This I haven’t done before so a quick bit of research reminded me how audio signals work – your baseline sits at zero volts across a speaker, anything above or below zero powers a speaker magnet at varying intensities and frequencies. Above and below zero. Hmmm… Arduino analog-to-digital converters (ADC) can only read positive voltage, so exactly one half of audio input will be chopped off unless you use a level shifter to raise the baseline a couple volts so the Arduino can see the whole wave. Simple enough circuit using a few resistors and capacitors… and I even have the parts but I’m not trying to reproduce the signal here – just tell when it’s there and it’s amplitude. I can do that with just the positive half, I think…
And I was right. But it turns out I only get maybe 50millivolts coming out of Alexa or my phone headphone jack and I wasn’t thrilled working with single-digit changes so it needs to be amplified to get read useable values. I ripped the amplifier out of some old computer speakers I had handy, piped through that and sampled right at the speaker. Nowww I was getting some great numbers to work with – The ADC test code puts out 0 when Alexa is silent and bounces from 20-240 when she’s talking and it was still much quicker than even the simple level-shifting circuit everyone else seems to be using. Perfect for me.
Step Two – Move the Motors When Speech Detected:
I used simple digital high and low values instead of messing with PWM. I determined that 3 volts was plenty, but the existing board was also happy with the 5 volts Arduino already outputs so I went with it. To get fancy I can do partial mouth opening by not holding the pin high as long. As indicated above I directly wired a couple pins from the Arduino (12 and 13) to the original Billy Bass circuit board outputs and made use of its original motor drive (amplifier) circuits. Worked like a charm. I will note that unpowered the mouth springs more-or-less closed, but not completely – power in one polarity opens it the mouth and power in the opposite polarity closes it. Had I used an H-bridge type controller that could reverse polarity to the mouth motor I could have made it close even more. I decided, given my time constraints and that the effect was pretty darn good already, that it wasn’t worth the extra parts and coding required to pull that off. No one seems to know the difference.
My code works something like this: It sets an initial average value of the input ADC value, then starts its loop. it reads the pin and adjusts the average reading to count in this new read. The mouth close function is always called (which just turns off stimulation to the mouth-open circuit), but if the current reading is 25 Arduino ADC units above average it the open function is called again before it even starts physically moving. Along with a couple delays in the millisecond range, this is how I can get the mouth to move partially at times – the next syllable can start it opening before it closes all the way.
All values in the code are still up for adjustment – from the delays in the loop to the number of iterations before I recalculate the average… clearly the serial println statements I used for debugging/experimenting aren’t needed at all. Some of other variables and probably the initial average calculation can go too. I’ll get it cleaned up after Christmas.
Step 3 – Audio Out of Original Speaker:
I had hoped I could just find the pin that Billy Bass outputs audio with and inject the signal from Alexa right there, but audio was ridiculously quiet with that method. Could the audio amplifier be built right into the microblop? I dunno… Seems like it must be. Instead of spending more time studying the board I went for the sure thing and ripped the audio amplifier out of some old computer speakers I had in a box – after making sure they worked on 5 volts because they came with a 9 volt power supply. Mounted it in the Billy Bass plaque with room to spare, ran two power wires and the audio input from Alexa to it, and ran it’s output to the Billy Bass speaker. Quick, dirty, done.
So that’s pretty much the whole deal. I wouldn’t really make a tutorial type page if I had just copied someone else’s method but, per usual, I managed to march to my own drumbeat. Still appreciated the data and brainstorming material from the other pages – especially James Bulpin’s. I just found a way I felt was easiest for me. Hope you found something fun or educational here. Please let me know what you think or if there is something I could make more clear or any suggestions…especially interested in how others write their code. I’m here to share and learn. Must. Always. Learn.
Companion Instructional Video: https://youtu.be/HT1VWAUlJrw
Sample vid: https://youtu.be/He57zYd4TQw
Inspired and helped by James Bulpin at: