mehrere Relais schalten

Hallo,
ich habe mal wieder Probleme mit einem Sketch, der nicht das macht was ich möchte...

Folgende Situation: Ich habe ein paar LTO Akkus (Enzellzellen) mit welchen ich ein paar Versuche bezüglich der Kapazität usw machen möchte.
Da es keine fertige Schaltung gibt die so flexibel ist wie ich es gerne möchte, wollte ich das mit einem Arduino und dem passenden Sketch machen.

Der Sketch soll eigentlich nichts anderes machen, als bei jeder Zelle die Spannung messen und, so fern die jeweilige Spannung erreicht ist ein Relais schalten.

Die Verwendete Hartware sind ein Nano (Clone) und eine 8er Relaiskarte. Die Stromversorgung des Arduino erfolgt über eine Festspannungsregelung, die Referenzspannung ist also OK.

Im Versuchsaufbau wird jede Zelle für sich (aus einer eigenen Stromquelle) geladen, es soll deshalb auch jede Zelle für sich geschaltet werden. Um die Tiefentladung einer Zelle zu vermeiden, soll beim erreichen der Minimalspannung die komplette Last von der Batterie genommen werden.

Hier der Sketch mit dem ich das erreichen möchte:

/*
Experimentelle Laderegelung für "12V" LTO Akkus.
Die Regelung misst jede Zelle einzeln und schaltet den Ladestrom bei Erreichen der Ladeschlussspannung ab. 
Es wird jede Zelle separat geladen, weshalb auch die Zellenspannung separat gemessen und der Ladestrom 
für jede Zelle separat geschalten wird. 


*/

const byte voltin1 = A1; // input Pin für Spannung Zelle 1
const byte voltin2 = A2; // input Pin für Spannung Zelle 2
const byte voltin3 = A3; // input Pin für Spannung Zelle 3
const byte voltin4 = A4; // input Pin für Spannung Zelle 4
const byte voltin5 = A5; // input Pin für Spannung Zelle 5
const byte voltin6 = A6; // input Pin für Spannung Zelle 6

//const byte voltinall = A7; // input Pin für Spannung ganze Batterie

const int lssp = 512; // digitalwert für Ladeschlussspannung 
const int lwasp = 480; // digitalwert für wiederaufnahme des Ladevorgangs
const int cutoffsp = 390; // digitalwert für Unterspannungs Abschaltung

int voltzelle1 = 400; // Startwerte setzen 
int voltzelle2 = 400; 
int voltzelle3 = 400; 
int voltzelle4 = 400; 
int voltzelle5 = 400; 
int voltzelle6 = 400; 




void setup() {
  digitalWrite(2, HIGH);
  pinMode(2, OUTPUT);
  digitalWrite(3, HIGH);  
  pinMode(3, OUTPUT);
  digitalWrite(4, HIGH);
  pinMode(4, OUTPUT);
  digitalWrite(5, HIGH);
  pinMode(5, OUTPUT);
  digitalWrite(6, HIGH);
  pinMode(6, OUTPUT);
  digitalWrite(7, HIGH);
  pinMode(7, OUTPUT); 

  digitalWrite(10, HIGH);
  pinMode(10, OUTPUT); 

  
}



