Code Toggling Plugins

misc

I’m a firm believer that creative coding is a very different activity than the kind of coding that most people do for their day jobs. In feature / application / systems programming, there’s usually a fair amount of planning, scoping and architecting that comes before you start coding. Ideally, when you start coding, you have a pretty good idea of what you are going to make and how you’re going to make it.

But creative coding, for me at least, starts with “what would happen if I did this…?” and generally follows that line of logic all the way until I have something published.

So I’m always going to this value or that, deleting “true” and typing “false” or vice versa. Or, I’m using a sine function and want to see what happens if I use cosine. Or tangent. Or I want to swap greater than with less than and see what that does. Or change plus to minus or minus to plus.

After way too many times doing this type of thing, I figured there must be some plugins that would make this easier. And so there are! I use vim, and found several. I tried a few and had almost settled on vim-toggle and then checked out switch.vim, which I found to be the most powerful of the lot.

I recognize that most people probably use VS Code or Sublime Text or other editors. A quick search informed me that there are similar plugins for those editors as well (all links below). I haven’t tried the non-vim ones, so I can’t vouch for their quality, only their existence. There may be better ones, so do your research.

The way these work is you put your cursor on the word or symbol you want to change and hit some keyboard shortcut. For switch.vim, that’s gs. Each time you hit that shortcut the word will toggle back and forth between, say, “true” and “false”. Or “on” and “off” or “1” and “0”.

Most of the plugins come with several obvious definitions pre-defined. But make sure you find one that will also allow you to set up custom toggle sets. Some of the plugins only support binary switching between two options, but some, like switch.vim, will let you specify a list of as many items as you want. It will cycle through all of those options when you hit the shortcut key over any one of them. Here’s just a few of the custom toggle sets I set up:

["width", "height"]
["moveTo", "lineTo"]
["x", "y"]
["-", "+"]
[">", "<"]
["cos", "sin", "tan"]

And there are more niche ones I use in my day to day creative coding using cairographics bindings for Golang (blgo). Sometimes I’ll be making a piece where the background is white and the foreground is black. I use a function, ClearWhite to clear the surface to white, and set the drawing color to black using SetSourceRGB(0, 0, 0). but occasionally I want to invert these to use a black background with white shapes. So I set up some toggles like so:

["ClearWhite", "ClearBlack"]
["0, 0, 0", "1, 1, 1"]

This lets me easily make the change in just a few key strokes.

switch.vim even allows you to set up toggling rules using regx, which seems super powerful, though I haven’t dug into that so far.

So far, I’ve found these immensely useful. Maybe you will too. Here are the links:

Vim / Neovim:

VS Code:

Sublime Text 3:

Pixel 3XL vs Oneplus Nord n10 5G

misc

Almost exactly two years ago I bought my last phone, a Pixel 3XL. The phone I had before that was a Samsung Galaxy S8. It was two years old and was in good condition, but I didn’t like it that much. All the extra Samsung garbage was not to my taste. I like stock Android or as close as I can get.

After two full years, I was totally happy with the Pixel. I had no plans on upgrading or changing until I had to. And then… I had to. The first sign was the the volume buttons weren’t working. I have one of those rubber bumper cases. When I took it off, the volume worked fine. But not with the case on. The case seemed fine, and then I took a closer look at the phone beside the volume keys.

Here you can see the back cover has separated from the phone. The whole back plate was swelling out. That’s why the volume wasn’t working. The buttons on the case were no longer aligned with the buttons on the phone.

I had noticed that it was seeming to get pretty hot when I wirelessly charged it but hadn’t thought too much about it. Obviously the battery was on its last legs and getting ready for some kind of catastrophe. I kept an eye on the phone the rest of the day and started looking for a new device.

I was really pretty bummed out about this because I didn’t actually WANT a new phone. And I had to get one quick and didn’t have a chance to do a bunch of research. I was curious about the Oneplus line. Their flagships go for $600 – 900 or even higher. I didn’t want to spend that much when I wasn’t really sure what I wanted. Maybe I wanted a Pixel 6 when it came out. What to do? What to do???

I finally wandered across the Oneplus Nord n10 G5. It was under $300 but decently specced for that price. I watched a few Youtube reviews and while nobody was raving about how great it was, the consensus was that it was a pretty good phone for its price. I crossed my fingers and ordered it with next day delivery.

In the meantime I wondered if I could possibly replace the Pixel’s battery. Quick search revealed a few Youtube videos that made the process seem not too formidable, and a number of under $20 replacement kits. Worth a shot, right?

The repair kit came the same time as the new phone. I set up the Oneplus, got my sim card in it and all my apps. It looked and felt pretty nice. No regrets. Then onto the battery repair.

The toughest part was getting the back off. You need a heat gun (which I have, luckily) and a lot of time and patience. You apply heat to the back of the phone judiciously so as to not damage it. This softens up the glue, then you pry the crap out of back of the phone. The kit had tools and a suction cup. It took a good half hour of heating and prying, heating and prying – and I had a head start since the battery had already started the job – but eventually I got the back off.

Then you have to pry the battery out. It’s also glued in. That was a bit easier, but not… easy.

Finally, the recharging coil is just like a piece of thick paper with the coil inside, glued to the battery. You have to carefully pry that off. If you’ve ever tried to peel a glued-on paper label off of something, you can imagine how that went. I got all of the coil and about half of the paper backing, but I was pretty sure I had wrecked it.

The battery with a chunk of the charging coil backing still holding on. You can also see the battery casing puffed up like a balloon.

Then you put it all back together. The kit also came with glue strips to put the battery back in with. Stuck the coil back on the new battery, plugged everything in. Cleaned up all the old glue. Crossed my fingers and turned it on. It worked fine. Put it on the charger. It charged right up. Didn’t even get hot. And it held its charge really well.

The last thing I needed was some glue to put the back on again. I ordered that and finished up the next day. But since then it was working fine, holding a charge and charging just fine. Now I had some options:

  1. Keep using the Oneplus and keep the Pixel as a backup.
  2. Go back to the Pixel and return the Oneplus.
  3. Go back to the Pixel and keep the Oneplus as a backup.

