Trying Elementary OS and saving waste

I make no apologies for being a Windows desktop user in a very Linux heavy community. For all the "Linux is better" sentiment I've always struggled to deal with its deficiencies as a desktop OS.

However I decided to make a foray into using it more on the desktop as I feel 'daily driver' use of Linux is a gap in my experience. A lot of this was prompted by recent versions of Elementary OS looking like a good candidate with a 'curated' app store from which things are supposedly going to 'just work'. Some are even paid for, at the sort of price you see on mobile apps, ie. 1-5$.

I'd thought about sticking Elementary alongside my desktop install, and even went as far as clearing the space on the SSD but then a 'free' laptop appeared at work. A colleague brought it in to go into our WEEE recycling but I snapped it up, much to the amusement of my team.

The machine is an old Acer V5-552 (quad core AMD A10 and 6GB RAM) which would have been pretty decent in its day but what I had in my hands was filthy, covered in cruft and greasy marks and had no HDD as that was taken out and smashed after failing.

It also transpired they didn't have the PSU, all the screws were missing from the base when they'd dismantled it and they'd set a BIOS password they couldn't remember. I had a little look under the base cover and found that it also had a nastily failing battery that I wouldn't consider safe to charge.

So yes it's a 'free' laptop but to most people a basket case and I sort of see that as a challenge. I hate stuff getting thrown out and I've wanted a 'disposable' laptop for a while.

Over the next few days I transformed it from trash to treasure for about £40.

  • A really good clean with a microfibre cloth and warm water, removal of peeling stickers, cruft fished out of all the crevices etc.
  • Fitment of a 120GB SSD taken from an older and slower laptop I had lurking a drawer.
  • Fitment of a new battery supplied from Amazon for £23.99.
  • Upgrade to 8GB RAM with a SoDIMM out of a machine going for recycling.
  • BIOS password recovery using a code from
  • Use of a generic laptop PSU with changeable tips I got in the Maplin closing down sale for something like £5.
  • Some generic laptop screws from a big eBay box that cost £6.
  • Installation of Elementary OS 5.1, which has a suggested donation of $10.
Despite being nominally worse than my Zenbook by most criteria I really like it to use, mostly I think because I like the screen, keyboard and feeling of solidity. It's also not short of connectivity with a wired Ethernet, full size HDMI and so on. The performance is good as Elementary is quite lightweight and the quad core A10 is still acceptable for light use.

After a few days with Elementary I've found that the curated apps are relatively rare and you resort to installing generic Debian versions of most things. There are a few bugs to do with the way Elementary is skinned, notably some apps end up with a double title bar and you need to manually edit the shortcuts to fix this (edit the shortcuts in /usr/share/applications and add env GTK_CSD=0 to the Exec= line). Also Dropbox works but took some fighting to install and doesn't integrate with the desktop at all.

Sadly though Bluetooth mouse support is execrable, they work for a bit then fail and kill the ability to click with the pointer on some elements and the Bluetooth status app (sometimes the whole status bar). I can live with the appearance gremlins but that's really poor for a 'curated' distro and is the kind of thing that reminds me why I've given up on Linux desktops before. I need a mouse for working with KiCAD, which is one of the things I'm learning, and I can see myself falling back to carrying a wired mouse around. Irritating, but I'll persevere as otherwise it's working nicely.

Creality Ender 3

I've come to really like the cheap Creality Ender 2 3D printer I bought a while back but have found the small build area limiting. Then a Banggood Black Friday sale spat out an Ender 3 for £129 and I couldn't resist it. Shipped from the EU it came in just two days but I had to wait until I had some free time to put it together.

The improvements in design and packing over the Ender 2 are really obvious.  It's not complicated to assemble, if you can build IKEA furniture you can do this. Every little bag of components is clearly labelled, right down to the bolts, which come with matching washers already threaded onto them. You even get cheap but usable examples of the tools needed supplied. I would really recommend one of these if you want a minimally viable cheap 3D printer. Contenders for 'best value' come and go but the Enders are a consistently safe bet. The contrast with my Ormerod is striking, things have really moved on.

There's a massive modding community for these but I've shied away from doing anything to it at all. When I remember I'll put a neoprene 'sock' around the hot end to stop stray filament sticking and that's mostly because I got a pack of two when I bought one for the Ender 2.

Makevember 2019

This year I stumbled onto something Dominic Morrow started, Makevember.

The original concept outlined in his blog is to do something 'new' and time limited, but like a lot of others participating I ended up using it as an impetus to work on things most days of November even if it wasn't something particularly new or quick.

I've found this was massively helpful. I've been tackling loads of 'round tuit' things, over the last month I have...

  • Mounted my laser engraver on a board, fitted end stops, rebuilt LaserWeb and made the software changes to make auto-homing work. This turned it from a dust gathering ornament into a much more usable tool.
  • Familiarised myself with the workflow for my SLA 3D printer and printed things for a friend.
  • Built a UV curing enclosure for output from my SLA 3D printer.
  • Fixed up an old medical analyser prop.
  • Fixed up my Orac prop as it had developed a couple of faults.
  • Fixed up my Enigma Machine prop so the keycaps were more robust and the gaps round the LED matrix displays were filled.
  • Made a set of 12V spotlights using Poundland LED GU5.3 units.
  • Experimented with a cheap pico-projector for future use in a new prop.
  • Learned basic use of Meshmixer.
This has been a really positive experience and shows how an incentive can work. If I can keep up this focus the rest of the year then it will be a very productive one.

Photon printing progress

I've finally started using my Anycubic Photon for something after a casual chat with a friend showed they wanted some custom parts made for collectable action figures.

When the thing somebody wants already exists on Thingiverse and you've got an SLA printer this kind of thing becomes an easy favour to do and it has the added benefit of giving you an excuse to get more experience with the printer.

Levelling the bed and slicing with appropriate supports is definitely a learning exercise and I've had a few failed prints, which are annoyingly wasteful of resin.

In the end watching a few YouTube videos got me to this good process for levelling. There seems to be a lot of superstition about the levelling process with vocal adherents for different methods but I'm now getting good prints with this variant.

  • Cut a piece of copier paper so it fits where the vat would go and so you can pull it back/forth from the front.
  • Loosen the hex screw in the middle of the build plate so it can move around on the ball joint.
  • CAREFULLY lower the build plate onto the paper (no vat) until it touches.
  • Lower it slowly, 0.1mm at a time until the paper is firmly held and can't be pulled.
  • Tighten the hex screw while putting light downward pressure on the build plate so it's firmly against the paper and screen.
  • Raise the build plate 0.3mm.
  • Lower the height of the build plate 0.1mm at a time until you can pull the paper out from underneath, but you can't push it back in. You may need to go back and forth a few times.
  • Set this as zero through the menu.
  • You do not need to do this every time, even if you've removed the build plate to extract a print.
