Overview
The 3S 12V 18650 Lithium Battery Protection Board (also marketed as 11.1V / 12.6V Balanced BMS) is a three-cell-series battery management system that produces a nominal 11.1V output and fully charges to 12.6V. It is the most popular BMS for 12V replacement applications because the cell-balanced output closely matches a sealed lead-acid 12V battery, making it ideal for LED lighting, small motors, e-bike accessories, and battery-backed solar projects.
The board supports up to 25A continuous discharge, includes passive cell balancing on each cell, and provides over-charge, over-discharge, over-current, and short-circuit protection. Three battery taps (B-, B1, B2, B+) connect to the four nodes of the 3-cell pack, while a single P+/P- output drives your load.
At a Glance
Specifications
| Parameter | Value |
| Cell Configuration | 3S (three cells in series) |
| Nominal Pack Voltage | 11.1V (3 x 3.7V) |
| Full Charge Voltage | 12.6V (3 x 4.2V) |
| Per-Cell Over-Charge Cutoff | 4.25V - 4.35V |
| Per-Cell Over-Discharge Cutoff | 2.5V - 2.8V |
| Continuous Discharge Current | 25A |
| Peak Discharge Current | ~40A (short bursts) |
| Balancing Method | Passive resistor bleed |
| Balancing Threshold | Activated when a cell > 4.2V |
| Quiescent Current | < 50 uA |
| Operating Temperature | -40 to +85 C |
| PCB Dimensions | ~58 x 45 x 8 mm |
Pinout Diagram
Wiring Guide
3S Battery Wiring
You need four wires to the battery pack: B- at the negative end of cell 1, B1 between cells 1 and 2, B2 between cells 2 and 3, and B+ at the positive end of cell 3. The intermediate taps let the BMS monitor each cell individually.
| BMS Pad | Battery Connection |
|---|---|
| B- | Cell 1 Negative (lowest) |
| B1 | Cell 1 Positive + Cell 2 Negative |
| B2 | Cell 2 Positive + Cell 3 Negative |
| B+ | Cell 3 Positive (highest) |
Load Wiring
Connect your load to the P+ and P- pads on the opposite side of the board from the battery taps. The 25A rating handles 12V LED strips, small DC motors, fans, hobby ESCs, and Raspberry Pi clusters with room to spare.
| BMS Pad | Load Terminal |
|---|---|
| P+ | Load Positive (+) input |
| P- | Load Negative (-) / GND |
Charging the Pack
Use a 3S Li-ion charger that outputs 12.6V CC/CV. Charge current should be 0.3C - 1C of pack capacity (for a 3 Ah pack, charge at 0.9A - 3A). Connect the charger to P+/P-, not to the battery pads directly.
| Charger Pin | BMS Pad |
|---|---|
| Charger + (12.6V) | P+ |
| Charger - (GND) | P- |
Powering Microcontrollers and 12V Loads
11-12V is well-suited for Arduino Mega / Uno barrel jack input, but too high for ESP32 / Pico VIN. Step down to 5V with a buck converter for any 5V dev board.
| BMS Output | Target | Details |
|---|---|---|
| P+ (12V) | Arduino Mega / Uno barrel jack | Direct (7-12V range) |
| P+ (12V) | ESP32 / Pico | Via LM2596 / MP1584 buck to 5V |
| P+ (12V) | Raspberry Pi 5V | Via 5V 3A buck converter |
| P+ (12V) | 12V LED strip | Direct, with MOSFET driver |
| P+ (12V) | 12V DC fan | Direct, with PWM driver |
| P- | Common GND | Tie all grounds together |
Code Examples
The 3S 12V BMS does not communicate digitally with a microcontroller. The examples below show how to read pack voltage with a voltage divider, useful for displaying battery percentage on a screen or logging usage to an SD card.
Arduino (Pack Voltage with Percentage)
// 3S Pack Voltage Monitor for Arduino
// Voltage divider: P+ -- 470k -- A0 -- 100k -- GND
// Max ADC voltage: 12.6V * (100 / 570) = 2.21V (safely under 5V)
const int adcPin = A0;
const float dividerRatio = (470.0 + 100.0) / 100.0; // = 5.7
const float vRef = 5.0;
float pctFromVoltage(float v) {
if (v >= 12.6) return 100.0;
if (v <= 9.6) return 0.0;
return ((v - 9.6) / (12.6 - 9.6)) * 100.0;
}
void setup() {
Serial.begin(9600);
}
void loop() {
int raw = analogRead(adcPin);
float vAdc = (raw / 1023.0) * vRef;
float vPack = vAdc * dividerRatio;
Serial.print("Pack: ");
Serial.print(vPack, 2);
Serial.print(" V (");
Serial.print(pctFromVoltage(vPack), 0);
Serial.println(" %)");
delay(1000);
}
ESP32 (Pack Voltage Monitor)
// ESP32 reads 3S pack voltage through a 470k/100k divider on GPIO34
// 12.6V / 5.7 = 2.21V at ADC -- safely below 3.3V
const int adcPin = 34;
const float dividerRatio = (470.0 + 100.0) / 100.0; // = 5.7
const float vRef = 3.3;
void setup() {
Serial.begin(115200);
analogReadResolution(12);
}
void loop() {
int raw = analogRead(adcPin);
float vAdc = (raw / 4095.0) * vRef;
float vPack = vAdc * dividerRatio;
Serial.printf("Pack: %.2f V\n", vPack);
delay(1000);
}
Raspberry Pi (Python)
#!/usr/bin/env python3
# Raspberry Pi has no built-in ADC -- use an MCP3008 or ADS1115.
# Example uses ADS1115 over I2C with a 470k/100k voltage divider.
import time
import board
import busio
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
i2c = busio.I2C(board.SCL, board.SDA)
ads = ADS.ADS1115(i2c)
chan = AnalogIn(ads, ADS.P0)
DIVIDER_RATIO = (470.0 + 100.0) / 100.0 # = 5.7
try:
while True:
v_adc = chan.voltage
v_pack = v_adc * DIVIDER_RATIO
print("Pack: {:.2f} V".format(v_pack))
time.sleep(1)
except KeyboardInterrupt:
print("Stopped")