08 | 06 Das Batterie-Alarm-System

 

So, nun wird es interessant. Wir werden ein Batterie-Alarm-System umsetzen. Zunächst brauchen wir einige Überlegungen, wie die Stufen eines Alarms aussehen können. Natürlich kannst du später dein eigenes Alarm-System entwickeln und dir coole Feedbacks ausdenken. An dieser Stelle bestimmen wir drei Stufen:

1. Stufe: Alles in Ordnung / Es ist genug Akkukapazität vorhanden

2. Stufe: Vorsicht / Die Energie neigt sich dem Ende zu.

3. Stufe: Gefahr / Der RoverBB kann jederzeit ausfallen.

 

Die Schwellwerte

Aus den oben aufgezählten Alarmstufen stellt sich jetzt die Frage nach den jeweiligen Schwellwerten. Betrachten wir dazu eine einzelne NiMH-Zelle: Die Spannung einer NiMH-Batterie beträgt bei voller Ladung bis zu 1,4Volt, ###1,25Volt bei 50% Ladung und 1,0 Volt bei fast vollständiger Entladung.

Die Spannungsdifferenz von 0,4Volt stellt die Basis der Schwellenwerte dar. Ich möchte betonen, dass wir hier eine sehr einfache und nicht unbedingt genaue Kapazitätsmessung vornehmen. Aber es geht mehr um das dahinter steckende Konzept.

Für die 1. Stufe definiere ich 40% aufwärts der Spannungsdifferenz.

Die 2. Stufe zwischen 40% und 20% der Spannungsdifferenz.

Die 3. Stufe unter 20% der Spannungsdifferenz.

Addieren wir die jeweiligen Prozentwerte auf die 1,0 Entladeschlussspannung so ergibt das:

Stufe 1: 0,4V * 0,4 = 0,16V => 1,0 + 0,16 = >1,16Volt

 

Stufe 2: 0,4V * 0,2 = 0,08V => Obere Grenze: 1,0 + 0,16 = <1,16Volt

Untere Grenze: 1,0 + 0,08 = >1,08Volt

 

Stufe 3: 0,4V * 0,2 = 0,08V => 1,0 + 0,08 = <1,08Volt

Wie du sehen kannst, sind dies sehr knappe Toleranzen. Das bedeutet, dass schon eine kleine Stromschwankung (Motoren!) kurzfristig den Alarm auslöst und wieder in den „grünen“ Bereich springt. Dem kann man mit verschiedenen Strategien entgegenwirken. In einem späteren Kapitel verwenden wir einen internen timer, um dieses Problem zu lösen.

Übergangsweise werden wir an dieser Stelle einen einfachen Ansatz verfolgen, dass den beschriebenen Effekt zumindest etwas abschwächt. Wir platzieren Toleranzlücken von 0,1. D.h. wir schmälern Stufe 2 etwas. Das sind Bereiche, in denen sich die Werte aufhalten, ohne eine Änderung zu verursachen. Dadurch wird das Flimmern zwischen zwei Alarmstufen etwas abgemildert.

Es ist auch hilfreich, dass wir es mit vier NiMH-Zellen zu tun haben, da die Toleranzbereiche sich etwas ausweiten und wir mehr Luft bekommen. Hier die Skalierungswerte der vier Zellen:

1. Stufe: 1,16Volt * 4 => >4,64Volt

 

2. Stufe: 1,16Volt * 4 => Obere Grenze: <4,64Volt

1,08Volt * 4 = > Untere Grenze: >4,24Volt

 

3. Stufe: 1,08Volt * 4 = > >4,24Volt

Die endgültigen Werte mit Toleranzlücken:

###bild

2. <4,5 und >4,1

 

 

Alarm-Feedback

Als letzten Schritt brauchen wir für jede Alarm-Stufe ein Feedback. Hier gibt es eine Vielzahl an Möglichkeiten. Ich verwende ein visuelles und auditives Signal. Für Stufe 1 setzen wir eine durchgehend grün leuchtende LED ein. Für Stufe 2 ist es eine rote durchgehend leuchtende LED. Für die letzte Eskalationsstufe lassen wir die rote LED blinken und geben gleichzeitig einen Warnton aus.


Der Sketch

Die Programmstruktur gleicht sich dem Sketch aus dem letzten Kapitel. Zusätzlich sind die Alarm-Stufen hinzugekommen.

//RGB LED-------------------------------------
const int rgbRedPin = 5;
const int rgbGreenPin = 4;
const int batteryPin = A2;
const int piezoPin = 6;

const float referenceVolts = 5.0; //Standard-Referenzspannung 5V

