CCCV-Ladeschaltung mit RPi Pico              

von Martin Müller                            

Elektronik-Labor  Projekte  Mikrocontroller  Raspberry            



Li-Akkus werden im sogenannten CCCV - Ladeverfahren (constant current constant voltage) aufgeladen. Der Akku wird bis zum Erreichen einer vorgegebenen Ladespannung zunächst mit einem konstanten Strom geladen. Wird die Ladespannung erreicht, wird der Ladevorgang mit dieser konstanten Spannung fortgesetzt, bist der Ladestrom nahezu 0 mA beträgt. Damit ist der Ladevorgang abgeschlossen.

Bei Li-Akkus mit einer nominalen Spannung von 3,7 V (wie sie in Einweg-E-Zigaretten zu finden sind), darf die Ladespannung 4,2 V auf keinen Fall überschreiten. Die Akkus reagieren sehr empfindlich, verlieren an Kapazität und können sich erwärmen. Es besteht Brandgefahr.




Mit einem Raspberry Pi Pico und einigen weiteren Bauteilen kann man eine solche Ladeschaltung selber bauen. Optimalerweise funktioniert die ganze Schaltung an dem USB-Anschluss eines Laptops oder Computers. Der Pico misst sowohl den Ladestrom (Spannungsabfall über R9 und R10) als auch die Ladespannung (Spannungsabfall über dem angeschlossenen Li-Akku). Ladestrom und Ladespannung werden von einem N-Channel-MOS-FET reguliert. Bei der Auswahl des FETs ist darauf zu achten, dass dieser mit einer GS-Spannung von deutlich weniger als 3,3 V durchschaltet und dabei einen Widerstand (RDS(on)) von weniger als 1 Ohm hat. Bei VGS = 2,5 V beträgt RDS(on) beim TSM 2302 weniger als 0,1 Ohm.

Die GPIO-Pins des Pico vertragen nur 3,3 V. Mit den Widerständen R1 bis R6 werden die zu messenden Spannungen halbiert. Diese Halbierung und die Toleranzen der Widerstände müssen im Sketch der Arduino-IDE ausgeglichen werden. Die Schaltung wurde in SMD-Technik auf einer Lochrasterplatine aufgebaut. Zwei 10-polige Buchsenleisten stellen die Verbindung zum Pico her. Sie werden auf die Pins 1-10 und 31-40 aufgesteckt. Die dargestellte Schaltung lädt mit einem Strom von ca. 200 mA. Möchte man mit höherem Strom laden, müssen die Widerstände R9 und R10 angepasst werden. Ebenso muss ein MOS-FET mit höherer Verlustleistung gewählt werden und die entsprechenden Parameter im Sketch der Arduino-IDE geändert werden.

#include "hardware/pwm.h"

long vcc, ohm, fet, dauer, plotu = 0, plotualt, ploti = 0;
int led = 40, ann = 40, imp = 1000, voll = 0, zeit = 2400, mA200 = 115, mV4200 = 1304, fehlercode;
String fehlertxt;

// Spannungen messen und mitteln
void VCC() {
vcc = 0;
for (int i = 0; i < 1000; i++) {
vcc += analogRead(28);
}
vcc = vcc / 500;
}

void OHM() {
ohm = 0;
for (int i = 0; i < 1000; i++) {
ohm += analogRead(27);
}
ohm = ohm / 500;
}

void FET() {
fet = 0;
for (int i = 0; i < 1000; i++) {
fet += analogRead(26);
}
fet = fet / 500;
}

// LED ansteuern, Blinkfrequenz 1 Hz
void STATLED() {
led -= 1;
if (led == 0) {
led = 40;
}
if (led > ann) {
digitalWrite (25, 1);
}
if (led <= ann) {
digitalWrite (25, 0);
}

//|*___| initialisieren
if (ohm - fet < mA200 - 4 && vcc - ohm < mV4200 - 4) {
ann = 37;
}
//|**__| CC
if (ohm - fet >= mA200 - 3 && ohm - fet <= mA200 + 3 && vcc - ohm < mV4200 - 4) {
ann = 20;
}
//|***_| VC
if (vcc - ohm > mV4200 - 3) {
ann = 5;
}
}

// Ladeverlauf plotten
void PLOT() {
Serial.print((plotu / 2400) * 3.22);
Serial.print(", ");
Serial.print((ploti / 2400) * 17.83);
Serial.print(", ");
Serial.println(imp);
plotualt = plotu;
plotu = 0;
ploti = 0;
}

void FEHLER() {
pwm_set_chan_level(2, PWM_CHAN_B, 0);
while (true) {
Serial.println(fehlertxt);
for (int i = 0; i < fehlercode; i++) {
digitalWrite (25, 1);
delay(100);
digitalWrite (25, 0);
delay(250);
}
delay(1000);
}
}


void setup() {
Serial.begin(115200);

//LED initialisieren
gpio_init(25);
gpio_set_dir(25, GPIO_OUT);

//PWM initialisieren
gpio_set_function(5, GPIO_FUNC_PWM); //GPIO 5 = PWM2B
pwm_set_wrap(2, 8191);
pwm_set_chan_level(2, PWM_CHAN_B, imp); //Duty-Cycle
pwm_set_enabled(2, 1); //PWM2 einschalten
delay(1000);
}