I had a good 2-3 days in on the Oneplus, which gave me a good idea of how much I liked it. In general, I did like it. I concur with all the reviews – it’s a great value for it’s price. But there is no doubt that the Pixel is way better. Some details:

  • Performance. Pixel wins hands down. Opening apps takes probably 1.5-2x longer on the Oneplus. Random scrolling around is obviously way smoother on the Pixel. But this was really only noticeable on a side-by-side comparison. I could have lived with the Oneplus’s performance easily.
  • The Oneplus screen pales in comparison to the Pixel… LITERALLY! (sorry) Not surprising. The Oneplus is an LCD whereas the Pixel has OLED. Again though, wouldn’t be a deal breaker for me.
  • Bluetooth performance was not good. I use Galaxy Buds Plus and love them. They have been virtually 100% flawless on the Pixel. On the Oneplus, I had various issues:
    • Garbled sound. I’ve had that on cheaper BT earbuds, but never on the Galaxy Buds. I was getting it regularly every time I used them on the Oneplus.
    • Unresponsive controls. The tap to start / stop failed multiple times. Never recall it failing while on the Pixel.
    • Connection. I think it failed to auto-connect once in the couple of days I used it. I don’t recall it ever having a problem on the Pixel.
  • Touch responsiveness. Very noticeable on one of the puzzle games I was playing. Tapping on on-screen items would fail close to 50%, requiring multiple taps. Never experienced it on the Pixel and when I retried the same game on the Pixel again, it was night and day.

To be fair, those are the only negative performance points I could come up with on the Oneplus. I would add that Oneplus have started creating their own UI stuff. A customized settings app, a custom launcher, a bunch of preinstalled Oneplus apps. I was under the impression that Oneplus was close to stock, so this was a bit disappointing. Not as bad as Samsung, but not a plus.

But overall, not bad. The Bluetooth and touch screen stuff were the only points that really pushed me over the edge to going back to the Pixel.

I am really happy to be back to the Pixel though and have a renewed appreciation for what a good phone it is. As I said, I didn’t want to switch phones to begin with and I’m happy that I don’t have to.

I’ve decided to keep the Oneplus though as a backup. I don’t know how long my Pixel surgery is going to hold up. So far it’s flawless, but who knows what the next few weeks or months hold. If the Pixel does crap out on me, I’ll have something to switch over to instantly. Maybe I can last long enough to see how the Pixel 6 does and maybe even long enough to see it come down a bit in price from its initial release.

Inoreader

misc

Back in the day, I was a big fan of Google Reader. There were lots of blogs and feeds I followed and Google Reader kind of set the standard of what an RSS reader was supposed to work, and what it was supposed to look like

I’m one of those people who will never fully trust Google again – but only because they shut down Reader.

When they did that, I looked at what was available and wound up on Feedly. The other main option was The Old Reader. And for whatever reason, I liked Feedly better.

And I’ve used Feedly pretty much every since. I’ve gotten used to it, but there was a lot I never really liked about it.

One thing that really bugged me about Feedly was it’s in-your-face upgrade call to actions. There’s a bright orange upgrade button front and center. There’s stuff all over the place about using “Leo” which is apparently the AI assistant that helps you … manage your feeds? Discover new content? At any rate, you have to upgrade in order to use it, and every time I’ve looked at it, it held no interest for me.

Also, in spite of years of using it, I can’t say I really ever understood the UI. There’s a “Today” section and an “All” section, as well as layouts and sorting and sharing and read later and boards. And sometimes things open up in this kind of tab container, but there’s only one tab ever… I really only ever wanted to just show my unread and sometimes my read feeds and just ignored all the other stuff. And a lot of the advanced features which are stuck out begging you to click them wind up telling you you need to upgrade anyway. I often did think about upgrading and paying something for the app, but there was nothing in the paid features that I really needed or wanted.

Tiny Tiny RSS

So a couple of months ago, I started looking at alternatives. I wound up self-hosting tt-rss. It’s fully open source and free. There’s a mobile app (like Feedly) and there are no calls to upgrade, which I liked.

The UI however, was not a whole lot better than Feedly in a lot of ways. There are various layouts and sorting and sharing options. But there’s also the concept of “Fresh” articles and “Adaptive” filtering, which I never really figured out. It reminds me of Twitter’s timeline algorithm where they try to figure out what you want to read. That annoys the hell out of me and The fresh and adaptive stuff was starting to do the same.

I was reworking my server last week and rather than setting up tt-rss again, I decided to have another look at what’s out there.

Inoreader

I tried going back to Feedly for about 10 minutes, but quickly remembered all the ways it annoyed me. I checked out a few others. The Old Reader is still out there. I still didn’t like it. Then I ran across Inoreader, which I had never used before.

I imported my OPML and started using it and was totally hooked. I really love this app. The UI is exactly as simple as it should be, but there is enough under the hood to make it look and work just like you want it to.

The free tier really had all I wanted, but I loved it so much that I upgraded to the supporter plan for a dollar-something a month. This gives you more available feeds (I wasn’t even close to the limit on the free tier), custom CSS capabilities, and the ability to add a newsletter subscription. For $5-something a month, there are a bunch of other filtering, searching, collaboration, etc. features that I don’t really need. The mobile app is also really good and just as usable.

I know it’s just an RSS reader, but I just feel like they nailed the UX so well, that it really is a joy to use each time I open it up. Nothing there confuses me. It’s exactly what I want it to be and works exactly like I expect it to. Any up-sell is subtle and I haven’t run across any sneaky elements that are just features you don’t have, hoping you’ll click on them so they can try to get you to upgrade.

AweGif 2021

misc

For the month of August 2021, I’m going to try to post an original animated gif on twitter every day of the month. I’ll be tagging them #awegif2021. I invite anyone to join along.

I’ve done this twice before. And the cool thing is that all the entries are easily searchable in twitter.

In May of 2018 we did #MayContainGifs https://twitter.com/hashtag/MayContainGifs

And in July of 2018 we did #GulyIsForJifs https://twitter.com/hashtag/GulyIsForJifs

