Mein erstes Projekt - Wohnwagen Bordcomputer

Moin moin,

so ich bin Andreas mein Spitzname ist Fini daher auch der Username bin 40 Jahre Jung und erste sein kurzem mit dem Arduino Vertraut.

Wie ich zu meinem ersten Arduino Projekt kam? Batterie Ladestands Anzeigen im Caravaning Bereich sind nicht Billig und ich hatte den Arduino noch herumliegen.

Da ich mich mit C nicht so gut auskenne, würde ich mich über Vorschläge zu Code-Optimierung freuen.

Hier jetzt zum Projekt:

Ich wollte eine einfache Spannungs-/Ladestand Anzeige für meinen Wohnwagen bauen. Auf Tasten Druck werden für ca. 5 sek die aktuellen Volt und der Ladestand in Prozent angezeigt. Weitere Aufgaben wie Anzeige der innen und Aussen Temperatur sollen folgen.
hier jetzt mein Sketch:

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
float mess1 = 1;
int switchPin = 8;
int ledPin = 13;
int count = 0;
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = true;

void setup() {
  analogReference(INTERNAL);
 Serial.begin(9600);
  lcd.begin(16, 2);
  lcd.setCursor(1,0);
  lcd.print("WoWa-Batterie");
  lcd.setCursor(1,1);
  lcd.print("Version 0.0.3a");
  delay(4000);
  for (int positionCounter = 0; positionCounter < 15; positionCounter++) {
    // scroll one position left:
    lcd.scrollDisplayLeft(); 
    // wait a bit:
    delay(150);
  }
  lcd.clear();
}

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current= digitalRead(switchPin);
  }
  return current;
}

void loop() {
  int a1 = analogRead(mess1);
  Serial.println(a1);
  float Volt = map(a1, 0,1024,0,1460)/100.00;
  Serial.println(Volt);
  lcd.setCursor(0, 0);
  lcd.print("Akt. Volt:");
  lcd.setCursor(11,0);
  lcd.print(Volt);
  lcd.setCursor(0,1);
  lcd.print("Ladung:");
  int perc = constrain(a1, 827, 897);
  int Prozent = map(perc, 827, 912, 0 , 100);
  if (Prozent < 100) {
    lcd.setCursor(13,1);
  } else {
    lcd.setCursor(12,1);
  }
  lcd.print(Prozent);
  lcd.setCursor(15,1);
  lcd.print("%");
  //delay(500);
  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    ledOn = !ledOn;
    lcd.display();
    count = 0;
  }
  else if (lastButton == LOW && count == 50)
  {
    lcd.noDisplay();
    ledOn = LOW;
    count = 0;
  }
  count++;
  Serial.println(count);
  lastButton = currentButton;
  digitalWrite(ledPin,ledOn);
  delay(100);
}

So ich freue mich auf eure Kommentare und Verbesserungsvorschläge.

Gruß Fini

Der Ladestand der Batterie hat recht wenig mit der Voltzahl zu tun, diese ist nämlich bis zu einem bestimmten Punkt recht konstant. Soll heißen, dass eine halb entleerte Batterie nicht 6, sondern nach wie vor 12V haben wird. Der reale Ladestand richtet sich danach, wieviel Kapazität die Batterie hat und wieviel Ladung ihr über die Zeit genommen wurde.

Hi,

jetzt bin ich grad verwirrt.

Die Meisten Ladestandsanzeige in Wohnwagen /Wohnmobilen Zeigen nur die Spannung an zwichen 12,8 und 11,8 Volt sind die LED Grün da drüber bzw da drunter rot. Auch Laut Wikipedia kann man von der Spannung auf den Ladezustand schliessen.

Klemmspannung 	Ungefährer Ladezustand
12,65 V 	                100 %
12,45 V 	                 75 %
12,24 V 	                 50 %
12,06 V 	                 25 %
11,89 V 	                   0 %

Kann mich jemand aufklären?

Gruß Fini

Ist für dieses Anwendungsgebiet wohl auch vollkommen ausreichend denke ich. sth77 wollte wohl nur darauf hinweisen das die Spannung nicht exakt und linear den Ladungszustand wiedergibt.
lg DrSeus

Bei Bleiakkus kann man durch die Leerlaufspannung auf den Ladezustand schließen. Wenn Dir die Anzeige voll, 3/4, halb, 1/4 und leer genügt ist es sicher ein weg. Falls Du Prozentangaben willst die auf 5% genu sind dann brauchst Du eine Lade/Entlade-Strommessung mit Controlle der Akkutemperatur und rechnerische Korrektur der Kapazität, da diese von der Größe des Stromes abhängt. Die Angaben der Nennkapazität beziehen sich auf einen Entladestrom von einem 20/der Nennkapazität ( 60Ah -> 3A).
Grüße Uwe

Hi,

es soll ja kein Messgerät werden. Ich möchte nur wissen ob die Batterie voll oder doch schon fast leer ist. Das mit der Prozent Anzeige ist mehr als spielerei zu sehen.

Ich frage mich ob ich den Code noch Optimieren kann, z.b: das abfragen der Spannung in eine eigene Funktion.

Gruß Fini

Moin moin,

das mit Batterie Anzeigt funktioniert so weit ja schon ganz gut. Ich habe nur das Problem das sich die Anzeige der Spannung und der Prozent nun dauernd ändern und so das LCD etwas hektisch wirkt. Zur ist es so das wenn ich den Button drücke ich einen Anzeige für ca. 20 Sek bekomme. Nun möchte ich das so lösen das sich Spannung und Prozent alle 5 Sek in diesem 20 Sek aktualisieren.

