Brüchte Hilfe

Hallo, ich versuche gerade meinen zweiten Code hinzubekommen... ich schaffs aber ums verrecken nicht....
Ich habe mir diesen Code aus verschiedenen zusammen genommen. Ich möchte (am Schluss) damit ein relais schalten für eine bestimmte Zeit.. Quasi eine einstellbare Eieruhr... ich bekomme aber einfach nicht hin das es mir richtig auf dem Display angezeigt wird. Würde sich jemand erbahmen und mir den Code umschreiben ? Und wenn ihr ganz gut drauf seit evtl. dazu erklären was ich falsch gemacht habe.

Im moment ist da denke ich ziemlich Chaos drin :slight_smile:
Ich muss gestehen das ich mich noch nicht auskenne, aber ich möchte mich irgendwie auch nicht geschlagen geben.... Ich spiele da jetzt schon Tage rum und verliere ziemlich den Spass an der Geschichte.

Hoffe auf Hilfe von euch.

Danke Andy

#include <Wire.h>
#include <Adafruit_SSD1306.h>
#include <Adafruit_GFX.h>
#define OLED_ADDR   0x3C

Adafruit_SSD1306 display(-1);

int Variable1;  // Create a variable to have something dynamic to show on the display

#define Start 4 // start stop button
int hours = 0;
int minutes = 0;
int seconds = 0;
boolean timeState = false;
#define encoderPinA 2 // right
#define encoderPinB 3 // left
#define encoderButton 5 // switch
//#define OLED_RESET LED_BUILTIN
int HMS = 1;
int encoderPos = 0; // a counter for the dial
unsigned int lastReportedPos = 1; // change management
static boolean rotating = false; // debounce management
boolean A_set = false;
boolean B_set = false;

void setup() {

  display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR);
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.clearDisplay();
  display.display();
  delay(100);  // This delay is needed to let the display to initialize
  pinMode(Start, INPUT_PULLUP);
  pinMode(encoderPinA, INPUT_PULLUP); //enabling pullups
  pinMode(encoderPinB, INPUT_PULLUP);
  pinMode(encoderButton, INPUT_PULLUP);
  attachInterrupt(0, doEncoderA, CHANGE); //pin 2
  attachInterrupt(1, doEncoderB, CHANGE); //pin 3


}

void loop() {


  Variable1++;  // Increase variable by 1
  if (Variable1 > 150) // If Variable1 is greater than 150
  {
    Variable1 = 0;  // Set Variable1 to 0
  }




  // Convert Variable1 into a string, so we can change the text alignment to the right:
  // It can be also used to add or remove decimal numbers.
  char string[10];  // Create a character array of 10 characters
  // Convert float to a string:
  dtostrf(Variable1, 3, 0, string);  // (<variable>,<amount of digits we are going to use>,<amount of decimal digits>,<string name>)

  if (digitalRead(encoderButton) == LOW)
  {
    HMS = HMS + 1;
    if (HMS == 4)
    {
      HMS = 1;
    }
    delay(1000);
  }
  rotating = true; // reset the debouncer
  encoderPos = constrain(encoderPos, -1, 1);
  if (lastReportedPos != encoderPos) {

    if (HMS == 1) {
      hours = hours + encoderPos;
      hours = constrain(hours, 0, 48);
    }
    else if (HMS == 2) {
      minutes = minutes + encoderPos;
      minutes = constrain(minutes, 0, 60);
    }
    else if (HMS == 3) {
      seconds = seconds + encoderPos;
      seconds = constrain(seconds, 0, 60);
    }



    if (hours <= 9)
    {
      display.print("0");

    }

    display.print(": ");

    if (minutes <= 9)
    {
      display.print("0");

    }

    display.print(": ");

    if (seconds <= 9)
    {

      display.print("0");

    }


    encoderPos = 0;
    lastReportedPos = encoderPos;
    //display.display();

    display.setCursor(4, 1);
    display.clearDisplay();
    display.print("hours ");
    display.println(hours);
    display.print("minutes ");
    display.println(minutes);
    display.print("seconds ");
    display.println(seconds);
    display.println(" ");
    display.display();
  }
  if (digitalRead(Start) == LOW) { //start count down timer
    timeState = true;
    delay(1000);
    while (timeState == true) {
      if (minutes == 0 && hours >= 1) {
        minutes = 60;
        hours = hours - 1;
        display.setCursor(4, 1);
        display.clearDisplay();
        display.print("hours ");
        display.println(hours);
        display.print("minutes ");
        display.println(minutes);
        display.print("seconds ");
        display.println(seconds);
        display.println(" ");
        display.display();
      }
      if (seconds == 0 && minutes >= 1) {
        seconds = 60;
        minutes = minutes - 1;
        display.setCursor(4, 1);
        display.clearDisplay();
        display.print("hours ");
        display.println(hours);
        display.print("minutes ");
        display.println(minutes);
        display.print("seconds ");
        display.println(seconds);
        display.println(" ");
        display.display();
      }
      else if (minutes == 0 && hours == 0 && seconds == 0) { //count down alarm
        while (timeState == true) {
          display.setCursor(4, 1);
          display.clearDisplay();
          display.print("hours ");
          display.println(hours);
          display.print("minutes ");
          display.println(minutes);
          display.print("seconds ");
          display.println(seconds);
          display.println(" ");
          display.display();

          tone(11, 600, 250);

          delay(250);
          tone(11, 800, 250);
          delay(250);
          if (digitalRead(Start) == LOW) { // turn alarm off
            timeState = false;
            seconds = 1; /////////////////////////////////////////////

            display.setCursor(4, 1);
            display.clearDisplay();
            display.setCursor(0, 0);
            display.print("COUNT DOWN TIMER");
            display.setCursor(4, 20);
            display.print("00: 00: 00");
            display.display();
            break;
          }
        }
      }
      delay(992); // delay for keping time master setting!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
      seconds = seconds - 1;

      display.setCursor(4, 40);
      if (hours <= 9)
        display.clearDisplay();
      {
        display.print("0");
        display.print(hours);
        display.display();
      }

      display.print(":");

      display.display();
      if (minutes <= 9)
      {
        display.print("0");
        display.print(minutes);
        display.display();
      }

      display.print(":");
      display.display();
      if (seconds <= 9)
      {
        display.print("0");
        display.print(seconds);
        display.display();
      }


      if (digitalRead(Start) == LOW) {
        delay(1000);
        timeState = false;
        break;
      }
    }
  }


}

