I have a slightly complicated construct for how I control my robot vacuums at home.
While I want to document things a bit for myself, this is also a show and tell of something fun to do with flexible smart home tooling.
Everyone Worked in Harmony A while ago, I got myself one of those Roomba to keep dust under control. And while it keeps my floors nice and dust free, it is pretty loud when it does so. To avoid having to think about it, I set it up to run at 9am every morning. This also worked well, since I used to be in the office at that point.
DB Journeys Since I tend to work with hardware and actually like my colleagues, I commute to work at least some days. And while it has some downsides, going by train effectively “recovers” some of that commute time, as it allows me to use the time, instead of concentrating on the road or other people.
Sadly, one of the inconveniences of trains is their schedule. And while it won’t wait for me, I’ve had to wait for delayed trains before. Or worse, wait for the next train in the schedule, because mine was cancelled. To combat this, I want to see the current expected departure times before I leave for the train.
Did someone say Container? vscode has some rather nice docker integrations. There are some that will allow you to manage your containers form inside the editor, which may be interesting to control databases to connect to, but today we are interested in another feature.
Devcontainer The other way to use containers in development workflows is about the actual build env. Since we may be on a different environment with our production machines than our development machines, or just don’t want to clutter the dev’s machine, we may not be able to install all dependencies on the host environment.
With dev containers, this is easy.
Debug on the Moon One of the cool features of the debugging integration of vscode is it’s modularity. While the extension provide a way to get deep integration automatically, vscode is designed to allow a lot of configuration by hand. We can use this, to build some more powerful commands as well.
In this case, I want to debug my binary. But not on my build machine, but an external host. I can connecto to this host via ssh and got a configuration that doesn’t ask for passwords to do so (public keys and ssh-agent are your friends).
The way we build this, builds on launch commans but also some custom stuff.
Having Fun With vscode Recently I have started phasing out my long love vim and use vscode much more. While doing so, I’ve discovered some more involved tricks, and I was recently asked if I can do a primer for vim users.
Getting Started I generally use the visual-studio-code-bin package on arch, or the official microsoft branded variant on ubuntu. Though none of this is specific to the microsoft release. At worst you have to find the exensions yourself.
First Look When we first look at vscode, it greets us with a somewhat bare welcome view.
While we could use the editor like any old editor and just open files, I think the most relevant mode of operation comes with “Open Folder”.
This post continues after Interrupts squred.
Since all I do is playing with things I feel like, and designing the bits to make this a usable keyboard sounds like work, we got another intermediate step to have some fun with.
There’s an LCD display connected to the board as I bought them. So let’s get that up an running. Can’t be hard, right?
During some earlier research, I had found an lcd library on github that claims to support DMA, which apparently the vendor lcd example does not. So I grabbed the code from github, and got started.
There’s even a commit for it.
This post continues after Interrupts Squared.
This is just a quick update to show off the changes done to add a secondary mcp23017. The hardware change is pretty simple, just add it to the existing lines.
Pictures Most important is probably that the A0 address pin is set to high instead of low. Schematic:
And new pictures (notice some re-wiring):
Code Changes On the code side this commit contains the interesting changes. The following are mostly cleanup and re-enabling interrupt style setup.
The uint16_t state became a uint32_t state to fit all bits. Doesn’t really change anything about execution, since it still fits into a register.
This post continues after Keyboard from scratch. We are on the same set of hardware as before. Starting point in code is commit bd6d3eeaad.
You may have noticed, that a main loop that simple sleeps until we get an interrupt isn’t very “interrupt based execution”. So this time, we’ll take a look into getting at least the setup step of our mcp23017 interrupt based. Simply because it’s the easiest starting point for now.
Bunch of Plumbing Since I2C only allows for a singular device to communicate with the controller at a given time, we have to do time based multiplexing. OTOH this allows us to just pass through any event of the I2C hardware to a device specific handler relatively unfiltered.
This post continues after Keyboard from scratch. or Back to Blinky for a debugging session.
From a hardware perspective, there’s only a minor change. The interrupt line from the mcp23017 is connected to PA3 on the longan nano. I picked that one arbitrarily, since I was testing on this one before. This time, no picture. But here’s a circuit diagram. It’s .svg, so you can open it in a new tab and zoom as much as you want.
Going down the interrupt route While the current plan for the firmware is not to have very piece of code in an interrupt context, the main loop should block in wfi as much as possible.
This post continues after Keyboard from scratch. I messed up. I don’t know the exact details yet, but for some reason with the code linked in the previous post, the interrupts don’t come through.
So, back to blinky we go.
Blinky? Blinky is quite literally the example that just lights up an LED for a second then turns it off for a second again. The code is pretty simple and just downloaded from upstream.
So, stepwise we iterate on building up interrupt driven code again, to see what’s going wrong here.
Add GPIO IN Step one, add GPIO read to see whether what we are doing on the outside of the device actually has the impact on MCU state that we want.