Here are the rules:

  1. Post an animated gif to twitter (or wherever else, really) and tag it with #awegif2021
  2. Do it every day, or whenever you want. If you only do one all month, that’s fine.
  3. Use whatever you want to make the gifs. Custom code, some software package, we don’t care, as long as it’s something you actually created yourself.
  4. If you want to create a bunch over the weekend and post them throughout the week, that’s fine. Post something you created last year, we don’t care.

Follow along with the entries here: https://twitter.com/hashtag/awegif2021

That’s all. Looking forward to what people create!

Technology Update

misc

This is just a post about some changes I made to my personal computers. Probably not interesting for most people, but I like to document this stuff so I can go back and say, “when did I switch to ____? And how did that go?” And who knows? A few people might find it vaguely interesting after all.

Back to Mac.

I’m not switching back to Mac by any means, but I did buy a new Mac for personal use.

My summary of Apple computers up to now:

  1. They have OK hardware. Mac fans will say how amazing the hardware is, but when you drill down, they’re usually talking about the machined aluminum body. I’ve seen and experienced more hardware issues on Macs than I have on PCs. Motherboards, keyboards, screens. I will agree that Macs look good and feel good. Historically, they’ve had the best trackpads. The screens are bright and crisp and have nice color, but also develop dead spots and weird color patches that I’ve never seen on any other laptops.
  2. MacOS is OK. It’s frustratingly un-customizable and locked down. I’ve never felt that I really fully owned a Mac that I bought. It felt more like I was being given the special privilege of being able to use this device as long as I used it only in the way that Apple decided I should use it. It’s probably more useful if you own a Mac and an iPhone and an iPad and an Apple Watch and an Apple TV and all the other Apple/i-devices. And buy your music and apps and games and movies and tv and books and subscriptions from Apple. And use Apple services/apps for your email and backups and online file storage and sharing and chat and web browsing and documents. But I do exactly none of that stuff.
  3. I hate Apple as a company. I get infuriated watching their keynotes. They are all so smug and in love with themselves about how amazing this or that new feature is and how it’s going to change your life and transform the world. They constantly claim to invent things that have existed for years. Or rename existing technology to make it sound like something new they created. They are actively developer hostile. They PR themselves like they are saving the world, but don’t ask about their sweatshops. All this is my opinion. You are free to disagree with me, but I’m not going to argue about it. If you don’t see it like I see it, that’s cool.

So if you’ve even read this far, you’re probably baffled at why I actually bought a Mac. I’ll be honest, it pained me to give the company any of my money. But I was doing a lot of work with Minicomps and bljs and I was finding a lot of issues with Safari that I needed to fix, as well as stuff that worked or looked differently in Chrome and Firefox on the Mac. I was using a Mac VM, which was not great, and my work Mac, which I don’t like to use for personal stuff.

I had some money come in for a project I did and decided after long deliberation to pick up a new Macbook Air with the M1 chip. I got the cheapest version. $1049 on Amazon. I’ll be honest, it helped a little bit giving Amazon the money rather than Apple directly.

And I’ll be damned if the stupid thing didn’t start winning me over. As I said, Macs are good looking machines. This thing looks nice. It’s thin, it’s light, it’s quiet, it does not get hot. It is goddamned fast. Faster than it has a right to be. The trackpad is still really nice. Other manufacturers have caught up with Apple over the years on the trackpads, but it’s still probably the best. The screen is bright and colorful and crisp and no splotchiness yet, but we’ll see how it looks in a year or two. I have to say though, the screen is the worst fingerprint magnet I’ve every seen. I don’t recall ever actually touching it, but it constantly looks like I ate a couple of tacos and wiped my hands off on the screen. The keyboard is meh. I don’t really like it, but it’s not the worst I’ve ever used. To be fair, my main computer is a Thinkpad, and I love Thinkpad keyboards.

The sound. This gets its own paragraph. I am shocked how good this thing sounds. As much as Apple’s overuse of the word “magical” has become a meme, the sound on this device really is magical. It’s deep and rich and loud and sounds like it’s coming from a foot or two behind the machine. I have no idea how they accomplished that kind of quality in this thin little laptop. I’ve never had a laptop that sounded a tenth as good as this sounds, including other Macs.

MacOS is… still MacOS. I still don’t like it but I’ve used it for many years at work and I’ve learned to live with it. As I said, I’m not into the Apple ecosystem or have any other Apple devices, so all I really need MacOS for is to launch the apps I use. For me, this mostly means a terminal (Alacritty) and a browser (Firefox and Chrome mostly).

I still hate the dock. I’ve tried a few alternatives – cdock (not supported on M1) and ubar. Both are pretty good, but in the long run they wind up being a bit frustrating to use – inconsistencies and things not working just right. I suspect that this comes down to Apple not sanctioning these kinds of UI customizing apps and not supporting the things that they do, if not outright making it harder for them to do those things. So I’ve gone back to the dock and I’m trying to make peace with it.

Summary: I hate to admit how much I like this machine. In spite of it’s 13-inch screen, it’s great for watching videos, listening to music, browsing the web etc. It’s OK for coding, but great for coding on the train or in the car while waiting for my wife to finish shopping or whatever. Although I used it a LOT in the first few weeks, I’m over the honeymoon period and mainly back to my Thinkpad as my main machine. But fairly often I’ll have both machines open in front of me.

KDE

The other big change in my technical life was switching Linux desktops environments from XFCE to KDE.

If you’re not into Linux desktops, most of this will go over your head. But unlike MacOS which is severely locked down from a UI viewpoint, Linux almost has too much choice. Beyond all the differences between various distros under the hood, your graphical user environment, display manager, window manager, theming, default applications and a bunch of other stuff are all packaged into what is known as a desktop environment, or DE.

Probably the two most popular DEs are Gnome, which is the default DE on Ubuntu and several other distros, and KDE. Others include XFCE, Mate, Budgie (Solus), Pantheon (Elementary OS), and Cinnamon (Linux Mint). Not a comprehensive list at all, but that goes to my point about too much choice.