const float R1 = 1000; // Wert für max. Spannung von 10 Volt 
const float R2 = 1000;

// Wird durch Spannungsteiler-Widersta ̈nde bestimmt
const float resistorFactor = 105.0 / (R2/(R1 + R2));


void setup() 
{
  Serial.begin(9600); 
  
  //RGB LED-------------------------------
  pinMode(rgbRedPin, OUTPUT);
  pinMode(rgbGreenPin, OUTPUT);
}


void loop() 
{
  // +V der Battere ist mit Analogpin 0 verbunden
  int val = analogRead(batteryPin); // Wert vom Sensor einlesen

  // Verh ̈altnis berechnen 
  float volts = (val / resistorFactor) * referenceVolts ; 

  volts = 3.7; //Diese Zeile ist hier zuviel und dient nur Testzwecken.
               //die Variable volts wird hier überschrieben.
  Serial.println(volts); // Wert in Volt ausgeben


  if(volts >= 5.2) //grüner bereich
  {
    digitalWrite(rgbRedPin,0);
    analogWrite(rgbGreenPin,10);
  }//if

  else if(volts < 4.8 && volts > 3.8)
  {
    digitalWrite(rgbGreenPin,0);
    digitalWrite(rgbRedPin,255);
  } //else
  
  else if(volts <=4.0) //rot
  {
    digitalWrite(rgbRedPin,0);
   for(int i=0; i<4; i++)
    { 
      tone(piezoPin, 100);

      analogWrite(rgbRedPin,255);
      delay(100);    
      noTone(piezoPin);
      digitalWrite(rgbRedPin,0);
      delay(100);
    } //for
  } //else
} //void

Wie du sehen kannst, definieren wir die Variable volts:

float volts = (val / resistorFactor) * referenceVolts; 

und überschreiben sie direkt in der nächsten Zeile mit:

volts = 3.7; //Diese Zeile ist hier zuviel und dient nur Testzwecken.
             //die Variable volts wird hier überschrieben.

Das ist natürlich völlig unsinnig. Aber wir brauchen sie für Testzwecke. Es wäre noch unsinniger die Akkus voll aufzuladen, sie an unseren Batterie-Checker anzuschließen und ewig zuwarten bis sie sich selbst entlädt, um alle Alarm-Stufen zu testen. Indem wir die Variable volts mit hardgecodeten Werten überschreiben, können wir bequem alle Alarm-Szenarien testen. Am Ende muss diese Zeile aber herausgelöscht werden!

Alle drei Stufen verpacken wir in if-else-Abfragen und platzieren das entsprechende Feedback darin. In der ersten Stufe (Alles in Ordnung) schalten wir die grüne LED durchgehend ein, solange volts einen Wert größer/gleich 4,64 hat. Wie du sehen kannst, benutze ich statt digitalWrite() den analogWrite()-Befehl. Das hat den Grund, dass mir persönlich die Helligkeit der grünen LED viel zu intensiv leuchtet. Mit dem zweiten Argument in analogWrite() kann ich die Helligkeit kontrollieren. Je höher der Wert (max. 256), umso heller. Der Wert 10 scheint mir in Räumlichkeiten gut zu passen. Bei praller Sonne ist der Wert 10, dann doch schlechter zu erkennen. Experimentiere für dich, welcher Wert für dich passender ist. In einem zukünftigen Projekt könntest du einen Lichtsensor einsetzen und die Helligkeit vom Tageslicht abhängig machen.

if(volts >= 4.64) //grüner bereich
{
  digitalWrite(rgbRedPin,0);
  analogWrite(rgbGreenPin,10);
}

In der zweite Stufe (Vorsicht!) ziehen wir mit der UND-Funktion einen Wertebereich zwischen 4,5 und 4,1 auf. Fällt volts innerhalb diesen Bereichs wird die grüne LED ausgeschaltet und die rote dafür eingeschaltet.

else if(volts < 4.5 && volts > 4.1)
  {
    digitalWrite(rgbGreenPin,0);
    digitalWrite(rgbRedPin,255);
  } //else

In der dritten Stufe (Gefahr!) tut sich schon etwas mehr. Um die “Dramatik“ zu steigern kombinieren wir Licht und Sound. In der for-Schleife wird ein tiefer Ton erzeugt, der #####.

else if(volts <=4.0) //rot
{
  digitalWrite(rgbRedPin,0);
  
  for(int i=0; i<4; i++)
  { 
    tone(piezoPin, 100);

    analogWrite(rgbRedPin,255);
    delay(100);    
    noTone(piezoPin);
    digitalWrite(rgbRedPin,0);
    delay(100);
}