S21Evo - an open source custom driver for Convoy S21E and H series

Hello,

I have talked about this project before, mainly in my ebastlers electronics corner, but I feel like it has been clogging up what was supposed to be a fun thread about small random projects too much, so I moved it into it’s own thread as a central place for information and updates about this project.

Introduction

What is the S21Evo Boost? It is a powerful and feature-rich open hardware driver to replace the rather limited drivers in Convoys S21E hosts. I really like the S21E for a variety of reasons (looks, price, emitter choice, ability to use with both TIR and reflector, small dimensions for a 21700 light, USB charging…), but I am not the biggest fan of Convoys e-switch drivers. While they work well (The MP3231 in their boost drivers is really good) the UI is a bit lackluster. No way to get from moonlight to the regular modes, strange ramping speed, 10c for lockout, no aux… If you are spoiled by Anduril lights, they are not great.

I am a hardware developer in my dayjob, so I figured I should just solve these issues myself instead of waiting for someone else to fix them for me and started working on my own replacement driver for the S21E (for now, boost only. Buck might follow). And since I tend to get lost in feature creep, that was exactly what I did. More about that in the next chapter :wink:

Feature overview

The driver focuses heavily around making full use of the USB port. Apart from that it also is a rather efficient boost driver, but not expected to be significantly more so than Convoy’s default Boost drivers. The most important features* are listed below:

  • Firmware updates over USB - say goodbye to dedicated flashing dongles. Will work from Windows, MacOS and Linux (or any other platform that supports drivers for STM32 USB DFU).
  • Up to 5V 3A USB charging
  • Up to 5V 3A USB powerbank functionality
  • 30W Boost converter (most likely too much heat for the host, but might be nice as a short turbo)
  • Very low resistance reverse polarity protection FET and oversized inductor for high efficiency
  • HDR capability (2 shunts with n-ch FET)
  • User settable charge termination voltage
  • User settable max charging current
  • User settable powerbank behavior (prefer source/prefer sink/sink only/how deep the battery is supposed to discharge…)
  • Setup of all parameters via USB. Most likely a web-app, similar to something like VIA/vial/remap-keys for custom computer keyboards

*Note: Many of these features will need extensive software effort to work, so they might take a while to be included. This list contains the hardware capabilities, not the actual software capabilities (for now).

Technical information

MCU

For the implementation of my planned USB features I needed an MCU that was small enough to fit on the very tight PCB, offers USB (including USB capable bootloader from the factory) and has sufficient flash/RAM for the live remapping feature. It should also not be BGA/WLSCP since the microvias/buried vias needed to contact those add a fortune to the PCBs in small and medium batch sizes.

There is exactly 3 MCUs on the market which I am aware of that fit this niche, the AVR32DU family (very new, not sure if they actually ship with a USB bootloader), the STM32F041 family (very limited in RAM and flash) and the STM32C071 family (very new). I ended up opting for the C071 (to be precise, STM32C071GBU6), due to it having the largest RAM/flash and guaranteed USB bootloader capability.

What they all have in common is, sadly, the lack of a DAC. Therefore the LED current must be controlled via filtered PWM in all three cases. In theory, with a sufficiently low low pass frequency and sufficiently high PWM frequency, this should have zero visible jitter/flicker, as the feedback loop sees a smooth DC signal. How well it works in practice (how much dynamic range I can get out of it) remains to be seen. It also means I need an additional capacitor and resistor, and that was, as you will see, a challenge to fit. But it was the best compromise I could find.

The STM is a 3V class MCU, which is why I am running it at 2.8V via a small LDO - this way the MCU voltage will not fluctuate from a full to an empty battery. 2.8V is outside the USB2.0 FS specs for the MCU, but according to ST it seems like it will still work, just slightly out of nominal specs.

LED driver

The LED driver is a MP3432 - very similar to the MP3431 used in the Convoy boost drivers, and the same chip used, among others, in the D3AA. It is highly integrated and very efficient. My schematic is based a lot on the valuable feedback and help @thefreeman offered me (huge thanks at this point for everything!), so I hope it will work well.

I opted for a 5mOhm and a 1 Ohm shunt, and a n-ch FET of approx. 2mOhm (so ~7 mOhm total shunt resistance for the high current shunt). A larger value high current shunt would allow for lower min current (and therefore a larger low current shunt, and higher overall dynamic range), but it would also mean higher losses. I do not have the experience to predict if I made the right tradeoffs for this particular application, but a simple resistor change is no big deal and something I can experiment with on the first batch drivers if needed.

