Mixing my ESP-Now mesh, ESPUI and physical objects in a LARP experience

As I've mentioned before, all the stuff I work on tends to be to make props for Live Action Role Playing (LARP) events. LARP comes in many flavours but the variant I'm involved in has people solving problems and fighting skirmishes with Lasertag weapons as part of a collaborative story, usually with a science fiction element.

With the arrival of the pandemic, almost all LARP except that which was conducted via video chat went on hiatus, including a game we'd been planning for a couple of years.

However things kicked off again for us on the weekend of 3-5 September 2021 with an 'anthology event' that consisted of several short games. After a chat with one of the game organisers I agreed to set up some stuff to round their Cyberpunk themed game out.

We play on exclusively outdoor sites, almost always with no access to mains power or permanent Internet service so everything needs to be self-sufficient for the duration of the game. Also with only a couple of hours of setup time available it needed to go out quick and dirty right beforehand.

I put together several elements that got included in the game, spread across three different locations on the site.

When to use send callbacks in ESP-Now

Long time no post, I've been kind of away from microcontroller project work recently. Having picked up coding again I've come across an interesting issue with ESP-Now on ESP8266.

It's not really an issue as such, but might catch you out.

Most of the time, when you send ESP-Now packets with...

esp_now_send(uint8 *da, uint8 *data, uint8 len);
...there's a temptation to assume they will always be sent.

However packets are not sent until the core gets around to it.

If your code does some slow blocking work after asking for the packet to be sent, the core will abandon sending the packet silently. You should instead register a callback function with... 

esp_now_register_send_cb(esp_now_send_cb_t cb);
...and only continue with other activity, especially slow blocking activity, once that occurs.

My code was registering callbacks but as all it seemed they did was confirm a send I didn't really need confirming, the functions were stub ones where I'd commented out everything of note.

Most of the time this won't catch you out, but the timeout before the core abandons sending is rather short. A very dirty workaround might be to delay/yield for a short while after sending, but flagging the send as successful or not in the callback is the better option.

I had been struggling with unexplained packet drops in certain parts of my big ESP application and waiting for the send callbacks has eliminated these. A less I/O heavy application would probably never experience them.

ESP-Now BATMAN Real-time clock

I'm still slowly adding features to my retro computer terminal props and one of the things they lacked was a real-time clock.

So far I've been using 'mesh time' a millisecond uptime value that syncs across the mesh network.

I've now added the option for one or more nodes in the mesh network to share real-time clock information. This leverages the built in libraries for time that are included in the ESP8266/ESP32 SDK. It's just an offset from the mesh uptime with some simple logic to pick a preferred real-time source. Much like the mesh uptime it's not millisecond accurate, but good enough for human scale time, eg. the timestamps on chat messages. It also shares timezone information to correctly handle daylight saving.

At the moment I'm testing with SNTP (which is supported directly in the SDK) but my plan is it can take any RTC source. My code just checks "is the time set?" before sharing time so this should be trivial. this could include manually setting the clock from a watch, but I suspect it would drift fairly quickly. I'll attach some GPS modules onto a couple of my nodes for a time source in the field.

Chindōgu - part 3

I've been tempted for some time to do my planned updates to the Chindōgu, adding sound and more importantly, trying to throw together some code that avoids using Ekiga in the graphical desktop. The Pi Zero really struggles running the desktop and graphical applications but is fine when throwing stuff straight at the framebuffer.

Some research suggests it's possible to spin up OMX player wrapped in such a way it'll play a network stream straight from a camera and I'm going to try and use that for the video at least.

Coincidentally, there's currently a Hackaday retro competition and I think this could make an acceptable entry, if I get the software together and have several all talking to each other. I've accumulated multiple Sony Watchmen and Pi Zero Ws to do the build with.

To get started I've pinned out the main components on a board as it's otherwise hard to work on. One thing I want to do is get the image as decent as it can be and these horizontal gun CRTs were always dodgy.

Lacking a service manual I've worked out the function of the trimmers by trial and error.

  • RV501 - Vertical size
  • RV502 - Horizontal hold
  • RV503 - Keystone adjustment
  • RV504 - Horizontal size
Tweaking the framebuffer settings on the Pi Zero and tweaking these has made the display almost usable. With is set to 320x240 you can actually read the command line.

In praise of Adafruit IO

After a long delay on the delivery of the solar panels I want for my solar mesh nodes, I finally got around to doing some testing with them.

