Problem mit oled und rtc

Hallo Kollegen,
vorab muss ich beichten dass ich blutiger Anfänger bin. Nichtsdestotrotz hab ich es geschafft, die Zeit eines DS3231 Modul auf einem 0.96" OLED anzeigen zu lassen.

In meiner Anwendung will ich über einen Button mehrere Anzeigen durchschalten; eine der Anzeigen soll die Uhrzeit enthalten.
Die unterschiedlichen screens will ich durch eine switch/case Schleife durchschalten. Sobald ich aber "case 2: … " hinzufüge, kompiliert der sketch nicht mehr mit folgender Fehlermeldung:

/Users/Sebastian/Documents/Arduino/tacho_nano/tacho_nano.ino: In function 'void draw()':
tacho_nano:60: error: crosses initialization of 'DateTime now'
     DateTime now = rtc.now();   
              ^
exit status 1
crosses initialization of 'DateTime now'

Damit kann ich ehrlichgesagt wenig anfangen… anbei mein Code: (wie gesagt, lässt an case2 weg, dann läuft es sauber durch…)

void draw() {
  u8g2_prepare();
  switch (screen) {
    case 0:
    u8g2.drawStr( 0, 15, "screen1");                           //dummy-screen, hier kommt später noch mehr
    break;
    case 1:
    Serial.println("case1");
    DateTime now = rtc.now();   
    String(now.minute(), DEC).toCharArray(Minute, 3);   //minuten-string für drawStr()in char umwandeln
    String(now.hour(), DEC).toCharArray(Stunde, 3);      //stunden-string für drawStr()in char umwandeln
    u8g2.drawStr( 0, 15, Stunde);
    u8g2.drawStr( 50, 15, ":");
    u8g2.drawStr( 62, 15, Minute);
    break;  
    case 2:
    u8g2.drawStr( 0, 15, "screen2");
    break;      
    }
}

danke im Voraus

mfg
Basti

Edit:
wenn ich "DateTime now = rtc.now(); " vor die switch/case Anweisung setze funktioniert es… aber kann mir einer erklären wieso?

Fehlermeldungen kann man Googeln. Das hier zeigt dir dein Problem:
"error: crosses initialization of"

Du musst mit { } Code-Blöcke in den Cases anlegen in denen du du lokale Variablen erzeugst. Die Variable hat sonst Scope/Gültigkeit selbst danach obwohl sie unter Umständen nie kreiert wurde

Kurz gefasst und etwas vereinfacht: Du kannst im switch/case nicht so einfach Variablen deklarieren.
Außerdem ist eine Fehlersuche mit einem Codefragment einfach Sch... .

Gruß Tommy

Bitte poste den kompletten Sketch und nicht nur Fragmente.
Dann können wir besser den Fehler herausfinden.

HotSystems:
Bitte poste den kompletten Sketch und nicht nur Fragmente.
Dann können wir besser den Fehler herausfinden.

Du kannst dir das auch mal sparen. Der Fehler ist offensichtlich und liegt genau in dem genannten Teil

Serenifly:
Du kannst dir das auch mal sparen. Der Fehler ist offensichtlich und liegt genau in dem genannten Teil

Na dann haben wir ja mal Glück gehabt. :wink:

Danke!!

Leider reißen meine Probleme nicht ab.
Wenn die Uhrzeit einstellige Minuten oder Stunden aufweist (z.B. 14:03), so wir dies als “14:3” dargestellt.
Kurzum - es fehlt vor der drei eine Null…

Die Minuten lese ich als String von der rtc und wandle sie dann in ein char, damit sie von drawStr() “gefressen” werden.

Mein Ansatz wäre jetzt, die länge von dem char abzufragen, und einfach eine führende 0 zu addieren, wenn die Länge einstellig ist…

Um zu sehen, ob da überhaupt was brauchbares rauskommt, habe ich die Zeile
“Serial.println(strlen(Stunde));” eingebaut. Leider wird danach garkeine Uhrzeit mehr angezeigt :o

Erste Frage: wieso legt diese serielle Ausgabe alles lahm?
Zweite Frage : wie bekomme ich elegant immer eine zweistellige Stunden/ Minuten anzeige?

Anbei nun der gesammte code (bitte keine Frotzeleien über mein Gestümpere :slight_smile: )

#include <RunningAverage.h>
#include <Wire.h>
#include "OneButton.h"
#include <U8g2lib.h>
#include "RTClib.h"

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 16, /* data=*/ 17);   // ESP32 Thing, HW I2C with pin remapping
RTC_DS3231 rtc;

RunningAverage myRA(10);
volatile unsigned long dauer = 0;             // microsekunden seit dem letzten Interrupt
volatile unsigned long last = 0;              // Zählerwert beim letzten Interrup
short geschwindigkeit;                         // selbstredend
short VAnzeige;
short wegstrecke;
const int buttonPin = 4;
const int reedPin = 3;
int interruptCounter = 0;
int screen = 0;
OneButton button(buttonPin, true);
char Minute[3];
char Stunde[3];
int test;

void setup()   {
  Serial.begin(9600);      // open the serial port at 9600 bps:
  pinMode(reedPin, INPUT_PULLUP); // Reed-Sensor an Pin 3
  pinMode(buttonPin, INPUT_PULLUP); // Taster an Pin 2
  attachInterrupt(digitalPinToInterrupt(3), readmillis, RISING);
  myRA.clear();
  button.attachClick(klick);
  button.attachLongPressStop(callSetup);
  u8g2.begin();
  delay(1000);

}