All these environments have a different look and feel, different levels of customization, and different opinions on how things should work. For a few years now I’ve been very happy with XFCE. It’s one of the older DEs and has a reputation for being ugly and boring and unchanging. The last point I agree with. The “exciting new features in the latest XFCE” is a bit of a meme – you’d be hard put to tell the last several versions apart. But it’s actually very customizable and can look really nice if themed correctly. The Manjaro distro has a very beautiful and functional implementation of XFCE.

But I’ve been feeling the need to switch things up after so long on one environment.

I don’t like Gnome at all these days. I used to, but it’s been going down a really strange path in terms of limiting customization. It relies almost entirely on 3rd party extensions for adding and customizing it, but does not curate or take any responsibility for those extensions.

I’d tried KDE a few times years ago and always found it over the top in terms of drop shadow, glows, sound effects and gratuitous animations. It felt like a UI that was made in Flash. But I gave it a test a year or so ago and found it a lot better. Toned down all the goofy stuff. Now it looks really slick and professional. KDE also has the reputation of being uber-configurable. Almost every single UI element on the screen can be configured. You can go down a serious rat hole, but if you want configurability, KDE is where it’s at. I came away from that test run knowing that if I ever wanted to move off of XFCE, I would most likely move to KDE.

And so I decided to go with Manjaro KDE this time. I’m really, really liking it so far. More than I thought I would. I’ve gone down a few rat holes configuring things to death, but managed to get out alive. In addition to its built-in options, KDE has a rich ecosystem of 3rd party plugins, similar to Gnome’s extensions, but it seems like they take an active role in curating them, so from what I’ve seen, the quality is much higher than what you see in Gnome.

All that flashy over the top stuff is still available, but it’s not the default anymore. I’ll admit that I turned on the cube rotation effect for switching between virtual desktops – something I recall fondly from early OS X days. Other than that, I’m keeping it pretty understated, and to be honest I find myself recreating my earlier XFCE look and feel.

So I think I’m pretty sold on KDE for now. I’ve committed to using it for several months. But already, I don’t see any compelling reason why I’d go back to XFCE. There’s nothing in XFCE that you can’t do as well or better in KDE. The biggest selling point of XFCE is its minimalism.

So that’s that. If you actually read all of that, hoping for more, I apologize.

Raspberry Pi Pico – What I’ve Learned

misc

So the new Raspberry Pi Pico board came out a few weeks back and there’s all kinds of news about it. For the uninformed, it’s a shift from other RPi boards. Most Pis are single board computers. They run an operating system – usually some Linux-based variant. The Pico is a microprocessor. Basically an Arduino alternative. But a pretty damn powerful one. Two cores, fast, good memory, 26 gpio pins, analogue to digital converter, real time clock, temperature sensor, etc. All for $4. So I grabbed a couple. By the way, if you’re ordering on line, make sure that you buy the header pins. They are not always included by default.

There are a ton of tutorials on line already, most of which are nearly exact clones of each other: solder pins on, plug in it while holding down the bootsel button, drag the micropython uf2 file onto the mounted drive, it will reboot, install Thonny, write a script to make an LED blink. So I’m not going to go through all that. Or you could say I just went through all that in one sentence.

One thing I highly recommend is the “Get Started with MicroPython on Raspberry Pi Pico” book put out by the Pi people themselves. It’s a bit cartoony and starts off really basic. In fact, going all the way through chapter 4 will get you through what most of the tutorials on line cover. But with a lot more depth. There’s several pages on how to solder the pins on. But further chapters get into some pretty good stuff, including various sensors and controls and I2C and SPI control of an LCD panel. Good starter stuff.

Stuff I’ve learned

Ran into lots of snags going through the process of learning this board and figuring out what I even want to do with it. A lot of this has to do with the fact that it’s really in its infancy. I’m sure that things will get better as time goes on, but there are a lot of rough edges right now. And beyond the book, there’s very little searchable info out there. Unfortunately, there are other boards/technologies out there named “pico” so that clouds your results. Throw in “Rapsberry Pi” into the search and you’re mostly going to get other RPi stuff. But even when you craft a good search, mostly what you’re going to find is the multiple cloned tutorials mentioned above. There is also a scattering of C/C++ tutorials and resources for the Pico. They look dauntingly complex so I have not dived into those yet.

Another problem is that the version of MicroPython that was made for the Pico is a fork of the official version. And it’s very definitely a subset. The official MicroPython documentation is fantastic, but huge swaths of it are just inapplicable to the version that works with the Pico.

For example, MicroPython has a machine module. In the official version, machine contains the following classes:

class Pin – control I/O pins
class Signal – control and sense external I/O devices
class ADC – analog to digital conversion
class UART – duplex serial communication bus
class SPI – a Serial Peripheral Interface bus protocol (master side)
class I2C – a two-wire serial protocol
class RTC – real time clock
class Timer – control hardware timers
class WDT – watchdog timer
class SD – secure digital memory card (cc3200 port only)
class SDCard – secure digital memory card

The ones struck through are not available on the Pico right now. Since the Pico does not have an SD card, the biggest miss there is the RTC class – the Pico has a real time clock, but no way to access it directly. That doesn’t seem too bad, but it extends from there. The Pin class is missing almost half of the methods on the Pico version of MicroPython. Other classes are missing methods as well, and there are several standard Python modules that are part of MicroPython that are missing from the Pico’s version.

All that said though, there is enough there to get you started on most common projects, and as I said, I’m sure this will grow and become more expansive in the coming months.

Tips and Tricks

A few random tricks and tips for using Micropython on the Pico:

When you install the MicroPython editor, Thonny, it will ask you if you want to run in regular mode or in Raspberry Pi mode. Naturally, I chose Pi mode. And naturally I was wrong. Although it seems to work fine, you wind up missing a lot from the UI.

Here’s the Pi mode:


Thonny in RaspberryPi mode, aka “simple”

And here it is in regular mode:

Thonny in regular mode

I was running in Pi mode for a while and thought it was pretty damn lame. Then I discovered you could go into the options and change it to regular mode. (Also that Pi mode is really called “simple” mode, and there is also an “expert” mode.)

Regular mode gives you full menus, which opens up a massive wealth of features I did not realize even existed. For example, I could find no way to copy files onto the Pico other than opening them up in Thonny and then saving them to the device. But the View menu lets you open a files panel (and a lot more) where you can access files both on your device and your local file system, and “upload” and “download” between the two. Brilliant.

