Kleine Frage zwecks Motor

Hallo liebe Community,

Erfahrung mit Arduino habe ich null aber mit anderen Programmiersprachen wie Java.

Und zwar möchte ich einen Rolladenmotor mittels Taster, Relais und LED mit Blinkfunktion solange der Motor fährt.

Hardware ist auf dem Weg, aber ich hatte noch ein paar kleine Bauteile zum testen hier und Frage mich ob der angesetzte Weg der Richtige ist. Mein aktueller Programmcode, aktuell gibt es noch keine Laufzeit.

/*

*/
int led = 13;                               // Variable für Pin 13

int button = 8;                             // Variable für Pin 8

int buttonStatus;                           // in dieser Variable wird die Information

                                            // abgespeichert ob der Taster gerade gedrückt

                                            // wird oder nicht
                                            
int relais1pin = 9;                         // Relai 1 für Hoch

int relais2pin = 10;                        // Reali 2 für Runter

int upDown=1;                               // Status = unten 1, oben 2


void setup() {
  pinMode(LED_BUILTIN, OUTPUT);             // definiere Pin 13 als Ausgang
  pinMode(button, INPUT);                   // definiere Pin 8 als Eingang
  pinMode(relais1pin,OUTPUT);
  pinMode(relais2pin,OUTPUT);
}
void loop() {
  buttonStatus = digitalRead(button);       // prüfe ob Taster gedrückt oder nicht und
                                            // speicher die Information in
                                            // buttonStatus ab

  if (buttonStatus == HIGH)                 // Wenn buttonStatus = 1, also HIGH führe den
  {
    if(upDown == 1){
      digitalWrite(LED_BUILTIN, HIGH);   // schalte LED an 
      delay(1000);                       // warte 1 sek
      digitalWrite(LED_BUILTIN, LOW);    // schalte LED aus
      delay(1000);                       // warte 1 Sekunde
      digitalWrite(relais1pin, HIGH);    // Relai für  Hoch
      digitalWrite(relais2pin, LOW);
      buttonStatus = LOW;                //buttonStatus wieder auf LOW
      upDown = 2;                        //Status oben
    }
    else if (upDown == 2) {
      digitalWrite(LED_BUILTIN, HIGH);   // schalte LED an
      delay(1000);                       // warte 1 sek
      digitalWrite(LED_BUILTIN, LOW);    // schalte LED aus 
      delay(1000);                       // warte 1 sek
      digitalWrite(relais1pin, LOW);     // Relai für runter 
      digitalWrite(relais2pin, HIGH);
      buttonStatus = LOW;                // buttonStatus wieder auf LOW
      upDown=1;                          // Status unten
    }
  }
  else{
    digitalWrite(LED_BUILTIN, HIGH);                // pin 13 = 0, mache LED an dauerleuchten
    digitalWrite(relais1pin, LOW);                  // Relais nix machen
    digitalWrite(relais2pin, LOW);                  
  }
}

Hier wäre auch die Frage wie ich es umsetze.
Ideen die ich gefunden habe wäre mit millis() und eine do while schleife bis er oben ist oder hat jemand andere ideen.

Setze Deinen Code bitte in 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.

Du brauchst keine weitere Schleife, Du hast doch loop.

Gruß Tommy

Okay, aber wie mache ich das mit der Zeit. das quasi das ding 60 sekunden läuft

Hi

Wie machst Du Das, wenn Du eine Pizza in den Ofen schiebst?
Du merkst Dir, wann Diese fertig ist.
Beim Arduino geht's ähnlich - Du PRÜFST, ob Diese fertig ist, da Du Dir die STARTzeit gemerkt hast und die aktuelle Zeit mit millis() eh zur Verfügung hast.

Dann nur noch beachten: Tür erst öffnen, wenn die Pizza fertig ist - wofür machen wir das ganze Zeig sonst auch :wink:

MfG

Schau Dir das Beispiel BlinkWithoutDelay in der IDE an und verstehe es.
Alternativ kannst Du Dir die MoBaTools anschauen, die haben auch Timer drin.

Gruß Tommy

Hallo,

millis() ist schon mal gut, do while Schleife ist schlecht. Du hast eine Schleife, die nennt sich loop. Mit if verzweigst du dann dahin wo du es willt.

