millis() und I2C 16x2 LCD

Ich begrüße alle hier.
Bin noch “fortgeschrittener Anfänger” in Arduino-Programmierung und als Projekt muss ich eine Wetterstation bauen und programmieren. Die ausgewertete Sensorendaten sollen auf einem I2C 16x2 LCD ausgeben werden.

Ich habe schon ein Teil vom Sketch fertiggestellt, nun habe ich ein Problem mit der Darstellung von Werten, bzw. das Abwechseln dazwischen funktioniert zwar, nur nicht genau in den zeitlichen Intervalen die ich eingestellt habe, sondern eher “sporadisch”.

Ich möchte mehrere Werte auf dem Display in festen Intervalen abwechselnd ausgeben.
Ich stelle hier mein Code rein, wäre sehr dankbar sein, wenn jemand mir helfen würde mein Problem zu lösen oder zumindest ein Tip geben.

Im Voraus danke

// Bibliotheken
#include <SimpleDHT.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <MyDS3231.h>

// Peripheriegeräte
LiquidCrystal_I2C lcd(0x27, 16, 2);  // LCD Parameter (I2C Adresse, Länge, Breite)
MyDS3231 RTC(0x68);

// Variablen für millis Funktion um zwischen den Anzeigen zu wechseln
unsigned long currentTime_dht = 0;
unsigned long currentTime_ntcAno = 0;
unsigned long currentTime_zeit = 0;

//const int currentTime_loop;
int interval_dhtShow = 5000;
int interval_ntcAnoShow = 10000;
int interval_zeitShow = 15000;
int interval_annoRead = 300000;

// Arrays Datum und Zeit
char dowString[11];
char dateString[11];
char timeString[9];

// Variablen um DHT Sensor auszuwerten
float temperature = 0;
float humidity = 0;
int err = SimpleDHTErrSuccess;
int pinDHT22 = 7;
// SD-Karten Initialisierungspin
int chipSelect = 4;

#define Anno 3
#define lcdFeddback A1    // LCD Feedback

SimpleDHT22 dht22(pinDHT22);

// Uhrzeichen
uint8_t clock[8] = {0x0, 0xe, 0x15, 0x17, 0x11, 0xe, 0x0};

void setup()
{

  lcd.init();                 // LCD inizialisieren
  lcd.backlight();            // Hintergrundbeleuchtung aktivieren
  lcd.createChar(2, clock);   // Uhrzeichen erstellen

  // Startanzeigen:
  // 1. Willkommen
  lcd.setCursor(1, 0);
  lcd.print("Wetterstation");
  delay(4000);

  // 2. Ladebalken
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print("DATA LOADING");
  lcd.setCursor(0, 1);
  for (int8_t i = 0; i < 16; i++) {
    lcd.print("\377");
    delay(120);
  }
  
  // 3. Zeit, Datum
  lcd.clear();
  RTC.nowDateTime();
  RTC.getDowString(dowString);
  RTC.getDateString(dateString, YEAR_4_DIG);
  RTC.getTimeString(timeString, HH_MM);
  lcd.setCursor(0, 0);
  lcd.print(dowString);
  lcd.setCursor(10, 0);
  lcd.print("\2");
  lcd.setCursor(11, 0);
  lcd.print(timeString);
  lcd.setCursor(3, 1);
  lcd.print(dateString);
  delay(6000);
}

void loop()
{
  if (millis() - currentTime_dht >= interval_dhtShow) {

    if ((err = dht22.read2(&temperature, &humidity, NULL)) != SimpleDHTErrSuccess) {
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print("DHT Lesefehler");
      lcd.setCursor(6, 1);
      lcd.print(err);
    }
    // Wenn der Sensor nicht ausgewertet werden kann, dann volgende Meldung ink. Fehlercode ausgeben
    else {
      dht22.read2(&temperature, &humidity, NULL);
      lcd.clear();
      lcd.setCursor(0, 0);
      lcd.print("DHT Temp:");
      lcd.setCursor(10, 0);
      lcd.print(temperature, 1);
      lcd.print("\337C");

      lcd.setCursor(0, 1);
      lcd.print("Humid:");
      lcd.setCursor(9, 1);
      lcd.print(humidity, 1);
      lcd.print("%RH");
    }
    currentTime_dht = millis();
  }

  if (millis() - currentTime_ntcAno >= interval_ntcAnoShow) {

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print("NTC Temp: ");
    if (analogRead(A0) > 370) { // Wert wurde nur zum Testzwecken angegeben! Sonnst im Betrieb auf 0 setzen!
      lcd.setCursor(11, 0);
      lcd.print("DEF");
    }
    else {
      lcd.print(analogRead(A0));
      lcd.print("\337C");
    }

    lcd.setCursor(0, 1);
    lcd.print("Wind V: ");
    lcd.print(analogRead(A3));
    if (analogRead(A3) < 550) { // Wert diehnt nur zur Funktionsprüfung, die Umrechnung wird noch angepasst
      lcd.print("m/s");
    }
    else {
      lcd.print("km/h");
    }
    currentTime_ntcAno = millis();
  }

  if (millis() - currentTime_zeit >= interval_zeitShow) {

    lcd.clear();
    RTC.nowDateTime();
    RTC.getDowString(dowString);
    RTC.getDateString(dateString, YEAR_4_DIG);
    RTC.getTimeString(timeString, HH_MM);
    lcd.setCursor(0, 0);
    lcd.print(dowString);
    lcd.setCursor(10, 0);
    lcd.print("\2");
    lcd.setCursor(11, 0);
    lcd.print(timeString);
    lcd.setCursor(3, 1);
    lcd.print(dateString);

    currentTime_zeit = millis();
  }

  //  if (digitalRead(lcdFeddback) == LOW) {
  //    // LCD inizialisieren nach dem die Spannungsversorgung der LCD getrennt wurde
  //    // !!!Im Betrieb auf LOW setzen!!!
  //    lcd.init();
  //    lcd.backlight();
  //  }
}

