Skip to content

Batteries

joric edited this page Jun 16, 2024 · 662 revisions

Non-chargeable batteries

Non-chargeable batteries are cheap and convenient, they have larger capacity than the chargeable batteries of the same size (CR2032 is 250 mAh while LIR2032 is just 45 mAh, AA batteries are typically 2500 mAh, same as large Li-Po), they have no deep discharge or thermal runaway issue, they also have much smaller leak and they last much longer than a fully charged Li-Po.

To use them, desolder the PROG resistor (10K) to set PROG pin to float (disconnected), it's the official way of disabling the TP4054/MCP73831 charger. Some nRFMicro revisions (1.3) can disable the charger in software.

You can also use chargeable AA Ni-Mh batteries (i.e. Panasonic Eneloop) and a separate wall charger, but they self-discharge in about 1-2 months. See https://en.wikipedia.org/wiki/Self-discharge about Ni-Mh batteries.

Chargeable batteries

Note that nRFMicro charger only supports Li-Po/Li-Ion batteries. Other batteries such as Ni-Mh, Ni-Cd, Li-Fe-Po, etc. use totally different charging strategy, current and voltage, I don't use them and nRFMicro charger doesn't support them.

301230

I'm using 301230 (301230 means 3.0 x 12 x 30 mm) Li-Po batteries, they sit flush and fit snugly between two 4.5mm tall machine pin sockets (read the Sockets article about the hotswap headers).

Use RAW and GND or B+ and B- pins for the battery (those pairs of pins are internally connected so they are essentially the same). Avoid reverse polarity (charger ICs usually fry first)!

Note that a few keyboards have RAW and VCC pins connected together (namely Helix and Gherkin), and will kill the controller (RAW pin is for the charger only). You may just not solder RAW pin to the keyboard as a workaround.

Latest batches come blank without printing but with 80 mAh sticker on the bag. I'm not sure if they are 110 mAh or 80 mAh (probably the latter, they are pretty small, but all the 301230 batteries, even declared as 110 mAh look precisely the same). New batch vs old batch, same seller:

301230

18650

