MC2023 Chapter 2: Blinking, buzzing, events, PWM, and a new book.Page created: 2023-03-05 , updated: 2023-04-22
Welcome to the second "chapter" of my Year of the Microcontroller!
As I mention in the chapter list on the main YotM page, I had a big hiatus right off the bat with some personal projects with deadlines. This is a very unusual situation for me. Actually, one would be unusual, two is unprecedented!
But now I’m back!
The truth is, I was a little wary about returning to this after the hiatus.
When I ended Chapter 1, I had completed all of the official tutorial documentation. It was all high-quality official Raspberry Pi stuff (which is exactly why I’ve chosen the Pico platform). But it did leave me knowing only the bare basics and a big sense of "now what?"
Of course, there’s a ton of example code out there and I’m sure there are other guides to using the C SDK.
But going out on the Web for that stuff leads to distraction. And distraction leads to the Dark Side.
For some bizarre reason, it didn’t occur to me to actually look for a 3rd party book until I awoke with the thought fully formed in my head one morning.
And of course, there is a book. I ordered it immediately and had it by the weekend. The title: "Programming The Raspberry Pi Pico/W In C, Second Edition" by Harry Fairhead.
You can see it in this image.
(I wanted to be where the family was so I moved my portable Pi dev setup to the kitchen counter. Gotta love being portable!)
By the way, I’ve got a little paper notebook (you can see it above the book in the picture) that I’ve been keeping since I started these explorations. It was invaluable for reminding myself how to do everything after two months of being absent from the project!
So what did I get done today? Well, I read the first three chapters
of the new book, which
takes you from getting the SDK and tooling setup (which I’d previously done),
understanding a basic
cmake build, making a "blinky" program that blinks
the Pico board’s built-in LED, and then hooking up an LED and resistor
to make a proper circuit for a "blinky2" program.
If you can believe it, I even went a step further and blinked both LEDs so they flashed back and forth like an emergency vehicle. That’s right: two LEDs. Please hold your applause for the end.
I like this book so far. Fairhead uses actual numbers instead of SDK-defined constants to make the function calls less opaque (he explains this at the beginning). He shows the smallest possible cmake setup and explains what each line does.
He also peppers the text with factual information about the hardware that I wouldn’t have known to ask.
I’m still just blinking LEDs, but I already feel like I have a better foundation. I’ve also added a couple more shell aliases to take some of the tedium out of the build process (I’ll probably share a round-up of these in a while, when I feel more confident that I know what I’m doing).
Mostly a night of reading more of Programming the Raspberry Pi Pico in C.
If I didn’t already know Harry Fairhead has a hardware background from the author bio on the back of the book, I’d know it after reading the next two chapters.
I really appreciate the electrical explanations (and oscilloscope/logic analyzer screen shots) showing the timing of the different types of sleep function available on the Pico in Chapter 4 "Simple Output".
I thought the "sleep" vs "busy wait" function explanation was very interesting. If you use a "sleep", the Pico actually goes into a low power state to wait it out. The extra overhead of waking the pico back up means there is an extra delay, which would be undesirable if you need really fast and accurate actions.
As someone who is used to programming desktop computers, the idea that I’m putting the whole computer to sleep and then having it wake up to flash an LED (and this is on the scale of microseconds), is just nuts and I love it.
All of Chapter 5 "Some Electronics" was an exercise in humility for me. It’s a whirlwind of digital I/O basics from an electrical standpoint.
Essentially, I was reminded how little electrical engineering I really know.
Now, the old me would have closed the book about halfway through the chapter and said, "Okay, looks like I’d better learn electronics!"
Then I would have set about a several-week quest to "learn electronics". That would have failed, of course, because you can’t "learn electronics" in a couple weeks any more than you can "learn programming" in some short amount of time. (Ha ha. It’s taken me over 20 years to learn exactly how little I know.)
But the new me can simply appreciate the wisdom contained in this chapter and be humbled by it. I will refer back to it as needed. I am not, however, going to "go learn electronics". Instead, I’m going to plow forward.
If there’s one thing I know, it’s that I’m never going to understand the bizarre world of electricity until I actually apply it. Rote learning has not worked for me with this subject.
And you know what else? If I’m going to fry some LEDs or even a whole Pico or two, so be it. These are cheap parts. If I melt them with "big watts" or "too many amps" or "the wrong flavor of volts", then that’s gonna be a great teaching exercise. I’ll learn what I did wrong and hopefully not do that thing again.
In other words, I’m probably gonna do some really dumb things with electronic components the same way I wrote a lot of accidental infinite loops and crashed programs when I was learning to program.
NOTE: That is not to say that I take the safety aspect of electronics lightly. Killing your operating system is fine. Killing yourself is not. This article: Working With Electronics Safely (circuitbasics.com) is a good set of general guidelines.
Okay, enough about that. It looks like the next two chapters are about input and that is going to be very practical for me because I have some cool light-up arcade-style switches I’m excited about using in a project soon!
I went on another little hiatus to make this and some other things. But I’m back now and pretty determined to do this more-or-less daily for the foreseeable future.
Now I’m on Chapter 6 in Programming the Raspberry Pi Pico in C. Today’s task is creating a "simple button".
I think Fairhead does a great job explaining why input is so much harder than output: your device decides when to send output, but input can happen any time.
Tonight’s task was to setup a switch connected to a GPIO pin and write a simple polling loop to see if it’s pressed. If it is, light up an LED.
Actually, the big task for me was to semi-automate the creation of new projects and the compile/upload process.
You might recall the super-silly
pooload Bash function
I created in Chapter 1
to load the compiled program to the Pico
("poo" comes from a juvenile shortening "Pico OpenOcd").
Well, I also made a
poomake alias at some point to compile the
Now there’s a new function combining the two called, you
poop. What can I say, I like really, really
stupid names for hobby stuff sometimes to remind me that
this isn’t work.
In addition, I made a
newpoo that clones an existing project,
renames stuff to match the new project name, and does the
poomake - compile program pooload - send to pico poop - compile and send newpoo - clone new project from existing
(Yup, I’ve gone all-in on this stupid naming. So help me.)
I’m happy with this setup because it’s really simple, but saves me a boat-load of typing (and memorization!) while I’m making these tiny example programs.
Oh! And something else made it fun to get back to playing with circuits: I ordered some cheap breadboard-friendly pushbutton switches. Total game-changer versus soldering leads on the horrible grab-bag of switches I’ve recycled from broken electronics. Look at how cute these are!
Today I made "buzzy", the most horrible sound device known to humans. It’s just a little "passive" piezo speaker hooked up to a GPIO pin and a while loop with a sleep of various lengths that toggles the pin on and off.
It’s a 5v speaker and the Pico’s GPIO pin puts out 3.3v so it was pretty faint. But the sounds were so terrible that they annoyed the family even in the other room.
The funny/terrible part is that there was no way to stop the sound other than to cut the power or comment out some of the code and re-load the program. Good times.
Real simple one today. I already had the wiring hooked up for UART serial communication with the Pi computer. So I just followed the simple instructions in the book for yet another "Hello World." Can’t have too many of those, especially now that I’m getting my feet wet again.
Also a good opportunity to make a few tweaks to my
poo* shell stuff.
Interrupts and events today. I’m on Chapter 7 of Programming the Raspberry Pi Pico in C.
Learned a ton of stuff today.
I’d already learned how to use interrupts with the MicroPython book.
But this was a much deeper dive. Fairhead explained the IO event abilities of the Pico and how to use them even though the C SDK doesn’t provide any direct functions for doing so.
Basically, the Pico stores a flag when GPIO events happen on a pin such as "edge fall" or "edge rise". You can read these through a struct set up in the SDK and clear them with a function the SDK does provide.
By checking these events, you don’t have to worry about missing something like a button press while your "main loop" is busy doing something else. And you also don’t have to worry about creating an interrupt (with an IRQ).
Fairhead has some strong opinions about the downsides of interrupts. They’re handy, but they’re basically pure overhead. A polling loop will almost always have better raw performance and it’s also more predictable. (On the other hand, all that logic in the loop runs into code complexity problems.)
I ended today’s session very pleased. And here’s the funny part:
it didn’t work! I’m sure I just made a simple mistake somewhere,
but my program didn’t see the button press. I tried some simple
printf() debugging and didn’t see the expected value in
the struct. So I’m really not sure what went wrong.
But I really didn’t need to see it working to have gained a ton of insight into how this amazing little computer works. I’m also increasingly impressed with this book.
Moving on to Chapter 8 of Programming the Raspberry Pi Pico in C.
Today’s lesson is PWM (Pulse-Width Modulation).
Wow, the SDK interfaces for the PWM features are low-level stuff. Like, I would have expected this with assembly, but not with this big old SDK.
I was actually pretty shocked at how hard this is.
(For comparison, I took a look just now, and the MicroPython PWM class (micropython.org) is exactly what I would have expected. You create an object with a pin, set a frequency and a duty period (how long the pin is on during the frequency). Done.)
With the C SDK, you’re basically given a set of primitive computing tools and told to "have fun" in a manner of speaking.
On the plus side, you sure as heck know how PWM works at the end of it all. I hope I have this right:
The frequency is based on the CPU clock
You can set a clock divider value to get different resolution
There’s a counter that keeps track of each "tick"
You can set a "top" value for the counter
And choose whether the counter resets when it hits the top
Or have it count down when it hits the top
Then there’s another value called the level that toggles the GPIO state when the counter passes the level value
That’s what you get.
Given those primitive tools, you do some math to figure out how to get PWM to set your pin on and off at the rate you want.
(It’s even more complicated because the Pico has less PWM generators than GPIO pins, but pairs of pins share a "slice" of the generator and divide them into two channels, Channel A and Channel B. Some things are set at the slice level and some things are set at the channel level.)
Luckily, Fairhead provides some example utility functions to do the math for typical usage. (I started doing it on paper, just to say I did. About halfway through, I decided I just really didn’t have a need for that kind of masochism at this stage of my journey.)
Update: I ended up doing this manually after all in Chapter 3 to get a servo moving!
I felt pretty good about getting some LEDs to fade in and out (following and modifying Fairhead’s examples). I also used PWM to make my piezo speaker (last featured in "buzzy", see above) emit a variety of horrifying smoke detector-like shrieks. Again, I hadn’t programmed a way to make it stop, so I had to quickly load a "blinky" program on the Pico to make it stop the noises!
Alright, that’ll do for Chapter 2.
Thanks for reading. Join me next time in Chapter 3, which shouldn’t take as long to appear (no promises). I’m starting it off with servos!
Back to Year of the Microcontroller!