Another gotcha from the book. The book states that by default, gpio input pins are set to be pulldown by default. Pulldown inputs are attached to ground with a resistor and connecting them to positive voltage triggers them. Pullup inputs are connected to a positive voltage with a resistor and connecting them to ground triggers them. If you didn’t pull them one way or the other, stray charges could trigger the inputs. Anyway, the book says that input pins are pulldown and you can create a pin by typing:

pin = machine.Pin(15, machine.Pin.IN)

I did this while testing physical buttons to make an LED turn on. And I was getting all kinds of crazy behavior. If I touched a wire or even just tilted the whole breadboard in a certain direction, the LED was coming on as if I’d pressed the button. I honestly thought that I’d accidentally tapped into some internal accelerometer at one point – I was totally able to control the LED by tilting the board back and forth. After looking up the official MicroPython docs for creating a pin, I found there was a third parameter for controlling pullup/pulldown. So I changed it to:

pin = machine.Pin(15, machine.Pin.IN, machine.Pin.PULL_DOWN)

When I did that – explicitly setting the pin to be pulldown – it was rock solid and worked 100% as expected.

Another question I finally answered for myself is how to have a program run as soon as the Pico boots up. Simple enough – you just name the Python script main.py.

An Alternative Python

There is an alternative to MicroPython though, and that is CircuitPython. As I understand it, CircuitPython is another fork of MicroPython and it is supported on a multitude of microprocessor boards, including the Pico. Because it’s been around a lot longer the the Pico, it is way more expansive in what it supports and has a ton (like 280+) libraries that work with it. CircuitPython is supported by Adafruit, and they’ve also created some really useful libraries, many specifically designed to work with the hardware they sell. So all in all, this is a really great option.

You install CircuitPython the same way you flash the Pico with MicroPython – download a uf2 file, start the Pico while holding down the bootsel button and dragging the uf2 to the mounted drive. It will reboot and be a CircuitPython device now.

One thing to say about CircuitPython is that it is quite different than MicroPython. Although it may be a fork, they forked the hell out of it.

For example, a simple program to blink an LED in MicroPython:

import machine
import utime

led = machine.Pin(25, machine.Pin.OUT, machine.Pin.PULL_DOWN)

while True:
    led.value(1)
    utime.sleep(0.5)
    led.value(0)
    utime.sleep(0.5)

And the same program in CircuitPython:

import board
import digitalio
import time
 
led = digitalio.DigitalInOut(board.D13)
led.direction = digitalio.Direction.OUTPUT
 
while True:
    led.value = True
    time.sleep(0.5)
    led.value = False
    time.sleep(0.5)

Not a huge deal, but I think it might be a good idea to choose one and roll with it. You’re not going to be able to run your MicroPython projects on your Pico after you flash it to CircuitPython (and vice versa – though you can simply reflash between the two systems relatively easily).

Personally, I’m torn at the moment. CircuitPython has way more stuff in it and so many existing libraries. But it’s so far different from the standard language, and I’m hoping that the Pi folks will continue to make their implementation more expansive and people will come up with new libraries for it as well.

On the other hand, CircuitPython already has some libraries allowing the Pico to act as an HID device. In other words, you can use it to send keyboard and mouse events to the host computer it’s connected to via USB, good for making custom keyboards or other controllers. And with 26 gpio pins, this winds up being way more useful for complex projects like this than the Arduino Pro Micro clones that I’ve been using. I haven’t found anything in MicroPython to do the same thing, though there is some C++ code out there that seems to support this. I may just end up using both MicroPython and CircuitPython for a while.

More about CircuitPython – the recommended editor is not Thonny, but the Mu Editor. For the most part it seems pretty basic, more like the simple mode of Thonny. No menus or extra panels or anything like the regular mode of Thonny – at least not that I could find. But as an editor, it does have some nice autocompletion and other features that I didn’t see in Thonny.

Something that confused me about Mu: I created a new file and saved it to the Pico and hit the run button, but the other default code.py hello-world type file ran instead. Nothing I could do would make my new file run. It turns out that’s by design. As mentioned, MicroPython devices will auto-run main.py on boot. And CircuitPython will auto-run either code.py or main.py on boot. But Thonny will run whatever active script you have open when you hit run, whereas Mu will always run code.py (or presumably main.py) when you hit run. This can be good or bad. It mimics what will happen when the device boots, but makes it harder to test some other script. The solution recommended is to have code.py or main.py be a simple launcher script that in turn executes some other script. Anyway, good to know.

Another big plus about CircuitPython is that when the device is connected to your computer it also mounts as an external drive. So if you want to add additional libraries to it, you can just drag and drop them to that drive. A bit easier than Thonny’s upload feature.

Summary

So that’s some of what I’ve managed to learn so far. As there is very little data out there at the moment, I hope some of this helps people just getting into this new, fun little board.

Edits/Additions

In the first version of this posts I used the word “robust” several times, indicating that the version of MicroPython for the Pico was not as robust as it hopefully would be in the future and that CircuitPython was more robust. That was the wrong choice of word. Robust in the context of code means that it is able to handle and recover from various unexpected conditions. To say that something is not robust implies that it is unstable. That’s not what I meant to imply.

I changed the word to “expansive”. My intention was to say that the current version of MicroPython on the Pico does not support as many features as it hopefully will and to say that CircuitPython supports more features. Examples are, as I described earlier, the missing RTC class for the real time clock that is in standard MicroPython but not on the Pico. Also, stuff like HID support in the usb_hid library of CircuitPython, but nowhere to be seen in MicroPython (that I can find), as well as all kinds of libraries for working with specific sensors and peripherals that are available for CircuitPython. MicroPython has some of that, but nowhere near what I see in CircuitPython.

Learning CNC and Making a MediaBox

misc

Earlier this year I talked about my “Bit-Box” – a custom keyboard, program launcher, Stream Deck clone, device. https://www.bit-101.com/blog/2020/07/bit-box/