Hallo,

Erkläre doch mal genauer, in welchen Abständen was angezeigt werden soll.

Und auch was genau jetzt nicht funktioniert.

Wenn du eine komfortable Lösung nutzen möchtest, dann sieh dir dazu diese Seite an.

Dein Loop ist ja kaum zu lesen.

Entrümpeln:

mache für jede Ausgabe eine eigene Funktion void showDht() void showNtc() void showRtc()

merke dir den aktuellen Status in einer Variable

schalte nach Zeitablauf den Status weiter, Überlauf nicht vergessen, wieder zurücksetzen auf 0. rufe das zugeordnete showXXX auf.

P.S.: das macht sicher nicht das was du willst: int interval_annoRead = 300000; lies mal nach, wie groß ein int sein darf.

int interval_annoRead = 300000;

Wie groß, kann ein int auf deinem System werden?

HotSystems: Hallo,

Erkläre doch mal genauer, in welchen Abständen was angezeigt werden soll.

Und auch was genau jetzt nicht funktioniert.

Wenn du eine komfortable Lösung nutzen möchtest, dann sieh dir dazu diese Seite an.

Hi, ich würde gerne die Anzeige alle 5-7 sek. aktualisieren und dementsprechende Werte anzeigen lassen. Wobei bei manchen Sachen wie z.B. Windgeschwindigkeit soll die Messung seltener durchgeführt werden.

Also der Plan ist: a) die Werte (Temperatur, Lüftfeuchtigkeit, Zeit, Datum und Windgeschwindigkeit) an einem Display alle 5-7 Sekunden abwechseldn anzeigen. b) Sensorenmessungen in anderen Abständen durchführen. (z.B. Windgeschw. alle 5-10 min.) Der aktueller Stand ist - die Ausgelesene Werte werden abwechslend angezeigt, nur in anderen Abstandsintervalen, wie ich oben eingestellt hatte. Für jeden Wert habe ich eigenen Anzeigeinterval gesetzt z.B. Temp alle 5 Sek., Windgeschwindigkeit 5 sek. nach dem die Temp. angezeigt wurde usw. Danke für den Link - lese ich mir durch.

noiasca: Dein Loop ist ja kaum zu lesen.

Entrümpeln:

mache für jede Ausgabe eine eigene Funktion void showDht() void showNtc() void showRtc()

merke dir den aktuellen Status in einer Variable

schalte nach Zeitablauf den Status weiter, Überlauf nicht vergessen, wieder zurücksetzen auf 0. rufe das zugeordnete showXXX auf.

P.S.: das macht sicher nicht das was du willst: int interval_annoRead = 300000; lies mal nach, wie groß ein int sein darf.

Danke für deinen Tipp, mit den eigenen Funktionen hatte ich mir auch schon überlegt, werde mich hinsetzen und alles noch mal anpassen. Der "interval_annoRead" wurde von mir falsch als integer deklariert, nur das wird in dem Code noch nicht verwendet.

Soweit ich das sehe, ist Messung und Anzeige eigentlich völlig unabhängig bei dir.

Du hast ein zweizeiliges LCD mit Datum/Uhrzeit in Zeile 1, Wert in Zeile 2 ?

  • Uhrzeit kann jede Sekunde aktualisiert werden.
  • In Zeile 2 wird alle 5 Sekunden reihum ein anderer Wert angezeigt.
  • Die Messwerte werden in unterschiedlichen Intervallen erfasst. Unabhängig von der Anzeige.

