Problem beim nachbau Tea Timer "gelöst"

Hallo erst mal an die Gemeinde, bin neu hier.

und hab gleich ein problem auf dem ich nicht ganz so bewandert bin,
hab mir den Tea-Timer nachgebaut :slight_smile:
mit einen arduino pro micro (Leonardo)

damit beginnen meine Probleme der sketch ist für einen arduino pro mini v13

bei meinen läuft das Display und der servo alles in einer endlos-schleife ohne eine Funktion des Knopfes oder des Potis für die zeit einstellung...

könnt ihr mir helfen.

 The circuit:
 * LCD RS pin to digital pin 14
 * LCD Enable pin to digital pin 16
 * LCD D4 pin to digital pin 6
 * LCD D5 pin to digital pin 5
 * LCD D6 pin to digital pin 4
 * LCD D7 pin to digital pin 3
 * LCD R/W pin to ground
 * LCD VSS pin to ground
 * LCD VDD pin to 5V
 * LCD LEDA pin to digital pin 9
 * LCD LEDB pin to ground
 * 10K contrast potentiometer:
   * ends to 5V and ground
   * wiper to LCD VO pin
 
 * selection button to digital pin 2 and ground
 * 10K selection potentiometer:
   * ends to 5V and ground
   * wiper to analog pin A0
 * servo motor:
   * power wire to 5V
   * ground wire to ground
   * signal wire to digital pin 7
 * buzzer to digital pin 8 and ground
*/

#include <LiquidCrystal.h>
#include <Servo.h>

//state identifiers:
#define MENU 0
#define INPROCESS 1
#define DONE 2

const String welcomeMessage = ("Willkomen!");
const String doneMessage = ("Fertig!");

const int buttonPin = 2;
const int servoPin = 7;
const int buzzerPin = 8;
const int backlightPin = 9;
const int potPin = A0; // selection potentiometer
const int servoHighPosition = 150;
const int servoLowPosition = 70;
const int servoSpeedDelay = 20; // decrease this value to increase the servo speed

unsigned long steepingTime;
unsigned long startTime;
long timeLeft;

volatile int state;

LiquidCrystal lcd(14, 16, 6, 5, 4, 3);
Servo servo;

//custom LCD characters:
byte leftArrow[8] = {0,0,4,12,28,12,4,0};
byte rightArrow[8] = {0,0,4,6,7,6,4,0};
byte clock[8] = {0,14,21,23,17,14,0,0};
byte sandTimer[8] = {31,17,10,4,10,31,31,0};
byte teaCup[8] = {10,5,0,31,25,9,15,0};

void setup() {

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buzzerPin, OUTPUT);
  pinMode(backlightPin, OUTPUT);
  
  attachInterrupt(0, buttonISR, CHANGE);
  servo.attach(servoPin);
    
  digitalWrite(backlightPin, HIGH);
  
  lcd.createChar(0, leftArrow);
  lcd.createChar(1, rightArrow);
  lcd.createChar(2, clock);
  lcd.createChar(3, sandTimer);
  lcd.createChar(4, teaCup);
  
  state = MENU;
  
  lcd.begin(16, 2);
  lcd.print(welcomeMessage);
}

void loop() {

  switch(state){
  
    case MENU:       moveServoTo(servoHighPosition);
                     lcd.clear();
                       
                     lcd.setCursor(11,1);
                     lcd.print("start");
                     
                     lcd.setCursor(8,1); 
                     lcd.write(byte(0));  //display selection arrows
                     lcd.write(byte(1));
                     
                     lcd.setCursor(1,0); 
                     lcd.write(byte(2));  //display clock symbol
                                                                        
                     while(state == MENU){
                                              
                       steepingTime = 30000 * map(analogRead(potPin),0,1023,1,20);
                       lcd.setCursor(3,0);
                       lcd.print(millisToTime(steepingTime));
                       delay(200);                                               
                     }
      break;
    
    case INPROCESS:  moveServoTo(servoLowPosition);
                     startTime = millis();
                     
                     lcd.clear();
                     
                     lcd.setCursor(12,1);
                     lcd.print("stop");
                     
                     lcd.setCursor(1,0); 
                     lcd.write(byte(3));  //display sand timer symbol              
          
                     while(state == INPROCESS){
                      
                       timeLeft = steepingTime - (millis() - startTime);
                       
                       if(timeLeft > 0){                    
                         
                         lcd.setCursor(3,0);
                         lcd.print(millisToTime(timeLeft));
                       }
                       else state = DONE;    
                       
                       delay(500);                    
                     }               
      break;
       
    case DONE:       lcd.clear();
                     lcd.setCursor(1,0);
                     lcd.print(doneMessage + " ");
                     
                     lcd.write(byte(4));  //display tea cup symbol
                                          
                     moveServoTo(servoHighPosition);
                                        
                     doneBeep();
                     
                     lcd.setCursor(12,1);
                     lcd.print("menu");
                     
                     while(state == DONE);                
      break; 
  }
}


void buttonISR(){
  
  static unsigned long lastInterruptTime = 0; //used to debounce button input
  unsigned long interruptTime = millis();
  
  if(interruptTime - lastInterruptTime > 500){ //long debounce time to allow long presses
       
    switch(state){
    
      case MENU:       state = INPROCESS;
                  
        break;
      
      case INPROCESS:  state = MENU;
                     
        break;
      
     case DONE:        state = MENU;
                  
        break;
    }
  }
  lastInterruptTime = interruptTime;
} 


void moveServoTo(int finalPosition){ //move the servo slowly to the desired position

  int currentPosition = servo.read();
  
  if(finalPosition > currentPosition){
  
    for(int i = currentPosition; i <= finalPosition; i++){
    
      servo.write(i);
      delay(servoSpeedDelay);
    }
  }
  else if(finalPosition < currentPosition){
  
    for(int i = currentPosition; i >= finalPosition; i--){
    
      servo.write(i);
      delay(servoSpeedDelay);
    }
  }
}  