Now I'm printing a few of the same thing in different sizes so my friend can try them with the figure, my first guess was perhaps a little oversize but the level of detail is fantastic. It's even better than it looks from the photo.

ESP32-VGA board from Bitluni

There's been a ton of work done by various people to make the ESP32 do things nobody ever really expected. One of those is to output quite decent VGA video.

In principle this is done with just some resistor ladders but building a board to do this is a bit fiddly so I've just picked up one from Bitluni on Tindie.

I don't have an immediate use for this but the vague plan is to use it as some kind of display interface that speaks to my mesh network kit. Connect a PS/2 keyboard and you've got a terminal device based on a microcontroller, rather than using a Raspberry Pi as a bit of middleware and this appeals to me greatly.

YG300 pico projector

I have in mind to build a handheld prop that projects information as you hold it.

What I'm not sure about yet is how this will be implemented but I've been thinking about building a low resolution matrix of lasers and doing something with persistence of vision as you move it.

Which may of course be completely impractical. 
I also saw these pico projectors on sale for only £30 and have picked one up as a more realistic cheap solution. You get what you pay for, they're only a 320x240 resolution, but it does work.

With a Raspberry Pi connected video playback of 4:3 SD content with omxplayer is actually perfectly acceptable for your £30. It's very dim, you have to use it in total darkness but turn the lights off and it's watchable. It'll also play off USB/SD.
To see what's inside I did a teardown. It's all quite predictable, some fresnel elements, a mirror to turn the image through 90 degrees, an LCD shutter and a COB LED illuminator with a big heatsink.

These can take an optional battery pack and there's a space behind the mirror for this. I did a little poking around with a meter and there are three unused connections on the top right of the board.
These connections are labelled B/R/Y

B - Ground
R - Battery positive, it expects a 2S Lipo pack so ~7.2-8.4v
Y - Supply positive which by default is 12V

I assume there's a balance charger built into the battery pack as there seems to be no charging circuit on the board. It runs quite happily off these connections and provides a little battery meter on the menu screens.

Using these connections seems perfectly reasonable although I can see myself making them external rather than squeezing them into the case.

I'd like to run this off a Raspberry Pi Zero, although equally something like an ESP32 can be wired up very easily to generate composite video. At 32x240 it really doesn't need to connect over HDMI.

Space inside is very limited but it would not be impossible to 3D print a replacement case that spaces the elements out like they are in in the original.

It could perhaps make for an interesting "pepper's ghost" setup that emulates a sci-fi hologram projector, just so long as it's in the dark.

EleksLaser end stops

I've had this laser engraver for quite some time but not used it as much as I originally expected.

Lots of that is because it is quite bulky so I can't leave it taking up a table and it's then a bit of a pain in the neck to set up every time, with lots of dangling cables and connections. So over the last couple of evenings I spent a bit of time screwing it down to a mounting board and making it portable.

Once I'd done this I was reminded that it doesn't have any end stops and is prone to hitting the end of travel if you're not careful. This irritates me more than it should as it doesn't actually do any damage, but it can waste loads of time making you set it up afresh with every run and occasionally ruining a job.

I did a little reading round the topic and decided to add end stops and configure it so it will auto-home. This is supported by GRBL but not the controller board supplied, it omits the connectors as well as the limit switches. It is however straightforward to solder the limit switches direct to the bottom of the board.

It was a real surprise to me there was no complete how-to for this even though the information is pretty freely available. So I wrote one and put it up with the designs for the switch holders on Thingiverse.

I'm still using LaserWeb to drive this but thinking about purchasing a copy of  LightBurn as it's quite affordable.

Enigma machine refresh

One of my favourite projects iss my Enigma Machine prop but it had a few shoddy areas. In particular the keys were just hot-glued in place on the end of the brass tubes. This made them prone to damage and they weren't 100% even.

Now my Ender 2 is printing beautifully I made some little cups to hold the keys squarely on the tubes and epoxied them in place. It's more solid and looks better too.
While I was giving it a freshen up I also made some little surrounds for the matrix 'rotor' displays. The Enigma was being made in a hurry and I simply didn't have time to cut neat square holes for the displays so I drilled out some round holes and wedged them in.

This has always annoyed me so I made round spacers to hide this. At some point I'll cut some tinted acrylic to fill the space above each matrix and act as a diffuser.

Repurposing the Nook Simple Touch

A long time ago my brother and I were gifted a pair of Nook Simple Touch e-readers but eventually Barnes and Noble abandoned the UK market and they ended up as drawer cluttering e-waste.

However they are actually quite interesting devices and a small community has built up around modding them so they can be used more freely. They're very low power Android tablets with Wi-Fi, an excellent e-ink touchscreen and five usable buttons round the edge.

So I dragged them out of the drawer and went through a tutorial I found to see how they behaved.

Once rooted and with the new launcher installed they work just fine and I found a few more tips online to make them more usable. No, I've no idea what they'll get used for yet but they can run things like the SSH client ConnectBot if you pick an old APK.

Supposedly with the new kernel I've uploaded which will make plugging in a keyboard etc. possible so they might make for an interesting low power terminal. They don't have the CPU or RAM to run a modern web browser, but the one on there is OK for minimalist web apps.

Creality Ender 2 fixed

I finally got my Ender 2 3D printer fixed. As I'd diagnosed, there was a near short in the heater cartridge and I've now done my first test print after replacing it, which came out perfectly. Absolutely no fancy tuning, just level the bed with the thumbscrews and a piece of paper then press print on the test file on the supplied SD card.

There are a few surface blobs but for a zero effort test print I couldn't have asked for more. Definition on the Chinese characters is excellent. I also lined up a Benchy and it came out pretty well but it did take a while to print so wasn't any kind of speed test.

This little £100 printer is so impressive, it seems a shame they aren't widely sold any longer. I know the Ender 3 is nominally upgraded but the Ender 2 is already a sufficiently good 'first 3D printer'.

I can see myself using this a whole load, as my Ormerod is still sadly kind of unreliable.

