Füllstandsanzeige mit Extras

Hallo Forum,

ich habe ein Arduino und möchte damit eine Füllstandsanzeige mit Untermenüs aufbauen, soweit der Plan :slight_smile:

Zur verfügung steht mir ein:

  • Arduino 328 P Duemilaove
  • LCD 2x16 von DFRobot
  • Füllstand Voll = ca 1140 mV … Leer = ca 44mV (GND / Plus (auf A1))

Menüpunkte sollten sein:

-Hauptmenü (Uhrzeit, Datum, Füllstand in %)
|_ Füllstand (Füllstand im Detail. ( % ggf. Analogbalken)
|_ Reset
|_ Verbrauch (Verbauch l/100km wobei ich nicht weis wie ich die errechnen lassen soll)
|_ Ansteuerung Extern (Relais schalten für ca 1-2 Sekunden)

Jetziger Stand:

Füllstand (Zeile1 = Text, Prozentwert ; Zeile2= Analogbalken der den Prozentwert annimmt und anzeigt)

Zu lösende Probleme:

  • Menü
  • Woher die KM bekommen damit man den Verbrauch messen/errechnen kann
  • Ansteuerung Extern

Bitte helft mir :slight_smile:

    #include <LiquidCrystal.h>
    #include <LcdBarGraph.h>
     
    byte lcdNumCols = 16; // -- Anzahl der vollen Balken im LCD
    byte sensorPin = 1; // -- Analogeingang
     
    LiquidCrystal lcd(8, 9, 4, 5, 6, 7); // -- Aufbau der LCD Verbindung
    LcdBarGraph lbg(&lcd, lcdNumCols);  // -- Aufbau der Balken
     
/////////////////////////////////////////////////////////////////////////////////////////////////    
    
    void setup(){

      analogReference (INTERNAL);   //  Interne Spannung 1,1 V DC am AREF Ausgang bzw Max. Messwert am Analog 1
      lcd.begin(2, lcdNumCols);   // -- Initialisierung des LCD
      lcd.clear();
      delay(1000);
    }
     
     
//////////////////////////////////////////////////////////////////////////////////////////////////     
    void loop()
    {
 
      lbg.drawValue( analogRead(sensorPin), 1024);   // -- Setzt den Wert vom Analogen Eingang
      delay(300);
         
         
 int poti = analogRead(sensorPin);                  // Poti-Wert auslesen, max. Wert 1024
 int potiVal = ((poti/4) * 100)/251;                // Potiwert in Prozent umrechnen
 lcd.setCursor(0,1);                                // 0 = Zeile  ;  1 = Spalte
 lcd.print("Tankinhalt");
 lcd.setCursor(14,1);
 lcd.print("%");
 lcd.setCursor(11,1); 
 lcd.print(potiVal);
  if( potiVal < 100 )                               // Ist potiVal kleiner als 100 setze ein leerzeichen
  lcd.print( " " );
  if( potiVal < 10 )                                // Ist potiVal kleiner als 10 setze ein leerzeichen
  lcd.print( " " );

 delay(300);
    }

Hi, wie bzw. womit willst du denn den Füllstand messen? VG

Füllstand ist wohl schon gelöst ?

Fehlen noch - Taster für's Menü - Datum / Uhrzeit Eingabe ( RTC und Serial.read() vom Laptop ? ) - Wo sollen die "km" herkommen ? - l/100 km ist einfach, falls du den Füllstand in Liter umrechnen kannst, aber die wenigsten Tanks haben eine einfache Geometrie ...

michael_x: Füllstand ist wohl schon gelöst ?

Fehlen noch - Taster für's Menü - Datum / Uhrzeit Eingabe ( RTC und Serial.read() vom Laptop ? ) - Wo sollen die "km" herkommen ? - l/100 km ist einfach, falls du den Füllstand in Liter umrechnen kannst, aber die wenigsten Tanks haben eine einfache Geometrie ...

Sorry, hatte vergessen zu sagen das es sich um ein Tank im Auto handelt! Also Arduino muss völlig autark laufen!

Ja der Füllstand hat sich gelöst! Diesen habe ich jetzt über die Interne Spannung (Arduino 1,1V) messen lassen, da der Tank nur 1140 / 44 mV ausgibt, da Arduino standartmäßig ja am A0-A5 mit Max. 5 V und Min. 0 V rechnet :) Was ich beim testen im Auto gemerkt habe, ist das das Schwappen und das misst Arduino ja mit :( Wenn einer einen Vorschlag hat dieses zu ändern bitte gerne;)