void loop() {

voltzelle1 = analogRead(voltin1); //Spannungs an A 1 auslesen

if (voltzelle1 >= lssp) digitalWrite(2, HIGH); //Schaltet bei Ladeschlussspannung den Ladestrom ab
if (voltzelle1 <= lwasp) digitalWrite(2, LOW); //Schaltet bei Wiederaufnahmespannung den Ladestrom an.
if (voltzelle1 >= cutoffsp) digitalWrite(10, HIGH); //Nimmt bei Unterspannung einer Zelle die Last von der Batterie.

voltzelle2 = analogRead(voltin2); //Spannungs an A 2 auslesen

if (voltzelle2 >= lssp) digitalWrite(3, HIGH); //Schaltet bei Ladeschlussspannung den Ladestrom ab
if (voltzelle2 <= lwasp) digitalWrite(3, LOW); //Schaltet bei Wiederaufnahmespannung den Ladestrom an.
if (voltzelle2 >= cutoffsp) digitalWrite(10, HIGH); //Nimmt bei Unterspannung einer Zelle die Last von der Batterie.

voltzelle3 = analogRead(voltin3); //Spannungs an A 3 auslesen

if (voltzelle3 >= lssp) digitalWrite(4, HIGH); //Schaltet bei Ladeschlussspannung den Ladestrom ab
if (voltzelle3 <= lwasp) digitalWrite(4, LOW); //Schaltet bei Wiederaufnahmespannung den Ladestrom an.
if (voltzelle3 >= cutoffsp) digitalWrite(10, HIGH); //Nimmt bei Unterspannung einer Zelle die Last von der Batterie.

voltzelle4 = analogRead(voltin4); //Spannungs an A 4 auslesen

if (voltzelle4 >= lssp) digitalWrite(5, HIGH); //Schaltet bei Ladeschlussspannung den Ladestrom ab
if (voltzelle4 <= lwasp) digitalWrite(5, LOW); //Schaltet bei Wiederaufnahmespannung den Ladestrom an.
if (voltzelle4 >= cutoffsp) digitalWrite(10, HIGH); //Nimmt bei Unterspannung einer Zelle die Last von der Batterie.

voltzelle5 = analogRead(voltin5); //Spannungs an A 5 auslesen

if (voltzelle5 >= lssp) digitalWrite(6, HIGH); //Schaltet bei Ladeschlussspannung den Ladestrom ab
if (voltzelle5 <= lwasp) digitalWrite(6, LOW); //Schaltet bei Wiederaufnahmespannung den Ladestrom an.
if (voltzelle5 >= cutoffsp) digitalWrite(10, HIGH); //Nimmt bei Unterspannung einer Zelle die Last von der Batterie.

voltzelle6 = analogRead(voltin6); //Spannungs an A 6 auslesen

if (voltzelle6 >= lssp) digitalWrite(7, HIGH); //Schaltet bei Ladeschlussspannung den Ladestrom ab
if (voltzelle6 <= lwasp) digitalWrite(7, LOW); //Schaltet bei Wiederaufnahmespannung den Ladestrom an.
if (voltzelle6 >= cutoffsp) digitalWrite(10, HIGH); //Nimmt bei Unterspannung einer Zelle die Last von der Batterie.

}

Das Messen an sich scheint zu funktionieren, denn die Relaiskarte reagiert auf entsprechende Spannungsänderungen.
Allerdings wirden die Relais nicht einzeln geschaltet, sondern immer "on block".
D.h. wenn ich die Spannung an einem Eingang ändere ziehen die Ralais 1-6 gemeinsm an (oder fallen gemeinsam ab). Relais 8 (welches am A10 hängt) reagiert dagegen überhaupt nicht.

Ich bin recht überzeugt davon, dass meine "if Abfrage" und die daraus resultierenden Befehle nicht richtig sind... aber was falsch ist kann ich nicht erkennen...

was falsch ist kann ich nicht erkennen...

Ich auch nicht.

Verdrahtungsproblem? Zieh mal die Relaiskarte ab und schau dir die Ausgangspins direkt am Nano an.
Oder mach einen Test-Sketch, der definitiv einen Pin nach dem anderen schaltet.

Ich kann nirgendwo ein digitalWrite(10, LOW); entdecken.

Das erklärt aber nur einen Teil des Problems

Relais 8 (welches am A10 hängt) reagiert dagegen überhaupt nicht.

Bleibt die Frage, warum die anderen Relais gemeinsam reagieren...

Hallo,

Ich denke diejeweils 3. If Abfrage ist falsch , da ist immer pin 10 angegeben ? sollte abe sicher jeweils 2, 3, 4 usw sein

voltzelle1 = analogRead(voltin1); //Spannungs an A 1 auslesen

if (voltzelle1 >= lssp) digitalWrite(2, HIGH); //Schaltet bei Ladeschlussspannung den Ladestrom ab
if (voltzelle1 <= lwasp) digitalWrite(2, LOW); //Schaltet bei Wiederaufnahmespannung den Ladestrom an.
if (voltzelle1 >= cutoffsp) digitalWrite(10, HIGH); //Nimmt bei Unterspannung einer Zelle die Last von der Batterie.

Heinz

Die Relais sind wohl LOW aktiv
Ich verstehe das so, dass Pin 10 eine Art Not-Aus darstellen soll, wenn Zellen nicht geladen werden und bei einer der Zellen Tiefentladung droht.

Rücksetzen ist zur Zeit nur mit Reset vorgesehen.

in setup() würde dazu passen

  digitalWrite(10, LOW);  // Verbraucher aktiv
  pinMode(10, OUTPUT);

Die anderen beiden if je Analog-Kanal schalten dann mit Hysterese zwischen lssp und lwasp