// Interrupt on A changing state
void doEncoderA() {
  // debounce
  if ( rotating ) delay (1); // wait a little until the bouncing is done

  // Test transition, did things really change?
  if ( digitalRead(encoderPinA) != A_set ) { // debounce once more
    A_set = !A_set;

    // adjust counter + if A leads B
    if ( A_set && !B_set )
      encoderPos = 1;

    rotating = false; // no more debouncing until loop() hits again
  }
}

// Interrupt on B changing state
void doEncoderB() {
  if ( rotating ) delay (1);
  if ( digitalRead(encoderPinB) != B_set ) {
    B_set = !B_set;
    // adjust counter – 1 if B leads A
    if ( B_set && !A_set )
      encoderPos = -1;

    rotating = false;

  }

}

Kannst du mal besser und genauer beschreiben, was geht und was nicht geht.
So weiß man ja nicht wo man anfangen soll, zu suchen.

Zur Anzeige empfehle ich Dir die Speicher sparende Bibliothek Home · olikraus/u8g2 Wiki · GitHub

Für Zeiten versuche mal den Eggtimer der MobaTools.

Beide Bibliotheken lassen sich mit dem Bibliotheksmanager der IDE installieren.

In Deinem Programm sind die delays Gift. Bitte vergiß vorübergehend, daß es delay() gibt.

Hi

Du hast ein Char-Array von 10 Stellen, übergibst dtostrf aber eine Gesamt-Breite von Drei?
Mit Null Nachkommastellen wird die Eingangs-Variable, Die eigentlich als FLOAT erwartet wird, zu einer maximal 3-stelligen Zahl.

Äh - der Sketch macht ganz sicher nicht, was Du Dir irgendwie vorgestellt hast.
Alleine das delay(1000);, Welches bei JEDEM loop()-Durchlauf geartet wird, dürfte ein verstellen der Eieruhr nicht gerade vereinfachen.

WAS willst Du?
WAS erwartest Du von Deinem Sketch?
WAS bekommst Du statt Dessen?
WO klemmt's?

MfG

PS: Etwas aufhübschen hättest Du den Code schon können, oder?

Hand-Drehencoder kann man locker pollen, dafür braucht's keinen Interrupt, wo man 'auf beiden Seiten' benutzte Variablen volatile deklarieren sollte.
Du müllst das Display mit Zeichen voll - ganz egal, ob sich Diese überhaupt geändert haben.
Zeile 194 soll mir was sagen?
Ich meine

      delay(992); // delay for keping time master setting!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Nachdem Du in mühevoller Kleinarbeit die Uhrzeit auf's Display gezaubert hast, löscht Du Dieses und printest die Werte erneut, nur sieses Mal mit vorgestelltem 'hours' und so Kram.