The Ender 2 prints from an SD card, but I'm used to having remote control and monitoring of my printers over the network. To fill the gap I've set up Octoprint to drive the printer directly from a Raspberry Pi, doing away with the need for SD cards.

Octoprint is widely used and I've worked with it on the Hackspace 3D printers before but as my other printers have network interfaces this is the first time I've used it in my own workshop. The fact it adds support for a USB camera to observe printing is a nice extra. I used to do that with a standalone camera setup on the Ormerod. For a slicer for the Ender 2 I'm using Cura as that's well integrated with OctoPrint. By adding a Cura plugin you can send files directly to the printer and monitor progress, including getting a a nice view from the camera.

The external PSU, Raspberry Pi and so on makes for a slightly untidy setup so I will make myself a little stand base to put the extra clutter in.

Oh and it makes the proper 3D printer sing-song stepper driver noise. Ever since I upgraded my Ormerod to a Duet 3D with Trinamic drivers it's near silent and I'd missed the noise.

Just listen to it...

Presentation at Raspberry Pint September 2019

I recently gave a talk at Raspberry Pint about my mesh networking project. Nominally this is a Raspberry Pi meetup but they're happy to cover various tech and maker subjects and I've spoken there a few times before.

I'm reaching the stage where my code can be demoed and hopefully released soon.

Annoyingly, I managed to damage the Wemos D1 mini I'd brought with me to show the chat application demo on the projector but it worked on the netbooks I handed out.

ESP32-CAM breakout

While I'm waiting for a Brian Lough to make a proper breakout board I scratch built one for the fantastic ESP32-CAM board.

It's a bit ugly but it lets me program these up easily while I'm testing my code. The reset line isn't brought out on the headers. So you have to push the button on the underside of the module while simultaneously pushing the 'program' button I put on the breakout. Fiddly but it works.

Something I've also noticed is that if you use a Sparkfun 3.3V FTDI basic board to power the ESP32-CAM 3.3V line directly you get awful problems with power brownouts. This means that you might be able to program the board but it won't reliably boot and work. This isn't surprising, the board needs quite a chunk of power.

So I'm using a Sparkfun 3.3V FTDI basic with the power link changed on the back to 5V. This connects the 5V from the USB straight through to the device. The logic level is still 3.3V, so you won't kill the ESP32.

Ender 2 troubleshooting

To my shame I have left my DOA Creality Ender 2 to lurk in a corner pretty much ever since I got it. I managed to get a replacement PSU as it cut out when the hot end started but it just behaved the same with the new PSU.

My attempts to follow this up with the seller turned into a wrangle with them wanting me to contact Creality for support and I ran out of enthusiasm as I was busy and I had fixed the other printer. I just never take my own advice about not accepting repairs on new goods instead of demanding a replacement. One day I'll learn.

This weekend is quiet so I pulled it out and had the cover off the controller. It's a really easy printer to work on, just undo the three outer screws on the cover and it pops off giving you easy access to the board. I know it's never actually worked but I'm still impressed with how nicely this is put together for the money.

As I suspected, with the hot end heater cartridge disconnected the printer no longer cuts out when you apply power to the hot end. The heater cartridge isn't a dead short, but it's only about 2 Ohms.

To test things further I connected a 35W incandescent 12V light bulb to the heater terminals and everything works fine, so the board and PSU are almost certainly good.

I've now got a replacement hot end on the way, thankfully parts for these are dead cheap. You can get better quality upgrade parts for the Creality printers but when a good hot end is as expensive as the whole printer I'm unconvinced of the worth of this. Everything I've seen from other owners is that the stock hot end is perfectly adequate.


I bought this weird "WeMos Mega" combo board from Banggood on a whim. It's an Arduino Mega 2560 clone with an onboard ESP8266. They both operate independently but you can flip some DIP switches to connect the serial pins together allowing them to send messages back and forth. I assume there's some level shifting onboard to match the 3.3V/5V levels too. You don't have to link the two processors, they can in principle leave them disconnected although with a single USB serial you still need to use the DIP switch to set which one you're programming.

As the Mega has four serial ports it gives you the option flick a switch and connect the ESP8266 to Serial3 leaving Serial0 for USB comms/programming the Mega. There's also a separate pin header giving you access to the ESP8266 pins directly.

This is either the best of both worlds, or the worst of both. I've got a project coming up where I would like to use a few more pins than an ESP8266 has as standard and I grabbed it for that. It could easily be argued an ESP32 board with all the pins broken out would cover the same ground.

What's the target market? I'm unsure, I guess people who are used to old-school Arduino kit and want to use the ESP8266 in its somewhat old-fashioned role as a Wi-Fi co-processor rather than as the really useful microcontroller it is in its own right.

Anycubic Photon

I randomly saw a Twitter acquaintance posting about how these SLA printers were currently on offer direct from the manufacturer and couldn't resist.

My now incorrect world view includes SLA 3D printers being too expensive for casual hobbyists to buy and I'm glad this has changed.

As of Autumn 2019 you can pick one of these up for ~£275, which is around the same price as an effective FDM printer like a Creality CR-10. The build volume is tiny but if you're buying an SLA printer for the surface detail it can handle you probably aren't making things much bigger than would fit in the palm of your hand anyway.

A good thing about these specific printers is they are a few years old and have built up a strong community around them. This is helped by the fact it's a based around a generic controller board made by CBD Technology meaning it's not 100% locked to support by Anycubic. There is a newer AnyCubic Photon S which isn't markedly improved and suffers from having to use a proprietary slicer from AnyCubic.

The community has a lot of advice, tips and mods and one of the first things I did was to enable the onboard network port which allows you to upload things to the printer over the network. The Duet3D board in my old RepRapPro has spoiled me and messing around with swapping USB sticks or SD cards to provide files for printing seems quaint.

I don't have an immediate clear use for this but there have been times in the past where I want to print something small and detailed that my FDM printer can't manage. The first thing I'll probably try is some custom keycaps for some small handheld devices I would like to make.

These cheap SLA printers work by having a very thin flexible non-stick membrane in the bottom of the vat of resin. As each layer is printed, the plate moves up, the membrane flexes and this peels the print off this membrane. It's quite fragile and both the membrane and screen are considered consumables. So this won't get used for any high volume work.

Once printed the resin is not 100% cured and a strong UV source is needed to finish the job. I've left my test print in the sun for a few days, but I'll need to sort myself out a small curing cabinet.

Mesh network site test