void loop() {

//LED ansteuern
STATLED();
//Delay => 25 ms pro Schleifendurchlauf
delay(11);
delayMicroseconds(450);

//Spannungen messen
VCC();
OHM();
FET();

//Werte für Plotter addieren
plotu += vcc - ohm;
ploti += ohm - fet;

//Ladestrom,Akkuspannung und PWM-Impuls minütlich plotten
zeit += 1;
if (zeit >= 2400) {
zeit = 0;
PLOT();
}

//Ladestrom > 200 mA, Ladespannung < 1V
//|*_*____| Fehlercode 2, Kurzschluss am Akku
if (ohm - fet > mA200 && vcc - ohm < mV4200 / 4) {
fehlercode = 2;
fehlertxt = "Kurzschluss am Akku";
FEHLER();
}

//|*_*_*___| Fehlercode 3, Ladezeit > 4 h
if (millis() > 14400000) {
fehlercode = 3;
fehlertxt = "Ladezeit > 4 h";
FEHLER();
}

//Ladestrom < 200 mA, Ladespannung < 4,2V
if (ohm - fet < mA200 && vcc - ohm < mV4200) {
voll = 0;
imp += 1;
//|*_*_*_*___| Fehlercode 4, Keine Ladespannung am Akku
if (imp > 8191) {
fehlercode = 4;
fehlertxt = "Keine Ladespannung am Akku";
FEHLER();
}
}

//Ladespannung > 4,2V
if (vcc - ohm > mV4200 + 1) {
imp -= 1;
}

//Ladestrom > 200 mA
if (ohm - fet > mA200 + 1 ) {
voll = 0;
imp -= 1;
}

//Akku vollständig geladen
if (ohm - fet <= 2 && vcc - ohm >= mV4200 - 1) {
voll += 1;
if (voll > 3) {
pwm_set_chan_level(2, PWM_CHAN_B, 0);
digitalWrite (25, 1);
ploti = 0;
PLOT();
dauer = millis() / 60000;
while (true) {
Serial.print("Ladezeit : ");
Serial.print(dauer);
Serial.println(" Minuten");
delay(2000);
}
}
}

pwm_set_chan_level(2, PWM_CHAN_B, imp);
}

40 mal pro Sekunde werden Ladestrom und Ladespannung ermittelt und der MOS-FET wird über ein 13 Bit-PWM-Signal angesteuert. Es wird darauf geachtet, dass weder der vorgegebene Ladestrom noch die maximale Spannung überschritten werden.

Die LED des Pico zeigt den Ladestatus bzw. Fehlercodes an. Sie blitzt so lange kurz auf, bis der vorgegebene Ladestrom erreicht ist. Dann blinkt sie mit einem Impuls-Pausenverhältnis von 1:1. Wird der Akku später mit konstanter Spannung (4,2 V) geladen, ändert sich das Impuls-Pausenverhältnis zu Gunsten der Impulszeit. Ist der Akku vollständig geladen, leuchtet die LED dauerhaft. Blinkt die LED zweimal auf, zeigt das einen Kurzschluss am Akku an. Die LED blinkt dreimal, wenn eine Ladezeit von 4h erreicht ist. Viermaliges Blinken bedeutet, dass der Akku nicht geladen wird. Das passiert dann, wenn der Akku mit der Schaltung verbunden wird, ohne, dass an den Pico eine Versorgungsspannung angelegt wird. Über die DS-Diode des MOS-FET wird der Pico in diesem Fall vom angeschlossenen Akku mit Energie versorgt. Nach einer Weile merkt der Pico, dass der Akku so nicht geladen wird und gibt den entsprechenden Fehlercode aus.

Ist der Akku vollständig geladen oder tritt ein Fehler auf, wird der Ladevorgang sofort abgebrochen.



Einmal pro Minute werden die Werte für Ladestrom, Ladespannung und Duty-Cycle des PWM-Signals über die serielle Schnittstelle ausgegeben. Sie können mit dem Plotter der Arduino-IDE in Echtzeit betrachtet werden.

Der Nachbau diese Projekts geschieht auf eigene Gefahr. Wenn man nicht genau weiß was man tut, sollte man davon Abstand nehmen.

Hat man die Schaltung aufgebaut und mit dem programmierten Pico verbunden, wird zunächst ein Widerstand von 47 Ohm und entsprechender Leistung an Stelle des Akkus angeschlossen. Wird der Pico mit der Versorgungsspannung verbunden, liegt sehr bald die Ladespannung von 4,2V am Widerstand an. Mit einem präzisen Multimeter wird diese Spannung kontrolliert. Eine der wichtigsten Variablen ist : "mV4200 = 1304" in der zweiten Zeile des Sketches. Sie ist dort so anzupassen, dass die Spannung am Widerstand (später Akku) die genannten 4,2 V nicht übersteigt. Besser ist es 10 bis 20 mV unterhalb dieser Grenze zu bleiben als darüber zu liegen. Zu erwähnen bleibt, dass "mA200 = 115" -ebenfalls in der zweiten Zeile des Sketches- den Ladestrom vorgibt. Dieser Wert kann unter Berücksichtigung der Verlustleitungen des MOS-FETs und der Widerstände R9 und R10 verändert werden.





Elektronik-Labor  Projekte  Mikrocontroller  Raspberry