Dein Runterzählen erschließt sich mir nicht, habe aber auch nicht wirklich versucht, mir Das dann Alles durch's Hirn zu ziehen.
Würde mir Funktionen schreiben, Die nur die Sekunde/Minute/Stunde runterzählen und mir bei Übertrag ein Flag zurück geben.

boolean decSec(){
  boolean retvar=false;
  if (!sekunde){
    retvar=true;
    sekunde=60;
  }
  sekunde--; // *edit* ich vergaß
  return retvar;
}
// Dann Was in der Richtung:
if (decSec()){
   if(decMin()){
     if(decStd()){
        //wir sind auf 0:00:00, ALAAARM 1ELF1!!!!!!!
    }
  }
}

Nur, wenn Sekunde (Minute(Stunde)) 'untergelaufen' ist, wird die nächst größere Zeiteinheit überhaupt betrachtet.
Wenn selbst die Stunden auf 'unter Null' laufen, sind's überall Null - Merken, daß wir einen Alarm haben (und hier dann wohl nicht weiter runter zählen).

Deine Menü-Struktur kann man so machen, Das passt halbwegs.

MfG²

@postmaster-ino
Warum verwendest du für deinen Code keine Code-Tags. Mit wird das besser lesbar.

Also wie ich schon schrieb habe ich nicht wirklich Ahnung und habe mir die Codes zusammen geschustert aus mehreren.... Ich habe keine Ahnung von Interrupts usw... die Infos die da dahinter stehen kommen von den anderen Codes... Was ich wollte.... Ich möchte ein Programm bei dem ich per Encoder eine Zeit einstellen kann.. Minuten und Sekunden reichen mir.. Dann drücke ich auf Start und mein Relais geht an und das Display zählt runter bis null und schaltet dann das Relais wieder aus... Der Pieper ist nicht bedingt notwendig aber wäre trotzdem cool. Habe ein 0,96" Oled Display.
Hört sich bestimmt einfach an, für mich aber irgendwie ein unüberwindbares Problem, sorry ich kanns noch nicht. Wer weiss ob ichs überhauptmal Check.

Und ich habe auch keine Ahnung von Arrays.... mir ist das wurscht wie der Code aussieht... Einfach wäre natürlich cool, damit ichs überhauptmal verstehen kann.

Gruss Andy

Damit du das verstehst, solltest du mit einfachen Dingen anfangen und die Basics lernen.
Da gibt es genügend Beispiele in der IDE.

Um deinen Sketch zu optimieren, müsste der komplett umgeschrieben werden.
So ist der kaum zu verstehen.

Ja das dachte ich mir schon das der Code völligst daneben ist :slight_smile: . Ich habe schon paar versuche aus den Beispielen gemacht ! Aber irgendwie ist das schon bisschen heftiger... Vielleicht erbahmt sich ja jemand und versucht das für mich... Ich möchte hier auf keinen Fall den Eindruck erwecken, das ich mir hier nur den Code schreiben lassen möchte... aber dieser Code würde mir halt einfach weiterhelfen. Auch um besser zu verstehen wie das angeordnet werden muss etc.

Andy

PS: Habe mir gerade die u8g2 installiert

Hi

Wenn's Dir eh 'wurscht ist', wie der Code nachher aussieht, wirst Du wohl nicht vorhaben, mehr Zeit in Arduino und Co einzubringen - schade eigentlich.
Auch Deine Aussagen zu DEINEM Sketch lassen mich nicht erkennen, daß Du Interesse an der Entwicklung einer Lösung hast.
Wohl schon an der Lösung, aber bitte ohne selber dafür Finger krümmen zu müssen.

@Hotsystems
Die Code-Fetzen stellen eher Pseudo-Code dar, vll. etwas von der Arduino-IDE angehaucht.
Aber ok, packe einen Code-Tag drum herum.
(davon ab wären die paar Funktionsaufrufe so noch lange kein Ziel-Einlauf, Da fehlt dann doch schon noch die eine oder andere Gehirnwindungsanwendung)

MfG

PS: Besonders stolz bin ich auf die vielen Ausrufezeichen

Nö, das lass ich nicht so stehen... erstens habe ich tagelang rumprobiert bis es mir auf den Sack gegangen ist, und ich habe auch geschrieben das ich mir den Code aus anderen zusammen gewürfelt habe... leider wie man sieht ohne Erfolg. Ich möchte definitiv mehr lernen und finde es eigentlich auch etwas unverschämt was du schreibst... Ich habe mir schon mehrere Atinys gekauft und auch ATMegas !!!... Ich habe ein grosses Starterkit mehrere Nano Clone usw... Und ich benutze durchaus einige Hirnwindungen. Der Code sah anfangs auch anders aus... aber durch ewiges rumspielen sieht er nun so aus.... So. Aber ich kenne das ja aus Foren das immer einer dabei ist der sich seine Komentare nicht verkneifen kann... Was soll ich den noch machen ausser mir hier die blösse zu geben und zu sagen das ich es nicht check??? Einen Programmierer engagieren ?

