Hallo Arni;
ich hatte vor einiger Zeit mal sowas aufgebaut für 2 PB Akkus, vielleicht kannst du damit was anfangen und an deine Bedürfnisse anpassen.
Die Last bzw. das Ladegerät wird mit einem Relais abgeschaltet.
Gruß
Ardubu
/*
2+2 Kanal Spannungesmesser und Strommesser mit SD card datenlogger
Alle Belegungen sind für den Mega 2560, sowie das DF Robot KeyPad Shield
Dieser Sketch speichert die Daten von 4 analogen Engängen auf der SD Karte und zeigt sie auf dem LCD an
Die Relais schalten beim überschreiten der Ladeschlußspg. bzw. beim unterschreiten der Entladeschlußspg. ab 10,5V / 14,5V ab 14,2V wird die Gasspg. erreicht
Die Schaltung:
* 2 Spannungsteiler an den analogen Pins 8 und 12
* 2 ACS 714 an den Analogen Pins 2 + 3
* Pinbelgung für die SD Karte:
** MOSI - pin 51
** MISO - pin 50
** CLK - pin 52
** CS - pin 53
Die Schaltung für das LCD: (1602)
* LCD KeyPad shield auf den MEGA aufgesteckt
created 03 Juli 2012
geändert am:03.02.2013
by B. K.
*/
#include <SD.h> // benutzt den SD Library Code:
#include <LiquidCrystal.h> // benutzt den library code:
LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // initialisiert die library mit den Nummern der interface pins
#include <Wire.h>
#include <RTClib.h>
RTC_DS1307 RTC; // define the Real Time Clock object
File dataFile;
//------------------------------------------------------------------------------
// call back for file timestamps
void dateTime(uint16_t* date, uint16_t* time) {
DateTime now = RTC.now();
// return date using FAT_DATE macro to format fields
*date = FAT_DATE(now.year(), now.month(), now.day());
// return time using FAT_TIME macro to format fields
*time = FAT_TIME(now.hour(), now.minute(), now.second());
}
//------------------------------------------------------------------------------
const int chipSelect = 53;
unsigned long(nr)=0;//Zähler zur Berechnung des Durchschnittsstromes
unsigned int anz=1;
float u1=0;
float u2=0;
float I1=0;
float I2=0;
float C1=0;
float C2=0;
float(Strom1)=0;
float(Strom2)=0;
const float mb =16.0; //Messbereich
const float tm = 1023.0; // Teiler Messbereich (10 Bit)
const float pause = 3323.; //Abtastrate
unsigned long millisalt;
unsigned long millis10=millis();
int sel;
int taste(){sel = analogRead(0);}
int c=0;//Laufvariabele des Dateinamens
char d;// 8. Buchstabe des Dateinamens
char(dateiname)[13]="datalog0.csv";
void setup()
{
analogWrite(10 , 255); // setzt den Wert für die Hintergrundbeleuchtung ( PWM Pin 10) des LCD 0 - 255
Serial.begin(9600); // öffnet die Serielle Kommunikation und wartet bis der Port geöffnet ist
Wire.begin();
DateTime now = RTC.now();
pinMode(53, OUTPUT); //CS
pinMode(22, OUTPUT); // Rel. 1
pinMode(23, OUTPUT); // Rel. 2
digitalWrite(22,HIGH);
digitalWrite(23,HIGH);
lcd.begin(16, 2); // gibt die Zeichenanzahl und Zeilenzahl des LCD's vor:
lcd.print("Hallo!"); // schreibt die Nachricht auf das LCD.
lcd.setCursor(0,1);
lcd.print("U2 I2 C2 Blei"); // schreibt die Nachricht auf das LCD.
delay(2600);
lcd.clear(); // löscht das LCD
// setzt die date time callback Function
SdFile::dateTimeCallback(dateTime);
if (!SD.begin(chipSelect)) { // prüft ob die SD Karte eingeschoben ist und initialisiert werden kann
Serial.println();
Serial.print("SD Karte fehlt");
lcd.print("SD Karte fehlt");
delay(2000);
lcd.clear();}
while (SD.exists(dateiname))//püft ob der Datiename schon vergeben ist
{
c=c++;
if (c >9){Serial.println("Bereits 9 Dateien auf SD Karte");return;}
d= c+'0'; //Umwandlung von int in char
dateiname[7]=d; }
dataFile = SD.open(dateiname, FILE_WRITE);
Serial.println();
dataFile.println("Zeit,U1,U2,I1,I2,C1,C2"); // schreibt eine Kopfzeile auf die SD Karte
Serial.println("Zeit,U1,U2,I1,I2,C1,C2");
dataFile.close();
//Auswahlmenue
start();
digitalWrite(22,LOW); //schaltet das Relais 1 ein
digitalWrite(23,LOW); //schaltet das Relais 2 ein
millisalt=millis();
}
void loop()
{
nr++;//laufvariabele zum Berechnen des Durchschnittsstromes
float korrFakt[8]= {(1.0038496),(1.0038496),(1.0062802),(1.00506345),(1.0014308),(1.0038496),(1.0062802),(1.0038496)}; //Korrekturfaktoren für die 8 Eingänge
// Spannungsmessung
float(mw1)=analogRead(8); //liest den Eingang 1.1 für Spannung
float(mw2)=analogRead(12); //liest den Eingang 2.1 für Spannung
u1=((mw1*mb)/tm)*korrFakt[1];
u2=((mw2*mb)/tm)*korrFakt[5];
//Strommessung
float(mwI1) = analogRead(2); //liest den 1. Stromeingang
float(mwI2) = analogRead(3); //liest den 2. Stromeingang
float(DI1) = (mwI1-102);
float(DI2) = (mwI2-102);
if (DI1==1||DI1==-1) {DI1=0;}
if (DI2==1||DI2==-1) {DI2=0;}
I1 = ((DI1/1023)*30)*1.29813664596;
I2 = ((DI2/1023)*30)*1.29813664596;
//Abschalten der Realais, wenn die Spannung kleiner als 10 V wird
if(u1<=10.5 || u1>14.5) {digitalWrite(22,HIGH);I1=0;} //high schaltet Relais aus
if(u2<=10.5 || u1>14.5) {digitalWrite(23,HIGH);I2=0;} //low schaltet Relais ein
// Kapazitätsberechnung
Strom1=Strom1+I1;
Strom2=Strom2+I2;
long zeit=(millis()-millisalt)/1000;
C1=(Strom1/nr)*zeit/3.6; // Berechnung der ge- oder entladenen Amperstunden.
C2=(Strom2/nr)*zeit/3.6; // Berechnung der ge- oder entladenen Amperstunden.
//Ausgabe auf SD + Ser. Monitor
if (millis()-millis10>=10000){printSD();millis10=millis();}
// Ausgabe auf LCD
if (millis()-millis10>=0 && millis()-millis10<50){printlcdU();}
if (millis()-millis10>=3333 && millis()-millis10<3400){printlcdI();}
if (millis()-millis10>=6666 && millis()-millis10<6700){printlcdC();}
}//Loop ende
void start()
{
delay(250);
lcd.clear();
lcd.print("zum Messen");
lcd.setCursor(0,1);
lcd.print("Select druecken");
do {taste();} while (sel>800 || sel<700);//warten bis die Taste Select gedrückt wird
delay(150);
}
void printSD()
{
//Ausgabe auf die SD Karte (alle 10 sek.)
DateTime now = RTC.now();
dataFile = SD.open(dateiname, FILE_WRITE);
dataFile.print(now.hour()); dataFile.print(":");
if (now.minute()<10) {dataFile.print("0");}
dataFile.print(now.minute()); dataFile.print(":");
if (now.second()<10) {dataFile.print("0");}
dataFile.print(now.second());
dataFile.print(",");
dataFile.print(u1);// schreibt den Messwert auf die SD Karte
dataFile.print (",");// schreibt hinter den Messwert ein Komma
dataFile.print(u2);
dataFile.print (",");
dataFile.print(I1,2);
dataFile.print(",");
dataFile.print(I2,2);
dataFile.print(",");
dataFile.print(C1,1);
dataFile.print(",");
dataFile.println(C2,1);
dataFile.close();
//Ausgabe auf den seriellen Monitor (alle 10 sek.)
Serial.print(now.hour()); Serial.print(":");
if (now.minute()<10) {Serial.print("0");}
Serial.print(now.minute()); Serial.print(":");
if (now.second()<10) {Serial.print("0");}
Serial.print(now.second());
Serial.print(",");
Serial.print (u1 , 6); //schreibt den Messwert mit 6 Nachkommastellen auf den seriellen Monitor
Serial.print (", ");
Serial.print (u2 , 6) ;//schreibt den Messwert mit 6 Nachkommastellen auf den seriellen Monitor
Serial.print (", ");
Serial.print (I1,6);
Serial.print (", ");
Serial.print (I2,6);
Serial.print (", ");
Serial.print (C1);
Serial.print (", ");
Serial.println (C2);
millis10=millis();
}
void printlcdU()
{
lcd.clear();
lcd.home();
lcd.print("U1") ;
lcd.print("=");
lcd.print(u1); // zeigt den Messwert;
lcd.print(" V ");// zeigt hinter dem Messwert V;
lcd.setCursor(0, 1);
lcd.print("U2") ;
lcd.print("=");
lcd.print(u2); // zeigt den Messwert;
lcd.print(" V ");// zeigt hinter dem Messwert V;
}
void printlcdI()
{
lcd.clear(); // löscht das LCD
lcd.home();
lcd.print("I1=");
lcd.print(I1,2);
lcd.print(" A");
lcd.setCursor(0, 1);
lcd.print("I2=");
lcd.print(I2,2);
lcd.print(" A");
}
void printlcdC()
{
lcd.clear(); // löscht das LCD
lcd.setCursor(0, 0);
lcd.print("C1=");
lcd.print(C1,1);
lcd.print(" mAh");
lcd.setCursor(0, 1);
lcd.print("C2=");
lcd.print(C2,1);
lcd.print(" mAh");
}