Bei der Windgeschwindigkeit (alle 15 Minuten?) ist für mich fraglich, ob da eine Verarbeitung mehrerer Werte sinnvoller ist. Entweder ein Mittelwert oder eher der Spitzenwert der letzten Viertelstunde, oder mehrere verschiedene Wind-Werte (z.B. aktuell / gleitender Mittelwert / Viertelstunden-Max )

Bei dem Intervall - Link würde ich mir hauptsächlich combies INTERVAL.h (ziemlich am Anfang des langen Threads) ansehen.

Der “Ladebalken” im setup ist witzig. Ein Gerät, das zu schnell ist, erscheint
□ wenig beeindruckend
□ nicht vertrauenswürdig
Mehrfachauswahl möglich.
Ich würde noch ein gelegentliches leichtes Stocken beim Hochfahren des Balkens einbauen. :slight_smile:

michael_x:
Soweit ich das sehe, ist Messung und Anzeige eigentlich völlig unabhängig bei dir.

Du hast ein zweizeiliges LCD mit Datum/Uhrzeit in Zeile 1, Wert in Zeile 2 ?

  • Uhrzeit kann jede Sekunde aktualisiert werden.
  • In Zeile 2 wird alle 5 Sekunden reihum ein anderer Wert angezeigt.
  • Die Messwerte werden in unterschiedlichen Intervallen erfasst. Unabhängig von der Anzeige.

Bei der Windgeschwindigkeit (alle 15 Minuten?) ist für mich fraglich, ob da eine Verarbeitung mehrerer Werte sinnvoller ist. Entweder ein Mittelwert oder eher der Spitzenwert der letzten Viertelstunde, oder mehrere verschiedene Wind-Werte (z.B. aktuell / gleitender Mittelwert / Viertelstunden-Max )

Bei dem Intervall - Link würde ich mir hauptsächlich combies INTERVAL.h (ziemlich am Anfang des langen Threads) ansehen.

Der “Ladebalken” im setup ist witzig. Ein Gerät, das zu schnell ist, erscheint
□ wenig beeindruckend
□ nicht vertrauenswürdig
Mehrfachauswahl möglich.
Ich würde noch ein gelegentliches leichtes Stocken beim Hochfahren des Balkens einbauen. :slight_smile:

Ja genau, hab erst angefangen. An dem Code sollte noch viel nachgearbeitet werden. Mir geht es erstmal darum die delay() Funktion durch millis() zu ersetzen und die abgelesene Werte in richtigen Intervalen darzustellen.

Die Messung soll getrennt von den Anzeigen durchgeführt werden, dafür werden dann später eigene Funktionen (void’s) erstellt, da es später noch ein SD-Kaertenmodul angeschlossen wird um die abgelesene Werte zu loggen. Das möchte ich alles von einander trennen und jeder Funktion eigenen zeitlichen Intervall zuweisen.
Da es um eienen kleinen zweiteiligen Display handelt, sollten die Werteanzeigen in Gruppen (je 2) aufgeteilt werden.

Ladebalken sieht nur lüstig aus))

maxt_x: ...... Die Messung soll getrennt von den Anzeigen durchgeführt werden, dafür werden dann später eigene Funktionen (void's) erstellt, da es später noch ein SD-Kaertenmodul angeschlossen wird um die abgelesene Werte zu loggen. Das möchte ich alles von einander trennen und jeder Funktion eigenen zeitlichen Intervall zuweisen. Da es um eienen kleinen zweiteiligen Display handelt, sollten die Werteanzeigen in Gruppen (je 2) aufgeteilt werden.

Mit dem "später eigene Funktionen" ist das immer ein Problem. Wenn der Sketch erst funktioniert, nimmt man sich selten dazu die Zeit.

Möglichst immer gleich sauberen, übersichtlichen Code schreiben, das mach die Fehlersuche deutlich einfacher. Funktionen helfen dabei.

Also nicht erst damit warte, das gilt auch für eine übersichtliche Dokumentation, die auch wieder eine Fehlersuche einfacher macht.

 // 2. Ladebalken
  lcd.clear();
  lcd.setCursor(2, 0);
  lcd.print("DATA LOADING");
  lcd.setCursor(0, 1);
  for (int8_t i = 0; i < 16; i++) {
    lcd.print("\377");
    delay(120);
  }

Für was ist denn dass?
Wenn es keinen Nutzen hat schmeiß es raus und du sparst dir fast 2 Sekunden bei jedem einschalten.

Verzweifler: Für was ist denn dass? Wenn es keinen Nutzen hat schmeiß es raus und du sparst dir fast 2 Sekunden bei jedem einschalten.

maxt_x: Ladebalken sieht nur lüstig aus))

Die 2 Sekunden werden es nicht machen, denke mal das Ding soll 24/7 laufen