Dieser Code dient mir als Steuerung ein selbstgebauten Belichtungsanlage für Fotoplatinen, um dann mal bessere sachen hinzubekommen... Ja ich könnte auch wie jetzt aufs Handy schauen und dann nach 45sek den Stecker ziehen oder eine Zeitschaltuhr benutzen... Will ich aber nicht... Deswegen habe ich hier, ich hoffe, höfflich um Hilfe gebeten...

Das ist das frusttrierendste an allem das immer einer nen bescheuerten Kommentar hinterlässt der einem überhaupt nichts bringt ausser das man sich ärgert... Aber du hast natürlich nie um Hilfe gebeten und hast dir alles äusserst hart erkämpft....

So vielleicht hilft mir ja trotzdem jemand

Gruss Andy

Hi

Zumindest finde ich ab und an die Shift-Taste :slight_smile:
Wenn Du Das nicht so meinst, dann solltest Du Das nicht SO schreiben.

Und ich habe auch keine Ahnung von Arrays.... mir ist das wurscht wie der Code aussieht... Einfach wäre natürlich cool, damit ichs überhauptmal verstehen kann.

Gegen das 'keine Ahnung' ist gerade zu Zeiten des WWW durchaus ein Kraut gewachsen - GidF (auch Meiner).
Mir ist nicht wurscht, wie ein Code aussieht -vll. ticke ich Da einfach nur anders.

Aber Du musst Dich nicht über solche, meiner Meinung nach nicht ganz unnütze, Kommentare wundern.
Ich lese (ggf. zu Unrecht) in Deinem Post, daß Du keine Lust hast, Das selber zu erarbeiten.
Dein 'tagelanges Rumprobieren' lesen wir hier öfter - kann so passen, in 90% der Fälle war's vll. eine Stunde.
Tut Dir vll. Unrecht, aber immerhin besser, als mir - wenn's um meine Zeit geht, ist mir 'Meins' deutlich wichtiger, als Deines.

Zu meinen Fragen zu Deinem Sketch kam leider auch nur 'hmm ... zusammenkopiert ... was weiß ich, was Da passiert ... soll laufen ... mach Mal'.
Auch hatte ich irgend etwas zu Deiner Zählerei geschrieben - mir ist immer noch nicht klar, warum Du SO zählst - habe Dir aber auch meine Weise aufgezeigt - halt kein so ausführbarer Code - wo wir wieder bei Mitdenken wären.
Aber da Du keine Rückfragen dazu hast, wirst Du's ignoriert, oder verstanden haben.

Wenn Du den Sketch neu aufbaust und erst Mal NUR eine am Start festgelegte (fest im Code) Zeit 'runterzählst'.
Auch ist die Frage, ob man Stunden, Minuten, Sekunden macht, oder die Zeit rein in Sekunden zählt und nur für die Anzeige in Stunden/Minuten/Sekunden umrechnet.

Solange das einfache Runterzählen nicht klappt - brauchen wir uns um weitere Funktionalitäten keinen größeren Kopf machen.

Ich für meinen Teil möchte ganz gerne sehen, daß Du (eigentlich DU, sogar zwei große Buchstaben) die Lösung erarbeitest - halt mit Schubsern vom Forum.
Aber Du sollst Das machen - dann kannst Du Das - und schon hast Du genau Das gelernt, was Dir zuvor fehlte - mir geht Das, entgegen Deiner Annahme, nicht viel anders - wenngleich 'hart erkämpft' schon episch klingt.

MfG

Hi, ich kann dir dazu keine Antwort geben, da ich das aus einem anderem Timercode entnommen habe!!! Ich weiss nicht wie da irgendwas hoch oder runter zählt! Ich kann vielleicht eine Led zum leuchten bringen oder auch zwei... Ich habe mir diese u8g2 Lib installiert und habe auch nach dem MobaTools geschaut und diese auch installiert aber leider ist da nix von EggTimer drin. ICH HABE NOCH KEINE AHNUNG von dem ganzen Thema.. Ich kann noch nicht C++. Und du musst mir doch Recht geben wenn ich sage das diese Kommentare mich keinesfalls weiterbringen ! Ich bitte doch ganz höfflich um Hilfe... Ja mir wäre es auch sehr Recht wenn jemand einen Code schreiben würde, das ich diesen dann "analysieren" könnte... Tut mir Leid wenn ich das nicht so checke. Und ja ich habe da Tage wenn nicht über eine Woche die scheiss display hin und display her befehle von oben nach unten geschrieben und trotzdem macht das display nicht das was ich will....