If you're planning to use 18650 batteries, mind that nRFMicro/nicenano/bluemicro/whatever don't have discharge protection (Li-Po packs have it, but most 18650s don't).

You can control it it firmware though, and discharge rate in BLE is pretty low. You can also try using 3-rd party charger boards with discharge protection like 03962A and solder the to the USB power lines but that wouldn't be easy to solder and route.

There are 18650s with discharge protection but they are a little bit larger and more expensive. You may also want to replace PROG resistor on the nRFMicro from 10K to 2K to boost charging current to 500 mA (100 mA just takes 5 times longer to charge, e.g. 100 mA charger takes 35 hours to charge the 3500 mAh battery, 500 mA charger takes 7 hours). Those batteries are about 5 mm longer and have a side wire (may be hidden).

LIR2032

Those coin cells don't have over-discharge protection either, this is the main concern with the coin cell batteries. Mind that nominal capacity is just 40 mAh, while regular non-chargeable CR2032 cells offer 250 mAh. Max charging current is 35 mA, so you need to replace the PROG resistor to 33K (1000/33 ~ 30 mA) for safety.

The battery pack is open-source, see https://github.com/jpconstantineau/NRF52-Board/tree/master/BatteryPack it doesn't add much to the charger except the battery holder and the ON/OFF switch but it still might be handy. It also adds the physical reset button.

lir2032

Cellphone Batteries

You can use Li-Po/Li-Ion batteries from the old phones, they have about the same chemistry as Li-Po packs and the same protection circuit. Just solder to + and - terminals, ignore the third one (it's usually 1-wire interface for the battery info). You can't use NiMh/NiCd batteries because they are not compatible with the Li-Po charger. All newer batteries (e.g. starting from Nokia BL 5C/6C) should work.

batt_360

Charging

nRFMicro Charger

Charging current is set by the PROG pull-down resistor, Icharge = 1000V/Rprog. Safe charging current in mA roughly equals battery capacity in mAh (1C rate) and default batteries are 100 mAh so charging current is 100 mA and PROG resistor is 10K.

If you want 2500 mAh battery, mind that charging it at 100 mA would take 25 hours. Charging current is also limited by the USB port (USB 2.0 is 500 mA) and the charger (TP4054/MCP73831 both rated for about 500 mA), so the best you can do is replace 10K resistor with a 2K resistor for 500 mAh. Charging still takes at least 5 hours (2500 mA / 500 mA).

Software control in nRFMicro 1.3 (PROG resistor wired to the GPIO pin) adds more options with 13K internal pull-down:

  • 10K resistor (100 mAh default) with 13K pull-down option: 1000/(10+13) ~= 43 mA (for LIR2032 coin cell batteries)
  • 2K resistor (500 mAh default) with 13K pull-down option: 1000/(2+13) ~= 67 mA (for small Li-Po batteries)
nrf_gpio_cfg_input(PROG_PIN, NRF_GPIO_PIN_NOPULL); // charger disabled (PROG pin set to float)
nrf_gpio_cfg_output(PROG_PIN); nrf_gpio_pin_write(PROG_PIN, 0); // just the onboard resistor (100 mA)
nrf_gpio_cfg_input(PROG_PIN, NRF_GPIO_PIN_PULLDOWN); // onboard resistor and 13K internal pulldown (43 mA)

Note that Nice!nano uses BQ24072, internal LDO for the core, and no battery divider (it measures voltage internally on the VDDH pin). BQ24072 is not 5V the whole time, it's battery voltage +0.2V so it raises as battery charges.

03962A Charger

Neither TP4054 nor BQ24072 (introduced in nicenano V2) provide overdischarge protection. BQ24072 provides short-circuit protection but not the overdischarge protection. Unprotected 18650s (or coin cells) can't go lower than is 2.5V or they die. If they go lower it causes permanent damage to the cell. Even worse, if you don't realize you severely overdischarged a Li-Ion cell and try to recharge it, there's a significant chance of thermal runaway (explosion).

The 03962A schematic provides both overcharge and overdischarge protection with DW01A, R3 is RProg (charging current):

tp4056-breakout-boad-schematic-enh

You can use 03962A charger for LIR2032s (35 mA max charging current) either, but you must to replace R3 = RProg. TP4056 current is calculated differently from TP4054, it's Icharge = 1200V/Rprog, so closest R is 34K at 35 mA (you can buy 33K).

charger

Using default R3 = 1.2K (1000 mA) or 10K (120 mA) for coin cell LIR2032 batteries (rated at 35 mA max) is not safe.

You can use that as an external charger for 18650s batteries. You would have to disable the built-in nRFMicro charger by desoldering the PROG resistor, solder USB 5V+/GND to +/- and solder OUT+/OUT- to B+/B- pins of the nRFMicro.

Fast Chargers

It's very rare in DIY electronics, and nRFMicro doesn't support it either. There are IC's such as bq2054 (it is 5V):

There is fast charger on aliexpress, IP2312-based, supports up to 3A from USB-C. It also uses 5V input (not QC/PD):

charger

Other chargers

  • There's also MCP73812, it has CE pin but doesn't have digital power selector (charging current is Rprog-controlled).
  • There's a whole bunch of SOT-23-5 chargers it seems (TP4054, TP4055, TP4065), all SOT-23-5 all MCP73831 clones. Using MCP73831 at the time probably was a bad decision, it's just that Adafruit feather uses it. It's worth to go with TP4054 next time. The cheapest substitute with the english datasheet is LN2054Y42AMR.
  • You could try to get rid of the battery measuring voltage divider altogether (minus 2 resistors) and use internal input VDDHDIV5 of SAADC (still needs 10 uH inductor for the high voltage mode). Sadly, without the divider you can't measure the battery when the USB is on because power selector switches to USB.
  • Nicenano V2 and Mikoto use BQ24075 in VQFN-16 package.

Measuring battery capacity

You can measure either battery voltage with voltage divider or both battery current and voltage (also temperature) with fuel gauges.

Note that nRFMicro 1.1 uses 10K/13K divider (external pull up/internal pull-down). That'd give us about 4.2 V / 26 K = 0.16 mA leak (that's quite a lot), however it can be controlled from firmware (internal pull down can be turned off). Also the battery can be disconnected through the physical on/off switch. nRFMicro 1.2 introduces 800K/2M battery divider so the leak is almost non-existent (1.5 uA, or 0.0015 mA).

Voltage divider

There are two versions of the battery voltage measuring circuit pointed out here:

To reduce the leakage current through the voltage divider to the minimum, we want the total resistance to be as high as possible. Therefore, we choose R1 to be 800 KΩ. This is the maximum source resistance we can have if we use an acquisition time of 40 us, see here https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Fsaadc.html

We also want R2 to be large. R2 should be chosen such that the input voltage does not exceed Vdd when the battery is full (4.2 V). In this example Vdd is 3.3 V, so we choose R2 to be 2 MΩ which will give 3 V at AIN when battery is 4.2 V. With a gain of 1/5 we can use the internal reference at 0.6 V.

The leakage current with this configuration will be:

4.2 V / 2.8 MΩ = 1.5 uA If you are using lower Vdd, R2 will have to be smaller and the leakage current will increase.

Usable ADC resolution

If we assume that the voltage range of the Lithium battery is 2.7 V - 4.2 V, i.e. 2.7 V when empty and 4.2 V when fully charged, then the voltage range on the ADC AIN input pin is:

  • Maximum voltage: 4.2 V * (2 M/(0.8 M+2 M)) = 3 V
  • Minimum voltage: 2.7 V * (2 M/(0.8 M+2 M)) = 1.93 V
  • ADC value at 4.2 V – 12 bit setup: 3 V * (1/5) / 0.6 V * 4095 = 4095
  • ADC value at 2.7 V - 12 bit setup: 1.93 V * (1/5) / 0.6 V * 4095 = 2634
  • Usable ADC resolution - 12 bit setup: 4095 - 2634 = 1461

(Leakage current 4.2 V / 2.8 MΩ = 1.5 uA)

R1=4M, R2=10M, Cext=10nF, Csample=2.5pf, leakage current 4.2V / (10MOhm + 4MOhm) = 300nA

You can also try using a pfet controlled by a mcu pin with a capacitor in series, that way there's no leakage, apart from the iq from the pfet (via @gms):

Fuel gauge

  • There are things like STC3100 with a built in battery gauge (current in/current out over time), but it's controlled via I2C, so that might be too complicated and it's pretty expensive overall: STC3100 costs $1-$1.5. Current gives way more accurate measurement in terms of battery capacity though, voltage is superflat almost the entire discharge time:

  • There are also other dedicated ICs, like MAX17055 (The MAX17055 is a low 7μA operating current fuel gauge which implements Maxim ModelGauge™ m5 EZ algorithm. The MAX17055 provides precision measurements of current, voltage, and temperature). It costs $2 on lcsc.

  • There is also LC709203 used in BluePhage, this is the only one supported by Circuitpyhon, so recommended. Example wiring (note those fuel gauges do NOT include battery charging ICs):

LC709203 wiring

Note that the nRF52 chips have a temperature sensor embedded. ZMK doesn't use it in the keyboard software but it would be relatively easy to add. Perhaps a bit more difficult than just adding a library for the DHT temp sensor:

Discharge rates

More realistic charge for RC batteries (from http://learningrc.com/lipo-battery):

Disabling the charger

It's possible to monitor battery voltage accurately while charging. You'd need to disable the charger to see the lipo's actual voltage.

you will need to occasionally stop the charge current to read the battery voltage at open load. This will help you correctly find the actual State Of Charge (SOC)

Without disabling the charger you get somewhat average voltage between 4.2V and the actual battery voltage so you have to account for it.

Chargers such as MCP73831 or TP4054 can be disabled by setting PROG pin to float (this is official documented way of disabling those chargers). Disabling a charger in software is super easy. Just cut the line after the PROG resistor and put a digital pin there. Set it to 0 to enable, set it to float (input with no-pull or default high-z state) to disable.

It's probably even better when the charger is disabled by default, people using non-chargeable batteries all the time, getting a Li-Po is somewhat more complicated.

Another possible solution could be using MCP73811, which has enable pin (CE) and also can digitally switch between 85 mA and 450 mA, that could be useful for handling different batteries (recommended charging current is at most 1x capacity, e.g. 100 mA for 100 mAh battery).

WARNING: MCP73811 is not MCP73831 compatible, the pinout is different, they work differently!

MCP73811

  • 3.1 Charge Enable Input (CE) A logic High enables battery charging. A logic Low disables battery charging. The charge enable input is compatible with 1.8V logic.

  • 3.5 Current Regulation Set (PROG) For the MCP73811, the current regulation set input (PROG) functions as a digital input selection. A logic Low selects a 85 mA charge current; a logic High selects a 450 mA charge current.

Sadly MCP73811 are kind of rare and expensive, the cheapest I could find cost $0.50 a piece:

Reverse polarity protection

You may accidentally connect the battery in reverse. Neither nRFMicro nor Nice!nano 1.0/2.0 have reverse polarity protection (BQ24073 doesn't have it either). Connecting a battery in reverse leads to an instant death of a charger IC (typically MCP73831).

Same goes for the majority of DIY boards, e.g. Hasu and YDKB controllers. This is a very common mistake, considering battery connectors do not really have a standard. There is no rule for a proper connector orientation. Even in China, batteries from Taobao aren't always the same.

Hasu polarity is used by Particle, Sparkfun and Adafruit. YDKB polarity is used by Aliexpress sellers and Varmilo VB87M. Luckily you can change the order of the wires in the connector without recrimping or resoldering (there are plastic latches).

These boards use 2-pin JST-PH (2.0 mm pitch) battery connectors and 13-pin JST-ZH (1.5 mm pitch) switchboard connectors.

hasu vs ydkb

My battery, 785251 2600 mAh http://www.ebay.com/itm/261625368941 (7.8x52x51mm). Max height is about 8mm, max length is about 80 mm perhaps, max width is 45-50 mm (there's a piece of controller PCB). 10 mm batteries don't fit, let alone 18650s.

my-hhkb

To protect the board you can use a single N-FET after the battery (ala Mitosis hardware):

image

You could also use a P-FET and a Schottky diode as here (discord):

before after
image image

Given some space you could even have autodetected/arbitrary polarity:

image

Battery Life

QMK

Author of https://github.com/sekigon-gonnoc/BLE-Micro-Pro commented on battery life on twitter:

It highly depends on configuration and connection parameters which determine delay. With default parameters in master-slave configuration, current is 300uA while typing, <100uA in standby (keyboard is connecting but you don't type), and <1uA in deep-sleep mode (no connection).

So at 0.2mA average it discharges a 110 mAh battery in about 110/0.2 = 550 hours (22 days). With 2500 mAh battery that would be about 2500/0.2 = 12500 hours (520 days, 1.4 years).

Bluemicro

Check out this video by jpconstantineau (he got 1.2-1.6 mA average while typing): https://youtu.be/bMEYIw4oQrw

When powered up, the keyboard uses an average current between 1.2 mA and 1.6 mA. The current varies depending on whether the keyboard is connected to a computer, broadcasts BLE and also depends on keys being pressed or not.

The high current peaks you see on the trace are when the radio of the nrf52 is broadcasting. What has the most impact on current between the peaks is whether the processor in the nrf52 goes in low power mode until the next timer interrupt. If the processor never goes in low power mode, the average current of 1.2-1.5 mA can go as high as 7.5mA!

ZMK

Check out this patch to ZMK docs that adds power profiler:

You can play with battery capacity and parameters:

Also see Online Power Profiler for BLE:

image

Summary

I don't think QMK is really better than Bluemicro firmware in terms of battery life, 0.3 mA peak current looks unrealistic, I'd say it's rather somewhere in the 1.5 mA range.

Both QMK and Bluemicro work for about 2 weeks on a 110 mAh 301230 battery which averages to about 110/(14*24) ~= 0.3 mA of constant current (2500 mAh battery could last for about a year).