Taster für das Menü is ja nicht so schwer aber das kann ich auch später machen? Datum Uhrzeit muss der Arduino selber machen! (Taktung evtl.? Problem delays= aussetzer?, An/Aus des Autos= aussetzer?) KM wäre vllt über OBD-II möglich? :D Tank ist ein Donut ;)

Datum Uhrzeit muss der Arduino selber machen!

Na dann ... Selbst die millis() zum Weiterzählen zu nutzen, wird dir zeigen, dass 0.1 % Fehler beim Füllstand super wäre, bei der Tageszeit aber (Eine Minute am Tag) nervig sind. Eine batteriebetriebenes UhrenModul (RTC) muss auch erstmal gestellt werden, daher mein Vorschlag, temporär nen Laptop anzuschliessen... Funkuhr ?

KM wäre vllt über OBD-II möglich?

Da gibts auch den Verbrauch in l/h ???

Sonst Liter -> Füllstand : Ganglinie messen...

das Schwappen

Selbst bei heftiger Fahrweise ist die Änderung nur sehr langsam.

x = messung * 0.01 + x * 0.99 , alle 2 Sek neu ( ein Tiefpass mit T=200 sec ) sollte Schwappen und Kurvenfahrten filtern. Evtl. Geber Einschalten ohne Filter ...

michael_x:

Datum Uhrzeit muss der Arduino selber machen!

Na dann ... Selbst die millis() zum Weiterzählen zu nutzen, wird dir zeigen, dass 0.1 % Fehler beim Füllstand super wäre, bei der Tageszeit aber (Eine Minute am Tag) nervig sind. Eine batteriebetriebenes UhrenModul (RTC) muss auch erstmal gestellt werden, daher mein Vorschlag, temporär nen Laptop anzuschliessen... Funkuhr ?

KM wäre vllt über OBD-II möglich?

Da gibts auch den Verbrauch in l/h ???

Sonst Liter -> Füllstand : Ganglinie messen...

das Schwappen

Selbst bei heftiger Fahrweise ist die Änderung nur sehr langsam.

x = messung * 0.01 + x * 0.99 , alle 2 Sek neu ( ein Tiefpass mit T=200 sec ) sollte Schwappen und Kurvenfahrten filtern. Evtl. Geber Einschalten ohne Filter ...

Die Uhrzeit hat ja nix mit dem andern zu tun :) Es soll bloss ne Uhrzeit da stehen ggf. auch noch das Datum (einstellbar wenn möglich über Taster) Zur not lass ich das halt weg.... :)

Über ODB kannste ja alles auslesen lassen ohne viel tam tam, kost halt ein wenig Geld und das wollte ich mir sparen ;)

Was meinst du mit Ganglinie?

Ich habe mal aus Spaß die zeit zum messen alle 6 Sek. eingestellt. Furchtbar!! Erst 40 % dann 67 % dann 88% dann 33 % usw. das geht garnicht! Jetzt mal auf 3 ms und da sieht man mal wie das schwappt :(

ICh habe mir mal überlegt nur wenn der gerade fährt (Wage x/Y) das der dann messen soll aber brauch ich ja auch wieder ein Modul:( Alles nicht so einfach :)

Vielleicht kannst du das Schwappen mit einem Beschleunigungssensor "ausblenden". Also z.B. nur messen wenn seit x Sekunden nicht mehr großartig gebremst oder beschleunigt wurde.

kduin: Vielleicht kannst du das Schwappen mit einem Beschleunigungssensor "ausblenden". Also z.B. nur messen wenn seit x Sekunden nicht mehr großartig gebremst oder beschleunigt wurde.

das klingt auch gut ;) kann man sowas selber basteln?

Was meinst du mit Ganglinie?

In den Tank literweise ( oder in 5 liter Schritten) Benzin einfüllen und jeweis Füllstand merken. Wird sicher nicht linear ( 5l=10%, 10l=20%, 20l=40% , ... 50l=100% ) , sondern anders sein. Diese Werte brauchst du dann, um aus dem messbaren Füllstand auf die verbrauchten Liter zurückrechnen zu können.

Schwappen mit einem Beschleunigungssensor "ausblenden".

Gegen "Schwappen" wird ein Software Tiefpass Filter helfen. Aber wenn du sowieso schon so einen Beschleunigungssensor hast, wäre eventuell eine patentierfähige Variante, da das sicher so normalerweise nicht gemacht wird...

michael_x:

Was meinst du mit Ganglinie?

In den Tank literweise ( oder in 5 liter Schritten) Benzin einfüllen und jeweis Füllstand merken. Wird sicher nicht linear ( 5l=10%, 10l=20%, 20l=40% , ... 50l=100% ) , sondern anders sein. Diese Werte brauchst du dann, um aus dem messbaren Füllstand auf die verbrauchten Liter zurückrechnen zu können.