Der Motor soll doch anhalten wenn Du den Taster wieder los lässt. Dann müsste man die Tasterabfrange ausserhal der while Schleife , zum einschalten und innerhal nochmal zum ausschalten machen. Mach dir erst mal einen Ablaufplan, kann auch gerne in Textform sein. Mit etwas Übung kannst Du dann die einzelnen Textzeilen in code umsetzten. Schau Dir das Thema "Funktionen" an , dann kannst Du deine Aufgabe in logische Blöcke aufteilen und z.B das Blinken in eine Funktion auslagern. Das kennst Du doch aus Java.

etwa so.

Wenn taster heben gedrückt
Motor heben ein
blinken
sonst (else)
Motor heben aus

Wenn taster senken gedrückt
Motor senken ein
blinken
sonst (else)
motor senken aus

Heinz

Hallo Heinz,

vielen lieben Dank für deine Antwort :slight_smile:

Also das was du sagst ist fast richtig.

wenn Taster gedrückt wird
dann blinke
und motor fahre hoch

wenn Taster nochmal gedrückt wird
dann blinke
und fahre herunter.

Aktuell habe ich es so gelöst

/*

*/
const long interval = 1000; 

unsigned long previousMillis = 0;

int ledState = LOW;

int led = 13;                               // Variable für Pin 13

int button = 8;                             // Variable für Pin 8

int buttonStatus;                           // in dieser Variable wird die Information

                                            // abgespeichert ob der Taster gerade gedrückt

                                            // wird oder nicht
                                            
int relais1pin = 9;                         // Relai 1 für Hoch

int relais2pin = 10;                        // Reali 2 für Runter

int upDown=1;                               // Status = unten 1, oben 2


void setup() {
  pinMode(LED_BUILTIN, OUTPUT);             // definiere Pin 13 als Ausgang
  pinMode(button, INPUT);                   // definiere Pin 8 als Eingang
  pinMode(relais1pin,OUTPUT);
  pinMode(relais2pin,OUTPUT);
}
void loop() {
  buttonStatus = digitalRead(button);       // prüfe ob Taster gedrückt oder nicht und
                                            // speicher die Information in
                                            // buttonStatus ab

  if (buttonStatus == HIGH)                 // Wenn buttonStatus = 1, also HIGH führe den
  {
    if(upDown == 1){
      unsigned long start;
      start = millis();
      do {
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;
        if (ledState  == LOW) {
          ledState = HIGH;
        } 
        else {
          ledState = LOW;
        }
      digitalWrite(led, ledState);
     }
      digitalWrite(relais1pin, HIGH);    // Relai für  Hoch
      digitalWrite(relais2pin, LOW);
      } while (millis() - start < 6000);
      buttonStatus = LOW;                //buttonStatus wieder auf LOW
      upDown = 2;                        //Status oben
    }
  else if (upDown == 2) {
      unsigned long start;
      start = millis();
      do {
      unsigned long currentMillis = millis();
      if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;
        if (ledState  == LOW) {
          ledState = HIGH;
        } 
        else {
          ledState = LOW;
        }
      digitalWrite(led, ledState);
     }
      digitalWrite(relais1pin, LOW);    // Relai für  Hoch
      digitalWrite(relais2pin, HIGH);
      } while (millis() - start < 6000);
      buttonStatus = LOW;                //buttonStatus wieder auf LOW
      upDown = 2;                        //Status oben
  }
  else{
    digitalWrite(LED_BUILTIN, HIGH);                // pin 13 = 0, mache LED an dauerleuchten
    digitalWrite(relais1pin, LOW);                  // Relais nix machen
    digitalWrite(relais2pin, LOW);                  
  }
}
}

Klappt auch soweit, jedoch nur beim ersten mal.

Ich wenn ich den Taster das 3 oder 4 mal drücke blinkt zwar die LED aber die Relais schalten nicht mehr durch.

Ich dachte vielleicht liegt es daran, dass ich die variable upDown in der do-while schleife habe und sie dann rausgenommen habe aber brachte keinen Erfolg…

Zu Java ja habe ich gelernt aber das ist schon 10 Jahre her und seitdem habe ich damit auch nichts mehr am Hut. :smiley:

Hi

In Deiner Beschreibung hinkt Es 'etwas' - solange der Taster nicht wieder gelöst wird, wird man Den nicht erneut drücken können.
Etwas Präzision beim Umschreiben erspart eine ganze Menge Zeit beim Schreiben.

mfG

Hi ich setzt ja den Buttonstatus ja immer wieder auf LOW oder ist das Falsch

Hi

Wenn der Button-Status dem Status des Button entsprechen soll, wirst Du Den beim Einlesen (irgendwann) auch wieder als unbetätigt erkennen - Das geht schon automatisch (bei Tastern).
Deine Beschreibung lässt das Lösen des Taster aber komplett außen vor - ob und wann der Taster gelöst werden KANN und ob oder wann der gelöst werden MUSS, fehlt komplett.

MfG

Also mal ein besserer Ablaufplan

  • Tasterdruck
  • prüfe ob oben oder unten
    -> wenn Unten
    -> dann LEd fange an zu blinken und motor fahre hoch für 10sekunden
    -> setze Tastendruck auf LOW
    -erneuter Tasterdruck
  • prüfe ob oben oder unten
    -> wenn oben
    -> dann LED blinken und Motor für 10sek nach unten.
    -> setze taster auf LOW
    wenn nichts gedrückt wird
    -> LED LEUCHTEND
    -> RELAIS aus
    und das funktioniert an sich nur das es ich jeweils nur 1 mal hoch und 1 mal runter fahren kann.
    Bräuchte quasi einen restart dann :smiley:

postmaster-ino:
Hi

Wenn der Button-Status dem Status des Button entsprechen soll, wirst Du Den beim Einlesen (irgendwann) auch wieder als unbetätigt erkennen - Das geht schon automatisch (bei Tastern).
Deine Beschreibung lässt das Lösen des Taster aber komplett außen vor - ob und wann der Taster gelöst werden KANN und ob oder wann der gelöst werden MUSS, fehlt komplett.

MfG

Ich verstehe nicht was du meinst es ist ja ein Taster kein einrastknopf. also ich drücke kurz drauf und dann startet der Ablauf nur funktioniert das nur 1 mal

Hi

Trotzdem musst Du nicht den Taster 'auf LOW setzen' - mit der Flanke des Drückens startest Du die Aktion - da Diese etwas Zeit braucht, ist kein Entprellen nötig (da die Aktion schon gestartet wurde, sind Mehrfach-Tastungen eh 'für die Füße')

Du hast 2 Status

  • Motor fährt (egal welche Richtung)
  • Motor steht

Wenn der Motor fährt, prüfst Du 'nur', ob die Zeit um ist - wenn JA, Motor anhalten.
Wenn der Motor NICHT fährt, prüfst Du 'nur', ob Jemand auf den Taster drückt- wenn Nein, war's Das auch schon.
Wenn JA, prüfst Du, ob wir 'oben' stehen -> Richtung 'runter', SONST (und auch, wenn wir unten stehen) Richtung 'hoch'.
Weiter merkst Du Dir die Startzeit und schaltest den Motor AN.

if (motor_ist_an){
   //prüfe auf Ende der Laufzeit
   if (millis()-startzeit>=laufzeit){
      //MOTOR AUS
   }
}else{
   //hier ist der Motor aus, wir prüfen auf Taster
   if (Taster betätigt){
      if (Endlage OBEN betätigt){
         RICHTUNG=RUNTER;
      }else{
         RICHTUNG=HOCH;
      }
      startzeit=millis();
      //MOTOR AN
   }
}

MfG

PS: Für den Arduino drückst Du EWIGKEITEN auf dem armen Taster rum - Du schreibst aber nicht, wo das Lösen erkannt wird oder der Taster ZWINGEND gelöst sein muß.
Auch in meinem Pseudo-Code ist das Lösen nicht enthalten - wenn Du den Taster 'festklebst' fährt das Gelump die nächsten 35 Jahre nonstop raus und runter - weil eben vor dem Auslösen der Taster nicht losgelassen werden musste.
Der Arduino sollte loop() im ms Takt durchlaufen (oder schneller) - alleine ein Augenzwinkern sind >20ms - und Knöpsche drügge kann der Mensch auch nicht viel flotter.

PPS: Du brauchst nur einen Endschalter - für die obere Endlage.
Sonst - wenn kein Endschalter betätigt ist - fährt der Motor nicht los.

postmaster-ino:
Hi

Trotzdem musst Du nicht den Taster 'auf LOW setzen' - mit der Flanke des Drückens startest Du die Aktion - da Diese etwas Zeit braucht, ist kein Entprellen nötig (da die Aktion schon gestartet wurde, sind Mehrfach-Tastungen eh 'für die Füße')

