LiPo Charge Controller Repair Tutorial

This tutorial demonstrates the repair of an Adafruit nRF52840 Feather Express board with a defective LiPo charge controller.


Here’s the defective Feather board connected to a 3.7 V, 500 mAH LiPo battery.  Despite being plugged into a 5 V USB, the yellow LED charging indicator is not illuminated. It’s not just a broken LED because I verified the battery is not getting charged with a multimeter.

Feather with bad charger

Let’s start with a visual inspection.  Under magnification with the colors inverted there appears to be a possible burn mark on top of a 5 lead SOT23 package.  The board also has the distinct smell of burnt semiconductors so this chip is a very likely culprit.

Burned Controller Chip

When working with surface mount parts it can be difficult to identify a chip. The SOT23 package is labelled “KDO1” which doesn’t mean anything to me.   There are several resources online for identifying chips such as the SMD Codebook.   Although it looks like it hasn’t been updated since 2015. Here’s a PDF versionDigikey and S-manuals also have look-ups for SMD markings. I searched online but could not find a match for KDO1.  It’s probably a packaging code which I would not be able to decipher without the datasheet.


Fortunately, Adafruit provides excellent schematics for all their boards.  Here’s the schematic for the nRF52840 Feather.    If you’re going to design a schematic, this is a great example!  All the different board functions are neatly organized and labelled. 

nRF52840 Feather Schematics

For example, here’s a close-up of the Lipo charging section.   The main component is a MCP73831/2 LiPo charger IC.  It’s 5 pin which matches the burnt SOT23 chip.  Mouser has them in stock for  50 cents so it’s definitely worth fixing.  The circuit is very simple.  VDD goes to 5 V.  VBAT goes to the battery with a 10 uF decoupling cap. VSS goes to ground.   The STAT pin drives an LED status indicator in-line with a 1000 ohm resistor.  The PROG pin allows you to set the charging current via the R4 resistor.  The board uses a 4700 ohm resistor to set the current to 200mA.

LiPo Charging Schematic

Here’s a chart from the MCP73831/2 datasheet.  Raising the value of the programming resistor lowers the charging current.  My application for this board does not require fast charging so I’ll try raising the resistor value to 10K ohms to cut the charge current from 200 mA to 100 mA.  Hopefully, this will reduce heat and improve longevity.

Charge Current vs Programming Resistor Chart

I like to cover the board around the work area with Kapton tape so I don’t melt any of the plastic parts or accidentally remove something.  I’ll remove the charge controller chip and the programming resistor using my 858D hot air rework station

Feather with Kapton Tape

After replacing the MCP73831/2 chip and the programming resistor, the yellow LED charging indicator is illuminated.

Repaired nRF52840 Feather

Let’s write a quick CircuitPython program to verify  the charger is working.  An ST7735 color 128×64 LCD display will provide feedback even if the USB cable is disconnected from the computer.  The display uses a SPI interface and can be powered directly from the Feather’s 3.3 V pin even when running on battery. 

ST7735 LCD Display

I’m not going to go into detail on connecting the display because I already made a CircuitPython nRF52840 LCD Display tutorial dedicated to the subject. Here’s the wiring schematic.

ST7735 Wiring

The nRF52840 Feather board is connected to a computer via a micro-USB cable. I’ll use a Raspberry Pi 4. The latest version of Raspbian comes with the Mu editor which is an excellent IDE for writing CircuitPython code.

Here’s the code. The first section after the imports is boiler plate for the LCD display. One cool feature of the DisplayIO library is with just this basic set up, all REPL output will automatically be piped to the LCD display.  Afterwards, the Python print statement can be used to show output on the display.

import board
from time import sleep
from analogio import AnalogIn
import displayio
from adafruit_st7735r import ST7735R

spi = board.SPI()
cs = board.D11
dc = board.D10
rst = board.D9
displayio.release_displays()
display_bus = displayio.FourWire(spi, command=dc, chip_select=cs, reset=rst)
display = ST7735R(display_bus, width=128, height=160)

battery = AnalogIn(board.BATTERY)

minV = 1000
maxV = 0

while True:
    v = battery.value * 3.3 / 65535 * 2
    minV = min(v, minV)
    maxV = max(v, maxV)
    print("Battery: {0:.2f}V\n({1:.2f}V - {2:.2f}V)".format(v, minV, maxV))
    sleep(2)

The main loop polls the Feather’s analog battery pin, converts the results to voltage, tracks the minimum & maximum range and outputs the results. The analog pins have 16 bit resolution.  Therefore, the battery voltage is represent by a value between zero and 65535.  This is converted to voltage by multiplying by the reference voltage of 3.3 V and dividing by the resolution. Looking at the JST PH LiPo input section of the schematic, there’s a voltage divider comprised of two 100K ohm resistors between VBAT and GND. 

JST PH LiPo Input Schematic

The voltage measured by the board’s analog battery pin is at VDIV.  Since the resistors are identical, the measured voltage is equal to 1/2 the actual battery voltage.  The voltage is reduced because the LiPo battery voltage typically exceeds the 3.3 V reference voltage which is the maximum that the analog pins on the Feather can tolerate.

Here’s a breadboard with an ST7735 LCD connected to the Feather which is running off battery. The LiPo voltage is around 3.7 V which is about the nominal voltage.  A fully charged LiPo should be closer to 4.2 V.

Feather with Display

After about 1 hour of charging the battery is looking good at 4.1 V.

Feather with Display Charging