Schwappen mit einem Beschleunigungssensor "ausblenden".

Gegen "Schwappen" wird ein Software Tiefpass Filter helfen. Aber wenn du sowieso schon so einen Beschleunigungssensor hast, wäre eventuell eine patentierfähige Variante, da das sicher so normalerweise nicht gemacht wird...

Also die Abstufungen (Ganglinien) ist ja kein Problem ;) und daraus kann man dann ne rechnung machen wo man sieht wie viel verbauch man hat? Also Voll ---> 1140 mV

Lehr---> 44 mV

und wie sollte dann die Rechnung aussehen bzw wie viele Stände braucht man den für ein gescheites Ergebnis?

Software tiefpass hab ich noch nicht probiert ist das das oben beschriebene?

wie viele Stände braucht man denn für ein gescheites Ergebnis?

Das hängt dann von deinem Tank und deinen Ansprüchen ab.
Zeichne diene Messergebnisse auf und versuche, das Ganze durch wenige gerade Linien anzunähern.
Für jedes erforderliche Teilstück gibt dir eine map() Funktion die Umrechnung vom Analog.read() Ergebnis in eine liter -Zahl ( oder eher kleinere Einheiten, da map() nur mit long arbeitet und keine float Ergebnisse liefert ). Die Differenz zwischen zwei Liter-Werten sollte dann verbraucht worden sein… :wink:

Software tiefpass hab ich noch nicht probiert ist das das oben beschriebene?

Ja, der neue Wert wird nur zu einem kleinen Teil vom aktuell gemessenen , der Rest wird vom alten Wert bestimmt.
Eine Ausreisser-Messung geht so nur zu einem kleinen Teil in das gefilterte Ergebnis ein. Die Messungen und Berechnungen sollten zeitlich regelmässig erfolgen. Wie oft, und welche Gewichtung eine einzelne Messung hat, ist “Geschmackssache”.
Gegenüber einer elektrischen Filterung (mit dicken Kondensatoren) hat dies den Vorteil, dass man einen falschen Anfangswert (z.B. direkt nach Start) nicht erst langsam annähern muss, sondern den Filter einfach überspringen kann.

michael_x:

wie viele Stände braucht man denn für ein gescheites Ergebnis?

Das hängt dann von deinem Tank und deinen Ansprüchen ab. Zeichne diene Messergebnisse auf und versuche, das Ganze durch wenige gerade Linien anzunähern. Für jedes erforderliche Teilstück gibt dir eine map() Funktion die Umrechnung vom Analog.read() Ergebnis in eine liter -Zahl ( oder eher kleinere Einheiten, da map() nur mit long arbeitet und keine float Ergebnisse liefert ). Die Differenz zwischen zwei Liter-Werten sollte dann verbraucht worden sein... ;)

Software tiefpass hab ich noch nicht probiert ist das das oben beschriebene?

Ja, der neue Wert wird nur zu einem kleinen Teil vom aktuell gemessenen , der Rest wird vom alten Wert bestimmt. Eine Ausreisser-Messung geht so nur zu einem kleinen Teil in das gefilterte Ergebnis ein. Die Messungen und Berechnungen sollten zeitlich regelmässig erfolgen. Wie oft, und welche Gewichtung eine einzelne Messung hat, ist "Geschmackssache". Gegenüber einer elektrischen Filterung (mit dicken Kondensatoren) hat dies den Vorteil, dass man einen falschen Anfangswert (z.B. direkt nach Start) nicht erst langsam annähern muss, sondern den Filter einfach überspringen kann.

Da muss ich aber einige Zahlen abnehmen damit ich da ein guten Wert errechnet bekomme :( sind bei sa ca. 50 l = 50 Teilstriche oder 25 bei 2 Liter :D Kann man das nicht errechnen anhand der mV?

Wie würde den sowas genau aussehen wenn ich diesen Tiefpass in mein Script einfügen würde?

Kann man das nicht errechnen anhand der mV?

Wenn mans kann, vergiss meinen Einwand:

Angenommen (einfache Zahlen erleichtern das Rechnen) :

44mV = 1l
1044mV = 51l

Wenn du dann bei 6l etwa 144mV misst, bei 16l etwa 344mV , bei 36l 744mV, dann hat jemand für dich die Linearisierung schon gemacht.

Wenn du aber Daten wie auf dem angefügten Bild (immer noch stark vereinfacht) gemessen hast, sind 2 Bereiche besser:

michael_x:

Kann man das nicht errechnen anhand der mV?

Wenn mans kann, vergiss meinen Einwand:

Angenommen (einfache Zahlen erleichtern das Rechnen) :

44mV = 1l 1044mV = 51l

Wenn du dann bei 6l etwa 144mV misst, bei 16l etwa 344mV , bei 36l 744mV, dann hat jemand für dich die Linearisierung schon gemacht.

Wenn du aber Daten wie auf dem angefügten Bild (immer noch stark vereinfacht) gemessen hast, sind 2 Bereiche besser:

Recht hast du ! ;) Ich werde einfach mal Werte ablesen wenn ich Fahre ;)