Du hast 2 Status

  • Motor fährt (egal welche Richtung)
  • Motor steht

Wenn der Motor fährt, prüfst Du 'nur', ob die Zeit um ist - wenn JA, Motor anhalten.
Wenn der Motor NICHT fährt, prüfst Du 'nur', ob Jemand auf den Taster drückt- wenn Nein, war's Das auch schon.
Wenn JA, prüfst Du, ob wir 'oben' stehen -> Richtung 'runter', SONST (und auch, wenn wir unten stehen) Richtung 'hoch'.
Weiter merkst Du Dir die Startzeit und schaltest den Motor AN.

if (motor_ist_an){

//prüfe auf Ende der Laufzeit
  if (millis()-startzeit>=laufzeit){
      //MOTOR AUS
  }
}else{
  //hier ist der Motor aus, wir prüfen auf Taster
  if (Taster betätigt){
      if (Endlage OBEN betätigt){
        RICHTUNG=RUNTER;
      }else{
        RICHTUNG=HOCH;
      }
      startzeit=millis();
      //MOTOR AN
  }
}




MfG

PS: Für den Arduino drückst Du EWIGKEITEN auf dem armen Taster rum - Du schreibst aber nicht, wo das Lösen erkannt wird oder der Taster ZWINGEND gelöst sein muß.
Auch in meinem Pseudo-Code ist das Lösen nicht enthalten - wenn Du den Taster 'festklebst' fährt das Gelump die nächsten 35 Jahre nonstop raus und runter - weil eben vor dem Auslösen der Taster nicht losgelassen werden musste.
Der Arduino sollte loop() im ms Takt durchlaufen (oder schneller) - alleine ein Augenzwinkern sind >20ms - und Knöpsche drügge kann der Mensch auch nicht viel flotter.

PPS: Du brauchst nur einen Endschalter - für die obere Endlage.
Sonst - wenn kein Endschalter betätigt ist - fährt der Motor nicht los.

Wie ist es zu verstehen, dass mehrfachtastungen eh für den Arsch sind?

Ich möchte einen Rolladen motor mit elektrischer Abschaltung hoch und Runterfahren lassen mehr nicht.
Das kann man nicht über einen Taster lösen?

daveone1990:
Das kann man nicht über einen Taster lösen?

Doch, kann man. Gemeint ist das anders. Wenn Du beispielsweise mit dem selben Taster den Rolladen auch anhalten wolltest, bräuchtest Du eine Entprellung, weil sonst das Prellen jede gestartete Bewegung sofort wieder anhalten würde.

Dein Ablaufplan aus #10 läßt sich gut mit einer Schrittkette (= endlicher Automat = finite state machine) realisieren. Ich mag die mit switch/case realisierten.

Hey agmue,

vielen Dank für deine helfende Antwort. Ich habe dies auch schon herausgefunden mit dem Taster entprellen gestern abend :slight_smile:

Und so wie du es sagst hast du recht.

Da ich erst wieder damit Anfange entschuldigt manchmal die dämlichen Fragen oder das schwere Verständnis :slight_smile: Gebe mein bestes es zu bessern.

Ja Switch-Case macht sinn und schaue es mir später an.

Wünsche einen schönen Tag und bleibt gesund

Taster entprellt aber ich komme nicht weiter
habe schon an switch case und weiteres gearbeitet und wieder alles verworfen.....

Also wenn ich den Taster entprelle und dann eine do while schleife mache um danach die laufzeit des motors zu steuern bleibt der Tasterwert für den Switch Case immer bei 1 hängen und um Serial ist alles nur noch seeehr langsam..

daveone1990:
... eine do while schleife mache ...

Vermutlich falsch. Deine Schleife heißt loop!

Da die MobaTools schonmal angesprochen wurden, hier eine Variante mit dem Timer der MobaTools ( Die MobaTools kannst Du über den Bibliotheksverwalter installieren ).

Als zusätzliche Funktion wurde eingebaut, wenn der Taster während der Laufzeit gedrückt wird, hält der Motor an. Beim nächsten Tastendruck läuft er dann wieder in die andere Richtung. Damit kann man dann auch manuell umsteuern. Die jeweiligen (Rest-)Laufzeiten werden berücksichtigt.