String millisToTime(long milliseconds){

  unsigned long minutes = (milliseconds/1000) / 60;
  unsigned long seconds = (milliseconds/1000) % 60;
  
  String minutesString = String(minutes);
  String secondsString = String(seconds);
  
  if(minutes < 10) minutesString = "0" + minutesString;
  
  if(seconds < 10) secondsString = "0" + secondsString;
   
  return minutesString + ":" + secondsString; 
}

void doneBeep(){

  tone(buzzerPin, 4000, 700);
}

"

tea_timer_schem.pdf (675 KB)

Setze Deinen Code bitte direkt ins Forum. Benutze dazu Codetags (</>-Button oben links im Forumseditor oder [code] davor und [/code] dahinter ohne *).
Dann ist er auch auf mobilen Geräten besser lesbar.
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

Man sollte keinen Sketch übernehmen, außer man hält sich genau an die Vorgaben.
Man sollte keinen Sketch übernehmen, der Taster mit einer ISR abfragt.

Das einfachste ist natürlich, du besorgst dir einen Nano oder Pro Mini, wenn du schon genau diesen Sketch nachbauen willst.

ok, sorry

Schön dass du den Code hierein gestellt hast.
Den Interrupt brauchst du nicht, denke ich.
Die FunktionbuttonISRverstehe ich so, dass bei einem Tastendruck über 0.5 s der Zustand weitergeschaltet werden soll. Das geht auch einfach ohne attachInterrupt - Aufruf in setup()

aber mit

void checkButton() {
   static bool btnState;
   if (digitalRead(buttonPin) != btnState ) { btnState = ! btnState; buttonISR(); }
}

Die Funktion buttonISR() kann da unverändert weiterverwendet werden.

In die Schleifen

 while(state == MENU) {
   ...
  }