We're running a game in March where I'd like to use my mesh network stuff in anger.

As a Londoner I find it really hard to test any of this stuff properly as open space is at a premium and if you put boxes on poles up on the public land near where I live, people will think you're spying on them or doing something nefarious. It's just one of those things you get from living in London.

This weekend though, it got the real test as we conducted a site visit so we could plan out how we are going to use the various buildings and areas which allowed me to test in the actual environment.

I'm glad to say it all worked, but the heavy foliage on all the trees and shrubs really killed range and I had to put the test nodes much closer together than I hoped. Of course the point of all this is that the wearable/portable devices should gap-fill to ensure coverage but for one thing I need a guaranteed 'corridor' from one area to another so it's guaranteed to be always up.

I really must design those custom LiPo powered PCBs for the ESP8285 modules I have and order them from China. The current test boxes are based around WeMos D1 Mini Pro and Poundland NiMH batteries so they work but are a bit inefficient and simply won't run a whole weekend. My power budget suggests an ESP8285 powered by two 18650s and the high efficiency switched mode power supply I've specified will.

The wonderfully cheap ESP32-CAM

I have a vague aspiration to build networked bodycams for our Sci-Fi LARP system. You see it often in movies where people back in a control room can see what the 'away team' are doing. Action movie emulation is where we're at.

Since the first ESP32 based camera boards arrived I've been eyeing them up but there's been a sudden influx of cheap ones (about £4.20 delivered) on Banggood and I bought a small batch to play with.

There are a few bits of example code floating around on the Internet so I uploaded what proved to be a very solid 'streaming webcam' sketch and I'm very impressed. Now I need to port my ESP-Now mesh network code to ESP32 and see if I can do video, or at least frequently refreshing stills, over that.

ESP8285 programming

For the boards I'm planning on building I'm going to shift to using ESP8285 modules instead of ESP8266.

The main reason is the integrated flash and the secondary one is it's smaller, with more usable pins than an ESP-01S in less space. I'm not at all space constrained for the first iteration of my project but I will be for later items.

Nice as these are they're really designed for surface mount use so I had to build a little breakout to work with the handful I bought to test with. It's a bit rough and ready but works just fine.

A side effect of the integrated flash memory is you don't need to mess about with pulling pins high to boot. You just need to pull GPIO0 low if you want to program it. I put a couple of buttons on my breakout, one to reset and one to hold GPIO0 low, making for easy programming.

I did a little test with this and my mesh code works perfectly. Another bonus is these chips seem to use slightly less power, ~70mA instead of ~80mA for the ESP-01S. Some of that will be the lack of LED indicators but it's welcome nonetheless on a battery powered project.

Solar charging

I'm still working on my mesh network stuff but sometimes it feels like I'm working on so many things at once I never make any progress with any of them.

One of the things I want to make sure I have in place is a number of fixed nodes with decent batteries and passable antennas to do the heavy lifting of infill coverage.

I built ten of these and they worked but battery life with cheap NiMH cells was disappointing so I'm doing a second iteration where I'm throwing more serious batteries, better efficiency and top-up solar charging into the mix. The hope with this is that they will run for 2-3 days at least.

For the batteries I've purchased twenty brand new 2500mAh 18650 LiPo cells, planning to put them together in pairs. A quite naive calculation on battery life, assuming the nodes use about 80mA gives me 60 hours, but I know it'll work out less than this.

For efficiency I'm looking at an efficient PAM2301 switching regulator recommended to me by Mike, who's used them in some of his projects. This will generate the 3.3v needed for the ESP8266.

I'm also going down to ESP8285 modules with no status LEDs or clutter, which should help a bit. I've yet to measure their typical load.

The solar charging is a whim that may not deliver. I've picked up ten 1W 5.5V panels from China and after a bit of reading round the subject settled on using an MCP73871 charger chip and bought an official development board to play with.

With LiPo cells you can't just connect a charger to the batteries at the same time as the load. The charging algorithm for LiPos has constant current/constant voltage modes to ensure safe charging and attaching the load directly during charging messes with that.

The MCP73871 was very specifically chosen because it's not a simple charger but a power management device designed to supply power to the load as a priority, charging the battery if there's excess current available from the supply. It also manages switching the load from the incoming supply to the battery when there's no incoming supply. It's not an MPPT charger but it does reduce charging current when the supply voltage drops and tries to stabilise it. Which should achieve a similar end.

If I've read the datasheet correctly all this means it should fairly transparently 'top up' the 18650s if the solar cells can provide enough current.

There's a LOT of IF coming off this plan. One of the 1W panels delivered 100mA in the morning sun to an LED so I may not be completely out of luck.

I've got some INA219 current monitoring modules coming too so I'm hoping to get some fairly true readings of how this all behaves by putting them into the proof of concept build. I may be able to monitor the panel, charger and battery individually at the same so I can see what's going on and do fairly good efficiency measurements.

Or I may just give up, buy some bigger panels, better NiMH cells and connect the panels straight to them via a diode. :-)

Don't shoot the nuclear weapons

This weekend I was off to our anthology LARP event and I was going to spend the whole time as 'crew' where you're the 'baddies' or 'extras' needed to make the story happen.

The Saturday was a Legends of Tomorrow-esque setup with the players travelling through time to chase down a temporal conspiracy. So we had a Victorian military demonstration, 70s CND protest and 23rd Century spaceship launch in one story line.

Games like this often need props and I volunteered to make something. As part of the 70s section I ended up putting together a 'suitcase nuke', the sort of thing beloved of 90s action movies. The game organiser built a WWI tank and replica of the HG Wells time machine out of wood, carpet roll tube, random household junk and Correx sheet. I got the easy job.

This prop is a big pile of old-school Arduino stuff: a matrix keyboard, hand-wired LEDs for the 'plutonium core' and a 32x8 LED matrix driven by MAX7219 chips to show the countdown timer on. All housed in an equipment case a friend gave to me and accessorised with some 3D printing. It was a bit last minute and I made a deliberate effort to use up a bunch of stuff that was sitting in my storage boxes. The only thing I spent money on was a sheet of MDF and some spray paint.

It does the LED countdown thing and if you unscrew the display it conforms to the "help I'm being disarmed" trope of the counter speeding up, but you can quite easily switch it off.

It was quite a simple from a technical perspective but good fun in the game and there's plenty of scope for it to be re-used.

Creality Ender 2

I've been having some issues with my old RepRapPro Ormerod 2 3D printer, lots of it because I've run it hard and it's ageing badly.