Versuch mal den Code zu verstehen. Ich habe auch versucht, die Variablennamen wirklich entsprechend der Bedeutung zu wählen. Das ersetzt manchen Kommentar :wink:

#include <MobaTools.h>

const byte ledPin = 13;                     // Pinnummer für die Led
const byte buttonPin = 8;                   // Pinnummer für rauf/runter-Taster

bool buttonGedrueckt;                       // in dieser Variable wird die Information
// abgespeichert ob der Taster gerade gedrückt wurde
// wird oder nicht
bool lastButtonState;                       // zur Flankenerkennung

const byte relaisHochPin = 9;               // Relai 1 für Hoch
const byte relaisRunterPin = 10;            // Reali 2 für Runter

bool aufwaerts = true;                        // Status = unten true, oben false

MoToTimer BlinkTimer, MotorTimer;              // Zeiten für blinken und Motorlaufzeit
const long blinkZeit = 500;
const long laufZeit = 60000;
long restlaufzeit = 60000;                   // falls der Motor im Laufen angehalten wurde

void setup() {
  pinMode(ledPin, OUTPUT);                  // definiere Pin 13 als Ausgang
  pinMode(buttonPin, INPUT);                // definiere Pin 8 als Eingang
  pinMode(relaisHochPin, OUTPUT);
  pinMode(relaisRunterPin, OUTPUT);
}
void loop() {
  // Das Ereignis 'Taste wurde gerade gedrückt' erkennen
  buttonGedrueckt = false;
  if ( digitalRead(buttonPin) ) {
    if ( !lastButtonState ) {       // prüfe ob gerade Taster gedrückt wurde und
      buttonGedrueckt = true;
      lastButtonState = true;      // vorher noch nicht gedrückt war
    }
  } else {
    lastButtonState = false;
  }
  delay(20);                                // kurzes delay zum Entprellen

  // Bearbeiten des Tasterdrückens --------------
  if (buttonGedrueckt) {
    // Taster wurde gedrückt
    if ( MotorTimer.running() ) {
      // Taster wurde während des Laufens erneut gedrueckt: anhalten
      digitalWrite(relaisHochPin, LOW);
      digitalWrite(relaisRunterPin, LOW);
      restlaufzeit = laufZeit - MotorTimer.getTime(); // das ist die bisherige Laufzeit
      MotorTimer.stop();
      aufwaerts = !aufwaerts;
    } else {
      // Motor steht -> je nach Laufrichtung starten
      MotorTimer.setTime( restlaufzeit );
      if (aufwaerts) {
        digitalWrite(relaisHochPin, HIGH);
        digitalWrite(relaisRunterPin, LOW);
      } else {
        digitalWrite(relaisHochPin, LOW);
        digitalWrite(relaisRunterPin, HIGH);
      }
    }
  }
  // Bearbeiten, wenn Motorzeit abgelaufen
  if ( MotorTimer.expired() ) {
    // Motorlaufzeit zu Ende. Stoppen und Laufrichtung umdrehen
    aufwaerts = digitalRead( relaisRunterPin );    // wenn der Motor nach unten lief, steht er jetzt unten
    digitalWrite(relaisHochPin, LOW);                  // Relais nix machen
    digitalWrite(relaisRunterPin, LOW);
    restlaufzeit = laufZeit;
  }

  // Blinken der LED. Die Led blinkt immer, während der Motor läuft
  if ( MotorTimer.running() ) {
    if ( !BlinkTimer.running() ) {
      digitalWrite(ledPin, !digitalRead(ledPin ) );
      BlinkTimer.setTime( blinkZeit );
    }

  } else {
    // Wennd er Motortimer nicht läuft, Blinkt auch die Led nicht
    BlinkTimer.stop();
    digitalWrite(ledPin, LOW );
  }
}

P.S. Um das zu testen, musste ich ein paar Einstellungen ändern. Ich hoffe ich habe alles wieder so zurückgesetzt, dass es für deine HW passt.

Hey danke schonmal dafür :slight_smile:

Jetzt muss ich mich nur mal dransetzen, dass es quasi hochfährt ,angehalten werden kann und dann wieder weiter hochfährt.

Wenn er dann oben ist das ganze Spiel für nach unten :slight_smile:

Ist halt nach Jahren wieder alles neu für mich und muss mich erstmal iwie wieder reinarbeiten :smiley: Nur bei meiner begrentzen Zeit immer schwierig.