Helf mir doch einfach oder tut dir das weh.... Sonst kann ich alles wieder auf die Seite legen und gut...
Ich habe nach Timern mit Eingabe gesucht wie blöd...aber nichts ist so wie ich es wollte. Und was soll ich denn lernen dabei wenn es nicht so ist wie ich mir das vorstelle?

Ich wäre dir sehr dankbar wenn du mir hilfst!!!!!

Ich bekomme hin das mir das Display am Anfang die Sachen zeigt wie Stunden, Minuten und Sekunden... sobald der Timer startet sehe ich nichts oder alles wird übereinander geschrieben. Der Pieper piept wenn fertig... auch wenn das irgendwie doppelt so lange dauert wie gewünscht. Dann zeigt er mir Countdown 0:0:0.

Wenn du sowas kannst dann würdest du mir echt dabei helfen wenn du diesen doofen schreibst und dann z.B. mit // erklärst was dort gerade passiert... ich weiss ja nicht mal wann ich eine Klammer brauche, wann nicht usw.
Und ich sags nochmal.. Ich habe echt versucht mit meinem Pseudo Wissen das zu schaffen bis ich fast den Laptop in die Ecke gehauen habe... Gefühlte 1000mal hab ich den Code hochgeladen !!!
Bitte

Hi

Ok ... Challenge accepted

Du möchtest einen Timer, Der runterzählt und bei Null damit aufhört.
Wir brauchen dafür eine Startzeit - wenn wir der Schaltung das erste Mal Strom geben (... die Batterien wechseln), soll das Ding ja nicht direkt mit Höllenlärm daher kommen.