Unfortunately I was away from home and relying on tethering to a mobile phone for access to the Internet so using my home MQTT server for logging wasn't impossible, but was going to be inconvenient.

It occurred to me to give Adafruit IO a spin as it's designed for making generic IOT logging easy to set up.

Quick and easy to get working it has been logging just fine and I've not swapped back now I'm home. The dashboard is basic but all I need for this test.

In the first graph you can see the VPCC feature of the MCP73871 working well to avoid flatlining the voltage from the solar panel under load. It has a target voltage (arbitrarily set to ~5.3v here) and reduces current draw if the supply voltage drops below this. I've added a small trim pot to my test board to allow me to tweak this and do some runtime comparisons.

VPCC isn't MPPT but it will get better efficiency out of the panel than simply drawing until it can give no more and the voltage sags below a useful level. In the second graph you can see how without VPCC set the load on the same panel causes cycling like this, which also won't be doing the LiPo cells any good.

I have an idea ruminating to use an I2C controlled potentiometer along with a current sensor to make adjustments on the fly to try and optimise the solar output but it may be a minimal return compared to doing the tests once and picking a set value for VPCC. It will certainly increase component count.

There are packaged up MPPT solutions around, but there seems to be a gap in the market with them either super-efficient energy harvesting for tiny panels, or for large domestic/industrial power solutions. My scenario of ~4W panels with a ~100mA load isn't something I've spotted a good packaged solution for.

It wouldn't be impossible to roll my own MPPT boost convertor in front of the MCP73871 but like I said very likely to involve diminishing returns over careful use of VPCC.

Creating a UI on a microcontroller: Part 12


After much yak-shaving to make my UI library usable for other people I've finally made it public on GitHub.

It's very much a 'perfect is the enemy of good' initial release. It seems stable in use, I've written quite a chunk of documentation in Markdown and added an example for every widget type.

Now it's also been submitted to Arduino to see if I can get it listed in the Library Manager. If it is this will be a big milestone for me, giving back to the community.

I'm gonna need a bigger bench

Ever since I got my cheap Ender-2 I've been a fan of Creality 3D printers. That got partnered with an Ender-3 when a cheap Black Friday deal appeared and I can almost treat this one like an appliance. So long as the removable bed plate is cleaned and degreased occasionally it just prints.

I know some people struggle with their Creality printers, build quality can be variable, but both mine have been excellent and an Ender-3 of some flavour is my default recommendation to somebody new to 3D printing.

This is not because they're the best, they're far from it, it's because they're adequate and cheap. If you find you're using an Ender-3 lots, great now start modding it or buy something better. If it gathers dust after the novelty wears off you've only wasted £150-200 or thereabouts.

My Ender-3 gets used lots and short of an Octoprint setup, webcam and lighting isn't actually functionally modified at all. I'm into practical structural prints that will probably get some refinishing, not beauty prints. The Ender-2 is mostly idle but I sometimes run both at the same time if I'm working hard on a project.

Now I've scored a used CR-10 Max, which is at the other end of the spectrum of Creality printers. It's their biggest at a build volume of 450x450x470 and on account of that, by far their most expensive model. The huge heated bed has its own PSU.

For a long time I've wanted the facility to print larger items and I've got some costume parts I had literally been wondering about how to create in the days running up to seeing this for sale. Now I need to up my 3D modelling skills to being able to produce armour pieces.

Breaking out of the Espressif/Arduino rut

I have been noodling around with ESP8266/8285/32 microcontrollers almost exclusively now for a couple of years. 

The absolutely excellent price/feature/performance combo of these Espressif MCUs means I simply don't see any reason to change. There  have been a couple of things I built using AVR based Arduinos for very specific reasons to do with high I/O pin count or generating IR Lasertag signals with hardware timers, but that's it.

I've also mostly given up on Raspberry Pi based things because once an MCU has Wi-Fi and >64KB of RAM you can do most single-purpose things apart from a complicated GUI and I've been working on a workaround for the latter.

Likewise, much as people sneer at the Arduino IDE it is terribly easy to set up and use, broadly supported and just C++ (with an odd/incomplete selection of standard libraries) under the hood.

I have however been tempted by the new Raspberry Pi Pico. It's cheap (for now), dual core, has native USB, plenty of I/O and a massive push behind it comparable to the Adafruit Feather ecosystem. So I tacked a Pico and interesting carrier board onto an order from Pimoroni to have a play with one.

This could be my gateway to MicroPython, although I can see myself also having a go with C++ as this board is actually a good candidate for porting my serial terminal UI library, given it has no wireless connectivity.