Save money, buy misery: cheap STM32 boards

(I’m still writing this. It will change over time.)

Use an STM32 Blue Pill or Black Pill micro-controller board”, they said. “So cheap, so powerful”, they said. “You’ll love it”, they said.

Dear Reader, none of the above turned out to be true.

For some time now I’ve been looking for a cheap, USB HID micro-controller board that is somewhat more flexible than the ATMega32U4 (Arduinos Leonardo, Micro and Pro Micro; also the impossibly smol Atto) and yet not quite as flexible as the let’s-accidentally-overwrite-our-accessibility-code-with-the-holiday-snaps CircuitPython boards from Adafruit. And for a while it looked like the STM32 boards might do it: they’ve got a 72 MHz ARM Cortex-M3 with at least 64 KB of Flash and 20 KB of SRAM and they’re under $5. Yay?

Not quite. There are three main problems with the STM32 boards that get in the way of inexpensive electronic nerdery.

1: They may not actually be STM32 chips

Slightly grotty photos follow. One day I’ll get a better USB microscope.

First, the chip from a “Black Pill” board bought recently:

flux blobs aside, this is clearly marked STM32 F103C8T6

Compare with a “Blue Pill” bought last year:

the very tentatively marked CS32F 103C8T6 and its possibly fake CKS (“China Key System”) logo

Knock-offs are rife in the cheap end of the market, and at least this chip is honest enough to say that it’s not from STMicroelectronics. While it may be possible to program these things with some heroic faffing about, consider balancing the effort required versus the time cost of doing so.

2: They may not have working USB

moar later (about the Blue Pill’s incorrect resistor)

3: The documentation is everywhere and nowhere and Google is not your friend

even moar later (about a very dedicated amateur’s hosting of the project documentation becoming too successful for him to afford)

(Huge thanks to Andrew Klaassen who provided me his notes for getting some of these boards at least able to run Blink under Linux.)

Schotter on a Tek 4010

Georg Nees’ Schotter, reproduced on a simulated Tek4010 display

Georg Nees (1926–2016) was a pioneer of generative art. His piece “Schotter” (gravel) from 1968 displayed a rectangular array of squares with the position of each square becoming more random as the piece progressed.

The BASIC code for this video is based on Processing code by Jim Plaxco,

The Tektronix 4010 display simulator is by Rene Richarz,

The BASIC interpreter with Tektronix graphics support is Matrix Brandy BASIC maintained by Michael McConnell,

(Higher-quality video at Georg Nees’ “Schotter”, reproduced on a simulated Tek4010 display at YouTube.)

  100 REM Georg Nees "Schotter" reproduction - scruss, 2019-11
  110 REM based on Processing 3 code by Jim Plaxco,
  120 :
  130 scrn_wd% = 2048: REM fixed screen size, unlike Processing
  140 scrn_ht% = 1560
  150 columns% = 12
  160 rows% = 22
  170 sqsize% = FN_min(scrn_wd% / (columns% + 4), scrn_ht% / (rows% + 4))
  180 padding% = 2 * sqsize%
  190 randstep = 0.22
  200 randsum = 0.0
  210 randval = 0.0
  220 dampen = 0.45
  230 :
  240 SYS "Brandy_TekEnabled", 1
  250 A$=GET$: REM PLOT 4, 0, 0: PLOT 5, 0, 0
  260 FOR y% = 1 TO rows%
  270   randsum = randsum + (y% * randstep)
  280   FOR x% = 1 TO columns%
  290     randval = RND(1) * (2 * randsum) - randsum
  300     PROC_square((scrn_wd% / 2) - (sqsize% * columns% / 2) + (x% * sqsize%) - (sqsize% / 2) + INT(randval * dampen), scrn_ht% - (padding% + (y% * sqsize%) - (sqsize% / 2) + INT(randval * dampen)), sqsize%, randval)
  310   NEXT x%
  320 NEXT y%
  330 PLOT 4, 0, 0: PLOT 5, 0, 0
  340 END
  350 :
  360 DEF PROC_square(cx%, cy%, side, angle)
  370 LOCAL r, i%, pm%
  380 pm% = 4: REM plot mode - move = 4, draw = 5
  390 r = (side / 2) / (SQR(2) / 2)
  400 FOR i% = 0 TO 4
  410   PLOT pm%, cx% + r * COS(RAD(angle + i% * 90 + 45)), cy% + r * SIN(RAD(angle + i% * 90 + 45))
  420   pm% = 5
  430 NEXT i%
  450 :
  460 DEF FN_min(a%, b%) IF a% < b% THEN =a% ELSE =b%

