/* * Lipo-Wächter nach einer Idee von Volker Keck * Die die Zellenspannungen eines Lipos werden der Reihe nach gemessen und * die Zelle mit der geringsten Spannung festgestellt. So lange die Spannung * dieser Zelle oberhalb des festgelegten Schwellwertes liegt, wird PIN 3 auf * HIGH gesetzt. Ist die Spannung dieser Zelle kleiner oder gleich dem * Schwellwert, wird Pin 3 auf LOW umgeschaltet. * Um den Zustand auch am Board erkennen zu können, wird die interne LED * des Boards entgegengesetzt zu Pin3 geschaltet. D.h. Solange der Schwellwert * noch nicht erreicht ist, ist die LED aus und solange der Schwellwer erreicht * oder unterschritten ist, ist sie an. * * Pin 3 kann somit direkt an den Spannungsmessungseingang eines Futaba-Empfängers * angeschlossen und ein entsprechender Alarm auf dem Sender generiert werden. */ // symbolische Namen für Ausgänge #define po_sensor 3 // Anschluss für robbe Anlage #define po_led 13 // = interne LED // ******* Programm steuernde Konstanten und Variablen, diese sind jeweils anzupassen // Widerstände der Spannungsteiler // 1 1 2 2 3 3 4 4 5 5 6 6 const float r_st[] = {23, 47, 101, 47, 226, 47, 223, 47, 231, 33, 470, 47}; // Warnschwelle, ab der der Pin D1 auf low gesetzt wird const float u_warn = 3.3; // verwendete Referenzspannung für ADC (leider nicht immer wirklich 3,3 bzw. 5,0 V) const float u_ref = 5.0; //3.26; // Testausgabe const char test = 'j'; // bei j erfolgt serielle Testausgabe // ******* Ende der Programmsteuernden Definitionen // ADC-Werte an den Zellen 1 - 6 (Pin A0 bis A5) int adc[6]; // Spannungswerte der Spannungsteiler an den einzelnen Zellen float u_st[6]; // Berechnete Gesamtspannung an den einzelnen Zellen float u_ges[6]; // Zellenspannungen der Zellen 1 - 6 float u_z[6]; // sonstige Definitionen float f_ges; // Faktor für Berechnung der Gesamtspannung an den einzelnen Zellen float u_min; // kleinste ermittelte Zellenspannung int i_min; // Index zu u_min float adc_faktor; // Faktor zur Umrechnung des ADC-Wertes int i; // Index für For-Schleife unsigned long anz_mess; // Anzahl Messungen (die ersten 3 ignorieren) // Initialisierungsroutine void setup() { pinMode(po_led,OUTPUT); // LED zur Statusanzeige pinMode(po_sensor,OUTPUT); // Pin für robbe Sensor Serial.begin(9600); // Serielle Kommunikation für Testausgabe aktivieren digitalWrite (po_led, LOW); // LED ausschalten digitalWrite (po_sensor, HIGH); // Sensorpin einschalten // analogReference(EXTERNAL); // 3.3 V Pin auf AREF Pin geschaltet (nur bei UNO) adc_faktor = u_ref/1023; // Faktor zu Umrechnung des ADC-Wertes in Spannung } // Stuerschleife void loop() { u_min = 4.5; // u min vor der For Schleife auf zu hohen Wert, // so dass 1. Zelle auf jeden Fall eingetragen wird. for (i = 0; i < 6; i++) // schleife für alle 6 Spannungsteiler { adc[i] = analogRead(i); // ADC-Wert aktueller Spannungsteiler u_st[i] = adc[i] * adc_faktor; // = Spannung aktueller Spannungsteiler int i2 = i*2; // Index für Spannungsteiler berechnen f_ges = (r_st[i2] + r_st[i2+1])/r_st[i2+1]; // = Faktor für Berechnung Gesamtspannung an aktueller Zelle u_ges[i] = u_st[i] * f_ges; // Gesamtspannung an aktueller Zelle if (i == 0) { u_z[i]=u_ges[i]; // Zellenspannung erste Zelle } else { u_z[i] = u_ges[i]-u_ges[i-1]; // Zellenspannung an aktueller Zelle } if (adc[i] < 10) { // beim Duemilanove kommen sporadisch ganz kleine Werte statt 0 break; } if (u_z[i] < u_min) // kleinste Zellenspannung ermitteln { u_min = u_z[i]; // u_min versorgen i_min = i+1; // Zellennummer versorgen } if (test == 'j') testausgabe1 (); } // next for if (i_min > 0) anz_mess++; // Anzahl Messungen mit angeschlossenem Akku zählen if (u_min == 4.5) anz_mess = 0; // Akku neu angesteckt if (anz_mess > 2) // die drei ersten Messungen ignorieren { // weil Spannungsschwankungen beim Anstecken if (test == 'j') testausgabe2 (); if (u_min <= u_warn) { // u_warn erreicht oder unterschritten digitalWrite (po_led, HIGH); // interne LED einschalten digitalWrite (po_sensor, LOW); // Sensorpin auf 0 V } else { digitalWrite (po_led, LOW); // interne LED ausschalten digitalWrite (po_sensor, HIGH); // Sensorpin auf VCC } delay (500); // gemessen wird alle 0,5 Sekunden } } // Ende void loop void testausgabe1 () { Serial.print (anz_mess); Serial.print (":i="); Serial.print (i+1); Serial.print (",adc="); Serial.print (adc[i]); Serial.print (",u="); Serial.print (u_st[i]); Serial.print (",u_ges="); Serial.print (u_ges[i]); Serial.print (",u_z="); Serial.println (u_z[i]); } void testausgabe2 () { Serial.print(i_min); Serial.print(":"); Serial.println(u_min); Serial.println (" "); }