Lab Notes: Riding the Wave
Last Updated: 2021-09-14 09:00:00 -0500
As you probably recall from the previous update, the last little push for the PETI development kit is the “back board”, an extra expansion on the existing dev kit that will add key functionality like the battery pack to the device. One such feature is the ability to do auditory alters via a small speaker. In the true spirit of known and unknown unknowns, I went 100% Dunning-Kreuger and decided that this would be relatively trivial, and since it was the part of the back circuit I understood the least, it would be the first part of the board I would proof the concept of.
Since the last blogged update I’ve taken two occasions to dedicate streamed lab time to working on the circut. I spent much of the first session and the entire second session focused on a single aspect of that - generating the audio signal.
Audio has existed for over a century, this should be cake
Not… quite, if you can permit me a minute for engineering.
There’s effectively two kinds of electronic signals (to massively oversimplify) - analog and digital. In an analog system the voltage, current, and other properties of the electricity itself are relevant to the meaning of the signal. In digital, you’re effectively analogizing away all of those properties to simply determine if a signal is High or Low.
Computing, as you expect, is a digital process. So far everything about PETI has been more or less digital. But sound really isn’t. Speakers of most kinds are analog, and require to be driven by an analog signal.
Many digital systems, from PCs to microntrollers, accomplish this with something called a DAC (Digital Analog Converter), which handles the process of taking in digital information and doing black electronics magic to output a nice wavy analog signal. This is a common feature of plenty of microcontrollers, including many in the MSP430 line.
But not in the MSP430FR5994. Whoops.
Win if you can, lose if you must, but always always cheat.
The “right” solution to get good, clean sound out of a digital source in a case like this is to implement a DAC. Either by designing one, or finding a DAC IC and slapping it into your circut.
There is however a shortcut that harkens back to the bad old days of PC Gaming, the dreaded PC speaker, which uses a really cheaty solution to the problem - Pulse Width Modulation, or PWM.
Without putting it into a graphical representation, there are ways in a digital system to approximate some analog waveforms by rapidly toggling the state of a pin between high and low. In a sense, this is what PETI was already doing with its SPI features, like the SPI line between the controller and the LCD.
What I decided to do, because the quality of the sound is not as important as being able to generate a small number of distinct, single-voice tones, is generate PWM wave-forms by setting up a new peripheral in PETI’s brain - Timer_B.
If I know the speed of the system clock and can set the speed of the Timer accordingly, then by setting certain overflow values in the capture-compare registers of the timer, I can drive a certain very specific pin to a certain frequency. I can also control the duty cycle of the wave in a similar way.
By controlling these two values I can theoretically control both the frequency at which the speaker resonates (the “tone” it produces) and the amplitude of its movements (the “volume” of the sound produced) by controlling the frequency of my PWM wave and the duty cycle (which has a relationship to the “mean” voltage of the wave).
Old Hat, So What’s the Problem
I spent two whole live streams working on the PWM problem and convinced (for stupid reasons) that I was not forming the wave correctly, for two reasons:
- Right Reading, Wrong Tool. I forgot the golden rule of multimeters - they cannot measure usefully an oscillating signal unless it’s AC. Oops. Because of this I convinced myself that my special PWM pin was, for whatever reason, operating at half the expected voltage. It wasn’t. It was averaging out to about that value, which is expected in this case.
- That tracks. Because the buzzer I was using was being very, very quiet and I thought I was only supplying it 1.6V, I assumed the issue was the voltage.
I spent probably about 4 hours working on the voltage problem before I decided it was a limitation of the system (rather than my own misunderstanding) and implemented a new solution.
Throw a Transistor in there, it usually helps.
Deciding the problem was the voltage, I figured I could cheat a bit, and looked up a reference circuit to make sure my idea was sound. To be very brief, the idea is simple:
- Bring the speaker up to the full system 3.3V rail with some bias resistance to protect it.
- Use an NPN transistor to gate the negative leg of the speaker on its way to ground. In this capacity, the transistor acts as something akin to a digitally-controllable switch. Again, this is a horrifying oversimplification of what transistors actually do.
- Drive the gate of the transistor off the PWM signal. Effectively, toggle the path that the main voltage can take through the speaker according to the PWM signal.
This should ABSOLUTELY WORK and by now I’m reasonably confident we have working PWM so put the stuff together, hit the button, and… absolutely not.
I played around a little with the PWM parameters and started to realize that even tone deaf as I was, I couldn’t hear the pitch of the buzzer changing. So I did something I should have done hours earlier, and checked the data sheet for the buzzer in question - and sure enough, it’s regulated to a specific frequency.
This was the very long story of how I spent 5 hours bebugging something that never could possibly have worked. And if that was hard for you to read, well, that was hard for me to realize!
Lessons Learned: Let’s Not Do This Again
There’s a few key take aways here, but it’s important to note they came from a place of largely unknown unknowns. It never before occurred to me that a buzzer would be regulated to a particular frequency, but of course it would - if you want a simple alarm circuit for any of a number of practical reasons, you don’t necessarily want to have to reinvent the driving circuit to make it “hum” just so.
I could have cut down the time this wasted in a variety of ways:
- Checking the data sheet on the Buzzer. This was something I actually tried to do during the first stream, in order to find what I was calling the “minimum” voltage of the buzzer. During that stream I failed to locate the part number (which I now can’t unsee, naturally), and never bothered finding the data sheet. This would have saved me ~2.5 hours.
- Confirming the PWM signal was valid without proofing the whole circuit, which could have been achieved with a sufficiently fast oscilliscope or even with a logic analyzer. This could have saved basically the entire process - if I generated a PWM signal, found it matched what I expected, and the speaker didn’t work, I’d have known right away it was down to hardware.
- Checking a reference circuit set first, which hadn’t occurred to me at the time but is now, again, entirely impossible to not find when I’m even looking near it. If I’d known I had a perfectly valid circuit I could have stayed mired in troubleshooting the signal forever, but with both a valid reference circuit and supposedly-valid reference code (which I had access to), I could have been driven back to checking the part number much more quickly.
To move on, I’ll have too order a new type of part - a piezoelectric transducer. This is essentially the same idea as the piezoelectric buzzer I was using, but without the elements that cause it to function at a fixed pitch. I’m told you can salvage them from all sorts of devices but I’d just as soon order a couple of different ones as test components for the final device.
I’m also really, really going to need better metrics tools later, and people who know things are pushing me toward a logic analyzer. If you’re familiar with this class of tool and can make some recommendations, please let me know.
PETI is a major project intended to design and construct a virtual pet from Open Source Hardware and Software, and to encourage others to modify and tinker with similar projects. If you would like to support the development of this, or any of the other projects I’m working on for Arcana Labs, and you wanted to show your support financially, your best avenue is via my Github Sponsors account or by making a one-time donation to Arcana Labs via Ko-Fi.com or through other avenues detailed here. Github Sponsors also get access to a special patrons-only section of the Arcana Labs Discord Server, where we talk about the ongoing super-secret project.