All of the Argos Catalogues

The 1974 Argos catalogue has slide rules

A little slice of UK consumer history: The Argos Book of Dreams, scanned Argos catalogues from 1974 to present. (Via b3ta)

It seems that all (?) of these are also up at the Internet Archive. They’re a little harder to find, and some don’t have previews. A decent search for one uploader’s history is “retromash”, though “argos catalogue” finds more. The Book of Dreams site seems only to have autumn/winter catalogues, while the Archive has the spring/summer ones too.

Taxman – a BASIC game from 1973

Back in 1973, the future definitely wasn’t equally distributed. While in Scotland we had power cuts, the looming three-day week and Miners’ Strike I, in California, the People’s Computer Company (PCC) was giving distributed computer access, teaching programming and publishing computer magazines. I don’t think we got that kind of access until (coincidentally) Miners’ Strike II a little over 10 years later.

taxman drawn image from People's Computer Company magazine (1973) , with "1 for you 19 for me" quote from The Beatles song "Taxman"
flares? platforms? centre parting? bow tie? It was 1973 after all

But the People’s Computer Company magazine archive is a sunny thing, overfilled with joyful amateur enthusiasm and thousands of lines of code fit to make Edsger Dijkstra explode. Of course it was written for the local few who had access to mainframes and terminals, but it hardly seems to come from the same world as the dark evenings in Scotland spent cursing the smug neighbours’ house with all the lights on, their diesel generator putt-putting into the night.

Lots of these games from the PCC era are forgettable now. The raw challenge of guessing a number on a text screen has paled somewhat in the face of 4K photo-realistic rendering. One game I found is still a little challenging, at least until you work out the trick of it: Taxman (or as the authors tried to rename it later, Factor Monster). Here’s a tiny sample game transcript:

Hi, I'm the taxman
Do you want the regulations?
(1=Yes, 0=No)? 0

How many numbers do you want
in the list? 6

The list is: 1  2  3  4  5  6 

You take? 5
Your total is  5 
I get  1 
My total is  1 

New list:  2  3  4  6 

You take? 6
Your total is  11 
I get  2  3 
My total is  6 

New list:  4 
I get  4 
because no factors of any number
are left.
My total is  10 

You  11  Taxman  10 
You win !!!

Again (1=yes, 0=no)?

Seems I sneaked a lucky win there, but it’s harder than it looks. The rules are simple:

  • Start with a list of consecutive numbers
  • You choose a number, but it has to have some factors in the list
  • The taxman (or the factor monster, a concept I much prefer as it doesn’t reinforce the Helmsley Doctrine) takes all the remaining factors of your number from the list
  • You get to choose a number from the list, which is now missing your previous choice and all of its factors, and repeat
  • Once the list has no multiples of any other number, the taxman/FM takes the rest
  • The winner is whoever has the largest sum.

For such a simple game (or perhaps, such a simple me) the computer wins surprisingly often. Since I find it fun to play, I thought I’d share the 1973 love as much as possible by porting to all of the BASIC dialects that I knew.

Plain text BASICtaxman.bas —runs under interpreters such as bas. Almost verbatim from the 1973 publication. May not allow you to play again on some interpreters; you might want to try my slightly rearranged 40 column version that should run on systems that don’t allow a variable to be dimensioned twice.