Various chassis parts have cracked and needed replacing and a while back I had to replace the Duet3D controller board when the MOSFET for the heated bed burned out.

So on a whim a got a second printer
This Creality Ender 2 is an astonishingly cheap FDM 3D printer that a whole bunch of people have been picking up recently. You can get one for ~£100 which is amazing given they turn out good quality prints.

Overall design is similar to my Ormerod with a single upright, making for a very compact printer. The only cheesy bit is the PSU which is one of those generic silver box ones and the safety cover is functional but naff.

Annoyingly, it proved to be DOA as the PSU trips out as soon as the hot end starts to heat. It's a drop-ship direct from China and I have asked for a replacement PSU rather than try and get the whole thing replaced.

Resurrecting the Tilda MKe - part 2

Some time back I got interested in unravelling the set of libraries/board definitions for the 2014 EMFCamp badge so I could use it with modern versions of the Arduino IDE and associated libraries.

Well I had another fiddle over the last couple of days and now have the display working which was the last big hurdle. This was really just poking through other peoples' work from 2014 and working out where to stuff the information in a different library to make it work.

The display controller is supported by the common U8g2 library as it's an ST7565, but there's very little info about the JHD12864-G13BSW screen itself. So I initially got a visible image but with unusably low contrast and viewing angle. Wading through the old library showed up the settings needed to set the bias voltage on the display and a quick read of the U8g2 FAQ showed me how to feed this to it without having to change anything in the library. So now here's a working demo of one of the example sketches that come with the library.