Wie kann ich das am besten schreiben? Meine versuche die Spannungsmessung in eine eigene Funktion zu legen und dort mit einem delay zu arbeiten waren nicht die lösung.

Hier noch mal das Sketch:

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
float mess1 = 5;
int switchPin = 8;
int ledPin = 13;
int count = 0;
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = true;

void setup() {
  analogReference(INTERNAL);
  Serial.begin(9600);
  digitalWrite(ledPin,ledOn);
  lcd.begin(16, 2);
  lcd.setCursor(1,0);
  lcd.print("WoWa-Batterie");
  lcd.setCursor(1,1);
  lcd.print("Version 0.0.4a");
  delay(4000);
  for (int positionCounter = 0; positionCounter < 15; positionCounter++) {
    // scroll one position left:
    lcd.scrollDisplayLeft(); 
    // wait a bit:
    delay(150);
  }
  lcd.clear();
}

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current= digitalRead(switchPin);
  }
  return current;
}

void loop() {
  int a1 = analogRead(mess1);
  float Volt = map(a1, 0,1024,0,1460)/100.00;
  lcd.setCursor(0, 0);
  lcd.print("Akt. Volt:");
  lcd.setCursor(11,0);
  lcd.print(Volt);
  lcd.setCursor(0,1);
  lcd.print("Ladung:");
  int perc = constrain(a1, 827, 897);
  int Prozent = map(perc, 827, 912, 0 , 100);
  if (Prozent < 100) {
    lcd.setCursor(13,1);
  } else {
    lcd.setCursor(12,1);
  }
  lcd.print(Prozent);
  lcd.setCursor(15,1);
  lcd.print("%");
  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    ledOn = !ledOn;
    lcd.display();
    count = 0;
  }
  else if (lastButton == LOW && count == 5000)
  {
    lcd.noDisplay();
    ledOn = LOW;
    count = 0;
  }
  count++;
  lastButton = currentButton;
  digitalWrite(ledPin,ledOn);
}

Ich freue mich auf eure Antworten.

Gruß Fini

Ein Delay ist immer ganz böse. :wink: Besser ist es in den meuisten Fällen, die verstrichene Zeit zu beobachten. Schau dir dazu mal das Beispiel vom Sketch “Blink without delay” an, da sieht man die prinzipielle Vorgehensweise.

Hi sth77,

Danke für deine Antwort.

Das mit dem delay hab ich auch gemerkt ;). Die Idee das über millis() zu lösen kam mir vor 10 Minuten nach dem ich das von dir erwähnte Tutorial gelesen hatte.

So bin ich erstmal zufrieden XD Jetzt will ich das mal in ein kleines Gehäuse packen und am Wochenende im Wohnwagen testen.

Weitere Ideen sind das er ab ca 50% anfängt alle 5 Sekunden und ab ca. 25% jede Sekunde Blinkt.

Hier das angepasste Sketch:

// include the library code:
#include <LiquidCrystal.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
float mess1 = 5;
int switchPin = 8;
int ledPin = 13;
int startsek = 0;
boolean lastButton = LOW;
boolean currentButton = LOW;
boolean ledOn = true;
long previousMillis = 0;
long interval = 2000;


void setup() {
  analogReference(INTERNAL);
  Serial.begin(9600);
  digitalWrite(ledPin,ledOn);
  lcd.begin(16, 2);
  lcd.setCursor(1,0);
  lcd.print("WoWa-Batterie");
  lcd.setCursor(1,1);
  lcd.print("Version 0.0.5a");
  delay(4000);
  for (int positionCounter = 0; positionCounter < 15; positionCounter++) {
    // scroll one position left:
    lcd.scrollDisplayLeft(); 
    // wait a bit:
    delay(150);
  }
  lcd.clear();
  previousMillis = millis();
}

boolean debounce(boolean last)
{
  boolean current = digitalRead(switchPin);
  if (last != current)
  {
    delay(5);
    current= digitalRead(switchPin);
  }
  return current;
}
void lcdOutput(float Volt, int Prozent){
  lcd.clear();
  char zeige[5];
  dtostrf(Volt,4,2,zeige);
  lcd.setCursor(0, 0);
  lcd.print("Akt. Volt:");
  lcd.setCursor(11,0);
  lcd.print(zeige);
  lcd.setCursor(0,1);
  lcd.print("Ladung:");
  if (Prozent < 100) {
    lcd.setCursor(13,1);
  } else {
    lcd.setCursor(12,1);
  }
  lcd.print(Prozent);
  lcd.setCursor(15,1);
  lcd.print("%");
}

void loop() {
  
  int a1 = analogRead(mess1);
  float Volt = map(a1, 0,1024,0,1460)/100.00;


  int perc = constrain(a1, 828, 898);
  int Prozent = map(perc, 828, 898, 0 , 100);
  unsigned long currentMillis = millis();
  if(currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    lcdOutput(Volt,Prozent);
  }
  currentButton = debounce(lastButton);
  if (lastButton == LOW && currentButton == HIGH)
  {
    ledOn = HIGH;
    lcd.display();
    startsek = millis()/1000;
  }
  else if (lastButton == LOW && millis()/1000 == startsek+20)
  {
    lcd.noDisplay();
    ledOn = LOW;
    startsek = millis()/1000;
  }
  lastButton = currentButton;
  digitalWrite(ledPin,ledOn);
  
}

Was mich nur Wundert, ich hatte ledPin auf 9 gesetzte und meine Verdrahtung angepasst aber die LED blieb aus. Wenn ich es wieder auf Pin 13 lege alles OK.

Warum geht das auf DigitalPin 9 nicht?
Gruß Fini