void loop() {
      button.tick();
      VAnzeige = myRA.getAverage(), 0;        // Mittelwert errechnen
    //  Serial.println(Stunde);
      
      u8g2.clearBuffer();
      draw();
      
      u8g2.sendBuffer();
      myRA.clear();                           // Mittelwertdaten löschen
      delay(100);                                 // Alle 1/4 Sekunde Werte aktualisieren, bis dahin über Interrupt Werte sammeln
}


void draw() {
  u8g2_prepare();
  DateTime now = rtc.now();
  switch (screen) {
    case 1:
    u8g2.setFont(u8g2_font_timB24_tf);   
    u8g2.drawStr( 0, 15, "screen1"); 
    break;
    case 0:
    u8g2.setFont(u8g2_font_fub30_tr);
    String(now.minute(), DEC).toCharArray(Minute, 3);
    String(now.hour(), DEC).toCharArray(Stunde, 3);
    Serial.println(strlen(Stunde)); 

    u8g2.drawStr( 0, 15, Stunde);
    u8g2.drawStr( 50, 15, ":");
    u8g2.drawStr( 62, 15, Minute);
    break;  
    case 2:
    u8g2.setFont(u8g2_font_timB24_tf);
    u8g2.drawStr( 0, 15, "screen2");
    break; 
    case 6:
    u8g2.setFont(u8g2_font_timB24_tf);
    u8g2.drawStr( 0, 15, "Setup");
    break;          
    }
}


void u8g2_prepare(void) {
  u8g2.setFont(u8g2_font_fub30_tr);
  u8g2.setFontRefHeightExtendedText();
  u8g2.setDrawColor(1);
  u8g2.setFontPosTop();
  u8g2.setFontDirection(0);
}

void readmillis() {                           // Interrupt-Routine
  interruptCounter++;
  if (interruptCounter >537) {                //537 Radumdrehungen entsprechen einem km
    wegstrecke++;
    interruptCounter = 0;
    }
  
  unsigned long m = millis();                 // Microsekundenzähler auslesen
  unsigned long v = m - last;                 // Differenz zum letzten Durchlauf berechnen
  if (v > 5) {                                // ignorieren wenn <= 5ms (Kontaktpreller)
    dauer = v;                                // Wert in dauer übernehmen
    last = m;                                 // und wieder den letzten Wert merken
    geschwindigkeit = 1.86*3.6*1000/dauer;             // Geschwindigkeit: 1 Interrupt alle 1860mm (Radumfang)
    myRA.addValue(geschwindigkeit);           // Wert zur Mittelwerberechnung hinzufügen
    }
}

void klick() {
  if (!(screen == 6))  // nur wenn setup-screen nicht aktiv
   {   
  screen++;  
  if (screen > 2) { screen= 0; } 
  }
}

void callSetup() {    // setup nur über langdruck erreichbar und wieder zu verlassen
  if (screen == 6)  { screen = 0; }
  else  { screen = 6; }
}

Hi

Habe Deinen Sketch nur kurz überflogen - wenn Du mitteln .print eine Zahl ausgeben lässt, werden die führenden Nullen ignoriert.
Klar - wenn Du ein int ausgeben willst, möchtest Du ‘3’ sehen, oder ‘00003’ ??
Bei einem long ähnlich - eben mehr unnütze Nullen.

Du musst Dich also um die führenden Nullen selber kümmern - der Arduino weiß hier allerdings auch nicht, auf wie viele Stellen Du eigentlich kommen willst … tausendstel Sekunden z.B. wären 3 Stellen …

Bei Dir “if Zahl < 10 print ‘0’;” - vll. noch auf arduino-typische Syntax umgebrochen …

MfG

ja, auf diesen Trichter bin ich auch gerade gekommen.

Was mich gerade aber viel mehr beschäftigt:
Sobald ich in der draw-Funktion irgendwas anderes mit "Minute" oder "Stunde" mache, wird nix mehr angezeigt (siehe serial.println.. Anweisung im sketch von oben).

Des Weiteren klappt die von dir vorgeschlagene if-abfrage nach einstelligen Zahlen nicht mit meinem char-objekt... gibts da was vergleichbares? länge des chars?

Hi

Mir erschließt sich, ehrlich gesagt, nicht, was Du Da mit einem char-Array der Länge 3 für Minuten und Stunden machst.
Klar - irgend wer packt Da die Zahlzeichen rein und fügt ggf. ein /0 als Ende-Marker an - dafür müsste man sich die Lib Mal genauer anschauen.
Somit hast Du einen Text und keine Zahlen.
Eine Zehn sieht bei Dir dann wohl so aus: '1' '0' '/0'
Eine Neun dagegen '9' '/0' 'egal' (wobei 'egal' wirklich bedeutet, daß dieses Zeichen egal ist.

Hier könntest Du prüfen, ob Minute[1] =='/0' ist, wenn JA, Minute[2]='/0'; Minute[1]=Minute[0]; Minute[0]='0';
Gleiches mit Stunde.

Ggf. drüber nachdenken, wie man eigentlich eine Zahl bis 255 speichert - (Tip: byte) - damit kann man dann sogar noch rechnen, wenn's denn sein muß.

Die .draw Funktion kam mir jetzt gerade nicht unter - vll. schaue ich später noch Mal rein.

MfG