Projekt Motor-Steuern mit Arduino

Hallo zusammen :slight_smile:

....so mein erster Beitrag hier :slight_smile:

Ich möchte mit meinem Arduino einen Motor steuern, der soll in bestimmten Zeitintervallen Ein- und Ausschalten. Dafür möchte ich mit dem Arduino ein Relai schalten, welches dann den Motor schaltet. Ebenfalls ist es mein Ziel, mit unterschiedlichen Knopfdrückern, unterschiedliche Programme des Motors laufen zu lassen. Zusätzlich soll es eine Stopp-Taste geben, welche das laufende Programm sofort beendet. So soll es später mal sein.... Ich möchte an das ganze Schrittweise ran gehen, aber habe leider zu Beginn schon Probleme.

Zu Beginn möchte ich erstmal eine Led dazu bringen, dass ich den Taster drücke, LED geht an und nach 5 sek. aus.
Zunächst wollte ich das ganze mit dem Delay() Befehl machen, aber da habe ich hier im Forum schon einige Nachteile drüber gelesen - wenn ich mich recht erinnere, würde dann eine Stopp-Taste auch nur bedingt bzw. gar nicht gehen.

Zu dem Thema habe ich mir ebenfalls den Beitrag "BlinkwithoutDelay" durchgelesen, aber irgendwo ist bei meinem Programm ein Fehler. Wenn ich den Taster drücke, leuchtet die LED, wenn ich ihn loslasse, ist er wieder aus...

Wer kann mir weiterhelfen?

Beste Grüße,

Tobi

int Led_Pin = 13; //Belegung der Taster
int Button_Pin1 = 12; 
int buttonstatus = 0; // 
unsigned long LED_timestore;  // Variable Speicher für Systemzeit.
int LedStatus = 0;

/*************************************************************/
/* Hauptprogramm */
/*************************************************************/

void setup() {
  pinMode(Led_Pin, OUTPUT); //Deklarierung der Ein- und Ausgänge in Verbindung mit den Variablen
  pinMode(Button_Pin1, INPUT);
}