The box was handmade, but I had purchased a 3d printed plate to hold the switches. A little later I had the idea of making my own plate with wood. Initial tests, chiseling out a square hole for a single switch worked pretty well, but as soon as I tried to cut out several adjacent holes, the wood between the holes kept chipping out.

I started thinking about using a CNC to do this, and eventually picked up a Sainsmart 3018 Prover.

It took a couple of hours to assemble. Pretty easy actually. And it only came with some relatively useless v-shaped engraving bits, so I ordered a set of flat endmills in different sizes. Since then I’ve picked up a bunch of different bits.

In terms of software, I’ve tried a few different options.

One is Inventables Easel. This is a web app made for the Inventables X-Carve cnc machine. But it can export gcode that can be used with the 3018. Easel has some decent features for free, but you have to pay for full functionality.

The other one I’ve used is Carbide Create. This is made for Carbide3D’s Shapeoko machines. It’s desktop software and is totally free. It also exports gcode. I like Carbide Create a lot better.

The basic flow is to create a set of simple 2d vector shapes – rectangles, circles, paths – then apply tool paths to each shape. For example, you’d specify that you want to use this rectangle as an outline shape that is cut 1/4″ deep. Or you want to use this circle as a pocket, 1/8″ deep. A pocket cut cuts the entire inner area of a shape to a certain depth. You can also do boolean operations to combine or subtract different shapes. It’s super basic, but really does most of what you’d need.

If you want to really go crazy, you can get into 3d modeling with something like FreeCAD or Fusion360, and then create tool paths from those models. A much bigger learning curve and probably overkill until you get into some really complex stuff.

I use Candle to send the gcode to the machine itself.

MediaBox

My goal was to create a “MediaBox”. This is just what I call a custom mini keyboard with media keys – play/pause, next, previous tracks, volume up/down/mute. Six keys in all. Here’s an overview of all my attempts from one of the original hand-cut versions, some test cuts, a couple of failed attempts, through the final working build:

The initial holes for the keys worked perfectly. A 0.555 inch square hole is all you need. Spacing is something like 0.205 inches between keys.

The main design issue beyond that was where to fit the Arduino board and how to route the usb cable. I was initially using 1/2″ black walnut. On the top were the holes for the keys. I then flipped it over and created a recess on the bottom. But the half inch depth was really too shallow. And my original design was just too small once I attached the cable.

So I switched over to 3/4″ walnut and made the whole thing just a bit larger.

Wired it up much the same as I did for the BitBox. Did some finish sanding and applied some tung oil, glued on a leather bottom.

The software presented a bit of a problem. The Arduino keyboard library does not provide a way to send media key codes. Luckily there is another 3rd party library, HID-Project.

You can add this library to your project by going to sketch / manage libaries and searching for “hid project”.

Here’s the code I came up with:


#include <hid-settings.h>
#include <hid-project.h>

// Define Arduino pin numbers for buttons and LEDs
#define VOL_DOWN 2
#define VOL_MUTE 4
#define VOL_UP 3
#define PLAY_PREV 5
#define PLAY_PAUSE 6
#define PLAY_NEXT 7

const long debounceTime = 30;
unsigned long lastPressed = 0;
boolean A, a, B, b, C, c, D, d, E, e, F, f;

void setup() {
  pinMode(VOL_DOWN, INPUT_PULLUP);
  pinMode(VOL_MUTE, INPUT_PULLUP);
  pinMode(VOL_UP, INPUT_PULLUP);
  pinMode(PLAY_PREV, INPUT_PULLUP);
  pinMode(PLAY_PAUSE, INPUT_PULLUP);
  pinMode(PLAY_NEXT, INPUT_PULLUP);

  a = b = c = d = e = f = false;
  Consumer.begin();
  BootKeyboard.begin();
}

void loop() {
  if (millis() - lastPressed  <= debounceTime) {
    return;
  }

  lastPressed = millis();

  A = digitalRead(VOL_DOWN) == LOW;
  B = digitalRead(VOL_MUTE) == LOW;
  C = digitalRead(VOL_UP) == LOW;
  D = digitalRead(PLAY_PREV) == LOW;
  E = digitalRead(PLAY_PAUSE) == LOW;
  F = digitalRead(PLAY_NEXT) == LOW;
  if (A && !a) {
    Consumer.write(MEDIA_VOL_DOWN);
  }
  if (B && !b) {
    Consumer.write(MEDIA_VOL_UP);
  }
  if (C && !c) {
    Consumer.write(MEDIA_VOL_MUTE);
  }
  if (D && !d) {
    Consumer.write(MEDIA_PREV); // alternately MEDIA_REWIND
  }
  if (E && !e) {
    Consumer.write(MEDIA_PLAY_PAUSE);
  }
  if (F && !f) {
    Consumer.write(MEDIA_NEXT); // alternately MEDIA_FAST_FORWARD
  }
  a = A;
  b = B;
  c = C;
  d = D;
  e = E;
  f = F;
}

This was adapted from a few other sample projects I found, as well as the code I had for the BitBox. It works great.

Want one?

I made this for myself, but I’d love to make some more. The materials aren’t cheap though. Well over $30 for the wood, leather, Arduino, keys and key caps. Then the time for cutting, finishing, soldering. I’ve got to work out pricing and different options, and the best way to sell them, but contact me if you’re interested.

I’d also be open to selling just the wooden box, either finished or straight off the mill and you can buy the other parts and put it together yourself. It’s a fun project.

Or… if you have a cnc already, I’m going to post the Carbide Create file I used, with instructions, for free. Check back soon for that.

I Think Bluetooth is Finally OK

misc

Bluetooth was introduced on May 7, 1989. I think I first heard of it in the mid-2000’s. People would use it to try to send contact info or other files between feature phones. As I recall, it had about a 50% chance of actually working. All of my attempts fell squarely in the failing 50%. So I ignored it for a few more years.

Then there were smart phones with Bluetooth and laptops had Bluetooth. There were Bluetooth mice and eventually Bluetooth fitness devices and smart(ish) watches. And they all SUCKED.

Bluetooth and Me: A History

Mice