I really need to build a demo sketch that does all the functions but in the meantime here's something that will drive the screen if you've got one of these and want to play with it.

  Universal 8bit Graphics Library (
  Copyright (c) 2016,
  All rights reserved.
  Redistribution and use in source and binary forms, with or without modification,
  are permitted provided that the following conditions are met:
  * Redistributions of source code must retain the above copyright notice, this list
    of conditions and the following disclaimer.
  * Redistributions in binary form must reproduce the above copyright notice, this
    list of conditions and the following disclaimer in the documentation and/or other
    materials provided with the distribution.
#include <Arduino.h>
#include <U8g2lib.h>
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>

  U8glib Example Overview:
    Frame Buffer Examples: clearBuffer/sendBuffer. Fast, but may not work with all Arduino boards because of RAM consumption
    Page Buffer Examples: firstPage/nextPage. Less RAM usage, should work with all Arduino boards.
    U8x8 Text Only Example: No RAM usage, direct communication with display controller. No graphics, 8x8 Text only.
  This is a page buffer example. 
// Please UNCOMMENT one of the contructor lines below
// U8g2 Contructor List (Picture Loop Page Buffer)
// The complete list is available here:
// Please update the pin numbers according to your setup. Use U8X8_PIN_NONE if the reset pin is not connected
#define BOARD_SPI_SS2   (52u)
#define LCD_CS          BOARD_SPI_SS2
#define LCD_POWER       (40u)
#define LCD_BACKLIGHT   (35u)
#define LCD_A0            (38u)
#define LCD_RESET         (34u)
#define CMD_SET_BIAS_9 0xA2
#define CMD_SET_BIAS_7 0xA3

//Screen is JHD12864-G13BSW and ST7565 controller
U8G2_ST7565_ERC12864_1_4W_HW_SPI u8g2(U8G2_R0, /* cs=*/ LCD_CS, /* dc=*/ LCD_A0, /* reset=*/ LCD_RESET); // - Works well!

void setup(void)
  //Turn on the display
  //Turn on backlight
  //Start display
  //Set the bias so it's legible
  u8x8_cad_SendCmd(u8g2.getU8x8(), CMD_SET_BIAS_9);
  //Set some contrast now the bias is OK
void loop(void) {
  do {
    u8g2.drawStr(2,14,"Hello World!");
  } while ( u8g2.nextPage() );

Size matters more than ever

A few years ago I commented on how a smaller board makes more projects possible. Then it was comparing an Arduino Uno with a Nano.

Now I'm looking at the ESP8266 boards I've been using and thinking about the practicalities of building a wearable sensor/tracker. While I can never hope to replicate the level of integration in a commercial project I am looking for something to keep it as small as possible.

I had been working on some sneaky use of the pins on an ESP-01 module in my first prototype but it's still quite chunky and the 8-pin header makes it quite tall.

Time marches ever on and now decently packaged ESP8285 modules have appeared in the usual places. These are a minor update to the old faithful ESP8266 with integrated flash memory but otherwise backwards compatible. The integrated flash makes for a slightly smaller module and offers a certain guarantee of the quality of that flash as it's coming straight from Espressif. Some cheap ESP8266 based modules come with questionable quality flash memory.

Here's a Wemos D1 Mini, ESP-01 and the new ESP-M2. It doesn't save you much over the ESP-01 but it delivers a ton more pins and can be surface mount soldered onto a board.

Now all I need to do is make a breakout board so I can do some testing with it before I have some boards made.

D1 Mini breakout

I'm a big fan of the Wemos D1 Mini and Mini Pro as the basis of microcontroller projects.

They're cheap, the ESP8266 chip is powerful and can be used with several development environments/languages. You can program them in C/C++ with the official Espressif SDK, but also the Arduino IDE where support is excellent. They'll also run more modern interpreted languages like MicroPython and Lua, again with good support if some memory limitations.

Most of the time, people consider ESP8266 boards for IoT type projects but you don't have to use the WiFi, it can be switched completely off and at heart they're a 80/160Mhz 32-bit device with enough GPIO to handle many small projects. About the only thing they suck at is low power/sleep which is poorly implemented by comparison with other modern boards.

What they do lack is such a large ecosystem of 'shields' and breakouts. Wemos make their own but they're all a bit 'Arduino sensors 101' type things.

I saw these chunky screw terminal breakout boards mentioned on Twitter and while I have no immediate use for them I picked a couple up because I know they'll be great for prototyping stuff.

Made it into Hackaday

An acquaintance picked up on the Chindōgu and I made it into Hackaday, woohoo!

Things you don't normally need to worry about

Something we almost never think about nowadays with tech is 'how do I switch it on?', or vice-versa.

Decades of product design and familiarity means we 'just know' how things are supposed to turn on and off.

Except it's a big personal annoyance of mine that the Raspberry Pi has no on/off switch. I know why they've done this, it's all about saving a tiny bit on the cost and keeping the price down as low as possible.

So you're either plugging and unplugging the USB lead, switching it off at a wall socket or maybe you've bought a specific USB lead with an inline switch.

All of which is frankly rubbish. Modern computers aren't meant to be unceremoniously shut off and doing so can corrupt files and in the worst case break the file system badly enough they won't boot. It's unlikely but it does happen. So since the mid-1990s, we've expected computers to have 'smart' power switches that allow for a clean startup and shutdown process. If you shut a Raspberry Pi down, it still sits there consuming power, albeit lots less, until such time as you manually remove power.

I hate this and for anything where you expect a Pi, especially in a portable device, to be used by everyday people it needs an on/off switch that conforms to consumer norms.

I'm not the only person to think like this and there have been a few products over the years catering to this. If you want an off the shelf solution, the Pimoroni on/off shim looks good, but it doesn't fit my need to control power of differing voltages to other things.

So I've used a more generic smart power switch and made my own solution.

When you break it down, the accepted norm of a power button is now something like this.

  • If you push it and the device is turned off, it will turn on
  • If you push it and the device is turned on, it will turn off in a prompt but orderly fashion
  • (optional) If you push and hold some kind of reset/setup process may occur

The module I've gone with is the Pololu "Mini Pushbutton Power Switch with Reverse Voltage Protection, LV", which ticked my boxes. It has a very low current draw in the 'off' state and can be controlled by supplying signals on different pins. I've previously made myself little arrangements with MOSFETs for this but an off the shelf module keeps things compact.

Switching things on with the module is simple. Connect the incoming power supply to VIN & GND, feed that out to the Pi (and anything else) from VOUT & GND. Use a momentary switch to connect pin 'A' to ground and the power comes on. Pushing it again does nothing as the module latches in the on state.

Switching off is a bit more complicated as it has to be driven by the Raspberry Pi.

What I've done to achieve this is use a DPST button with the second 'pole' connecting a Pi GPIO pin to ground. So when you push the button the Pi knows you are asking it to shut down. Which needs a script. A script that needs to always run at startup.

I've opted to use a very basic systemd service for this, which is a very common way to shut down the Pi with a button, there are multiple how-tos around.

First create a file called '' somewhere you put your own scripts, I put this in '/home/pi/scripts/' and used GPIO pin 17 but you can change that easily.


# export GPIO pin and set to input with pull-up
if [ ! -e /sys/class/gpio/gpio$gpioShutdownPin/ ]
 echo $gpioShutdownPin > /sys/class/gpio/export
 echo "in" > /sys/class/gpio/gpio$gpioShutdownPin/direction
 echo "high" > /sys/class/gpio/gpio$gpioShutdownPin/direction

while [ true ]
if [ "$(cat /sys/class/gpio/gpio$gpioShutdownPin/value)" == '0' ]
 echo "$gpioShutdownPin low, Raspberry Pi Shutting Down!"
 sleep 1
 sudo /bin/systemctl poweroff
 exit 0
sleep 1
Now make the script executable.
sudo chmod +x /home/pi/scripts/
You should test this works nicely by running it manually and checking that when you push the power button it shuts the Pi down. Don't do the next step until you've debugged this as you might find your Pi immediately shuts down every time you power it up.

Once this is working reliably, you need to make a systemd service pointing at this script to make sure it starts when the Pi boots up.

Create the file /lib/systemd/system/gpioshutdown.service
 Description=GPIO driven shutdown service
Then enable it with the following
sudo systemctl daemon-reload
sudo systemctl enable gpioshutdown.service
Reboot the Pi, check the status of this new service with..
sudo service gpioshutdown status
..which should show it as running and make sure pushing the button shuts the Pi down.

So far so good and there are a ton of examples like this out there. However it doesn't fully power the Pi off and most how-tos don't cover this.

For that you need another connection to the Pololu module and another script.

The Pololu module has an 'OFF' connection and if you drive this high it will shut off power completely. I have connected this to GPIO pin 27.

To make this go high once the Pi has finished shutting down, create the file /lib/systemd/system-shutdown/


if [ "$1" = "poweroff" ]; then
 /bin/echo $gpioPowerOffPin > /sys/class/gpio/export
 /bin/echo out > /sys/class/gpio/gpio$gpioPowerOffPin/direction
 /bin/echo 1 > /sys/class/gpio/gpio$gpioPowerOffPin/value

Make it executable
sudo chmod +x /lib/systemd/system-shutdown/
Any scripts in this directory get run when the system has reached the final stage of shutting down and has remounted the file system read-only, so is safe to power off.

So now you have made the Pi behave like people expect a normal device to work, safely.

For extra credit it would be possible to make the shutdown script change/replace some files before shutting down if you do a 'long press' for a 'factory reset' but I haven't needed this yet.

Chindōgu - Raspberry Pint presentation

I did a presentation about my Raspberry Pi powered Sony Watchman project at Raspberry Pint, a London Raspberry Pi meetup.

Chindōgu - part 2

This weekend I spent a chunk of time building a second Watchman based device.

The initial plan was to add more resource by fitting a Raspberry Pi 3A+ giving it a big performance increase but after desoldering some of the headers from the board and poking around I just couldn't fit it in the case. It might be possible with extreme measures like removing the camera header and soldering the ribbon cable directly to the board but this feels like it would be a failure anyway.

I ended up doing the simple incremental change of fitting a camera and sticking with the Raspberry Pi Zero W and it can just about handle video calling with Ekiga.

As standard the Pi Zero camera comes with too short a cable for this to work at all and there's no way a full size Pi camera will fit in the space under the CRT. You can't buy Zero camera extension cables but you can convert them to a full size ribbon and back again so this is what I ended up doing. Three cables and two joints but it still works just fine. It's routed all the way round the left hand side of the case and emerges back on the right side. This is so it's possible to maintain the original slide on/off switch and volume control.

The tuner wheel has been converted to a 'rocker' type switch with a couple of tactile switches, epoxy and luck. I also made a better job of the power switch, fitting an actual slide switch rather than a momentary one and relying on a long cruddy lever to push it. This all works much better than my first prototype and I may go back and rework it in this style. I'll need to buy more camera cables/joints though.

I'm still yet to do anything about audio. I dug out a little USB microphone dongle and may see if I can slim it down and hardwire it to a USB cable plugged into the port on the Zero. I'm not keen on desoldering the USB port, just in case.

For audio output I need to test the PWM output method and build a suitable filter.

Oh and then there's all the software I need to tweak, while Ekiga works there's no realistic way to control it so I'm dialling in from a laptop to test.

Obscure Arduino tips #2

This one may not be so obscure if you're a competent C++ programmer, but if you're somebody just finding their way in writing their own Arduino libraries it can be a major roadblock.

It is not uncommon for libraries that allow you to do work triggered by external events or that happen asynchronously to use callback functions. Your code will work fine but once you start turning that sketch into into a C++ class as a library, you won't be able to compile it.

The example I'll use is the ESP8266 WiFi scanning class, as this is where I encountered the problem.

While my code was a monolithic Arduino sketch I could kick off a scan with code like this.
Where 'myCallbackFunction' is just the name of the callback function in my sketch. This is nice and easy.

Once you create a class, you can in principle have multiple instances of that class. Not to get into the detail of C++ classes (because I'm not a real C++ programmer) but when you need to refer to the specific instance of a class there is a 'magic' extra parameter 'this'.

A lot of the time you can ignore 'this' as a naive Arduino programmer when you make a library but you will bash up against it eventually, probably when you go to use a callback or function from another library.

You can use one of the standard C++ functional adaptors to help you, std::bind, which allows you to create a new function referring to the old, but change the arguments to the function. This allows you to pass 'this' into the callback without changing your original function at all.

So the code now looks like this.
The callback function in WiFi.scanNetworksAsync is passed an integer telling it how many networks were found and to make sure that is there in the new function it needs a placeholder 'std::placeholders::_1'.

For every argument in your original function you need a 'std::placeholder::_X' argument. So add extra parameters of 'std::placeholders::_2', 'std::placeholders::_3' etc. etc.

That's it. Unless you're actually trying to use a C library when it gets more convoluted.

ESP-Now BATMAN data encapsulation

I've been working on other stuff recently but haven't totally forgotten my mesh network library.

Over the last couple of days I've been fiddling around with encapsulating data in a way that's very easy for somebody writing an Arduino sketch.

The first third of this is done in that I've written a set of overloaded functions for the common Arduino data types including both char arrays and the much maligned String type.

There's a single function 'add' that starts building a packet for you and works out how to pack the data based off the type of the single argument.

To add some data then send it (flooding the network) it's just a few lines of code.


Both functions return true or false depending on whether they are successful. You can add as many values as will fit in an ESP-Now packet and if there's no space left, 'add' returns false.

I've written a small sketch to send random amounts of random data of random types every ten seconds. It can fit about 30 values in each packet depending on exactly which types are involved.

This has been running for about eighteen hours without any hiccups so I'm happy with it.

My next task is to write a set of functions to give access to this data from a sketch when it arrives. I've written the logic to decode packets and print out the contents nicely but need to think through how to present it to a person writing their own code with the library.

It's not as easy as the 'add' function as I can't really overload it, unless I do something like make people send pointers to their variable. Which I don't think is very friendly, however efficient it might be.

There's also the matter of sending messages to specific nodes, which means a whole load more public functions to find out about the mesh and allow the retrieval of MAC addresses. Which again feels unfriendly because you're going to end up with hard coded MAC addresses unless somebody layers on their own way of mapping MAC addresses to their various nodes' identities or functions.

I might implement my idea of giving nodes names which are simple text strings. Who cares what the MAC address is after all, it's what code is running that matters.

So you could call one node 'Daylight sensor' and another 'Light switch' and the former tells the latter to switch on when it gets dark. I'm not expecting this library to be used for IoT type things like this but I think it's a good example of why having human readable names is desirable. I could just add the name to the 'status' protocol packets I already send.

It's slow discovery of requirements as I write that demonstrate why this isn't a professional piece of software engineering and also why it's taking me so long. :-)

Chindōgu - part 1

A friend called this a Chindōgu and I had to look the term up. He called it dead right.

For some time I've been meaning to fit a Raspberry Pi inside a vintage Sony CRT portable TV, making the chunkiest most impractical yet still portable Raspberry Pi. I've been spending all my time coding my mesh network and last weekend needed a break so this practical project called out to me.

Squeezing the Pi inside was comparatively easy. Bigger than the more common 'oblong' models, this FD-250B has a rounded case, offering a bit of space round the edges, bigger screen and an AV in socket on the side making connecting the Pi trivial. No hacking into the tuning circuit, I just desoldered the AV socket and connected the Pi composite output up.

I'm using a Raspberry Pi Zero W, which has no sound output by default so at the moment this is silent, but there's a way to generate sound by re-allocating some PWM pins and feeding it through a low-pass filter. I may get back to this later but need to be clear if I'm sticking with the Zero or upgrading to a 3A+ with the sockets desoldered, which would give me audio.

I'm trying to keep this externally as original looking as I can so it's still running off the four AA batteries and uses the original slide on/off switch, but repurposed to trigger a smart power switch so the Pi can shut down gracefully when you switch off.

At the moment the tuning wheel is completely removed and I plan to turn it into a rocker switch for scrolling up/down, selecting things etc.

You can just about use the GUI with a paired Bluetooth keyboard and mouse. Web browsing sucks, not just because of the screen size and distortion, but also because the Zero doesn't really have enough horsepower. Here's a little video of it in use.

After this I tried playing a couple of 4:3 video clips and it excels at this. Which is right and proper given its original intended purpose. Right now you have to start omxplayer manually from the command line, but I can see how a simple file browsing GUI, probably written in Pygame, could turn this into a decent super-retro media player.

I have plans beyond this though, I want to squeeze one of the tiny Pi cameras inside, perhaps where the tuning pointer was, and it's occurred to me I might be able to fit a resistive touchscreen if I replaced the round bezel. Which I would like to do anyway if I fit the camera. This is to remove all trace of the tuning pointer.

ESP-Now BATMAN scaling work

A while back I built a little test rig to help with checking how my mesh network scales.

A test set up of two or three nodes simply doesn't show up the issues you get when there's twenty or more all talking.

Since I've managed to rework my code into an easily used library I'm inching towards releasing it and that means lots of testing so I'm sure it's not a complete dud.

The test rig allows me to have twenty-two nodes on my desk, eight WeMos D1 mini on USB and fourteen ESP-01 in the rig. Programming all these is quite time consuming so I tweaked the code on the USB connected nodes and when I felt it had reached an interesting point rolled it out to the ESP-01s.

When I first built the rig I was getting a lot of 'collisions', where my code detected another packet arriving while I was still working on the last one. This is done by setting and un-setting a flag to indicate 'node is currently doing something else'. I quickly found I'd made a simple coding error, not always un-setting the flag, and fixing this made all these 'collisions' go away.

What I did see however was a LOT of failures to send or forward packets once the mesh got to about 20 nodes. ESP-Now includes an acknowledgement so you can tell if a packet has been received, but complete failure to send just doesn't happen at a low node count.

ESP-Now does not use broadcasts when you send packets to all a node's neighbours/peers, it iterates through them. There's no documentation on how this is done, so I'll need to get a WiFi sniffer out to work out the exact behaviour.

Regardless this means the number of packets in the air goes up with the square of the number of neighbours when neighbours forward packets to all their neighbours, even though each one only forwards it once. This makes it believable there would be the odd in-air collision, and this is reflected in some missing ACKs, but I was seeing far too many failures to send.

I started coding in my own CSMA/CD re-transmission algorithm but had no luck reducing the failures and there's no documentation about what a complete failure to send means.

Many hours of fiddling around got me nowhere until it dawned on me this was only happening with the smallest packets, larger ones would be sent reliably even if they are not always received. As the code for this is identical to the other packet types, in a frustrated random guess I increased the packet size and it cured the problem.

I can only assume the ESP-Now library does its own CSMA/CD re-transmission and this breaks down with small packet sizes. I'll have to change my code so it pads out to some minimum size. This appears to be an ESP-Now payload of about 30 bytes. A payload of 18 bytes fails consistently once you've got 20 nodes.

With the boxed outdoor nodes I can add another ten to the test. Once I've done the code changes I'll add them in and see how things behave. This gets me very close to my target mesh size.

After this I need to check the routing algorithm again as I can see that seems to break down with lots of valid choices, flapping badly. Likewise the time sync protocol has got messy and is doing a poor job of syncing above about eight nodes. I have tried to make it discriminate and pick the sync packet that's traversed the fewest hops but clearly this is not working.

This is all quite time consuming to test but I can feel progress being made and I want to ensure when I release the library it stands up to scrutiny.

Yesterday was a good day

I've been fiddling with my B.A.T.M.A.N.-inspired mesh network code over the last few weeks and finally reached the point where I couldn't put off turning it into an Arduino library any more.

Sometime I'll learn from my past mistakes and start from the position of writing a library, but this project was not that time.

Now I'm in a position where an Arduino sketch needs just four lines of code to be a functional mesh network node that routes traffic.

  • Import the library eg. #include <EspNowMesh.h>
  • Declare an object eg. EspNowMesh mesh;
  • In setup() start the mesh eg. mesh.initEspNow();
  • In loop() keep it ticking over eg. mesh.meshHousekeeping();
As my goal is to make this simple usable code other people can work with I'm happy with this. My last mesh network code was too byzantine to be usable, even once wrapped up as a library.

I still need to refactor things to match common Arduino style conventions.

For example "initEspNow()" should really be "begin()" and so on. Also the functions I have for putting data into packets and retrieving it are very much single purpose kludgey things rather than something I'd want to offer for real use.

Maybe I'll also change the name of the class completely, I'm not sure I like EspNowMesh as a name

I've written Arduino libraries before but this was harder work. The big battle was around callback functions, which are sprinkled through the ESP8266 WiFi and ESP-Now libraries my library relies on.

Using class member functions as callbacks, or even worse, using class member functions as callbacks for C libraries is a real roadblock if your C++ skills are beginner level. When it's all a monolithic sketch this stuff 'just works'. Make it a class in a library and it's suddenly very broken. This is why I'm prone to just writing a flat Arduino sketch as a proof of concept and worrying about making it re-usable later.

I may do a couple of blog topics with the workarounds I did as other people may find them useful. Simple solutions did not jump off the page of a Google search.


Recently I treated myself to a Xiaomi Wowstick 1F+ as Banggood were doing big discounts around Black Friday.

These are a bit of a silly thing, a powered 'precision' screwdriver that's like a big fat pen.

Mostly they're very cute and come packaged like some kind of Apple product, all in separate little white boxes. They're the kind of thing that makes a cool gift for somebody who tinkers and even come with a carrying case that's like something from a sci-fi movie.

Notably the set I bought comes with many many high quality precision bits, perfect for taking modern consumer electronics to bits. I just used this to have the internal cover off my smartphone so I could replace the failing battery and it's already saved me from having to go and hunt a suitably small set of tools down.

There are a few variants available, I thought I was getting the one with a charging base but didn't realise this model was different, so check before order.

Squeezing a quart into a pint pot

The first mainstream appearance of the ESP8266 was the ESP-01 board and it's a breadboard unfriendly horror.

It has eight pins and only two of those are nominally GPIO, but even these are compromised as they have to be pulled high to enable normal bootup. You pull GPIO0 low to program the board.

I've got twenty ESP-01s I want to use. Mostly because I've already got them but also because barring some weird ESP8255 packages they're about as small as these things get.

For my application I need a GPS module, Infrared receiver, pushbutton, status LED and piezo buzzer and I've achieved this with a little care over pin choice.

First with the GPS module the ESP only needs to receive data. In principle you can send commands to the module but I don't need to and that saves the TX pin, GPIO1. It's not often you see this referred to but it's just a variant on the usual Arduino Serial configuration...
Serial.begin(9600, SERIAL_8N1, SERIAL_RX_ONLY);
Luckily the IR receiver is a pullup device, inverting the IR signal so that can be pretty safely connected to GPIO0. In the unlikely event you're unlucky enough to receive an IR pulse at the very moment you power the board on you'll notice as it has a startup sequence involving the buzzer and LED.

For the pushbutton I've combined it with the LED on GPIO2. The GPIO has a 10K pullup resistor, the button connects the GPIO to ground and I check for a low pin state. This is a very conventional setup for a button.

To double this up with the LED, it's connected in parallel with its cathode (normally connected to ground) connected to the GPIO and the anode to Vcc. If you push the switch then it connects the cathode to ground and the LED lights. However if you reconfigure the GPIO as an output and drive it low the LED also lights.

You can't use the button while the LED is lit but some simple logic swapping it from an input to output as needed works around this.

Which leaves the piezo buzzer but now that's enough free GPIOs to connect everything.

There's a lot of understandable negativity around ESP-01s in the community and I'm not sure I'd choose an ESP-01 afresh but you can use them in more than single use applications with some care.