In this video, I modify my car so my windshield wipers sync to the beat of whatever music I'm listening to. Also there are some costume changes and you get to (have to?) see me as a seagull.


For the hackaday audience I wanted to share some technical details that the average YouTube visitor may not be interested in. Curious readers, read on!


The hardest part of this project was the beat detection. It turns out that's not really a solved problem. It would be a LOT easier if the system could scan through an entire music file ahead of time, which would allow it to do deeper analysis and also normalize various constants and thresholds. But... no such luck, I wanted to do real-time beat detection on a live audio feed, which in the research literature is called "online" or "casual" beat detection. Reading through various research papers, everyone seems to start in the same general fashion. You do an FFT on the incoming audio stream, then watch the various frequency range bins for spikes, and then you do a bit of filtering on those and you call those spikes "note onsets" meaning a note has just been played or a drum has just been hit. From there, the algorithms diverge all over the place. 

The real-time beat detector I ended up going with was from researcher Sebastian Böck in Germany, and his really awesome python library called "madmom" - unfortunate name choice perhaps, but hey as Phil Karlton reminds us: ‘There are only two hard things in Computer Science: cache invalidation and naming things'  - I want to add that Sebastian was incredibly helpful over the madmom mailing list and super nice to me, in addition to being incredibly smart.

The madmom beat detection works by taking the note onsets and pushing that data through a neural net that was trained on a database of music where the beats were correctly identified by a human. How does that neural net work? Nobody knows! It's a neural net! I sure hope robotic surgery is never done using neural nets.

Where was I? Oh right. This code runs in python on a raspberry pi, and I nice'd the process so it can peg the cpu to 100% if it wants to. Or at least, it can peg the one core that it's using. On a raspberry pi 3+ it takes up about 80% of one core. The beat detection is the input to the phase locked loop (PLL). But what is the output?

The output variable or process variable is ultimately the voltage going off to the wiper motor. However the PI isn't able to source tens of amps without releasing the magic smoke, so instead what happens is the PI sends serial commands to an arduino, which outputs the correct PWM and Enable signals to control the boost-then-buck supply. Why add the arduino when the PI can output PWM? Because the arduino is more deterministic and with interrupts disabled I can trust it to reliably do just one thing and that thing is to control the power supplies correctly so they don't blow up. Also the arduino will turn off the supplies if it hasn't received a serial command from the PI within 5 seconds, so it functions as a watchdog as well.

And what is the feedback? I wish I had a rotary encoder on my windshield wiper motor, but unsurprisingly my economy vehicle shipped with no such feedback mechanism. It has what most all cars have, which is a park switch. Ever wonder how your wiper always stopped in the right place so it was out of sight? Because there's a little switch that closes when your wiper motor reaches the park position. The switch is incredibly noisy due to wiper noise (no, not windshield wiper noise... electrical contact wiper noise, silly) but I fixed that with your basic RC low-pass filter, after which the park switch signal goes to the PI. 

So my python code on the PI only knows when the wiper reaches the park position, and from that it has to extrapolate (read: guess) the position of the wiper at all other times. It works... most of the time. The larger source of noise is the beat detection....

Read more »