Every Bluetooth mouse I had was slammed down on the desk in frustration at least once. And only very narrowly avoided being hurled across the room. When you’re using something all day every day, 99% uptime is unacceptable. I’d be in the middle of something and the mouse would just stop responding and I’d have to spend a minute or so reconnecting it. Then it might be fine for several more hours. I tried several and finally quit. I’m firmly in the wireless USB dongle camp now as far as mice go. Logitech’s MX Master 3 is glorious. It actually supports Bluetooth AND wireless. I think I tried an earlier version of the MX Master on Bluetooth and quit the first time it disconnected. The wireless dongle has never once failed me, and I’ve used many.

Headphones

Specifically, I’m talking about “earbuds” or what the kids call “IEMs” (in-ear monitors) these days. I’ve had multiple sets of these. Historically, they suffer from four issues:

  1. Poor audio quality.
  2. Discomfort due to weight.
  3. Poor battery life.
  4. Connectivity issues.
  5. Cost.

You could probably come up with something where you could say you get to choose three out of those 5 points. Maybe. The point is, they play off each other. Better battery life means more weight and cost. Anyway, I never had a pair that I was happy with. In the end, the hassle of a cord (and these days a USB-C adapter) has always been less than the hassle of battery, discomfort, poor sound, and connection problems.

Speakers

I’ve also had multiple Bluetooth speakers. And I’ll even throw my car stereo system into this category. These have been so-so. Connectivity has often been an issue. Some good, some not so good. My car in particular is really bad. It always takes a minute or so and at least two tries to actually connect my phone.

The other thing that has killed me with Bluetooth speakers is that they’ve always had horrible performance on listening to voice audio sources. Music is ok, but just about every one I’ve had cuts out in the silence between words. It will pick up again when it hears the next set of words, but routinely a few words will be lost on almost every sentence. I listen to a lot of podcasts and audiobooks, and this was always impossible with every Bluetooth speaker I had.

Fitness Devices / Smartwatches

I’ve had multiple running watches that had Bluetooth, as well as several Fitbits and an Android Wear watch. Generally, the Bluetooth has worked great. Until it stopped working great. When they decided to stop connecting via Bluetooth, it seemed like there was nothing I could do to get them to reconnect. Even rebooting the device and whatever device it was trying to connect to. But then at some point it would just start working again for however many days.

All this is to say that I’m not just someone who hates something they’ve never tried. I’ve had dozens of Bluetooth devices and every single one of them has caused me some level of frustration. And yet, I keep buying them, holding out hope. (Except mice. I’ve eternally given up on Bluetooth mice.)

But wait!

In the last couple of months, I’ve purchased three Bluetooth devices that I’m actually quite happy with!

Galaxy Buds Plus

For some reason, I decided to take another leap of faith and got another set of Bluetooth ear buds. I checked out a ton of reviews on these things and these seemed like a solid buy. The cost was $139 on Amazon, which isn’t cheap, but not exorbitant. I’ve been amazed at how happy I am with these things. There’s nothing I can say about these that is negative.

Battery life is great. They have the charging case, which itself has wireless charging. I already have wireless charges scattered around the house, so it’s super easy to just toss it on one of them.

Connectivity has been flawless. They connect instantly, never lose the connection.

They are comfortable. I use them with foam tips, which I always get for any earbuds. Never get uncomfortable. I’ve used them while running and they stay put and feel fine.

Sound is quite good. Most of the time I’m listening to podcasts and audiobooks on my phone. They sound great for that. To be honest, for music, I stick with my Sony Walkman NW-A55 and wired Ikko OH-1 IEMs. That’s been a life changing combination. But if I’m running with my phone and want to listen to music, I’ll use the Buds for that, as the music is just background at that point.

I’ve had these for two and a half months now and I can’t say enough good about them. These are the items that have finally sold me on the idea that Bluetooth has made it.

JBL Flip 5

Speaking of sound, I recently picked up a Bluetooth speaker. To be completely transparent, I got this for free. A while back I switched to Verizon Fios and out of the blue they sent me this $100 coupon for the Verizon store as thanks for switching. Lots of phones and phone cases, chargers and headphones, none of which I really needed. I didn’t really need a Bluetooth speaker, but this had pretty good reviews and came to $95 with tax, so why not?

It sounds good, connectivity even on multiple devices has been great, and it works flawlessly with audiobooks and podcasts. Huge battery with lots of listening time. Also, you can turn off the power on/off and Bluetooth connect/disconnect sounds, which has been a big annoyance on every other speaker I’ve had.

Garmin Forerunner 235

In the last month I started running again. I pulled out my old Garmin running watch, which I hadn’t used in … sadly, years. After a full day of charging and trying to get it running, with no success, I ordered a new Garmin watch, the Forerunner 235.

It’s very nice. It’s a full on smartwatch (not Android), which you can add apps and watch faces to. I did set up a better watch face, but not really interested in other apps. It does all day heart rate and sleep tracking. Battery lasts a week if you’re not running. GPS while running will suck it down faster, but will still let you run for many hours without a problem.

It connects to the Garmin Express phone app via Bluetooth and that’s been nearly perfect. When I finish a run, if I have my phone on me, it nearly instantly syncs to the cloud via Bluetooth and phone. If I don’t have my phone on me, it often syncs as soon as I walk into my driveway, with my phone inside the house. Downright impressive.

Summary

Bluetooth may have won me over. I look forward to seeing other quality implementations, though I’m not holding my breath on the mouse situation.

My Wireguard Setup

misc

Disclaimer

Someone has been submitting my recent posts to online tech news aggregators, where they are criticized for not being cutting edge or paradigm shifting enough. If you’ve been led to believe that this post awe and amaze you, complain to the person who submitted it, not me. This is just my personal blog where I write about stuff that I’m doing, mostly technology based. It will not change your life. That said…

Background

I’ve had a “home server” for close to ten years now. It’s a Linux-based desktop pc. It acts as a file server, media server, backup server and a place to try out different things. I guess it’s what is now popularly called a “home lab”. All that’s great when I’m at home on my home network. I can stream movies and music, get files, ssh into the server and do whatever I need to do.