Wie Geht das jetzt aber mit dem Software Tiefpass?

Software Tiefpass ist sehr einfach:

gefilterter_wert = ((c*(uint32_t) gefilterter_wert)+neuer_messwert)/(c+1)

Je größer c desto stärker die Glättung. Du musst nur sicherstellen, daß die Zwischenergebnisse keinen Überlauf verursachen. Ich würde Messwerte mit uint16_t und c<2^16-2 verarbeiten.

OK :smiley: gerade eben versteh ich nur Bahnhof obwohl du es schon sehr einfach erklährt hast… denk ich
Woher bekomme ich C?
Ist das mein potiVal?
uint32_t damit kann ich nichts anfangen bzw uint16_t und c<2^16-2

Ich bin auch nur ein Mensch :smiley:

Woher bekomme ich C?

Die Nachmittags-Schicht übernimmt mal wieder ;) C ist eine Konstante, die du dir ausdenkst. Zusammen mit der Zykluszeit, bestimmt sie die Filter-Wirkung ( je höher, desto weniger Einfluss hat eine einzelne Messung ) Udo's Formel hat ( gegenüber meiner ) den Vorteil, dass mit ganzen Zahlen gerechnet wird. ( Das ist deutlich schneller auf einem Arduino )

Hat aber den Nachteil dass man auf Zahlenüberlauf aufpassen muss. Der vorgeschlagene Datentyp uint32_t ist eine vorzeichenlose 32 bit Integer Zahl. (Auf dem Arduino auch unsigned long genannt). uint16_t ist hier unsigned int ( 16 bit ) d.h. 0 .. 65535 Da vom Analog.read Werte 0 .. 1023 kommen, würdest du mit dem 16 bit int bei c >= 32 einen Vorzeichenwechsel, und bei c >= 64 einen Überlauf riskieren.

2^16 -2 = 65534 : ist der größte c Wert, den Udo empfehlen würde. ( Recht hat er, aber bleib lieber weit drunter... )

Ich könnte dich jetzt wieder verwirren, mit der Empfehlung , für c Werte wie 15, 63, 127 , 255 zu nehmen, dann kannst du die Division durch (c+1) durch eine schnellere shift Operation ersetzen.

michael_x:

Woher bekomme ich C?

Die Nachmittags-Schicht übernimmt mal wieder ;) C ist eine Konstante, die du dir ausdenkst. Zusammen mit der Zykluszeit, bestimmt sie die Filter-Wirkung ( je höher, desto weniger Einfluss hat eine einzelne Messung ) Udo's Formel hat ( gegenüber meiner ) den Vorteil, dass mit ganzen Zahlen gerechnet wird. ( Das ist deutlich schneller auf einem Arduino )

Hat aber den Nachteil dass man auf Zahlenüberlauf aufpassen muss. Der vorgeschlagene Datentyp uint32_t ist eine vorzeichenlose 32 bit Integer Zahl. (Auf dem Arduino auch unsigned long genannt). uint16_t ist hier unsigned int ( 16 bit ) d.h. 0 .. 65535 Da vom Analog.read Werte 0 .. 1023 kommen, würdest du mit dem 16 bit int bei c >= 32 einen Vorzeichenwechsel, und bei c >= 64 einen Überlauf riskieren.

2^16 -2 = 65534 : ist der größte c Wert, den Udo empfehlen würde. ( Recht hat er, aber bleib lieber weit drunter... )

Ich könnte dich jetzt wieder verwirren, mit der Empfehlung , für c Werte wie 15, 63, 127 , 255 zu nehmen, dann kannst du die Division durch (c+1) durch eine schnellere shift Operation ersetzen.

Uff..... Ich wusste nicht das man dafür einen Doktor brauch :D Ich weis jetzt was 16 und 32 bit zu beudeuten hat aber noch immer nicht wie ich das in meine schaltung bringe :D Bin eher der Pratiker anstatt Leser! :D

Uff..... Ich wusste nicht das man dafür einen Doktor brauch smiley-grin Ich weis jetzt was 16 und 32 bit zu beudeuten hat aber noch immer nicht wie ich das in meine schaltung bringe smiley-grin Bin eher der Pratiker anstatt Leser! smiley-grin

Dafür braucht es keinen Dokor. Dafür reicht schon lesen ;)