Charging/Powerbank

The charging part of this light is handled by a MP2722. This chip can both charge with up to 15W and be used as a 15W powerbank. It features fully integrated, USB spec compliant Type-C battery charging negotiations, and can be controlled via i2c from the MCU. On this chip you can set up almost everything. Whether it should be “sink only” (flashlight charging only, no powerbank), source only (only powerbank), “prefer sink” (if connected to a notebook or phone, the flashlight will prefer being charged by them), “prefer source” (opposite of before, and it will only charge when connected to a pure charging port) etc. You can set charge termination voltage and charging current, powerbank current, and many other things.

This chip will be the heart of the battery management on this light, together with (ofc) a beefy low Rds_on MOSFET for reverse polarity protection, ensuring the light is not affected by a wrongly inserted battery.

Due to space constraints I had to use a rather small inductor for this chip, which (while current wise within specs) is slightly outside of the recommended internal resistance range. This will affect efficiency, but I think it should still be acceptable - and I preferred having the higher efficiency for the main LED boost which is, after all, the primary function of this light.

E-Switch / AUX

Due to technical reasons, this driver needs both the e-switch and the aux logic inverted compared to Anduril lights. The e-switch needs to pull the MCU pin to Vdd as this is the method to enter the bootloader when held at powerup. Usually, e-switches connect the MCU pin to GND. Since my MCU runs at 2.8V, it would not have the forward voltage to light up green and blue LEDs reliably. Therefore the AUX LEDs are connected with their Anode directly to the battery voltage, and with the cathode (through resistors) to the GPIOs in open drain mode.

Since the MCU has all inputs 5V tolerant, both the e-switch and the AUX LEDs can connect to up to 5V without damaging the chip, even if it is running at only 2.8V.

The e-switch PCB has 4 RGB LEDs for a more uniform lighting than the default Convoy e-switch, and more wires (since it is RGB, as opposed to being RG only). Size-wise it is, obviously, compatible and can fit the host just the same.

Renders, main driver

Renders, button PCB

2D views, main driver

Yup, the MCU is a little close for comfort to the spring pad… Everything is, tbh. Should be fine, but I will try to squeeze it a little bit further up if possible. Will be tight with the retention ring. The whole PCB ended up being incredibly tight. Every space that is not occupied by components or pads, is filled with vias… The aux/button pads will be a pain to solder, but making them any larger was not possible. I really wish Simon made the driver for this light 1-2mm larger… The host would have the space for that.

Software and UI

This is where things get complicated. As many of you know, Anduril only works on a couple of Atmel chips, and does not support most of the features I am aiming at with this light. While I have heard of some community plans to port it to other chips, I decided that a driver that so clearly breaks off from community standards should also get a clean slate software wise - built around and optimized for the hardware capabilities.

I want to streamline and simplify the UI - many features you know (and maybe love) from Anduril may not be included. Others will be added. This driver is mainly a passion project of mine, and as such reflects primarily my own needs and preferences. The software is still the biggest WIP by far, and therefore this is just a rough sketch below that might change.

My basic UI is supposed to closely mirror the Anduril simple mode. It is proven, it is intuitive, it just works. Don’t fix what’s not broken. The UI is supposed to be very simple. Moonlight, a couple of modes (user selectable number & brightness), ramping mode (user settable floor/ceiling/speed), turbo mode, battcheck, lockout. I personally do not need any blinkies and specialty modes apart from battery check, so I am not planning to include any of those, at least not for the beginning. Maybe once everything else is settled.

RGB AUX will be used during charging, for battcheck (user configurable whether the light should use the emitter or the AUX LEDs), and as an optional indicator color when off (same behavior as Anduril for the most part).

The only addition to the basic UI will be a (hard to accidentally push) toggle to switch between sink only, source only and prefer source mode of the flashlight. Prefer source should work with almost every power supply and phone, but some devices have wonky USB-C implementations and might act up. Having a way to force those into the desired mode of operation can come in handy.

Flashing

Flashing will work using the STM DFU bootloader. This mode is entered by holding the e-switch down while the MCU boots (either by tightening the tailcap while holding the button, or by removing the battery and plugging it in while holding the button). Flashing new firmwares in DFU mode is mainly done through the ST dfu-util command line application, or one of the many existing GUI implementations. I will not reinvent the wheel there and use what others made. Since I already have it for custom computer keyboards, my own pick is “QMK Toolbox”.