taxman on Amstrad CPC: starting with numbers 1-6, player has taken 4, so taxman takes 1 & 2, leaving 3, 5 and 6
taxman on Amstrad CPC: how BASIC programs look to me, yellow on blue 4 lyfe

Amstrad CPC Locomotive BASICtaxman.dsk — or as I call it, BASIC. 40 columns yellow on blue is how BASIC should look.

taxman on BBC Micro, showing games tart for 1-6. Adjacent numbers are a full column apart
taxman on BBC, Mode 7: dig the weird spacing

BBC BASICtaxman.ssd — for all the boopBeep fans out there. You can actually play this one in your browser, too. Yes, the number formatting is weird, but BBC BASIC was always its own master.

taxman: Commodore 64 showing the instructions
taxman on C64

Commodore 64taxman.prg — very very upper case for this dinosaur of a BASIC.

taxman running on Apple II: loaded from disk, started with 6 numbers
taxman running on Apple II

Apple II AppleSoft BASICTAXMAN.DSK — lots of fiddling with import tools and dialect weirdness because Apple.

taxman: end of game on ZX spectrum
taxman: end of game on ZX spectrum

ZX Spectrum (Sinclair BASIC)taxman.tap — 32 columns plus a very special dialect (no END, GOTO and GOSUB are GO TO and GO SUB, …) meant this took a while, but it was quite rewarding to get going.

taxman - BASIC program listing on ZX-81 running under sz81 emulator, Linux window borders visible
Taxman on ZX81: more SCROLLs than the Dead Sea

Sinclair ZX81 (16 K) — taxman.p — this one was a fight. The ZX81 didn’t scroll automatically, so you have to invoke SCROLL before every newline-generating PRINT or else your program will stop. For some reason this version gets unbearably slow near the end of long games, but it does complete.

crude lithophane with OpenSCAD

small lithophane made from photographic portrait of Muhammad Ali in 1967. World Journal Tribune photo by Ira Rosenberg (source)

After reading I didn’t know lithophanes were so simple. They were hiding in Cura all along. : 3Dprinting, I thought I’d give OpenSCAD a shot at generating a lithophane image. It did not badly at all, considering this was my first try.

This isn’t a fast process and generates huge STL files, but it’s fairly simple. Here’s how I did it:

  1. Download your image. I used this 479 × 599 pixel preview.
  2. Convert your image to PNG, preferably grey scale
  3. Run it through the OpenSCAD script below, changing the parameters according to the instructions
  4. Render it in OpenSCAD (slow)
  5. 3D print the resultant STL in 0.05 mm layers (very slow)
//  somewhat rough OpenSCAD lithophane - scruss, 2019-10
 infile  = "479px-Muhammad_Ali_NYWTS.png";    // input image, PNG greyscale best
 x_px    = 479;  // input image width,  pixels
 y_px    = 599;  // input image height, pixels
 z_min   = 0.8;  // minimum output thickness, mm
 z_max   = 3;    // maximum output thickness, mm
 y_size  = 50;   // output image height, mm
 // don't need to modify anything below here
 translate([0, 0, z_max])scale([y_size / y_px, y_size / y_px, (z_max - z_min)/100])surface(file = infile, invert = true);
 cube([x_px * y_size / y_px, y_size, z_min]);

I used Makerbot warm white PLA. It looks decent at viewing distance, but close up it’s a bit stringy.

closeup of lithophane eye

There are better packages, but OpenSCAD does this better than I expected.

Lovely automata: bbcbasicbot

bbcbasicbot rendering of my one-liner

BBC BASIC bot [beta2] on Twitter is lovely. You tweet a BBC BASIC program to it and it replies with an animation rendering of what your program would look like on a BBC Micro.

I sent it this:


which readers might recognize as 10 PRINT, the endless random maze one-liner for the C64. This program even inspired its own book – also called 10 PRINT CHR$(205.5+RND(1)); : GOTO 10 – about simple generative art.

You can run it in your browser thanks to the amazing JSBeeb.

Weird thrift-store find: homebrew CD player

