Battery and Power Management
The battery is the lifeblood of any drone. Understanding LiPo chemistry, discharge characteristics, and power management is critical for safe and reliable flight.
LiPo Battery Fundamentals
Sponsored
Battery Specifications Explained
python
class LiPoBattery:
def __init__(self, cells, capacity_mah, c_rating):
self.cells = cells
self.capacity = capacity_mah
self.c_rating = c_rating
self.nominal_voltage = cells * 3.7
self.full_voltage = cells * 4.2
self.empty_voltage = cells * 3.0
@property
def capacity_wh(self):
"""Energy capacity in Watt-hours"""
return self.capacity * self.nominal_voltage / 1000
@property
def max_discharge_amps(self):
"""Maximum continuous current: Capacity x C-rating"""
return (self.capacity / 1000) * self.c_rating
@property
def weight_estimate(self):
"""Rough weight estimate in grams"""
return self.capacity * self.cells * 0.05 + 20
def voltage_at_percent(self, percent):
"""Approximate voltage at given capacity percent (0-100)"""
import math
# Simplified LiPo discharge curve
v_range = self.full_voltage - self.empty_voltage
# LiPo curve is not linear â drops slowly then quickly
exponent = 2.5
voltage = self.empty_voltage + v_range * (percent / 100) ** (1/exponent)
return voltage
def flight_time_minutes(self, avg_current_amps):
"""Estimated flight time"""
capacity_ah = self.capacity / 1000
# Use 80% of capacity for safety
usable_ah = capacity_ah * 0.8
return (usable_ah / avg_current_amps) * 60
def __repr__(self):
return f"{self.cells}S {self.capacity}mAh {self.c_rating}C"
# Analyze different batteries
batteries = [
LiPoBattery(3, 1500, 45),
LiPoBattery(4, 1300, 100),
LiPoBattery(6, 1100, 120),
LiPoBattery(6, 2200, 50),
]
for bat in batteries:
print(f"\n{bat}")
print(f" Nominal voltage: {bat.nominal_voltage}V")
print(f" Full charge: {bat.full_voltage}V")
print(f" Energy: {bat.capacity_wh:.1f} Wh")
print(f" Max discharge: {bat.max_discharge_amps:.0f}A")
print(f" Est. weight: {bat.weight_estimate:.0f}g")
print(f" Flight time @ 20A: {bat.flight_time_minutes(20):.1f} min")
C-Rating Explained
The C-rating tells you how fast you can safely discharge the battery:
python
def c_rating_analysis():
"""Understanding C-ratings"""
print("=== C-Rating Analysis ===\n")
capacity_mah = 1300
c_ratings = [45, 75, 100, 130]
for c in c_ratings:
max_amps = (capacity_mah / 1000) * c
print(f" {c}C rating:")
print(f" Max continuous: {max_amps:.0f}A")
print(f" Burst (10s): {max_amps * 1.5:.0f}A")
print(f" Max power (4S): {max_amps * 14.8:.0f}W")
print("\nRule of thumb:")
print(" Racing quads draw 100-200A peak")
print(" Cinematic quads draw 20-60A average")
print(" Your battery must handle your motors' max draw!")
c_rating_analysis()
Power Distribution
Advertisement
Battery Health Monitoring
python
class BatteryMonitor:
def __init__(self, battery):
self.battery = battery
self.history = []
self.voltage_alarm = battery.cells * 3.5 # Per-cell alarm
def update(self, voltage, current_amps):
"""Called each loop cycle"""
self.history.append({
"voltage": voltage,
"current": current_amps,
"power": voltage * current_amps
})
def cell_voltage(self, voltage):
return voltage / self.battery.cells
def is_low_battery(self, voltage):
return self.cell_voltage(voltage) < 3.5
def is_critical(self, voltage):
return self.cell_voltage(voltage) < 3.3
def remaining_capacity_percent(self, voltage):
"""Estimate remaining % from voltage"""
cell_v = self.cell_voltage(voltage)
if cell_v >= 4.1:
return 95
elif cell_v >= 3.9:
return 75
elif cell_v >= 3.7:
return 50
elif cell_v >= 3.5:
return 25
elif cell_v >= 3.3:
return 10
else:
return 0
def average_current(self):
if not self.history:
return 0
return sum(h["current"] for h in self.history) / len(self.history)
def status_report(self, current_voltage, current_amps):
cell_v = self.cell_voltage(current_voltage)
pct = self.remaining_capacity_percent(current_voltage)
avg_current = self.average_current()
flight_time = self.battery.flight_time_minutes(avg_current) if avg_current > 0 else 0
print(f"\n--- Battery Status ---")
print(f" Voltage: {current_voltage:.2f}V ({cell_v:.2f}V/cell)")
print(f" Capacity: ~{pct}% remaining")
print(f" Current draw: {current_amps:.1f}A")
print(f" Power: {current_voltage * current_amps:.0f}W")
if self.is_critical(current_voltage):
print(f" STATUS: CRITICAL - LAND IMMEDIATELY!")
elif self.is_low_battery(current_voltage):
print(f" STATUS: LOW - Begin landing")
else:
print(f" STATUS: OK")
# Simulate
bat = LiPoBattery(4, 1300, 100)
monitor = BatteryMonitor(bat)
for step in range(5):
voltage = 16.8 - step * 0.8 + random.gauss(0, 0.1)
current = 25 + step * 3
monitor.update(voltage, current)
monitor.status_report(voltage, current)
Hands-On Project: Battery Selection Tool
python
def select_battery(motors, motor_max_amps, desired_flight_min, drone_weight_g):
"""Select appropriate battery for a build"""
total_max_amps = motor_max_amps * motors
avg_amps = total_max_amps * 0.4 # Average is ~40% of max
print(f"Build requirements:")
print(f" Motors: {motors}x, Max draw: {total_max_amps}A")
print(f" Average draw: ~{avg_amps:.0f}A")
print(f" Desired flight: {desired_flight_min} min")
print(f" Drone weight: {drone_weight_g}g\n")
batteries = [
(4, 1000, 100), (4, 1300, 100), (4, 1500, 75),
(6, 1000, 120), (6, 1300, 100), (6, 1800, 50),
(6, 2200, 50),
]
best = None
for cells, mah, c in batteries:
bat = LiPoBattery(cells, mah, c)
if bat.max_discharge_amps < total_max_amps * 1.2:
continue # Not enough current capability
flight_min = bat.flight_time_minutes(avg_amps)
if flight_min < desired_flight_min * 0.8:
continue # Too short flight
weight = bat.weight_estimate
twr_penalty = weight / drone_weight_g
if best is None or flight_min > best["flight"]:
best = {"battery": bat, "flight": flight_min, "penalty": twr_penalty}
if best:
bat = best["battery"]
print(f"RECOMMENDED: {bat}")
print(f" Voltage: {bat.nominal_voltage}V")
print(f" Energy: {bat.capacity_wh:.1f} Wh")
print(f" Est. flight time: {best['flight']:.1f} min")
print(f" Weight penalty: {best['penalty']:.2f} (TWR reduction)")
else:
print("No suitable battery found. Consider custom pack.")
select_battery(motors=4, motor_max_amps=40, desired_flight_min=5, drone_weight_g=350)
select_battery(motors=4, motor_max_amps=25, desired_flight_min=20, drone_weight_g=600)
Summary
- LiPo cells are 3.7V nominal, 4.2V full, 3.0V empty (never go below 3.3V!)
- C-rating determines max safe discharge current
- Capacity (mAh) determines energy storage and flight time
- Higher cell count (S) = more voltage = more power but more weight
- Always use low voltage alarms and balance chargers
- Battery weight is a major factor in thrust-to-weight ratio
Next, we'll explore communication systems.