Setup

I’ll be honest, I am too dumb to remember set up patterns and click codes, and even with a diagram in front of me I still struggle with many options. That’s why I decided to take a step sideways, and instead of setting the light on the light, I will allow changing all settings via a computer. This is still only a rough concept, and I have not yet decided how the communication is exactly supposed to work, but the rough idea is that i would like to offer both a simple command line tool (for Linux) and a web-app (for webUSB enabled browsers) to change parameters, which the flashlight then stores internally. This will be the very last thing I will turn my attention to, after everything else is ready and working, so don’t expect anything more substantial within the next couple months.

The idea itself was inspired by VIA for mechanical keyboards, a software which allows the user to not only remap all keys, but also change things like the RGB illumination and others through a web UI (see the example picture below).

This part of the firmware is very intimidating to me, but I will decide how to tackle it (and if I should ask for help) when the time comes. For now I am approaching this topic step-by-step.

Roadmap

This roadmap of the design is much more detailed than it would have to be, as I thought it might be interesting for people to see how I approach a more complex project, and how many different things go into making such a tiny PCB. Most of it is hidden away behind spoilers to keep the thread a bit more clean (since none of it is information essential to the project). Still a long way to go…

:white_check_mark: HW Phase 1:

Concept
  • :white_check_mark: Decide on rough specs and requirements
  • :white_check_mark: Determine PCB shapes, dimensions, space availability
  • :white_check_mark: Decide which circuit topologies are planned
  • :white_check_mark: Decide which components best fit the requirements
  • :white_check_mark: Draft early sketch schematic, pick important/large components
  • :white_check_mark: Rough placement/plane concept
  • :white_check_mark: First Simulations and calculations
Design
  • :white_check_mark: Flesh out schematic, add components omitted in the first step
  • :white_check_mark: Finalize placement of important functional groups and components
  • :white_check_mark: Begin tracing, begin drawing of power planes
  • :white_check_mark: Iteratively optimize schematic and PCB based on space availability and ideal pin choices
  • :white_check_mark: Iteratively optimize placement of components and functional groups to optimize space utilization and current paths
Finalization
  • :white_check_mark: Re-run simulations and calculations to decide on the last open component values
  • :white_check_mark: Triple check schematic and PCB, apply last fixes and improvements
  • :white_check_mark: Assign part numbers to passive components, optimize BOM for availability and price
  • :white_check_mark: Add labels and informational text

:repeat: HW Phase 2: Production

Prepare production data
  • :white_check_mark: Final check of PCB and BOM
  • :white_check_mark: Create assembly frame
  • :white_check_mark: Export BOM/CPL/Gerber
  • :white_check_mark: Check exported data
Production
  • :white_check_mark: Send data off to fabrication partner
  • :white_check_mark: Wait for them to finish production and assembly
  • :repeat: Shipping
Inspection
  • :pause_button: Inspect PCBs
  • :pause_button: Perform first electrical tests

:pause_button: SW Phase 1: Testing

Test firmware
  • :pause_button: Create a bare minimals firmware (2 modes, single color aux)
  • :pause_button: Check if Boost driver and AUX LEDs function as intended
  • :pause_button: Test functionality of i2c communications with battery chip

:pause_button: Release hardware on github

:pause_button: SW Phase 2: Preliminary firmware

Concept
  • :white_check_mark: Decide on HAL/RTOS to be used (STM32 Cube HAL)
  • :pause_button: Sketch operational flowchart
  • :pause_button: Decide which variables need to be persistently changed in runtime (mode memory, setup changes)
  • :pause_button: Decide which values make sense to be modified before compilation in header files without digging into code files (to accomodate multiple flashlights with different featuresets, but also to allow hard-coded user configurations until live setup is ready)
  • :pause_button: Deep-dive into application note to figure out how to fully use hardware peripherals of the chip (DMA offloading as much as possible, hardware PWM instead of bitbanging where possible)
Writing
  • :pause_button: Create project
  • :pause_button: Write driver for MP2722
  • :pause_button: Create the actual firmware
  • :pause_button: Iterative approach of testing and rewriting/optimizing features (I am particularly worried about proper thermal regulation that does not oscillate like many lights do)

:pause_button: Release firmware on github

:pause_button: HW Phase 3: Early adopter batch

Optimization and bugfixes
  • :pause_button: Change passive component values if needed
  • :pause_button: Implement bugfixes if needed
  • :pause_button: Slightly move USB port if needed