I killed some time this lunchtime in a thrift store. I was half-looking for a case for a kit computer, but wasn’t expecting much to turn up. But I found this:

There really are no identifying marks on this. No idea how it got to be in Canada.

♫yoga then stone ants and I are waving♫

Robyn Hitchcock – Trilobite – Live At Sonic Boom Records In Toronto

YouTube’s automatic transcription is not quite there yet:

… it’s got a different feel to it it’s um
I write this in a shower in Thunder Bay
I mean you know like a shower that you
clean yourself in not a shower of rain
or you could clean yourself in a shower
of rain but you don’t always know it’s
gonna rain and you’re not necessarily
dirty at precisely the right time to go
out into the rain but it would be great
if people could time their dirt so they
went out and obviously if you’ve got
small kids and you need to bathroom
regularly because they’re not old enough
to voluntarily shower or bathe you could
just wait for for the shower that would
doom for you none for the infants anyway
I wrote this in Thunder Bay and it’s
about a creature that’s been extinct now
for about 100 million years but it
lasted about 400 million years which is
a lot longer than we are likely to
nonetheless we in our brief lifespan
have already named this creature and
it’s it looks kind of like a ladies
shaving device from the 1940s but
obviously it made a stone because it’s
fossilized it’s called a trilobite
because it has three lobes three
sections to it and you can find a lot of
these still fossilized trilobite sand
cliffs in various parts of the world
they may even be on on the moon for
honor but it’s very hard to prove either
way but you know we’ve called it this
thing the trilobite but long after it’s
like as if somebody dug one of you up in
years to come and said these are the
bones of Gloria Swanson you know you
always who remember you sir particularly
and not Gloria Swanson um as far as I
know because you haven’t proved you on
but I’m assuming you are for all I know
all of you are actually called Gloria
Swanson which only proves my point the
chorus of the song refers to
refers to Elton John buying cheap
confectionery in a down market cafe in
the late 60s before he became famous and
wasn’t able to do that had to get
someone else to do it for him and it has
no connection with the rest of the song
so ok that’s set the scene for this
trilobite right Dwight’s in the light by
trilobite right in the light by Dwight
trilobite right Dwight’s in the light by
trilobite right in the light by Dwight
basking on the shores of time the little
Stein creature ain’t dead to the world
they call him trilobite right rights in
the light by trilobite right in the
light by Dwight trilobite right rights
in the light by trilobite brighten the
light by Dwight Weldon Johnson but real
name is Richard wood creaking away for a
second of Fame a billion years later
they give it a name they call a
trilobite right and whites in life by
trilobite right in the light by Dwight
when I’m too wasted these rocks to
clamber then lean me on the cliff and
encase me in amber and the creature from
the future in way out when can clop my
fossil and name me span that’s a nice
built for a world where nothing needs
shaving yoga then stone ants and I are
waving trilobite right and whites in the
light by trial of pipe right in the
light by Dwight let’s hold a clicking
championship the trilobite wins and
everybody else loses
trilobite try to buy

Robyn Hitchcock, Trilobite, as transcribed by YouTube

The chorus in real life is:

Trilobite, right Dwight’s in the Lite Bite
Trilobite, right in the Lite Bite, Dwight

PLOTPOURRI rides again

PLOTPOURRI at many times original speed on emulated Apple II

PLOTPOURRI is an old BASIC graphics demo for the Apple II. It plots 3D functions immensely slowly. It was noticed on the stardot forum, and a BBC BASIC version was requested.

My conversion lives here: scruss/plotpourri_bbc.bas and runs in the browser here.

Possibly Painless Network Printing from your Raspberry Pi

Printing from computers goes through waves of being difficult to being easy, then back to difficult again. This is likely due to the cycles of technology, complexity and user demand flow in and out of sync. I think we’re at peak annoyance right now.

It’s even harder with Raspberry Pis, as when printer drivers support Linux, 90% of them are for x86 or x86_64 computers only (Canon: ಠ_ಠ). ARM doesn’t get a look in. But one technology does actually seem to help: network printers that support IPP — Internet Printing Protocol.