But when I’m out and about, traveling, working (when we used to go out and do stuff like that), I’d also like to have that same access. That’s all simple enough. You go into your router settings, do some port forwarding to that box and then you can stream, ssh, ftp, vnc, whatever. I’ve certainly done just that often enough. But as I became more security conscious, this started to worry me more and more. Having all those ports open into my main machine made me nervous. Yeah, they are behind passwords, or hopefully keys. I locked down ssh pretty tightly, but still worried about it, and all those other services. When I was on Xfinity for home internet, their management app provided a security section which listed all the various attempts to access different ports on the network with their IPs and locations. It was shocking. It became something that was not just theoretical. People were (and are) actually trying to hack into my network. That’s when I shut everything down.

Enter Wireguard

I’d heard quite a bit about Wireguard and it sounded like what I needed. I came upon this tutorial which described exactly what I wanted to do and in pretty clear terms:

https://zach.bloomqu.ist/blog/2019/11/site-to-site-wireguard-vpn.html

This all went together really well. It took a bit of learning and messing things up and fixing them, but I eventually got it all working really nicely and doing exactly what I need. Here’s my current setup:

  • Main wireguard server hosted on an inexpensive VPS in the cloud.
    • ufw set up to block all traffic other than specific ports from specific wireguard clients.
    • rinetd to forward any needed ports to my home server. Currently, that’s just the port that my airsonic server is running on.
  • Main wireguard server hosted on an inexpensive VPS in the cloud.
    • ufw set up to block all traffic other than specific ports from specific wireguard clients.
    • rinetd to forward any needed ports to my home server. Currently, that’s just the port that my airsonic server is running on.
  • wireguard client running on my home server.
    • airsonic music streaming server running there.
  • wireguard clients running on a couple of laptops, my Android phone and tablet. Each client has it’s own private key and the public key of the server. The server has its own private key and the public keys of each client.

With this setup I can ssh into the VPS from anywhere in the world, provided I’m doing it from one of the configured clients. Once I’m into the VPS, I can then ssh into any one of the other clients that has an ssh server running. I could use rinetd to forward ssh on specific ports to specific clients. But for now, that use case is not that common. When the world gets back to normal and I’m out of the house more, that will be useful.

I’ve got my airsonic server running on a specific port of my home server, let’s say it’s 1234. rinetd is set up to forward port 1234 on the VPS to port 1234 on the home server. So I can access my music in the browser from any wireguard client, or I can use any one of many subsonic-compatible Android apps and have my music streaming to my phone or tablet no matter where I am.

This setup is pretty flexible, and I will be able to add other services to it just by opening up a port in ufw and forwarding it as needed using rinetd. Important thing to remember is that when I say “opening up a port in ufw” I mean a wireguard client accessible port. Nothing is open on the VPS except via wireguard. Nothing is open on my home server except via the VPS or local LAN.

Monitoring and Recovery

One downside to this setup is that to access my music for example, I’m relying on a chain of multiple links: wireguard on VPS, ufw, rinetd, wireguard on home server, airsonic. If any one of those doesn’t function just right, I’m listening to silence. This has happened a couple of times, especially when I first set things up and had some things not quite right. Actually, if ufw goes down, I’ll still be able to listen to my music, but my VPS will be open. So I wanted to get some monitoring in place. When things were down early on, I’d be making assumptions on which piece was broke and spending time trying to fix it, only to find out it was one of the other links. With correct monitoring, I can now tell exactly what is up and down.

Monitoring with Healthchecks

I’ve been a big fan of Healthchecks.io. You set up “checks” which provide you with a url to ping. If a check doesn’t get a ping within a specified time period, it notifies you via email, sms, or through more than twenty other integrated services. I’ve been using it to monitor my daily backups. If a backup doesn’t happen at a specified time, I know about it.

So I set up a cron job that runs a script every 10 minutes on my VPS, and a similar one on my home server. This script first checks the status of wireguard. If it’s up, it pings Healthchecks. It does the same for rinetd and ufw. My home server checks wireguard and airsonic. Each of these five services is set up as a separate check in Healthchecks so I can see the status of each of them separately. The cron job runs every 10 minutes, so I give it one extra minute leeway – if Healthchecks doesn’t get a new ping after 11 minutes, that service is marked as down.

Recovery

Eventually I realized that if a particular service was down, once I became aware of it, I’d just go to whatever machine and restart it, so why not just do that automatically. So I built that into each of my checks.

If, say, wireguard is down on the VPS, it will NOT send the ping to Healthchecks. So a minute or so later it will be flagged as being down. But in this case, the script will also automatically try to restart wireguard. The next time it runs (10 minutes later), hopefully it sees that wireguard is up and sends the ping.

Healthchecks also has a “grace period” configuration. Once it notices something is down, it will not alert you until that grace period is done. I set this to 10 minutes. This results in the following sequence if something goes down:

  1. Service X is up and Healthchecks gets pinged at 10:00 pm.
  2. Service X goes down at 10:05 pm.
  3. At 10:10 pm, the script sees that Service X is down and fails to ping Healthchecks.
  4. The script also attempts to restart Service X.
  5. At 10:11 pm Healthchecks has not had a ping in 11 minutes and marks Service X as down.
  6. At 10:20 pm, the script runs again. Service X is up so it pings Healthchecks, which marks Service X as up again.
  7. Alternately, the restart didn’t work and at 10:20 pm no ping is sent.
  8. In this alternate case, at 10:21 pm, Healthchecks emails and texts me about the fact that Service X is down.

A potential improvement to this is that after step 4, when Service X is restarted, I could verify that it’s now working and ping Healthchecks. immediately. This way, if the restart works, nothing is marked as down. But I’m going to run it as is for a while and see how this works out. So far, so good.

I’ve gone through and tested each on of these checks, turning the service off and leaving it off. Within 11 minutes it was marked as down and restarted. And shortly thereafter marked as back up. All automatically.

If this were some kind of public service or mission critical workflow, I could easily set up the pings for every minute or so. But the 10 minutes seems perfectly adequate for my purposes.

More Details?

This post is pretty high level. Most of what went into the wireguard setup is covered in the above link. If you want to set up something similar, I’d be happy to go into more detail on any specific points. Just let me know.