Sind die Spannungen der Zellen denn überhaupt unterschiedlich, oder sind diese über den Verbraucher parallel geschaltet und alle Analog-Eingänge messen das gleiche?

Hi und Danke für die schnellen Antworten.

Wenn ich die Relaiskarte abziehe und an den Pins direkt messe habe ich genau das Gleiche. So bald ich einen zu messenden Akku anschließe wechseln die Ausgänge 2 - 7 den Status.

jep, im Setup müsste das LOW heissen...

In der 3 if Abfrage soll schon jeweils das gleiche Relais angesteuert werden.
Pin 10 steuert (soll) ein Relais steuern das den 12V Kreis abstellt, - egal welch Zelle zu wenig Spannung hat. Die Messungen über die Analogeingänge sind aber jeweils an einer einzelnen Zelle.
Wegen der gemeinsamen GND Verbindung (die zum Akku aber mt Diode gesperrt ist) habe ich auch mit nur einen Akku probiert, - genau das Gleiche...

Edit nach Michals 2. Post
ja genau so stelle ich mir das vor.
Die Zellen sind aber nicht parallel sindern in Reihe gescchalten damit ein 12V Block daraus wird.
Hauptziel ist es festzustellen wie viel die einzelnen Zellen von einander Abweichen.

herbk:
Die Zellen sind aber nicht parallel sindern in Reihe gescchalten ...

Und dann mißt Du mit dem Arduino gegen GND? Das kann ich mir gerade nicht vorstellen, da wäre ein Schaltbild (Bleistift und Papier genügt) für mich notwendig.

Alle Zellen sind in Reihe geschaltet. Also misst der A1 die 1. Zelle, A2 die 1. und 2. Zelle, A3 die 1., 2. und 3. Zelle oder wie?

Gibt es eventuell einen Schaltplan?

Gruß, Jürgen

Also misst der A1 die 1. Zelle, A2 die 1. und 2. Zelle, A3 die 1., 2. und 3. Zelle oder wie?

Der Arduino ADC misst in jedem Fall eine Spannung relativ zu Arduino-GND.
Alle analogRead-Kanäle brauchen einen gemeinsamen GND.
Mehr als Vcc kann man nicht direkt messen.

Ich nenne solche Programme immer "Bandwurm-Codes".

Mach' doch bitte eigene Funktionen mit "sprechenden Namen". Beginne mit Low-Level (z.B. 1 Rel an/aus) und erhöhe durch Zusammenfassen der getesteten (!) Trivial-Funktionen den Abstraktionsgrad stufenweise.

Im Hauptprogramm - respektive "Loop" stehen dann nur noch einige wenige Aufrufe wie "Messen", "Anzeigen" und "Schalten" usw...

Auch Mikrocontroller sind leistungsfähig genug für einen solchen modularen Programmierstil und du guckst, wenn du in einen Jahr den Code nochmal ändern musst, nicht wie ein "Schwein ins Uhrwerk" :slight_smile:

Hallo.

Jetzt hab ich's auch begriffen was der eine Ausgang machen soll :slight_smile:

Jetzt kannst du noch vor jeden Analogeingang einen Spannungsteiler bauen 1:3 sagen wir mal und Dan die gemessen Spannung voneinander abziehen . Dann ist alles auf Ground bezogen und durch 3 geteilt. Damit ist dann die größte gemessen Spannung bei 12 V am Akku 4Vam Analogeingang, ob dann die Auflösung noch reicht musst du selbst entscheiden .

Also
U1= Messwert 1
U2 = Messwert 2 - Messwert 1
U3= Messwert 3- Messwert 2

Usw

PS mit dem Handy ist das Mist :slight_smile:

Auch Mikrocontroller sind leistungsfähig genug für einen solchen modularen Programmierstil

Ich denke, das wäre sogar ressourcenschonender und damit gerade für einen kleinen µC einfacher.

Andererseits habe ich bewundert, wie ordentlich herbk nach dem c&p alle Variablennamen, Konstanten und sogar Kommentare editiert hat. Das wäre ja alles umsonst gewesen :frowning: :stuck_out_tongue:

@qualidat ja, das wäre schöner... aber so verstehe ich wenigstens halbwegs was ich da schreibe...
Platzmangel ist auf dem Nano aber noch keiner.

So ist die Schaltung aufgebaut, ohne Ladeanschlüsse, sind auch noch nicht dran im Moment

Hi

Wie schon geschrieben wurde, kann der Arduino nur bis Vdd messen - oberhalb dürften diverse Schutz-Dioden bei dem Versuch sterben, die höhere Spannung nach Vdd abzuleiten.

