Skip to content
Snowbird Power Systems

Build log

Why the Feather handoff is on 3V

Every Feather host already has a charger, so a power module under it has to decide which of the host's pins it touches. We touch 3V and EN, and nothing else.

· 3 min read · Jordan Edwards

The problem every stacked power board has

A Feather host carries its own 1S charger and exposes BAT, USB, EN and 3V on the header. The obvious way to power a host from an external battery board is to drive its BAT pin. That is what most people try first, and it is wrong for a board with a BMS.

Drive BAT and the host's charger sees your battery. The moment someone plugs a USB cable into the host, its charger pushes current into the cell: behind Snowbird's BMS switch, outside Snowbird's chemistry limits, at a Li-ion profile the host's charger was built for whether the cell is LiFePO4 or not. On a primary cell that is a charge current into a cell that must never see one. Nothing on Snowbird can stop it, because the current never passes through Snowbird.

Drive USB instead and you have two 5 V sources in parallel whenever both cables are in.

What we do

The handoff is on the 3.3 V side:

  • 3V is hard-wired to Snowbird's 3.3 V rail. The host runs from Snowbird's regulator.
  • EN is pulled to ground through a solder jumper that ships closed. That turns the host's own regulator off, so the two never fight on the 3V rail. Adafruit documents feeding 3V with EN held low as the supported way to use an external 3.3 V supply, so this is the host doing what its maker says it may do.
  • BAT is not connected, and there is no jumper, on purpose.
  • USB is not connected.

The host's USB can still be plugged in while stacked. Its charger finds no battery, its regulator is disabled, its MCU keeps running from Snowbird's 3V, and its serial port works. Snowbird's own VBAT and VSYS are on their own pads and castellations, never on the host's BAT or USB positions.

The signal positions

PG and CHG_DONE can be read over I2C, but a register read cannot wake a sleeping host. A pin can. So INT, PG, CHG_DONE and EN5V each get a Feather GPIO position, through a jumper that ships open. The signals are always on their own pads; the jumper adds the header position. All three outputs are open-drain with a pull-up to Snowbird's rail, so a host that drives the position as an output is not shorted.

Position Signal Why this one
11 INT Interrupt-capable on every current Feather host, not a host LED or battery-sense pin, unused by Wings except the radio Wing where it is user-wired
A2 PG Wings do not use analog positions; on the classic ESP32 Feathers it is an input-only GPIO, which suits a signal into the host
A3 CHG_DONE Same reasoning as A2
A5 EN5V Output-capable on every current host, unused by Wings

The GPIO12 trap

Position 12 looked good: free on most hosts, interrupt-capable. On the classic ESP32 Feathers it is GPIO12, a strapping pin. Held high at reset, it selects a 1.8 V flash supply and the board does not boot.

PG is high before the host boots, by definition: the rail is good, that is why the host is booting. A pulled-up EN5V would have done the same. Put either on position 12 and every ESP32 Feather stacked on a Snowbird fails to start, with nothing wrong on either board. We found it on the bench, on the second host we tried.

Position 13 is the host's LED on most Feathers. Position 9 is the battery-sense input on several and button A on the OLED Wing. 10, 5 and 6 are SD chip select and the OLED and TFT Wing buttons. The sixteenth position of the long row is unconnected on older Feathers and a different GPIO on each newer one. Those are all out.

What it costs you

One thing: if you have a host that must keep its own regulator running for some reason, open the EN jumper. We have not found that host yet. Everything else is the same board, the same code and the same four jumpers whatever is stacked on top.