We had an old Brother laser printer that just got slower and crankier and less useful as a printer, so yesterday I got a new Brother DCP-L2550DW to replace it. It says it supports Linux in the spec, but I knew not to be too optimistic with my Raspberry Pis. And indeed, it was seen on the network but no driver was found. I had a sad.

What turned my frown upside down was finding out about Raspbian’s cups-ipp-utils package. For desktop use, install it this way:

sudo apt install cups cups-ipp-utils system-config-printer

(leave off system-config-printer if you’re running from the terminal.)

On the desktop, open up Preferences → Print Settings and add a new printer. Yes, it prompts for your user password which you may have forgotten. I’ll wait while you try to remember it …

Now under Network Printers, you should see a device you recognize. Pick the one that says IPP network printer somewhere:

IPP network printer

Here’s where the magic happens: you actually want to pick the generic driver for once:

Select Generic (recommended) manufacturer

And again, the IPP utilities package will have picked the right driver for you:

Just go with what the driver suggests

Changing the name and location is optional:

Your new printer’s almost ready to go!

Hit Apply, and you should be printing!

(Hey, printer manufacturers have been known to be evil and make good, working stuff suddenly not work. IPP is supposed to make everything sparkly again, but I can’t guarantee that something wicked won’t come this way.)

Update: After a few months of using the Brother DCP-L2550DW, I don’t recommend you buy it. It’s a perfectly capable printer, but it takes ‘chipped’ toner cartridges that:

  1. stop dead when you hit their page count limit, wasting toner and preventing you from finishing the print job;
  2. can’t easily be refilled by local technicians, so are wasteful of resources.

gleeful bash scripting: contrived GCD function

The greatest common divisor (gcd) of two natural numbers is the largest number that evenly divides both. For instance gcd(8, 12) is 4. There are many clever and efficient ways to calculate the gcd of two numbers on a Linux machine. The method presented here is not among them.

gcd(){ comm -12 --nocheck-order <(factor $1|sed 's/^[^ ]*/1/;s/ /\n/g') <(factor $2|sed 's/^[^ ]*/1/;s/ /\n/g')|tr '\n' \*|sed 's/.$/\n/'|bc;}
gcd $1 $2

(Contrived) example: 24691357802469135780246913578 61728394506172839450617283945

Which breaks down as:

prime factors of
prime factors of

Multiply the factors common to both:

3 × 3 × 3 × 7 × 13 × 31 × 37 × 211 × 241 × 2161 × 3607 × 3803 × 2906161 = 12345678901234567890123456789

I’m sure someone else has used the output of factor and comm in this way before. The hard part was getting coprime numbers to output 1.

Digital Photo Archaeology: featuring hardware DRM from the crypt

So I picked up this large boy from the MSU Surplus Store:

Sony Digital Mavica MVC-FD91 (c. 1998 CE) — yes, that’s a 3½” floppy drive on there

You get about 7 high-resolution pictures on a disk. And high resolution by 1998 standards means this:

1024×768 whole pixels: that’s huge! The camera is autofocus with image stabilization, so it was quite a nifty unit at the time.

Pre-dating EXIF, its image metadata is limited. There’s an external ‘411’ thumbnail file that looks a bit like this:

If you care to dig about in such an ancient file, I’ve got a matching image and its 411 file here: And manuals? Here: Sony_Mavica-FDC91-W0007229M.pdf

Most annoyingly, the camera really only likes real Sony batteries, or it shuts down with an “InfoLithium” battery error. As this battery format is now used in generate photo lighting systems and Sony don’t make it any more, this may be a camera that dies from DRM before anything else.

Invented right here: the T-Nut

from US Patent 3480061 ‘Fastener member’ by W. H. Leistner, granted 1969-11-25

Simple things like fasteners don’t seem to be invented. It’s almost as if they’ve always been around. Like T-nuts — those hammer-in furniture nuts that also find use as 3D printable tripod mounts — someone invented those?