Zeiten laufen beim Arduino im Datentyp uint32_t - Das bedeutet
u unsigned, vorzeichenlos - nur positive Zahlen (und Null)
int Integer, keine Kommastellen, also nur ganze Zahlen
32 Länge in Bit, macht einen Zahlenvorrat von 2^32, oder 0...4294967295 (2^32 - 1, da die Null auch mit spielt ist's Einer weniger)

Der Einfachheit halber zählen wir nur Sekunden, so müssen wir uns nur EINE Zahl merken und auch nur prüfen, ob EINE Zahl Null ist.
Die Übergabe gerne in Stunden/Minuten/Sekunden - beim Einstellen gibt's die Werte ja eh.

Dann sekundenweise runtergezählt bis Null.

//Sketch soll einen Countdown ablaufen lassen
//Am Ende des Countdown soll ein ALARM angezeigt werden
//https://forum.arduino.cc/index.php?topic=661900.0

byte _stunde = 0; //Variablen, Die die Soll-Laufzeit beinhalten, später einstellbar
byte _minute = 0;
byte _sekunde = 11;
uint32_t countdowntimer;  //global, wird mit Null initialisiert
const uint32_t wartesekunde = 1000; //1000ms = 1 Sekunde, Wartezeit zwischen den Sekunden
const uint32_t wartealarm = 3000;   //3 Sekunden zwischen ALARM-Anzeigen
//somit haben wir keine 'magic numbers' im Sketch
void setup() {
  Serial.begin(9600);
  settimer();
}

void loop() {
  static boolean alarmaktiv = false; //bei Start 'kein Alarm'
  uint32_t aktmillis = millis(); //die aktuelle Uhrzeit
  static uint32_t oldmillis = aktmillis; //die 'alte' Uhrzeit, wird mit der allerersten Uhrzeit initialisiert
  if (!alarmaktiv) {
    if (aktmillis - oldmillis >= wartesekunde) {
      oldmillis += wartesekunde; //die gewartete Zeit aufaddieren
      if (--countdowntimer) { //hier erst runterzählen, dann auf NICHT-NULL prüfen
        printRestzeit(); //der Abzug ergab eine Zeit > 0
      } else {
        alarmaktiv = true; //der Abzug ergab Null -> Alarm
      }
    }
  } else {
    playAlarm();    //Wenn Alarm ... dann eben Alarm
  }
}

//Funktion setzt die Startzeit aufgrund der globalen Zeit-Variablen
void settimer(void) {
  countdowntimer =  (uint32_t)_stunde * 3600 + _minute * 60 + _sekunde;
}

//Funktion zeigt die Restzeit an
void printRestzeit(void) {
  Serial.println(countdowntimer);
}

//Funktion zeigt den Alarm an
void playAlarm(void) {
  uint32_t aktmillis = millis();  //lokale Variablen kann Es Mehrere geben
  static uint32_t oldmillis = aktmillis;
  static byte _status = 0;  //mehrere Alarm-Status (Mehrzahl ebenfalls Status)
  switch (_status) {
    case 0:     //Status 0=Ausgabe
      Serial.println("ALARM");
      _status++;
      oldmillis = aktmillis;
      break;
    case 1:     //Status 1=Warte auf Ende der Wartezeit
      if (aktmillis - oldmillis >= wartealarm) {
        _status = 0;
        oldmillis = aktmillis;
      }
      break;
    default: break; //wenn was Anderes als 0 oder 1 kommen würde, fängt
      // das default Das ab.
  }
}
/* Arduino Nano (oder Uno)
Der Sketch verwendet 2000 Bytes (6%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 224 Bytes (10%) des dynamischen Speichers, 1824 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.
*/

Bei Fragen: fragen!

MfG

PS: Der Sketch macht 'noch nicht ganz', was Du im Endeffekt haben willst :wink:

*Edit 08.02.2020
kam zufällig zum Testen - es fehlte (mindestens) ein static für alarmaktiv.
Sketch gegen definitiv funktionierende Version getauscht

Ich danke dir vielmals !!!! Genau so ist das super zu Checken... ein bisschen zumindest :slight_smile:

Ich schaue mir das gleich mal an !!!!
Ich habe wirklich verzweifelt versucht das hin zu bekommen !!!

Danke nochmals

Hallo, bissher versuche ich nun den Encoder (der ja funktioniert hat) mit einzubringen...

Warum macht er mir den Fehler bei settimer(); ??

//Sketch soll einen Countdown ablaufen lassen
//Am Ende des Countdown soll ein ALARM angezeigt werden

byte _stunde = 0; //Variablen, Die die Soll-Laufzeit beinhalten, später einstellbar
byte _minute = 0;
byte _sekunde = 10;
uint32_t countdowntimer;  //global, wird mit Null initialisiert
const uint32_t wartesekunde = 1000; //1000ms = 1 Sekunde, Wartezeit zwischen den Sekunden
const uint32_t wartealarm = 3000;   //3 Sekunden zwischen ALARM-Anzeigen
//somit haben wir keine 'magic numbers' im Sketch

#define encoderPinA 2 // links
#define encoderPinB 3 // rechts
#define encoderButton 5 // Schalterencoder
int SMS = 1;            //Stunde Minute Sekunde 
int encoderPos = 0; // a counter for the dial
unsigned int letzteencoderpos = 1; // change management ?????????
static boolean rotating = false; // debounce management
boolean links_set = false;
boolean rechts_set = false;
void setup() {
  Serial.begin(9600);
  settimer();
}




void loop() {
  boolean alarmaktiv = false; //bei Start 'kein Alarm'
  uint32_t aktmillis = millis(); //die aktuelle Uhrzeit
  static uint32_t oldmillis = aktmillis; //die 'alte' Uhrzeit, wird mit der allerersten Uhrzeit initialisiert
  if (aktmillis - oldmillis >= wartesekunde) {
    //sind seit der letzten 'alten Uhrzeit' 1000ms (=1 Sek) vergangen?
    if (!alarmaktiv) {  //Runterzählen nur, wenn kein Alarm
      if (--countdowntimer) { //hier erst runterzählen, dann auf NICHT-NULL prüfen
        printRestzeit(); //der Abzug ergab eine Zeit > 0
      } else {
        alarmaktiv = true; //der Abzug ergab Null -> Alarm
      }
    }
    oldmillis += wartesekunde; //die gewartete Zeit aufaddieren
  }
  if (alarmaktiv) {
    playAlarm();    //Wenn Alarm ... dann eben Alarm
  }


  if (digitalRead(encoderButton) == LOW)                    //Fehler
  {
    SMS = SMS + 1;
    if (SMS == 4)
    {
      SMS = 1;
    }
    delay(1000);
  }
  rotating = true; // reset the debouncer
  encoderPos = constrain(encoderPos, -1, 1);
  
  if (letzteencoderpos != encoderPos) {                         //Fehler

    if (SMS == 1) {
      _stunde = _stunde + encoderPos;
      _stunde = constrain(_stunde, 0, 48);  //Heisst maximal 48std? was bedeutet die 0?
    }
    else if (SMS == 2) {
      _minute = _minute + encoderPos;
      _minute = constrain(_minute, 0, 60);  //Würde sich hiermit erklären :-)
    }
    else if (SMS == 3) {
      _sekunde = _sekunde + encoderPos;
      _sekunde = constrain(_sekunde, 0, 60);
    }

}




//Funktion setzt die Startzeit aufgrund der globalen Zeit-Variablen
void settimer(void) {                                                 //Kann ich die Funktion nennen wie ich will ?
  countdowntimer = _stunde * 3600 + _minute * 60 + _sekunde;
}

//Funktion zeigt die Restzeit an
void printRestzeit(void) {
  Serial.println(countdowntimer);
}


void doEncoderA() {
  // debounce
  if ( rotating ) delay (1); // wait a little until the bouncing is done

  // Test transition, did things really change?
  if ( digitalRead(encoderPinA) != links_set ) { // debounce once more
    links_set = !links_set;

    // adjust counter + if A leads B
    if ( links_set && !rechts_set )
      encoderPos = 1;

    rotating = false; // no more debouncing until loop() hits again
  }
}

// Interrupt on B changing state
void doEncoderB() {
  if ( rotating ) delay (1);
  if ( digitalRead(encoderPinB) != rechts_set ) {
    rechts_set = !rechts_set;
    // adjust counter – 1 if B leads A
    if ( rechts_set && !links_set )
      encoderPos = -1
      break;
    case 1:     //Status 1=Warte auf Ende der Wartezeit
      if (aktmillis - oldmillis >= wartealarm) {
        _status = 0;
        oldmillis = aktmillis;
      }
      break;
    default: break; //wenn was Anderes als 0 oder 1 kommen würde, fängt
      // das default Das ab.
  }
}

Hi

Hehe - drück Mal in der IDE STRG+T.
Dann scrolle ganz nach Unten.
Du wirst sehen, daß die letzte Klammer NICHT ganz links am Rand steht.
Dir fehlt eine Klammer - denke, die schließende Klammer von loop() ist Dir verloren gegangen.

Die ganzen Funktionen, Die unter loop() stehen, fangen Alle eine Ebene weiter rechts an.
Das zieht sich bis zum Ende durch - also zumindest hier stimmen dann die Anzahl der Klammern wieder - aber am Ende von loop() wird Eine fehlen.

MfG

Mit den Datentypen aufpassen. Korrekt:

 countdowntimer = _stunde * 3600UL + _minute * 60 + _sekunde;

Und delay() hat hier eigentlich nichts mehr verloren. Jedenfalls nicht eine ganze Sekunde lang

Hi

Autsch - danke Dir - hatte nicht daran gedacht, daß hier (ohne das UL) in int gerechnet wird, dadurch kann die größte Zahl 32768 darstellen - bei mehr, fängt's unten wieder an (-32767).

Ggf. muß das 3600UL als erstes in der Formel stehen, damit der ganze Kram in UL (unsigned long ... uint32_t) berechnet wird.
Wobei selbst 23 (byte) *3600(uint32_t) ab dann in UL gerechnet werden sollte.

Das delay() ist hier, glaube ich, zu verschmerzen, sollte doch nur bei der Zeiteingabe 'greifen', oder was entging mir hier?
Aber Du hast schon rehct - wenn wir schon einen Drehencoder benutzen, sollte man Diesen auch drehen können - so macht's dann vll. doch keinen so großen Spaß, die Zeit einzustellen.

Beim Drehencoder kann man das delay() auch weglassen - einzig beim Button MUSS man das Prellen beachten.
Beim Encoder selber kann Das 'nur' zu vor-zurück-vor-zurück-vor Schlänkern führen.
So schnell drehst Du den Encoder nicht, daß Das 'aus dem Tritt' kommen dürfte.

Und den Button kann man als Flanke auswerten, ein delay(20) tut nicht weh und man ist trotzdem recht entprellt unterwegs.

MfG

Wo habe ich da jetzt wieder was vergessen und vorallem warum ? Jede Klammer hat seinen "Partner".

Fehler lautet jetzt 'playAlarm' was not declared in this scope.

//Sketch soll einen Countdown ablaufen lassen
//Am Ende des Countdown soll ein ALARM angezeigt werden

byte _stunde = 0; //Variablen, Die die Soll-Laufzeit beinhalten, später einstellbar
byte _minute = 0;
byte _sekunde = 10;
uint32_t countdowntimer;  //global, wird mit Null initialisiert
const uint32_t wartesekunde = 1000; //1000ms = 1 Sekunde, Wartezeit zwischen den Sekunden
const uint32_t wartealarm = 3000;   //3 Sekunden zwischen ALARM-Anzeigen
//somit haben wir keine 'magic numbers' im Sketch

#define encoderPinA 2 // links
#define encoderPinB 3 // rechts
#define encoderButton 5 // Schalterencoder
int SMS = 1;            //Stunde Minute Sekunde
int encoderPos = 0; // a counter for the dial
unsigned int letzteencoderpos = 1; // change management ?????????
static boolean rotating = false; // debounce management
boolean links_set = false;
boolean rechts_set = false;
void setup() {
  Serial.begin(9600);
  settimer();
}




void loop() {
  boolean alarmaktiv = false; //bei Start 'kein Alarm'
  uint32_t aktmillis = millis(); //die aktuelle Uhrzeit
  static uint32_t oldmillis = aktmillis; //die 'alte' Uhrzeit, wird mit der allerersten Uhrzeit initialisiert
  if (aktmillis - oldmillis >= wartesekunde) {
    //sind seit der letzten 'alten Uhrzeit' 1000ms (=1 Sek) vergangen?
    if (!alarmaktiv) {  //Runterzählen nur, wenn kein Alarm
      if (--countdowntimer) { //hier erst runterzählen, dann auf NICHT-NULL prüfen
        printRestzeit(); //der Abzug ergab eine Zeit > 0
      } else {
        alarmaktiv = true; //der Abzug ergab Null -> Alarm
      }
    }
    oldmillis += wartesekunde; //die gewartete Zeit aufaddieren
  }


  if (alarmaktiv)
  {
    playAlarm();    //Wenn Alarm ... dann eben Alarm
  }


  if (digitalRead(encoderButton) == LOW)                    //Fehler
  {
    SMS = SMS + 1;
    if (SMS == 4)
    {
      SMS = 1;
    }
    delay(20);
  }
  rotating = true; // reset the debouncer
  encoderPos = constrain(encoderPos, -1, 1);

  if (letzteencoderpos != encoderPos) {                         //Fehler

    if (SMS == 1) {
      _stunde = _stunde + encoderPos;
      _stunde = constrain(_stunde, 0, 48);  //Heisst maximal 48std? was bedeutet die 0?
    }
    else if (SMS == 2) {
      _minute = _minute + encoderPos;
      _minute = constrain(_minute, 0, 60);  //Würde sich hiermit erklären :-)
    }
    else if (SMS == 3) {
      _sekunde = _sekunde + encoderPos;
      _sekunde = constrain(_sekunde, 0, 60);
    }
  }
}




//Funktion setzt die Startzeit aufgrund der globalen Zeit-Variablen
void settimer(void) {                                                 //Kann ich die Funktion nennen wie ich will ?
  countdowntimer = _stunde * 3600UL + _minute * 60 + _sekunde;
}

//Funktion zeigt die Restzeit an
void printRestzeit(void) {
  Serial.println(countdowntimer);
}


void doEncoderA() {
  // debounce
  if ( rotating ) delay (1); // wait a little until the bouncing is done

  // Test transition, did things really change?
  if ( digitalRead(encoderPinA) != links_set ) { // debounce once more
    links_set = !links_set;

    // adjust counter + if A leads B
    if ( links_set && !rechts_set )
      encoderPos = 1;

    rotating = false; // no more debouncing until loop() hits again
  }
}

// Interrupt on B changing state
void doEncoderB() {
  if ( rotating ) delay (1);
  if ( digitalRead(encoderPinB) != rechts_set ) {
    rechts_set = !rechts_set;
    // adjust counter – 1 if B leads A
    if ( rechts_set && !links_set )
      encoderPos = -1;
    break;
  case 1:     //Status 1=Warte auf Ende der Wartezeit
    if (aktmillis - oldmillis >= wartealarm) {
      _status = 0;
      oldmillis = aktmillis;
    }
    break;
  default: break; //wenn was Anderes als 0 oder 1 kommen würde, fängt
    // das default Das ab.
  }
}
}
// Arduino Nano (oder Uno)
//Der Sketch verwendet 2012 Bytes (6%) des Programmspeicherplatzes. Das Maximum sind 30720 Bytes.erPos = -1;

rotating = false;


//Funktion zeigt den Alarm an
void playAlarm(void) {
  uint32_t aktmillis = millis();  //lokale Variablen kann Es Mehrere geben
  static uint32_t oldmillis = aktmillis;
  static byte _status = 0;  //mehrere Alarm-Status (Mehrzahl ebenfalls Status)
  switch (_status) {
    case 0:     //Status 0=Ausgabe
      Serial.println("ALARM");
      //_status++;
      oldmillis = aktmillis;
  }
}
//Globale Variablen verwenden 223 Bytes (10%) des dynamischen Speichers, 1825 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Schiebe mal die Funktion playAlarm vor die Benutzung. Da hat die IDE manchmal einen Hänger.

Gruß Tommy