In my recent post on finding a firmware bug, I commented that:

One thing I’ve learned about electronics is that basically any embedded symptom that isn’t clearly a software bug, can be caused by a power supply issue.

Today I confirmed that some weird behaviour - coincident with software changes - was in fact due to a power bug. I’m working on a project that has an ESP32s3 as the main application processor, and am using it as an opportunity to try async Rust. I’d just done a big refactor of the SIMCom SIM76xx LTE modem crate/library, but found that the firmware would apparently hang before connecting to the LTE network. It had been a few days since I’d tested the firmware against a real network (my project time had mostly been spent on mechanical design), and in that time I’d also inadvertently fried the development board that I’d done that initial testing on - a Waveshare esp32-s3-sim7670g-4g. I’ve only got one of those Waveshare boards, so replaced it (pending repair - I want to try out the camera) with a pair of basic dev boards - one with ESP32s3 and the other with SIM7670G - wired together equivalently to the Waveshare one, or so I thought…

I suspected that the new 2-board approach had problems because when the LTE did certain things that pull more power it would cause a brownout that would disrupt the ESP32s3. But, to confirm that I’d need to change to a more robust power supply, or make some measurements. Concurrently, one of the next tasks on this project is to design a PCB for it, the first decision about that new design is what size battery to power it with, and to decide what size battery I’d need to know how much power the rest of the board requires. So, I needed to make some measurements for two reasons!

Measuring power draw of battery-powered widgets can be surprisingly difficult. One problem is that modern designs tend to vary wildly in power draw between periods where they are idle and when they are doing something. Another problem is that, to save battery, they spend as much time idle as possible and are very good at that. The ESP32s3 microcontroller for instance, is claimed to draw about 8μA in deep sleep (keeping a real time clock running), maybe 50mA when powered up and lightly loaded but with radios off, and up to 340mA when transmitting. That’s a factor of over 40,000 between the deep sleep and transmitting current, and I imagine the LTE radio is a similar if not wider range! The change in current can happen very fast - I believe it’s often limited by the inductance of the wires powering the (teeny tiny) chip, fortunately the decoupling capacitors on a board will smooth out the changes typically seen by measuring equipment but still it’s very much faster than a typical current meter would indicate.

To make this measurement, there are a few different approaches that can work, one is using a device like an Otii Arc which provides both power and measurements at a relatively high rate and over a wide dynamic range. Fortunately, I’ve got access to one of those (the link goes to the current version, I’m using an Arc 1.0), and that would help diagnose my suspected power-related bug and inform the battery decision. Once the Arc was wired up (and software updated, etc), it quickly became obvious that there had been a power problem - I’m pretty sure it’s down to a diode in the new ESP32 board, there to prevent problems due to having two USB-C connectors which the original board didn’t have. So, the issue wasn’t due to my big firmware changes - another demonstration that I need to trust the Rust compiler that if it worked, and it still compiles, it probably still works too!