Sure enough, it seems that local company Sigma Tool & Machine have a lot to do with T-nut development. They’re now on Nantucket Blvd just north of me, and they used to be at 96 Crockford Blvd very close by.

The Quirkey: chording USB keyboard

This may not look much, but it’s a test build of Vik Olliver’s Quirkey USB chord keyboard. I didn’t quite build it to Vik’s specs, which are here:

The Microwriter was a late 1970s/early 1980s gadget that was essentially a portable word processor. Unusually, its keyboard was a single-hand 6 key layout — the thumb did double duty — that was operated by chording multiple keys at the same time. Later on in the Microwriter’s life it evolved into the Quinkey, a chording adaptive keyboard for computers of the time.

Technology has moved on a bit, and the ability to wire up a cheap USB-capable microcontroller and 3d print your own case is here. I used an Arduino Micro on a breadboard and six Omron momentary buttons.

I didn’t quite wire it the way that Vik intended:

Note lifted pins to prevent useless buttons

The buttons are wired like this:

Pin      Button
======= =======
D8 Control
D7 Thumb
D6 Index
D5 Middle
D4 Ring
D3 Pinkie

This requires changing line 22 of Vik’s code from:

const int keyPorts[] = {8, 7, 6, 5, 4, 9};


const int keyPorts[] = {8, 3, 4, 5, 6, 7};

While there are great tutorials on “microwriting” in the original manuals on Bill Buxton’s site, here are the basic alphabetic set derived from Vik’s code:

●○○○○ : Space
○●○○○ : e
●●○○○ : i
○○●○○ : o
●○●○○ : c
○●●○○ : a
●●●○○ : d
○○○●○ : s
●○○●○ : k
○●○●○ : t
●●○●○ : r
○○●●○ : n
●○●●○ : y
○●●●○ : .
●●●●○ : f
○○○○● : u
●○○○● : h
○●○○● : v
●●○○● : l
○○●○● : q
●○●○● : z
○●●○● : -
●●●○● : '
○○○●● : g
●○○●● : j
○●○●● : ,
●●○●● : w
○○●●● : b
●○●●● : x
○●●●● : m
●●●●● : p

The astute reader may note that these are binary values (low bit to high) of the character positions in Vik’s alphaTable variable. And yes, that’s supposed to be preformatted text.

Happy microwriting!

Tact & Buttons

The right and wrong ways to connect buttons

Buttons, Tactile switches, Momentaries, Clickies, SPST-NO; call ’em what you will, but my world seems to be full of them right now. Wiring them or breadboarding them may not be as simple as they look.

Whether they are the tiny 6 mm ones of the less-easily-lost 12 mm ones, both types typically have four pins or legs, two on the top and two on the bottom. If your appear to have the legs on the sides, flip ’em 90°: they won’t fit in breadboard sockets the wrong way.

The pins on the left and right side are common, so connecting top left to bottom left won’t ever change state if you press the button. So use either the pins both on the same side or those diagonally opposed if you want the switch to work.

You can use these buttons on a common breadboard rail. You must remember to have only one button pin connecting to the rail; lift the other pin so it won’t connect. You can then use just one wire connected diagonally across the the common rail pin and you’ve got a working button. This is especially useful when using a microcontroller with built-in pull up resistors (that’s most of them these days).

If you connect both pins to a common rail, you’ve just made a SPST-AO (single pole, single throw – always open) switch. Those aren’t much use at all.

ephemera: Government of Canada “Action Request” – phone memo slip

Government of Canada - Action Request slip paper, yellow, 100 × 133 mm (form refs: GC 12E, 7540-21-868-3907) c. 1990
Government of Canada – Action Request slip
paper, yellow, 100 × 133 mm
(form refs: GC 12E, 7540-21-868-3907)
c. 1990 (est)

found inside a copy of the “Commodore 64 User’s Guide” bought from JPPBM at World of Commodore 2018.