Selbst, wenn jede Deiner Zellen nur 1,0V voll geladen bringt, bist Du bei Zelle 6 bei 6.0V - ungefähr 1V mehr, als der Arduino 'ab kann'.

Dürfte auch erklären, warum 'Alles am Stück' schaltet - Dein Messpunkt für Zelle 2 sieht die Spannung Zelle 1 + Zelle 2 und ist damit WEIT oberhalb des erlaubten Bereich.

Zelle 3 braucht gar keine eigene Spannung, auch hier bist Du 'so oder so' weit außerhalb - Relais schaltet auch.
... für alle Weiteren.

Du könntest die tatsächliche Spannung runter teilen, musst dann aber mit den berechneten Teil-Spannungen das Minus-Potential der höheren Zellen bestimmen - denke, Da kommen nur Hausnummern bei rum.

MfG

Dein Messpunkt für Zelle 2 sieht die Spannung Zelle 1 + Zelle 2

Du hast recht, das Problem ist der gemeinsamme GND...

Es geht schon, aber eben so wie oben beschrieben.

Rentner:
Jetzt kannst du noch vor jeden Analogeingang einen Spannungsteiler bauen 1:3 sagen wir mal und Dan die gemessen Spannung voneinander abziehen . Dann ist alles auf Ground bezogen und durch 3 geteilt. Damit ist dann die größte gemessen Spannung bei 12 V am Akku 4Vam Analogeingang, ob dann die Auflösung noch reicht musst du selbst entscheiden .
Also
U1= Messwert 1
U2 = Messwert 2 - Messwert 1
U3= Messwert 3- Messwert 2
Usw

Bei einem Teiler von 14,7kOhm und 4,75kOhm ergeben sich rund 0,02V Auflösung wenn ich richtig gerechnet habe.
Beispiel:

Maximale Spannung pro Zelle scheinbar rund 2,8V also gesamt 16,8V. Spannungsteiler bringt bei 20V am Eingang 4,884V am Analogpin. Bei 5V ergibt der AD-Wandler 1023 und bei 4,884V 999. Theoretische Auflösung 0,02002...V. Weicht natürlich wegen der Toleranz der Widerstände auch ab.

Gruß, Jürgen

Hi Jürgen,
danke, wie das gemeint war hatte ich schon verstanden. Ich habe bei dieser Messweise aber ein wenig "Bammel" vor den Abweichungen. Die theoretischen 0,02V Genauigkeit sind nicht das Problem...
Wenn für das Ganze die Spannungsteiler aus Messwiederständen baue, für jeden Messkreis den genauen Digitalwert der Schaltspannungen getrennt ermittle und wenn nötig im Sketch "mappe" sollte es aber genau genug werden...?

Oder für jede Zelle einen separaten Arduino... :wink:

Wenn ich den 4,7K Widerstand durch einen 5K Spindeltrimmer ersetze um die Spannungsteiler zu justieren...?

Hallo,

Spindeltrimmer kannst Du auch nehmen ist aber eigendlich nicht nötig. Wenn Du zum abgleich eine einzelne Zelle nimmst, und die nacheinander an die an den Teiler anschliesst kannst Du doch die Skalierung auch durch einen Softwarefaktor festlegen der für jeden Analogeingang /bzw Teiler unterschiedlich sein kann ist.

es geht ja nur darum das bei gleicher Eingangsspannung die gleichen Messwerte entstehen. Also mußt Du dann irgendwo mal mit 1,000 oder 1,002 oder 0,995 multiplizieren. Der Erste Eingang hat dann 1.000 und dient so als Refferenz für die Anderen. Mit Dem Spindelpoti würdest Du es ja letztlich ebenso machen.

Heinz

Hallo,
ich habe die Spannungsteiler jetzt mit 1% Toleranz WIderständen und Spindeltrimmer aufgebaut. Funktioniert, ich kann die Spannung am Ausgang des Spannungsteilers sauber einstellen.

Allerdings habe ich für den Spannungsteiler 18k und 5,6k Widerstände verwendet. Das scheinen aber zu hohe Werte zu sein, der Arduino schaltet nicht wenn sich die Spannung am Eingang über die Schaltschwellen bewegt.
Kann das sein, dass da dann einfach der Strom zu niedrig wird?

Am Sketch liegt es sicher nicht, denn wenn ich mit dem Labornetzteil die Spannung direkt auf die Analogeingänge gebe schalten die Relais wie gewollt.