Frage zur LC Displayansteuerung

Hallo,
habe folgende Frage:

mit einer ISR zähle ich die gesamte Anzahl "zyklen" der Umdrehungen eines DC Motors. Gleichzeitig mit der Funktion void daten(), die alle 5 Sekunden die gesamte Anzahl an Zyklen auf die SD-Karte schreibt, soll das Display die Zyklen anzeigen. Jedoch zeigt es nur 0 an, einmal hat es 2 angezeigt. Warum? Zur Kontrolle habe ich den seriellen Monitor offen, der zeigt korrekte Werte an.
Habe versucht das Display direkt in void daten () einzubinden mit lcd. print (zyklen) ( jetzt auskommentiert), jedoch macht das Programm dann gar nichts, sprich der Motor dreht sich dann nicht und es wird nichts auf die SD-Karte geschrieben.
Vermute, weil ein Interrupt das Display nicht steuern kann. Bin deswegen bei der ersten Lösung geblieben.

Hier ist der Sketch:

      #include <LiquidCrystal_I2C.h> 
#include <TimerOne.h>
#include <Wire.h>  
#include <SD.h>
int Lichtschranke=2;//
int motor=3;
volatile unsigned long zyklen = 0;  
LiquidCrystal_I2C lcd (0x20,16 ,2);// IC2 LCD Display 
int l_c_d;
int duty_cycle=200;
#define Datei "Daten.txt"


void setup()
{
  
  lcd.init();                      // Initialisierung des Displays
 
  // 
  lcd.backlight(); 
   // Hintergrundbeleuchtung
  
   pinMode(Lichtschranke, INPUT); // 
   pinMode(motor,OUTPUT);
   analogWrite(3,duty_cycle);

  
 
  attachInterrupt(0, puls, RISING);
  Serial.begin(9600);
  Serial.println("SD-Card initialized.");
  
  Timer1.initialize(5000000); //  Timer, Aufruf alle 5 Sekunden
  Timer1.attachInterrupt(daten); // Timerinterrupt  
  
}

void _display()
{

switch (l_c_d)
{
case 0:

  lcd.setCursor(0,1);
  lcd.print(zyklen); 
break;
case 1:

 lcd.setCursor(0,1);
 lcd.print("Sleep"); 
break;
}
}

void daten () // 
{
  Serial.print (zyklen);

  
  File myFile = SD.open(Datei, FILE_WRITE); // 

  if (myFile)
  {
    l_c_d = 1;
    myFile.print (zyklen);
    myFile.close();
    //lcd.print (zyklen);
  }
  else
  {
    l_c_d = 0;
     Serial.println("Fehler beim Öffnen von Daten.txt");
 
  }
}

void loop()
{
  _display();
}

 void puls()
 {
   
   zyklen++;
 }

Vermute, weil ein Interrupt das Display nicht steuern kann

Richtig: eine Interrupt-Routine kann wenig und sollte fast nichts machen, ausser absolut zeitkritische Sachen.
Dein puls() ist ein gutes Beispiel.

Für eine Funktion, die alle 5 Sekunden drankommen soll, ist millis() das Richtige, aber keiner der Hardware-Timer.

 void loop()
{  
   static unsigned long lasttime;
   if ( millis() - lasttime >= 5000)
   { 
      lasttime += 5000;
      daten();  // wird alle 5 Sekunden einmal aufgerufen
   }
   // evtl. noch Sachen die häufiger drankommen
}

Habe umgeschrieben auf

    void  _display()
             {  
              if (daten)
                { 
                lcd.print(zyklen)}
              else
                     {
                       }

Das Display scheint auch mehr oder weniger was anzuzeigen. Allerdings macht er folgendes: Während das Programm läuft steht da eine 0 oder 1. Beim Betätigen eines Schalters geht das Programm aus und das Display aktualisiert den Wert zyklus.

if (daten)
{

war daten nicht eine Funktion ? void daten () { //
Dann liefert die Code - Zeile oben zwar leider keinen Fehler, aber wohl nicht das was du willst
(wobei mir nicht klar ist, was du willst)

Ja, habe den Sketch aus dem Beitrag 2 probiert, funktioniert.

Habe eine andere kurze Frage. Gibt es eine Möglichkeit nicht die ganze Anzeige auf dem Display zu löschen, sondern nur ein Ausschnitt.
Folgendes meine ich:
Programm runs...
gelaufen: zyklen

Programm runs und gelaufen sollen immer zu sehen sein und zyklen soll eben nur alle 5 Sekunden eingeblendet sein.
Geht so was?

Einfach den Teil den du Löschen willst mit Leerzeichen überschreiben

Cool, funktioniert. Man muss nur drauf achten so viele Leerzeichen zu setzen wie viele Stellen man löschen möchte.

Du kannst auch anderen Text darüber schreiben und dann die Differenz mit Leerzeichen auffüllen. Das flackert vielleicht weniger als wenn man erst Leerzeichen schreibt und dann gleich wieder Text. Obwohl diese Displays sowieso ziemlich langsam sind (auf einem TFT fällt das eher auf).
Kommt aber darauf an was man genau macht. Wenn du erst mal eine leere Anzeige an der Stelle willst - und nicht anderen Text - passt es so.

Bin zufrieden, passt absolut. Danke für die Tipps.
Eine letzte Kleinigkeit bleibt noch. Wenn ich einen Taster betätige soll mein Programm stoppen. Für das Display schreibe ich dafür

  lcd.clear()

die Hintergrundbeleuchtung bleibet aber an.

Den Befehl

  lcd.nobacklight()

kennt meine Lib wohl.
Kann man das Display irgendwie komplett deaktivieren oder so was?

clear() löscht das Display. Es wird dabei nicht ausgeschaltet!

Es sollte aber sowas wie nodisplay() geben (es gibt aber mehrere leicht unterschiedliche Libs). Schau mal in den Header. Das siehst du was es an Methoden gibt.

Wenn du das Display ausschaltest und vorher nicht clear() machst, dann stehen beim Einschalten immer noch die alten Daten da, was besser ist :slight_smile:

Habe in der Lib tatsächlich die Funktion

   noDisplay()

gefunden.
Beim Kompilieren kommt die Meldung, dass die Funktion nicht deklariert wurde.

Du hast schon lcd.noDisplay() gemacht, oder?

Achte auch auf Groß-und Kleinschreibung. Bei mir heißt das auch noDisplay(), aber auch noBacklight()

Ja, muss davor lcd schreiben. Dann werden die Funktionen erkannt.

Allerdings komischerweise geht die Hintergrundbeleuchtung nicht aus bei

      lcd.noBacklight();

habe die Anweisung

   lcd.backlight()

entfernt und festgestellt, dass das Display trotzdem beleuchtet wird.

  lcd.noDisplay()

deaktiviert es, aber nach dem Einschalten bleibt es auch aus.