Prepare production data
  • :pause_button: Final check of PCB and BOM
  • :pause_button: Create assembly frame
  • :pause_button: Export BOM/CPL/Gerber
  • :pause_button: Check exported data
Production and shipping
  • :pause_button: Run interest check to see how many drivers are needed
  • :pause_button: Send data off to fabrication partner
  • :pause_button: Wait for them to finish production and assembly
  • :pause_button: Shipping to me
  • :pause_button: Ship to customers

:pause_button: SW Phase 3: Live reconfiguration

API/FW side
  • :pause_button: Decide on a protocol
  • :pause_button: Decide which parameters are important to remap
  • :pause_button: Implement protocol on driver side, making sure it has flexibility for future expansions or other drivers with additional features
Desktop side
  • :pause_button: Implement simple command line client for protocol testing
  • :pause_button: Properly document the protocol for others
  • :pause_button: Decide on a desktop UI framework
  • :pause_button: Despair because I have no clue of this
  • :pause_button: Create some sort of UI based configuration tool that leverages the API

:pause_button: Release CLI/UI tool on github

:repeat: HW Phase 4: Go big

  • Talk to Simon whether he would be interested in mass producing and selling the driver.
  • With enough interest, make a Buck driver on the same platform, with the same capabilities
  • Think about other lights beyond the S21E
  • Full custom flashlight?
40 Thanks

Might need this post later on for something.

“This is where things get complicated…” :rofl:

Brilliant. Thank you for all your work!

1 Thank

Nice! I knew someone would take this step eventually. I’m actually pretty happy with Anduril, but I think making USB programming easier will open up new possibilities overall.

I’m looking forward to watching this project!

3 Thanks

This looks amazing! Sign me up!

1 Thank

Following this for sure :saluting_face:

1 Thank

This would be gold, but may I ask you: adjustable to which extent? Could it possibly be adjustable to enable LiFePO4 charging or are we talking about small adjustments to extend the battery service life?

1 Thank

The chip supports between 3.6 V and 4.6V full charge range.

3 Thanks

USB interface with no GUI to set UI. We want an android app ! :smiley:

1 Thank

Any phone app is not going to happen from my side. Too much hassle to read into app frameworks and stuff, to update the app for every OS update that changes permission handling etc, and too much hassle to register dev accounts at Google/Apple.

If anyone else feels like taking a shot, feel free. Would be awesome :slight_smile: I’m only planning to make a desktop app, and that one will most likely just be a website leveraging webUSB.

5 Thanks

The next driver then without USB C but with wireless charging and Bluetooth for the aforementioned Android App :smiley:
And the on-switch has a fingerprint sensor integrated…

Fun aside, having a super complex UI like Anduril 2.0 makes a program for programming it very handy.
Especially if you could save your profile and quickly load it onto another light.

2 Thanks

Your patch is difficult - be strong .

Lupine made Bluetooth setup for some of their current generation lights. If you want that, might be interesting to check it out. Their prices are usually a bit crazy and their UIs annoying, but their build quality is great.

I’m looking forward to your success. The 22mm driver is too small. Many components cannot fit in, making it difficult to achieve the intended functionality. Using a multi-layer PCB would be a better choice. Currently, I’m still using the custom el3 driver. If your idea can be realized, it will be one of the strongest 22mm flashlight drivers with charging function.

1 Thank

Yes, and I don’t really know why… The S21E would have enough space for a 2 PCB driver, and for a 24 or 25mm driver if Simon wanted and made the host a little bit differently internally…

Wish me luck, it’s a very complex piece of hardware, but I’m pretty optimistic. Compared to the stuff I do at work, 30W are nothing :joy:

5 Thanks

Got some new progress report from PCBway :partying_face:

17 Thanks

Having looked at those H-series lamps for a while, I’d even just be keen on a “lite” version with high efficiency, better ramping speed (maybe just Anduril since it’s so popular?), proper USB-C charging protocol (not sure how the H-series is, but I don’t want to have to keep using USB A → C adapters for the rest of my life).

Semi-related, does the S21E and M21H use the same driver?

No.

Also S21E can be charged from type-c charger (at least 6V version) while M21H can’t.

2 Thanks

Can confirm, this works stock with both the 3A and the 2.2A 6V version. 1A charging speed if I remember correctly.

Are there any plans for 21mm drivers in the future?
In various headlamps without charging?