etc. und am Anfang von loop vor
switch state() {
muss man jeweils den Funktionsaufruf checkButton(); einfügen.

Hallo und danke,

nach dem ich es eingefügt habe kommt eine Fehler Meldung.

tea_timer:91:19: error: initializer provided for function

void checkButton()( {

^

tea_timer:235:1: error: expected ',' or ';' at end of input

}

^

exit status 1
'buttonISR' was not declared in this scope

eingefügt hab ich es so.

 The circuit:
* LCD RS pin to digital pin 14
* LCD Enable pin to digital pin 16
* LCD D4 pin to digital pin 6
* LCD D5 pin to digital pin 5
* LCD D6 pin to digital pin 4
* LCD D7 pin to digital pin 3
* LCD R/W pin to ground
* LCD VSS pin to ground
* LCD VDD pin to 5V
* LCD LEDA pin to digital pin 9
* LCD LEDB pin to ground
* 10K contrast potentiometer:
  * ends to 5V and ground
  * wiper to LCD VO pin

* selection button to digital pin 2 and ground
* 10K selection potentiometer:
  * ends to 5V and ground
  * wiper to analog pin A0
* servo motor:
  * power wire to 5V
  * ground wire to ground
  * signal wire to digital pin 7
* buzzer to digital pin 8 and ground
*/

#include <LiquidCrystal.h>
#include <Servo.h>

//state identifiers:
#define MENU 0
#define INPROCESS 1
#define DONE 2

const String welcomeMessage = ("Willkomen!");
const String doneMessage = ("Fertig!");

const int buttonPin = 2;
const int servoPin = 7;
const int buzzerPin = 8;
const int backlightPin = 9;
const int potPin = A0; // selection potentiometer
const int servoHighPosition = 150;
const int servoLowPosition = 70;
const int servoSpeedDelay = 20; // decrease this value to increase the servo speed

unsigned long steepingTime;
unsigned long startTime;
long timeLeft;

volatile int state;

LiquidCrystal lcd(14, 16, 6, 5, 4, 3);
Servo servo;

//custom LCD characters:
byte leftArrow[8] = {0,0,4,12,28,12,4,0};
byte rightArrow[8] = {0,0,4,6,7,6,4,0};
byte clock[8] = {0,14,21,23,17,14,0,0};
byte sandTimer[8] = {31,17,10,4,10,31,31,0};
byte teaCup[8] = {10,5,0,31,25,9,15,0};

void setup() {

 pinMode(buttonPin, INPUT_PULLUP);
 pinMode(buzzerPin, OUTPUT);
 pinMode(backlightPin, OUTPUT);
 
 attachInterrupt(0, buttonISR, CHANGE);
 servo.attach(servoPin);
   
 digitalWrite(backlightPin, HIGH);
 
 lcd.createChar(0, leftArrow);
 lcd.createChar(1, rightArrow);
 lcd.createChar(2, clock);
 lcd.createChar(3, sandTimer);
 lcd.createChar(4, teaCup);
 
 state = MENU;
 
 lcd.begin(16, 2);
 lcd.print(welcomeMessage);
}

void checkButton()( {
  static bool btnState;
  if (digitalRead(buttonPin) != btnState ) { btnState = ! btnState; buttonISR(); }
}

void loop() {
 
ckeckButton()
 switch(state){
 
   case MENU:       moveServoTo(servoHighPosition);
                    lcd.clear();
                      
                    lcd.setCursor(11,1);
                    lcd.print("start");
                    
                    lcd.setCursor(8,1); 
                    lcd.write(byte(0));  //display selection arrows
                    lcd.write(byte(1));
                    
                    lcd.setCursor(1,0); 
                    lcd.write(byte(2));  //display clock symbol
                                                                       
                    while(state == MENU){
                                             
                      steepingTime = 30000 * map(analogRead(potPin),0,1023,1,20);
                      lcd.setCursor(3,0);
                      lcd.print(millisToTime(steepingTime));
                      delay(200);                                               
                    }
     break;
   
   case INPROCESS:  moveServoTo(servoLowPosition);
                    startTime = millis();
                    
                    lcd.clear();
                    
                    lcd.setCursor(12,1);
                    lcd.print("stop");
                    
                    lcd.setCursor(1,0); 
                    lcd.write(byte(3));  //display sand timer symbol              
         
                    while(state == INPROCESS){
                     
                      timeLeft = steepingTime - (millis() - startTime);
                      
                      if(timeLeft > 0){                    
                        
                        lcd.setCursor(3,0);
                        lcd.print(millisToTime(timeLeft));
                      }
                      else state = DONE;    
                      
                      delay(500);                    
                    }               
     break;
      
   case DONE:       lcd.clear();
                    lcd.setCursor(1,0);
                    lcd.print(doneMessage + " ");
                    
                    lcd.write(byte(4));  //display tea cup symbol
                                         
                    moveServoTo(servoHighPosition);
                                       
                    doneBeep();
                    
                    lcd.setCursor(12,1);
                    lcd.print("menu");
                    
                    while(state == DONE);                
     break; 
 }
}


void buttonISR(){
 
 static unsigned long lastInterruptTime = 0; //used to debounce button input
 unsigned long interruptTime = millis();
 
 if(interruptTime - lastInterruptTime > 500){ //long debounce time to allow long presses

ckeckButton()       
   switch(state){
   
     case MENU:       state = INPROCESS;
                 
       break;
     
     case INPROCESS:  state = MENU;
                    
       break;
     
    case DONE:        state = MENU;
                 
       break;
   }
 }
 lastInterruptTime = interruptTime;
} 


void moveServoTo(int finalPosition){ //move the servo slowly to the desired position

 int currentPosition = servo.read();
 
 if(finalPosition > currentPosition){
 
   for(int i = currentPosition; i <= finalPosition; i++){
   
     servo.write(i);
     delay(servoSpeedDelay);
   }
 }
 else if(finalPosition < currentPosition){
 
   for(int i = currentPosition; i >= finalPosition; i--){
   
     servo.write(i);
     delay(servoSpeedDelay);
   }
 }
}  

String millisToTime(long milliseconds){

 unsigned long minutes = (milliseconds/1000) / 60;
 unsigned long seconds = (milliseconds/1000) % 60;
 
 String minutesString = String(minutes);
 String secondsString = String(seconds);
 
 if(minutes < 10) minutesString = "0" + minutesString;
 
 if(seconds < 10) secondsString = "0" + secondsString;
  
 return minutesString + ":" + secondsString; 
}

void doneBeep(){

 tone(buzzerPin, 4000, 700);
}

Hi

Du darfst der Meldung glauben - dabei fängst Du von OBEN an - der Rest sind zumeist Folgefehler.
In der Zeile, Die angemeckert wird, sehe ich zwei öffnende Klammern und eine Schließende - hätte hier zumindest ein paarweises Auftreten erwartet.

MfG

Oops ja, da hat sich ein '(' zuviel eingeschlichen, bzw. ich habs in der IDE sofort korrigiert ohne das hier nachzuziehen.

Sorry. Den früheren Beitrag aktualisiert.
Würde vorschlagen, den nächsten Komplett-Sketch (bei Bedarf) lieferst wieder du :slight_smile:
Diesmal in ... Tags

Wenn dann muss es heissen:

void loop() {
 
ckeckButton();
 switch(state){

und nicht (wie bei Dir):

void loop() {
 
ckeckButton()
 switch(state){

checkButton() ist nicht das gleiche wie ckeckButton()
gerade gesehen: es gibt tatsächlich ckeckbutton() :sleeping:

es gibt tatsächlich ckeckbutton()

Nein, nicht wirklich. Definiert ist nur die Funktion

void checkbutton() {
...
}

Wer Tippfehler abschreibt, wird erwischt :slight_smile:

Gestern nach acht war offensichtlich zu spät für mich. Sorry.

Ein Funktionsaufruf braucht natürlich ein ; wie jede andere Anweisung auch.


Und das attachInterrupt muss/kann raus !

Nach bestem Wissen also:

 The circuit:
* LCD RS pin to digital pin 14
* LCD Enable pin to digital pin 16
* LCD D4 pin to digital pin 6
* LCD D5 pin to digital pin 5
* LCD D6 pin to digital pin 4
* LCD D7 pin to digital pin 3
* LCD R/W pin to ground
* LCD VSS pin to ground
* LCD VDD pin to 5V
* LCD LEDA pin to digital pin 9
* LCD LEDB pin to ground
* 10K contrast potentiometer:
  * ends to 5V and ground
  * wiper to LCD VO pin

* selection button to digital pin 2 and ground
* 10K selection potentiometer:
  * ends to 5V and ground
  * wiper to analog pin A0
* servo motor:
  * power wire to 5V
  * ground wire to ground
  * signal wire to digital pin 7
* buzzer to digital pin 8 and ground
*/

#include <LiquidCrystal.h>
#include <Servo.h>

//state identifiers:
#define MENU 0
#define INPROCESS 1
#define DONE 2

const String welcomeMessage = ("Willkomen!");
const String doneMessage = ("Fertig!");

const int buttonPin = 2;
const int servoPin = 7;
const int buzzerPin = 8;
const int backlightPin = 9;
const int potPin = A0; // selection potentiometer
const int servoHighPosition = 150;
const int servoLowPosition = 70;
const int servoSpeedDelay = 20; // decrease this value to increase the servo speed

unsigned long steepingTime;
unsigned long startTime;
long timeLeft;

volatile int state;

LiquidCrystal lcd(14, 16, 6, 5, 4, 3);
Servo servo;

//custom LCD characters:
byte leftArrow[8] = {0,0,4,12,28,12,4,0};
byte rightArrow[8] = {0,0,4,6,7,6,4,0};
byte clock[8] = {0,14,21,23,17,14,0,0};
byte sandTimer[8] = {31,17,10,4,10,31,31,0};
byte teaCup[8] = {10,5,0,31,25,9,15,0};

void setup() {

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buzzerPin, OUTPUT);
  pinMode(backlightPin, OUTPUT);
 
  servo.attach(servoPin);
   
  digitalWrite(backlightPin, HIGH);
 
  lcd.createChar(0, leftArrow);
  lcd.createChar(1, rightArrow);
  lcd.createChar(2, clock);
  lcd.createChar(3, sandTimer);
  lcd.createChar(4, teaCup);
 
  state = MENU;
 
  lcd.begin(16, 2);
  lcd.print(welcomeMessage);
}

void checkButton() {
  static bool btnState;
  if (digitalRead(buttonPin) != btnState ) { btnState = ! btnState; buttonISR(); }
}

void loop() {
 
 checkButton();
 switch(state){
 
   case MENU:       
          moveServoTo(servoHighPosition);
          lcd.clear();
                     
          lcd.setCursor(11,1);
          lcd.print("start");
                   
          lcd.setCursor(8,1);
          lcd.write(byte(0));  //display selection arrows
          lcd.write(byte(1));
                   
          lcd.setCursor(1,0);
          lcd.write(byte(2));  //display clock symbol
                                                                       
          while(state == MENU){
                      checkbutton();                                           
                      steepingTime = 30000 * map(analogRead(potPin),0,1023,1,20);
                      lcd.setCursor(3,0);
                      lcd.print(millisToTime(steepingTime));
                      delay(200);                                              
          }
          break;
   
   case INPROCESS:  moveServoTo(servoLowPosition);
          startTime = millis();
              
          lcd.clear();
                   
          lcd.setCursor(12,1);
          lcd.print("stop");
                
          lcd.setCursor(1,0);
          lcd.write(byte(3));  //display sand timer symbol              
         
          while(state == INPROCESS){
                      checkbutton();                                           
           
                      timeLeft = steepingTime - (millis() - startTime);
                     
                      if(timeLeft > 0){                    
                       
                          lcd.setCursor(3,0);
                          lcd.print(millisToTime(timeLeft));
                      }
                      else state = DONE;    
                     
                      delay(500);                    
           }              
           break;
     
   case DONE:
          lcd.clear();
          lcd.setCursor(1,0);
          lcd.print(doneMessage + " ");
                   
          lcd.write(byte(4));  //display tea cup symbol
                                         
          moveServoTo(servoHighPosition);
                                       
          doneBeep();
                   
          lcd.setCursor(12,1);
          lcd.print("menu");
                   
          while(state == DONE)  checkbutton();                                           
                
          break;
 }
}


void buttonISR(){
 
   static unsigned long lastInterruptTime = 0; //used to debounce button input
   unsigned long interruptTime = millis();
 
   if(interruptTime - lastInterruptTime > 500) { //long debounce time to allow long presses

      switch(state){
        case MENU:           state = INPROCESS;   break;
        case INPROCESS:  state = MENU;            break;
        case DONE:           state = MENU;           break;
      }
  }
  lastInterruptTime = interruptTime;
}


void moveServoTo(int finalPosition){ //move the servo slowly to the desired position

  int currentPosition = servo.read();
 
  if(finalPosition > currentPosition){
 
    for(int i = currentPosition; i <= finalPosition; i++){
   
     servo.write(i);
     delay(servoSpeedDelay);
    }
  }
  else if(finalPosition < currentPosition){
 
    for(int i = currentPosition; i >= finalPosition; i--){
   
      servo.write(i);
      delay(servoSpeedDelay);
    }
  }
}  

char*  millisToTime(unsigned long milliseconds){
 static char result[]="99:99";
 unsigned int sec = milliseconds/1000; 
 byte minutes =  sec / 60;
 byte minutes1 = minutes % 10;
 byte minutes10 = minutes / 10 % 10; 
 byte seconds1 =  sec % 10;
 byte seconds10 =  sec % 60 / 10;

 result[0] = '0' + minutes10; 
 result[1] = '0' + minutes1;
 result[3] = '0' + seconds10;
 result[4] = '0' + seconds1;
 return result;
}

void doneBeep(){
   tone(buzzerPin, 4000, 700);
}

P.S. Die String-Orgie hab ich nicht ertragen

danke für die Hilfe,

Fehler Meldung ist jetzt etwas anders.

******\tea-timer-master\sketch\tea_timer\tea_timer.ino:132:23: note: suggested alternative: 'ckeckButton'

                      checkbutton();

                      ^~~~~~~~~~~

                      ckeckButton

tea_timer:161:33: error: 'checkbutton' was not declared in this scope

          while(state == DONE)  checkbutton();

                                ^~~~~~~~~~~

C:\Users\MM\Downloads\tea-timer-master\sketch\tea_timer\tea_timer.ino:161:33: note: suggested alternative: 'ckeckButton'

          while(state == DONE)  checkbutton();

                                ^~~~~~~~~~~

                                ckeckButton

exit status 1
'The' does not name a type

hab die Schreibfehler ausgebester :slight_smile:

#include <LiquidCrystal.h>
#include <Servo.h>

//state identifiers:
#define MENU 0
#define INPROCESS 1
#define DONE 2

const String welcomeMessage = ("Willkomen!");
const String doneMessage = ("Fertig!");

const int buttonPin = 2;
const int servoPin = 7;
const int buzzerPin = 8;
const int backlightPin = 9;
const int potPin = A0; // selection potentiometer
const int servoHighPosition = 150;
const int servoLowPosition = 70;
const int servoSpeedDelay = 20; // decrease this value to increase the servo speed

unsigned long steepingTime;
unsigned long startTime;
long timeLeft;

volatile int state;

LiquidCrystal lcd(14, 16, 6, 5, 4, 3);
Servo servo;

//custom LCD characters:
byte leftArrow[8] = {0,0,4,12,28,12,4,0};
byte rightArrow[8] = {0,0,4,6,7,6,4,0};
byte clock[8] = {0,14,21,23,17,14,0,0};
byte sandTimer[8] = {31,17,10,4,10,31,31,0};
byte teaCup[8] = {10,5,0,31,25,9,15,0};

void setup() {

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buzzerPin, OUTPUT);
  pinMode(backlightPin, OUTPUT);
 
  servo.attach(servoPin);
   
  digitalWrite(backlightPin, HIGH);
 
  lcd.createChar(0, leftArrow);
  lcd.createChar(1, rightArrow);
  lcd.createChar(2, clock);
  lcd.createChar(3, sandTimer);
  lcd.createChar(4, teaCup);
 
  state = MENU;
 
  lcd.begin(16, 2);
  lcd.print(welcomeMessage);
}

void ckeckButton() {
  static bool btnState;
  if (digitalRead(buttonPin) != btnState ) { btnState = ! btnState; buttonISR(); }
}

void loop() {
 
 ckeckButton();
 switch(state){
 
   case MENU:       
          moveServoTo(servoHighPosition);
          lcd.clear();
                     
          lcd.setCursor(11,1);
          lcd.print("start");
                   
          lcd.setCursor(8,1);
          lcd.write(byte(0));  //display selection arrows
          lcd.write(byte(1));
                   
          lcd.setCursor(1,0);
          lcd.write(byte(2));  //display clock symbol
                                                                       
          while(state == MENU){
                      checkbutton();                                           
                      steepingTime = 30000 * map(analogRead(potPin),0,1023,1,20);
                      lcd.setCursor(3,0);
                      lcd.print(millisToTime(steepingTime));
                      delay(200);                                             
          }
          break;
   
   case INPROCESS:  moveServoTo(servoLowPosition);
          startTime = millis();
             
          lcd.clear();
                   
          lcd.setCursor(12,1);
          lcd.print("stop");
               
          lcd.setCursor(1,0);
          lcd.write(byte(3));  //display sand timer symbol             
         
          while(state == INPROCESS){
                      checkbutton();                                           
           
                      timeLeft = steepingTime - (millis() - startTime);
                     
                      if(timeLeft > 0){                   
                       
                          lcd.setCursor(3,0);
                          lcd.print(millisToTime(timeLeft));
                      }
                      else state = DONE;   
                     
                      delay(500);                   
           }             
           break;
     
   case DONE:
          lcd.clear();
          lcd.setCursor(1,0);
          lcd.print(doneMessage + " ");
                   
          lcd.write(byte(4));  //display tea cup symbol
                                         
          moveServoTo(servoHighPosition);
                                       
          doneBeep();
                   
          lcd.setCursor(12,1);
          lcd.print("menu");
                   
          while(state == DONE)  checkbutton();                                           
               
          break;
 }
}


void buttonISR(){
 
   static unsigned long lastInterruptTime = 0; //used to debounce button input
   unsigned long interruptTime = millis();
 
   if(interruptTime - lastInterruptTime > 500) { //long debounce time to allow long presses

ckeckButton();
      switch(state){
        case MENU:           state = INPROCESS;   break;
        case INPROCESS:  state = MENU;            break;
        case DONE:           state = MENU;           break;
      }
  }
  lastInterruptTime = interruptTime;
}


void moveServoTo(int finalPosition){ //move the servo slowly to the desired position

  int currentPosition = servo.read();
 
  if(finalPosition > currentPosition){
 
    for(int i = currentPosition; i <= finalPosition; i++){
   
     servo.write(i);
     delay(servoSpeedDelay);
    }
  }
  else if(finalPosition < currentPosition){
 
    for(int i = currentPosition; i >= finalPosition; i--){
   
      servo.write(i);
      delay(servoSpeedDelay);
    }
  }
} 

char*  millisToTime(unsigned long milliseconds){
 static char result[]="99:99";
 unsigned int sec = milliseconds/1000;
 byte minutes =  sec / 60;
 byte minutes1 = minutes % 10;
 byte minutes10 = minutes / 10 % 10;
 byte seconds1 =  sec % 10;
 byte seconds10 =  sec % 60 / 10;

 result[0] = '0' + minutes10;
 result[1] = '0' + minutes1;
 result[3] = '0' + seconds10;
 result[4] = '0' + seconds1;
 return result;
}

void doneBeep(){
   tone(buzzerPin, 4000, 700);
}

geht aber leider immer noch nicht.

Hi

Wenn 'Geht nicht' die komplette Fehlerbeschreibung ist, dann dürfte "mach's richtig" Dein Lösungsweg sein.

MfG

Hallo Rambrot,

es gibt mehrere Wege dein Projekt zum laufen zu bringen.
Ein Weg wurde oben schon beschrieben. ALle Bauteile 1 zu 1 wie im Originalprojekt kaufen.

Oder Programmieren lernen.
Programmieren lernen ist relativ leicht. Mit vielen anderen Programmierumgebungen.
C++ = Arduino-IDE ist da eher ungünstig. Es gibt ganz viele Fehlermöglichkeiten.

"@C++-Fans: Ihr könnt von der Palme unten bleiben. Klar gibt es noch abgefahrener Sachen wie Haskell oder "Brainfuck"
Schon mal mit Delphi oder im Microcontroller-Bereich mit Parallax-Propeller-Chip in SPIN programmiert?
Wahrscheinlich nicht. In diesen IDEs können gar keine so abfuckten Fehler wie mit C++ /Arduino entstehen.

Zurück zum TeaTimer. Wenn ich den Quellcode den du als letztes gepostet hast über die Zwischenablage in meine Arduino-IDE kopiere und compilieren lasse gibt es folgende Fehlermeldung:

'byte clock [8]' redeclared as different kind of symbol
byte clock[8] = {0,14,21,23,17,14,0,0};

Dann habe ich "clock" umbenannt. Dann kam folgende Fehlermeldung
error: 'checkbutton' was not declared in this scope

checkbutton();

Eine Definition der function checkbutton(); kommt in dem code den du gepostest hast gar nicht vor.
Das bedeutet den Code den du gepostest hast ist unvollständig.
Diese Code-Version werde ich bestimmt nicht weiter untersuchen.

Wenn es besonders schnell gehen soll - geht es in Wirklichkeit besonders laaaaaangsaaaaam.

Ich schlage folgendes vor:
Du gehst zurück zum Originalcode.
Als erstes speicherst du den Originalcode mit einer angehängten Nummer "-001".
Dann änderst du ein winzig kleiners Fitzelchen speicherst diese Codeversion und lässt dann sofort neu
compilieren um zu prüfen ob es compiliert. Wenn der Compiler einen Fehler meldet steckt in dieser WInzigänderung schon ein Fehler. Zuerst diesen einen Fehler beseitigen und erst dann die nächste Änderung mamchen.
usw. usw. usf.

Jetzt magst du denken "och nö das dauert aber"
Die eine Alternative dazu ist viele Änderungen vor dem ersten Compiliertetst machen und dann umso länger suchen
wo die vielen Fehler alle sind.

Die andere Alternative ist: so gründlich programmieren lernen dass man die ganzen Compilerfehler auf Anhieb versteht und weiß was zu tun ist. Dauert noch länger.

Es stimmt schon was einer der Vielposter hier im Spruch stehen hat
"Wer den schnellen Erfolg sucht sollte nicht Programmieren sondern Holz hacken"

Und dann noch eine Bitte: Wenn du Quellcode im Forum postest dann bitte die ganz aktuelle Version
Einfach in der ArduinoIDE mit Strg-A, Strg-C in die Zwischenablage Code-Symbol im Forum anklicken
und mit Strg-V einfügen.

viele Grüße

Stefan

StefanL38:
Schon mal mit Delphi

Wie willst Du Delphi auf den MC bekommen?

Lazarus für Arduino gibt es ja schon.

Gruß Tommy

So - jetzt habe ich mir die Hardware-Beschreibung von Arduino pro mini und Arduino pro micro durchgelesen.
Du sagtest dass das Poti und der Button keine Wirkung haben.

Der Arduino pro kann externe Interrupts auf Pin 2 und pin 3

Der arduino pro micro hat einen anderen Chip als der pro mini.
Beim arduino pro micro kann man auf IO-Pin zwei nur den Interrupt 1 am PIN 2 auslösen

Im Tea_Timer-code steht

attachInterrupt(0, buttonISR, CHANGE);

Der Erste Parameter ist die Interrupt-Nummer beim arduino pro mini v13 wird interrupt 0 durch IO-Pin 2 ausgelöst.
Deshalb ist im Schaltplan der Schalter mit pin 2 verbunden.

Beim arduino pro micro wird interrupt 0 durch IO-Pin 3 ausgelöst.
Das heißt man müsste den code ändern auf
Diese Shit-Forums-software kriegt copy und Paste nicht auf die Reihe

const int buttonPin = 3;  // statt 2
// mit
attachInterrupt(0, buttonISR, CHANGE);

oder man müsste die Interrupt-Nummer ändern

const int buttonPin = 2
// mit
attachInterrupt(1, buttonISR, CHANGE);

Ob es dann so schon funktioniert kann ich nicht sicher sagen.

Dieses Tea-Timer-Projekt ist wieder eins von denen wo jemand was scheinbar einfaches zusammengefrickelt hat
und es mit minimaler Dokumentation veröffentlicht. Das MUSS ja geradezu zu Anfänger-Schwierigkeiten führen.

Noch besser wäre den code abzuändern, dass er OHNE Interrupt funktioniert.

@Tommy: Delphi auf dem Arduino geht net schon klar.
Lazarus kenne ich noch nicht. Ist der Name Programm = Programm weckt tote CPUs wieder auf??
Hab nachgeschaut aha OpenSource Delphi Nachbau.

so genug für heute.

viele Grüße

Stefan

Der erste Ansatz war, das ohne Interrupt zu machen, Stefan.
Da hast du nun vergebliche Mühe reingesteckt.

Dass bevorzugt Leute die was zusammengefrickelt haben und stolz sind, dass es trotzdem geht, das im Internet veröffentlichen, ist ein wesentlicher Bestandteil des Internets. Wer da was findet, der hat es an der Backe.

Jetzt zu deinen vorigen Details:

Mit byte clock[8] = {0,14,21,23,17,14,0,0};
sollte man eigentlich keine Schwierigkeiten haben ...
wird einmal definiert und einmal verwendet:

lcd.createChar(2, clock);

Dass clock (wie z.B. jede Variable namens status) rot dargestellt wird, nun ja: keine Ahnung warum die Arduino-IDE so beliebt ist. :slight_smile:

Das bedeutet den Code den du gepostest hast ist unvollständig

... oder die Funktion heißt checkButton statt checkbutton oder es schwirrt gar noch ein ckeckButton herum...
aber so weit waren wir auch schon.

Stimmt schon, in C++ kann man Fehler machen, die man in Basic nicht hinkriegt.
Das ist allerdings eine OT Diskussion.

Zumindest probe-übersetzen sollte man schon etwas, bevor man es postet, wenn der Compilerfehler nicht der Inhalt des Threads ist. Da bekenne ich mich schuldig!
Daher hier nochmal eine kompilierende Version (auch wenn es nicht mehr interessiert):

#include <LiquidCrystal.h>
#include <Servo.h>

//state identifiers:
#define MENU 0
#define INPROCESS 1
#define DONE 2

const char* welcomeMessage = ("Willkomen!");
const char* doneMessage = ("Fertig! ");

const int buttonPin = 2;
const int servoPin = 7;
const int buzzerPin = 8;
const int backlightPin = 9;
const int potPin = A0; // selection potentiometer
const int servoHighPosition = 150;
const int servoLowPosition = 70;
const int servoSpeedDelay = 20; // decrease this value to increase the servo speed

unsigned long steepingTime;
unsigned long startTime;
long timeLeft;

int state;

LiquidCrystal lcd(14, 16, 6, 5, 4, 3);
Servo servo;

//custom LCD characters:
byte leftArrow[8] = {0,0,4,12,28,12,4,0};
byte rightArrow[8] = {0,0,4,6,7,6,4,0};
static byte clock[8] = {0,14,21,23,17,14,0,0};
byte sandTimer[8] = {31,17,10,4,10,31,31,0};
byte teaCup[8] = {10,5,0,31,25,9,15,0};

void setup() {

  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(buzzerPin, OUTPUT);
  pinMode(backlightPin, OUTPUT);
 
  servo.attach(servoPin);
   
  digitalWrite(backlightPin, HIGH);
 
  lcd.createChar(0, leftArrow);
  lcd.createChar(1, rightArrow);
  lcd.createChar(2, clock);
  lcd.createChar(3, sandTimer);
  lcd.createChar(4, teaCup);
 
  state = MENU;
 
  lcd.begin(16, 2);
  lcd.print(welcomeMessage);
}

void checkButton() {
  static bool btnState;
  if (digitalRead(buttonPin) != btnState ) { btnState = ! btnState; buttonISR(); }
}

void loop() {
 
 checkButton();
 switch(state){
 
   case MENU:       
          moveServoTo(servoHighPosition);
          lcd.clear();
                     
          lcd.setCursor(11,1);
          lcd.print("start");
                   
          lcd.setCursor(8,1);
          lcd.write(byte(0));  //display selection arrows
          lcd.write(byte(1));
                   
          lcd.setCursor(1,0);
          lcd.write(byte(2));  //display clock symbol
                                                                       
          while(state == MENU){
                      checkButton();                                           
                      steepingTime = 30000 * map(analogRead(potPin),0,1023,1,20);
                      lcd.setCursor(3,0);
                      lcd.print(millisToTime(steepingTime));
                      delay(200);                                             
          }
          break;
   
   case INPROCESS:  moveServoTo(servoLowPosition);
          startTime = millis();
             
          lcd.clear();
                   
          lcd.setCursor(12,1);
          lcd.print("stop");
               
          lcd.setCursor(1,0);
          lcd.write(byte(3));  //display sand timer symbol             
         
          while(state == INPROCESS){
                       checkButton();                                          
           
                      timeLeft = steepingTime - (millis() - startTime);
                     
                      if(timeLeft > 0){                   
                       
                          lcd.setCursor(3,0);
                          lcd.print(millisToTime(timeLeft));
                      }
                      else state = DONE;   
                     
                      delay(500);                   
           }             
           break;
     
   case DONE:
          lcd.clear();
          lcd.setCursor(1,0);
          lcd.print(doneMessage);
                   
          lcd.write(byte(4));  //display tea cup symbol
                                         
          moveServoTo(servoHighPosition);
                                       
          doneBeep();
                   
          lcd.setCursor(12,1);
          lcd.print("menu");
                   
          while(state == DONE) checkButton();                                      
               
          break;
 }
}


void buttonISR(){
 
   static unsigned long lastInterruptTime = 0; //used to debounce button input
   unsigned long interruptTime = millis();
 
   if(interruptTime - lastInterruptTime > 500) { //long time to force a long press
      switch(state){
        case MENU:       state = INPROCESS;   break;
        case INPROCESS:  state = DONE;        break;
        case DONE:       state = MENU;        break;
      }
  }
  lastInterruptTime = interruptTime;
}


void moveServoTo(int finalPosition){ //move the servo slowly to the desired position

  int currentPosition = servo.read();
 
  if(finalPosition > currentPosition){
 
    for(int i = currentPosition; i <= finalPosition; i++){
   
     servo.write(i);
     delay(servoSpeedDelay);
    }
  }
  else if(finalPosition < currentPosition){
 
    for(int i = currentPosition; i >= finalPosition; i--){
   
      servo.write(i);
      delay(servoSpeedDelay);
    }
  }
}

char*  millisToTime(unsigned long milliseconds){
 static char result[]="99:99";
 unsigned int sec = milliseconds/1000;
 byte minutes =  sec / 60;
 byte minutes1 = minutes % 10;
 byte minutes10 = minutes / 10 % 10;
 byte seconds1 =  sec % 10;
 byte seconds10 =  sec % 60 / 10;

 result[0] = '0' + minutes10;
 result[1] = '0' + minutes1;
 result[3] = '0' + seconds10;
 result[4] = '0' + seconds1;
 return result;
}

void doneBeep(){
   tone(buzzerPin, 4000, 700);
}

Eigentlich geht es um die Verwendung der buttonISR ohne Interrupt. Und da scheint was zu gehen...

Hab mal LCD und Servo durch Serial Testausgaben ersetzt und das "Poti" fest auf 04:30 eingestellt.

//state identifiers:
#define MENU 0
#define INPROCESS 1
#define DONE 2

const char* welcomeMessage = ("Willkomen!");
const char* doneMessage = ("Fertig! ");

const int buttonPin = 2;

unsigned int servoSpeedDelay = 200;
int servoHighPosition = 10;
int servoLowPosition = 1;

unsigned long steepingTime;
unsigned long startTime;
long timeLeft;

int state;

void setup() {
  Serial.begin(9600);
  pinMode(buttonPin, INPUT_PULLUP);
  state = MENU;
 
  Serial.print(welcomeMessage);
}

void checkButton() {
  static bool btnState;
  if (digitalRead(buttonPin) != btnState ) { btnState = ! btnState; buttonISR(); }
}

void loop() {
 
 checkButton();
 switch(state){
 
   case MENU:       
          moveServoTo(servoHighPosition);
          Serial.print("start");
                   
          while(state == MENU){
                      checkButton();                                           
                      steepingTime = 30000 * map(450,0,1023,1,20);  // Voreinstellung 04:30
                      Serial.println(millisToTime(steepingTime));
                      delay(400);                                             
          }
          break;
   
   case INPROCESS:  moveServoTo(servoLowPosition);
          startTime = millis();
          Serial.print("stop");
          while(state == INPROCESS){
                      checkButton();                                          
                      timeLeft = steepingTime - (millis() - startTime);
                      if(timeLeft > 0){                   
                        Serial.println(millisToTime(timeLeft));
                      }
                      else state = DONE;   
                      delay(500);                   
           }             
           break;
     
   case DONE:
          Serial.print(doneMessage);
          moveServoTo(servoHighPosition);
                                       
          doneBeep();
          Serial.print("menu");
                   
          while(state == DONE) checkButton();                                      
               
          break;
 }
}


void buttonISR(){
 
   static unsigned long lastInterruptTime = 0; //used to debounce button input
   unsigned long interruptTime = millis();
 
   if(interruptTime - lastInterruptTime > 500) { //long time to force a long press
      switch(state){
        case MENU:       state = INPROCESS;   break;
        case INPROCESS:  state = DONE;        break;
        case DONE:       state = MENU;        break;
      }
  }
  lastInterruptTime = interruptTime;
}

void moveServoTo(int finalPosition){ //move the servo slowly to the desired position
  static int currentPosition;
  if(finalPosition > currentPosition){
    for(int i = currentPosition; i <= finalPosition; i++){
     Serial.write('+'); 
     currentPosition++;
     delay(servoSpeedDelay);
    }
  }
  else if(finalPosition < currentPosition){
    for(int i = currentPosition; i >= finalPosition; i--){
      Serial.write('-');
      currentPosition--;
      delay(servoSpeedDelay);
    }
  }
  Serial.println();
}

char*  millisToTime(unsigned long milliseconds){
 static char result[]="99:99";
 unsigned int sec = milliseconds/1000;
 byte minutes =  sec / 60;
 byte minutes1 = minutes % 10;
 byte minutes10 = minutes / 10 % 10;
 byte seconds1 =  sec % 10;
 byte seconds10 =  sec % 60 / 10;

 result[0] = '0' + minutes10;
 result[1] = '0' + minutes1;
 result[3] = '0' + seconds10;
 result[4] = '0' + seconds1;
 return result;
}

void doneBeep(){
  Serial.println("beep");
  delay(200);
}

Was wäre daran noch "geht nicht" ?

michael_x:
Hab mal LCD und Servo durch Serial Testausgaben ersetzt und das "Poti" fest auf 04:30 eingestellt.

//state identifiers:

#define MENU 0
#define INPROCESS 1
#define DONE 2

const char* welcomeMessage = ("Willkomen!");
const char* doneMessage = ("Fertig! ");

const int buttonPin = 2;

unsigned int servoSpeedDelay = 200;
int servoHighPosition = 10;
int servoLowPosition = 1;

unsigned long steepingTime;
unsigned long startTime;
long timeLeft;

int state;

void setup() {
Serial.begin(9600);
pinMode(buttonPin, INPUT_PULLUP);
state = MENU;

Serial.print(welcomeMessage);
}

void checkButton() {
static bool btnState;
if (digitalRead(buttonPin) != btnState ) { btnState = ! btnState; buttonISR(); }
}

void loop() {

checkButton();
switch(state){

case MENU:
moveServoTo(servoHighPosition);
Serial.print("start");

      while(state == MENU){
                  checkButton();                                           
                  steepingTime = 30000 * map(450,0,1023,1,20);  // Voreinstellung 04:30
                  Serial.println(millisToTime(steepingTime));
                  delay(400);                                             
      }
      break;

case INPROCESS: moveServoTo(servoLowPosition);
startTime = millis();
Serial.print("stop");
while(state == INPROCESS){
checkButton();
timeLeft = steepingTime - (millis() - startTime);
if(timeLeft > 0){
Serial.println(millisToTime(timeLeft));
}
else state = DONE;
delay(500);
}
break;

case DONE:
Serial.print(doneMessage);
moveServoTo(servoHighPosition);

      doneBeep();
      Serial.print("menu");
               
      while(state == DONE) checkButton();                                      
           
      break;

}
}

void buttonISR(){

static unsigned long lastInterruptTime = 0; //used to debounce button input
unsigned long interruptTime = millis();

if(interruptTime - lastInterruptTime > 500) { //long time to force a long press
switch(state){
case MENU: state = INPROCESS; break;
case INPROCESS: state = DONE; break;
case DONE: state = MENU; break;
}
}
lastInterruptTime = interruptTime;
}

void moveServoTo(int finalPosition){ //move the servo slowly to the desired position
static int currentPosition;
if(finalPosition > currentPosition){
for(int i = currentPosition; i <= finalPosition; i++){
Serial.write('+');
currentPosition++;
delay(servoSpeedDelay);
}
}
else if(finalPosition < currentPosition){
for(int i = currentPosition; i >= finalPosition; i--){
Serial.write('-');
currentPosition--;
delay(servoSpeedDelay);
}
}
Serial.println();
}

char* millisToTime(unsigned long milliseconds){
static char result[]="99:99";
unsigned int sec = milliseconds/1000;
byte minutes = sec / 60;
byte minutes1 = minutes % 10;
byte minutes10 = minutes / 10 % 10;
byte seconds1 = sec % 10;
byte seconds10 = sec % 60 / 10;

result[0] = '0' + minutes10;
result[1] = '0' + minutes1;
result[3] = '0' + seconds10;
result[4] = '0' + seconds1;
return result;
}

void doneBeep(){
Serial.println("beep");
delay(200);
}



Was wäre daran noch "geht nicht" ?

Die erste CodeVersion die du (micheal_x) gepostest hast hatte checkButton und checkbutton.
Der Thread-opener hat dann die Schreibweise korrigiert und es irgendwie geschafft dabei die Definition der function checkButton rauszulöschen. Dann geht natürlich noch nix.
viele Grüße
Stefan

vielen dank, hat geklappt.

das war der Fehler

attachInterrupt(1, buttonISR, CHANGE);

ich hatte

attachInterrupt(0, buttonISR, CHANGE);

drin.

vielen dank, an alle.

grüße
rambrot