wie 1 LCD mit 2 Seiten einrichten; zusätzlich backlight on/off mit interrupt

Hallo liebe Gemeinde ich muss Euch leider um Hilfe bitten:

zuerst mal was zum Projekt:

ich baue derzeit ein Fuelgauge-System auf, welches auf 2 LCDs Informationen anzeigen soll (je Display Werte wie Spannung, Strom, State of Charge und Temperatur; getrennt nach 2 Systemspannungen 12 und 12V und 36V). So war der Plan. Schnell kam dann der Wunsch auf, dass auf einem der beiden Displays abwechselnd alle Werte beider Systeme angezeigt werden sollen. Und als letztes nun noch beide Backlights per Interrupt ein bzw. aus schalten zu können.

So weit so gut. Einzeln klappt das soweit alles ganz gut, aber alles zusammen zukippen bereitet mir echte Probleme.

2 Seiten auf einem Display anzuzeigen ging mit Delay relativ einfach und gut. Dann funktioniert aber der Interrupt nicht mehr, wenn man die Taste drückt solange der µC in der pause is passiert ja nix. Dann habe ich versucht das Beispiel blinken ohne Delay zu adaptieren und genau dran hackt es jetzt.

So sieht der Code zur zeit aus:

#include <Wire.h>
#include <LCD.h>
#include <LiquidCrystal_I2C.h>

volatile byte state = LOW;
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
const long interval = 5000; 


LiquidCrystal_I2C  lcd1(0x27,2,1,0,4,5,6,7);
LiquidCrystal_I2C  lcd2(0x23,2,1,0,4,5,6,7);

void setup()

{
attachInterrupt(1, toggle, RISING);
lcd1.begin (20,4);
lcd2.begin (20,4);

lcd1.setBacklightPin(3,POSITIVE);
lcd2.setBacklightPin(3,POSITIVE);
lcd1.setBacklight(LOW);
lcd2.setBacklight(LOW);

}

void loop()
{
 if (currentMillis - previousMillis >= interval) {
   previousMillis = currentMillis;
    lcd1.home ();
    lcd1.setCursor (0,0);
    lcd1.print("Werte 12V-System");
    lcd1.setCursor (0,1);
    lcd1.print("Spannung: 12V");  
    lcd1.setCursor (0,2);
    lcd1.print("Strom: 2A");
    lcd1.setCursor (0,3);
    lcd1.print("SOC: 50%");
 }
 else {
    lcd1.setCursor (0,0);
    lcd1.print("Werte 36V-System");
    lcd1.setCursor (0,1);
    lcd1.print("Spannung: 36V");  
    lcd1.setCursor (0,2);
    lcd1.print("Strom: 6A");
    lcd1.setCursor (0,3);
    lcd1.print("SOC: 100%");
 }

lcd2.home ();

lcd2.setCursor (0,0);
lcd2.print("Display2 fuer 36V");
lcd2.setCursor (0,1);
lcd2.print("Spannung: 36V");  
lcd2.setCursor (0,2);
lcd2.print("Strom: 6A");
lcd2.setCursor (0,3);
lcd2.print("SOC: 100%");

lcd1.setBacklight(state);
lcd2.setBacklight(state);

}

void toggle() {
 state = !state;
 
}

was geht:
beide Displays zeigen jeweils Ihre Werte an
mit dem Taster lässt sich umgehend Licht ein bzw. aus schalten.

was nicht geht:

lcd1 zeigt nur die Werte unter ELSE an und schaltet nicht alle 3 Sekungen zwischen den Werten von System 1 und den Werten von System 2 hin und her.
Die Werte unter IF werden nie angezeigt. Woran liegts? sicher mache ich den if-else-Aufruf falsch, aber ich steig einfach nicht hinter.

Ich hoffe ich hab mich verständlich ausgedrückt und jemand kann mir helfen.

Setz bitte den Code in Codetags </>, dann wirst du mehr Antworten kriegen!!
Benutze bitte die Editierfunktion.

Ich verstehe absolut nicht was du mit dem Interupt machen willst.
Schon garnicht was der Interupt beim Backlight machen soll.
Das solltest du mal besser beschreiben.

Hm ok dann versuch ich es mal besser zu beschreiben:

Ich möchte einfach nicht, dass ständig die Hintergrundbeleuchtung der Displays leuchtet. Ich möchte dies nach bedarf ein bzw ausschalten können. Ich könnte dazu natürlich auch einfach jeweils eine der VLED-Leitungen mit nem Taster unterbrechen und die Beleuchtung so bei Bedarf ein- und wieder ausschalten. Nur das war mir dann doch zu einfach...
Also habe ich mich für einen Interrupt entschieden, welcher umgehend das laufende Programm unterbricht und das Backlight umschaltet. Wenn ich jetzt in der void loop aber irgendwo nen Delay unterbringe, dann wird der Interrupt natürlich nicht sofort ausgeführt, sondern erst nach beenden der Pause. Mithilfe von Delay hatte ich bei einem der Displays halt 2 Seiten aufgebaut, welche abwechselnd für 5 Sekunden angezeigt werden sollten.

einen Fehler habe ich inzwischen gefunden:

die Zeile

unsigned long currentMillis = 0;

war natürlich falsch. Ich habe Sie entfernt und am Anfang von void loop{} folgende eingefügt:

void loop()
{
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
  previousMillis = currentMillis;

jetzt wird alle 5 Sekunden für ganz ganz kurze Zeit die Werte aus der IF-Schleife eingeblendet, gehen aber sofort wieder weg. Das schaffe ich nicht auf 5 Sekunden auszudehnen.

Um die Hintergrundbeleuchtung (Display-Led) ein bzw. auszuschalten, brauchst du def. keinen Interrupt, das geht ganz normal über einen Taster in der Loop.

Da darf natürlich (wie du erkannt hast) kein "delay" vorhanden sein.

Den Taster fragst du in der Loop ab und reagierst entsprechend im Sketch darauf.

Hm ok aber das löst dann immer noch nicht mein Problem wie ich 2 Seiten auf einem LCD für jeweils 5 Sekunden abwechselnd darstellen kann OHNE Delay zu nutzen. Kann mir da jemand weiterhelfen?

braini:
Hm ok aber das löst dann immer noch nicht mein Problem wie ich 2 Seiten auf einem LCD für jeweils 5 Sekunden abwechselnd darstellen kann OHNE Delay zu nutzen. Kann mir da jemand weiterhelfen?

Das machst du ähnlich wie du es schon versucht hast, mit der Funktion "millis()" und rufst abwechselnd 2 Funktionen auf. Die erste Funktion beschreibt dein Display mit dem Inhalt der ersten Seite, die zweite Funktion mit der zweiten Seite.

Auch dazu brauchst du keinen Interrupt.

in etwa so (Pseudeocde)

boolean isSeite1 = true;
uint32_t lastChange, aktmillis, intervall = 5000;

...
loop() {
  aktmillis = millis();
  if (aktmillis - lastChange >= intervall) {
    lastChange = aktmillis;
    if (isSeite1) {
      // Ausgabe Seite 1
    }
    else {
      // Ausgabe Seite 2
    }
    IsSeite1 = !isSeite1;
  }
}

Ungetestet, so in der Richtung.

Gruß Tommy

Danke Tommy56, der Denkanstoß und deine Beispiel hat mir sehr geholfen. Jetzt läufts.

Prima. Schön, wenn ich helfen konnte.

Gruß Tommy

Warum schaltest du nicht das Backlight direkt in der Interruptroutine.
Das ist doch nur ein einfacher IO-Pin ?
Dann, abgesehen das delay immer eine schlechte Idee ist, würde auch delay
die Umschaltung nicht blockieren.

Ulli

das ahtte ich versucht, leider ohne Erfolg.

und zwar so:

void toggle() {

  state = !state;
  lcd1.setBacklight(state);
  lcd2.setBacklight(state);
}

war nur leider nicht von erfolg gekrönt

Kommt denn der Interrupt ?

Mach mal eine LED an und aus im Int.

Ulli

wenn ich die LED mit rein nehme, dann schaltet Sie zwar beim ersten Drücken des Taster ein, aber beim nächsten mal drücken nicht wieder aus. Bleibt also HIGH.

void toggle() {
 state = !state;
 digitalWrite(13, state);
 lcd1.setBacklight(state);
 lcd2.setBacklight(state);
 
 }

gerade noch was probiert:
wenn ich die Zeilen
lcdx.setBacklight weglasse, dann schaltet er auch die LED hin und her. Muss also was mit der Funktion zu tun haben. werde da mal dran bleiben.