void loop() {
 buttonstatus=digitalRead(Button_Pin1); //Auslesen des Tasters
 if (buttonstatus == HIGH)// Wenn Taster gedrückt...
 {
  digitalWrite(Led_Pin, HIGH); //...dann soll die LED leuchten
  if(millis() - LED_timestore> 5000 )///Wenn  Sek. um sind...
  {
    digitalWrite(Led_Pin, LOW); //... soll die LED aus gehen.
    LED_timestore = millis();
    LedStatus = LOW;
  }
 else
 {
 digitalWrite(Led_Pin, LOW); //Wenn Taster nicht gedrückt, bleibt LED aus 
 }

tobis1999:
Zunächst wollte ich das ganze mit dem Delay() Befehl machen, aber da habe ich hier im Forum schon einige Nachteile drüber gelesen - wenn ich mich recht erinnere, würde dann eine Stopp-Taste auch nur bedingt bzw. gar nicht gehen.

Da hast Du richtig gelesen.

tobis1999:
Wer kann mir weiterhelfen?

Dir fehlt eine ganz einfache Schrittkette (= endlicher Automat, = finite state machine), mit diesem Thema müßtest Du Dich auch noch beschäftigen.

Hi

Was Du möchtest:
Bei Tastendruck die Zeit merken
Wenn seit dem Tastendruck keine 5 Sekunden um sind, die LED leuchten lassen

Was Du machst:
Wenn der Taster nicht gedrückt ist, die LED AUSschalten
Wenn der Taster gedrückt ist, die LED ANschalten, prüfen, ob die Zeit schon vorbei ist und DANN die Zeit merken

MALE Dir in möglichst kleinen Schritten auf, Was Du Wann machen möchtest.
Wenn die LED 5 Sekunden nach Lösen des Taster aus gehen soll, brauchst Du Dir NUR die aktuelle Zeit merken, wenn der Taster gedrückt ist (Diese wird so lange immer neu gemerkt, wie der Taster betätigt ist).
Im 2.ten Schritt prüfst Du, ob die Zeit vorbei ist - Nein: LED an - Ja: LED aus

MfG

Aktuell bin ich echt schwer von Begriff. Ähm ich habe das Internet und auch ein Buch zum Thema "Endlicher Automat" durchforstet, und auch etwas besser verstanden wie es geht, aber so ganz den Durchblick habe ich da noch nicht....

Jetzt habe ich mein Skript umgeschrieben, aber der Fehler tritt immernoch auf. Sobald ich den Begriff millis() anwende, beginnt meine Zeit doch zu Zählen, korrekt?

Ich habe, das was ich mir dabei gedacht habe, mal als Kommentar daneben geschrieben...Na bis der Motor so läuft mit den geplanten Programmen, wird es noch ein weiter weg und ich werde noch viel "nerven" müssen... :confused:

int Led_Pin = 13; //Belegung der Taster
int Button_Pin1 = 12; 
int buttonstatus = 0; // 
unsigned long Startzeit1;  // Variable Speicher für Systemzeit.
int LedStatus = 0;

/*************************************************************/
/* Hauptprogramm */
/*************************************************************/

void setup() {
  pinMode(Led_Pin, OUTPUT); //Deklarierung der Ein- und Ausgänge in Verbindung mit den Variablen
  pinMode(Button_Pin1, INPUT);
}

void loop() {
 buttonstatus=digitalRead(Button_Pin1); //Auslesen des Tasters
 if (buttonstatus == HIGH)// Wenn Taster gedrückt...
 {
  millis() == Startzeit1; //Hier beginnt die Zeit zu zählen
 if (Startzeit1 < 5000 ) //Wenn Startzeit1 kleiner ist als 5 sek...
 {
  digitalWrite(Led_Pin, HIGH); //...dann soll die LED leuchten
 }
 else
 {
    digitalWrite(Led_Pin, LOW); //... soll die LED aus gehen.
}
 }
 else
 {
 digitalWrite(Led_Pin, LOW); //Wenn Taster nicht gedrückt, bleibt LED aus 
 }
 }

Sobald ich den Begriff millis() anwende, beginnt meine Zeit doch zu Zählen, korrekt?

Nein! millis() ist der Aufruf einer Funktion, die die Zeit seit Systemstart zurückliefert. Das kannst du speichern und wenn du später einen neuen Wert dieser Funktion mit dem gespeicherten vergleichst, ist diese Differenz die Zeit seit dem Speicherzeitpunkt.

Ahhhh ok. Klappen tut es trotzdem noch nicht. Heißt, ich muss mit der Zeitdifferenz arbeiten. Aber ich habe noch, so glaube ich, einen grundlegenden Fehler im Programm...

void loop() {
 buttonstatus=digitalRead(Button_Pin1); //Auslesen des Tasters
 if (buttonstatus == HIGH)// Wenn Taster gedrückt...
 {
  millis() == Startzeit1; //Hier beginnt die Zeit zu zählen
 if (millis() - Startzeit1 < 5000 ) //Wenn Startzeit1 kleiner ist als 5 sek...
 {
  digitalWrite(Led_Pin, HIGH); //...dann soll die LED leuchten
 }
 else
 {
    digitalWrite(Led_Pin, LOW); //... soll die LED aus gehen.
}
 }
 else
 {
 digitalWrite(Led_Pin, LOW); //Wenn Taster nicht gedrückt, bleibt LED aus 
 }
 }

millis() == Startzeit1;

Mein Compiler sagt

E:\Programme\arduino\portable\sketchbook\sketch_may02b\sketch_may02b.ino: In function 'void loop()':
E:\Programme\arduino\portable\sketchbook\sketch_may02b\sketch_may02b.ino:12:11: warning: value computed is not used [-Wunused-value]
   12 |  millis() == Startzeit1;
      |  ~~~~~~~~~^~~~~

Ist das so beabsichtigt?

Nein, das ist nicht beabsichtigt. == ist ja ein Vergleich, korrekt? An dieser Stelle wäre ein = ja richtig, dann müsste das Programm ja laufen, leider schreibt mein Compiler dann aber folgende Fehlermeldung raus...

Beregnungsanlage_Weide_v1.ino:29:14: error: lvalue required as left operand of assignment

   millis() = Startzeit1; //Hier beginnt die Zeit zu zählen

              ^~~~~~~~~~

exit status 1
lvalue required as left operand of assignment

Ich stimme dem Kompiler zu

Beachte,eine Zuweisung funktioniert so:

Ziel = Quelle;

Da hattest du in deinem ersten Post schon eine soweit brauchbare Vorlage:

  if(millis() - LED_timestore> 5000 )///Wenn  5 Sek. um sind...
  {
    digitalWrite(Led_Pin, LOW); //... soll die LED aus gehen.
    LED_timestore = millis();    // ... neue Startzeit merken
    LedStatus = LOW;
  }

combie:
Ich stimme dem Kompiler zu

Beachte,eine Zuweisung funktioniert so:

Ziel = Quelle;

Danke dafür, das war mir so nicht bewusst! Ist wieder in Vergessenheit gerutscht.

michael_x:
Da hattest du in deinem ersten Post schon eine soweit brauchbare Vorlage:

  if(millis() - LED_timestore> 5000 )///Wenn  5 Sek. um sind...

{
    digitalWrite(Led_Pin, LOW); //... soll die LED aus gehen.
    LED_timestore = millis();    // ... neue Startzeit merken
    LedStatus = LOW;
  }

Aber hier war doch der Ablauf, also die Reihenfolge falsch. Das ist auch bisher mein größtes Problem, ich verstehe noch nicht so ganz in welcher Folge die Befehle ablaufen müssen...

Vom Sinn her, soll mein Programm ja folgende Schritte durchlaufen:

  1. Schaue ob Taster gedrückt ist.
  2. Wenn Taster gedrückt ist, überprüfe ob seit dem Tasterdruck 5 Sek. um sind.
  3. Wenn keine 5 Sekunden um sind, lass die LED leuchten.
  4. Wenn 5 Sekunden um sind, dann soll die LED aus sein.
  5. Wenn Taster nicht gedrückt, dann soll die LED auch nicht leuchten,

So, und dass jetzt umschreiben scheint ja für mich als "Anfänger" sehr schwer. Wie genau sage ich dem denn jetzt, dass er sich zuerst die Zeit des Taster-Drucks merken soll, danach überprüfen soll und je nach Lage die LED an oder aus ist...

Sorry für die "dummen" Fragen...

Ich könnte dir zeigen, wie das Endprodukt bei mir aussehen würde.
Aber vermutlich hilft dir das nicht unmittelbar aufs Pferd.

So, und dass jetzt umschreiben scheint ja für mich als "Anfänger" sehr schwer.

Wenn der Programmlaufplan vor dir liegt, brauchst du ihn nur noch aus zu füllen.

Also erst den Programmlaufplan(Flussdiagramm) malen?
Nein, erst ein Datenflussdiagramm malen.

Danach dann .....

Beim malen des Programmlaufplanes, wirst du merken, dass du einen endlichen Automaten bauen musst/willst.

Also malst du vor dem Programmlaufplan, Zustandsdiagramme und zugehörige Tabellen.

Das eigentliche Programmieren ist dann nur noch wie "Malen nach Zahlen".

Das habe ich ja gemacht, und dann folgt das Programm, welches ich euch gezeigt habe. Nur irgendwo habe ich eine Fehler bei der Anwednung von millis...so glaube ich :smiley: Den Fehler finde ich nicht...

Vom Sinn her, soll mein Programm ja folgende Schritte durchlaufen:

  1. Schaue ob Taster gedrückt ist.
  2. Wenn Taster gedrückt ist, überprüfe ob seit dem Tasterdruck 5 Sek. um sind.
  3. Wenn keine 5 Sekunden um sind, lass die LED leuchten.
  4. Wenn 5 Sekunden um sind, dann soll die LED aus sein.
  5. Wenn Taster nicht gedrückt, dann soll die LED auch nicht leuchten,

Da sehe ich keine 5 Schritte, sondern 2 Bedingungen. Und die Aufgabe, den Beginn eines Tastendrucks zu erkennen.

Und mir fehlt da das loslassen des Tasters.

const byte Led_Pin = 13;
const byte Button_Pin = 2; // Taster schaltet nach GND !
bool Taster; // true = gedrückt
unsigned long Startzeit;
void setup() {
  pinMode(Button_Pin,INPUT_PULLUP);
  pinMode(Led_Pin,OUTPUT);
}
void loop() {
  if (! digitalRead(Button_Pin)) { // Taster gedrückt 
    if (! Taster)      {// Wenn neu gedrückt...
      Startzeit = millis(); //  ... beginnt die Zeit zu zählen
      Taster = true; 
    } 
    if (millis() - Startzeit < 5000 ) //Wenn unter 5 sek...
      digitalWrite(Led_Pin, HIGH); //...dann soll die LED leuchten
    else
      digitalWrite(Led_Pin, LOW); //...sonst soll die LED aus gehen.
  }
  else {  // Taster nicht gedrückt
      digitalWrite(Led_Pin, LOW); //Wenn Taster nicht gedrückt, sofort LED aus
      Taster = false;
  }
}

Sollte sogar ohne Entprellen funktionieren

Hi

@combie
Wieso?

Nur, wenn die Taste gedrückt ist, wird überprüft, ob die Leuchtdauer überschritten ist (und dann abgeschaltet), sonst angeschaltet.
Wenn der Taster nicht gedrückt ist, geht die LED eh aus.
Das Lösen des Taster hat hier nur die Auswirkung, daß der Taster nicht gedrückt ist und die LED somit aus zu sein hat.
Edit
Ok, wurde dann doch 'anders herum'
/Edit

if (Taster && millis()-lastopen<=wartezeit){
   LED-AN
}else{
   LED-AUS
   lastopen=millis();
}

Vll. noch unschön, daß der Pin bei jedem Durchgang angesteuert wird - wird aber wohl schneller sein, als eine zusätzliche Abfrage.

MfG

Also sorry erstmal, ich stelle mich echt blöd an. (Ich weiß gar nicht wie ich diese Steuerung jemals umsetzen soll...) Aber ich habe mir ja einen Plan gemacht, und den abgearbeitet... So, das Ergebnis habt ihr ja gesehen, bzw. ich setze es unten nochmal ein.

Ebenfalls habe ich, mit Hilfe verschiedener Anleitungen den millis() befehl umgesetzt. Aber warum klappt es nicht? Ich habe nochmals alles überprüft und versucht, aber die LED leuchtet nur wenn der Taster gedrückt ist....

void setup() {
  pinMode(Led_Pin, OUTPUT); //Deklarierung der Ein- und Ausgänge in Verbindung mit den Variablen
  pinMode(Button_Pin1, INPUT);
}

void loop() {
 buttonstatus=digitalRead(Button_Pin1); //Auslesen des Tasters
 if (buttonstatus == HIGH)// Wenn Taster gedrückt...
 {
  Startzeit1 = millis(); //Setze aktuelle Zeit als Start
 if (millis() - Startzeit1 < 5000 ) //Wenn Startzeit1 kleiner ist als 5 sek...
 {
  digitalWrite(Led_Pin, HIGH); //...dann soll die LED leuchten
 }
 else
 {
    digitalWrite(Led_Pin, LOW); //... soll die LED aus gehen.
}
 }
 else
 {
 digitalWrite(Led_Pin, LOW); //Wenn Taster nicht gedrückt, bleibt LED aus
 }
 }

Ist das grundlegend denn überhaupt der richtige Ansatz, oder muss alles nochmal in Müll? Dann würde ich mal einen neuen Ansatz suchen, denn hier komme ich nicht weiter.

Hi

Drück Mal STRG+T in der IDE.
Solange der Taster HIGH zurück gibt, setzt Du die Startzeit IMMER WIEDER NEU - und fragst ab, ob bereits 5 Sekunden um sind ... ne, haben ja eben gerade eine neue Startzeit gesetzt.

Was unterscheidet Deinen Code von z.B. meinem Pseudo-Code?

MfG

...

void setup() {
  pinMode(Led_Pin, OUTPUT); //Deklarierung der Ein- und Ausgänge in Verbindung mit den Variablen
  pinMode(Button_Pin1, INPUT);
}

void loop() {
  buttonstatus = digitalRead(Button_Pin1); //Auslesen des Tasters
  if (buttonstatus == HIGH && millis() - Startzeit1 < 5000) {// Wenn Taster gedrückt...
   digitalWrite(Led_Pin, HIGH); //...dann soll die LED leuchten
  } else {
   digitalWrite(Led_Pin, LOW); //... soll die LED aus gehen.
   Startzeit1 = millis(); //Setze aktuelle Zeit als Start
  }
}

kompiliert nicht, da oberhalb von setup() wohl noch ein/zwei Kleinigkeiten fehlen

Ok, du hast die 5 Sek. Bedingung mit in die If Abfrage gepackt, aber ändern tut es bei mir nichts. Taster gedrückt = LED an, Taster nicht gedrückt = LED aus. Lediglich ein Unterschied (was mir im nachhinein auch einleuchtet) ist, dass jetzt nach Sek. die LED ganz ausbleibt....Zumindest glaube ich zu verstehen warum das so ist :smiley: