Motor + Endschalter - ohne Delay

Guten Abend zusammen, ich habe hier einen Code umgeschrieben um einen Schlitten von A nach B zu fahren und dann mit Endschaltern zu stoppen.

Dazu habe ich einen funktionieren Code im endeffekt einfach mit Copy & Paste dupliziert. Laut Seriellen Monitor funktioniert auch alles. Aber sobald ich die Relais anschließe 'Flackern' diese wie wild. Ich bin mir sicher es liegt am 'Delay' jedoch sind alle versuche es rauszukürzen erfolglos gewesen.

Kann mich hierbei einer von euch unterstützen?

Lg aus der Quarantäne
Simon

const byte Taster = A0;
const byte Endschalter = 2;

const byte Taster1 = A1;
const byte Endschalter1 = 3;

const byte Relais = 13;
const byte Relais1 = 12;

bool btnstate, lastbtnstate;
int count = 0;


bool schaltzustand, letzterschaltzustand;
int zaehler = 0;



void setup() {
 
  pinMode(Taster, INPUT_PULLUP);
  pinMode(Endschalter,INPUT_PULLUP);

  pinMode(Taster1, INPUT_PULLUP);
  pinMode(Endschalter1,INPUT_PULLUP);

  pinMode(Relais, OUTPUT);
  pinMode(Relais1, OUTPUT);
 
  Serial.begin(9600);

}

void loop() {
// TASTER 


  {
  btnstate = !digitalRead(Taster); //Taster lesen
  
  delay(20); // entprellen 

  // Motor dreht Links
  if ( count == 0) {
    digitalWrite(Relais, HIGH);
    digitalWrite(Relais1, LOW);
   if (!digitalRead(Endschalter)) count=1;  // Wenn Endschalter gelesen - setze Count auf 1
  }


 // Motor Stop
  if (count == 1) { 
    digitalWrite(Relais, LOW);
    digitalWrite(Relais1, LOW);
  }


  
  if (btnstate & !lastbtnstate) { // Schalterzustand abfragen
    count++;
    if (count == 2) count = 0;
    lastbtnstate = HIGH;
    Serial.print("Taster2->");
    Serial.println (count);
  }


  if (!btnstate) lastbtnstate = LOW;

}


// TASTER1


  {
  schaltzustand = !digitalRead(Taster1); //Taster lesen
  
  delay(20); // entprellen 

  // Motor dreht Rechts
  if ( zaehler == 0) {
    digitalWrite(Relais, HIGH);
    digitalWrite(Relais1, HIGH);
   if (!digitalRead(Endschalter1)) zaehler=1;  // Wenn Endschalter gelesen - setze Zähler auf 1
  }


 // Motor Stop
  if (zaehler == 1) { 
    digitalWrite(Relais, LOW);
    digitalWrite(Relais1, LOW);
  }


  
  if (schaltzustand & !letzterschaltzustand) { // Schalterzustand abfragen
    zaehler++;
    if (zaehler == 2) zaehler = 0;
    letzterschaltzustand = HIGH;
    Serial.print("Taster1->");
    Serial.println (zaehler);
  }


  if (!schaltzustand) letzterschaltzustand = LOW;

}


}

wenn du deinen Sketch mit mehr Serial Print ausgaben ausstattest dann erkennst du was passiert:

const byte Taster = A0;
const byte Endschalter = 2;

const byte Taster1 = A1;
const byte Endschalter1 = 3;

const byte Relais = 13;
const byte Relais1 = 12;

bool btnstate, lastbtnstate;
int count = 0;


bool schaltzustand, letzterschaltzustand;
int zaehler = 0;

void setup() {

  pinMode(Taster, INPUT_PULLUP);
  pinMode(Endschalter, INPUT_PULLUP);

  pinMode(Taster1, INPUT_PULLUP);
  pinMode(Endschalter1, INPUT_PULLUP);

  pinMode(Relais, OUTPUT);
  pinMode(Relais1, OUTPUT);

  Serial.begin(115200);

}

void loop() {
  // TASTER
  {
    btnstate = !digitalRead(Taster); //Taster lesen
    delay(20); // entprellen
    // Motor dreht Links
    if ( count == 0) {
      Serial.println(F("D39"));
      digitalWrite(Relais, HIGH);
      digitalWrite(Relais1, LOW);
      if (!digitalRead(Endschalter)) count = 1; // Wenn Endschalter gelesen - setze Count auf 1
    }
    // Motor Stop
    if (count == 1) {
      Serial.println(F("D46"));
      digitalWrite(Relais, LOW);
      digitalWrite(Relais1, LOW);
    }

    if (btnstate & !lastbtnstate) { // Schalterzustand abfragen
      count++;
      if (count == 2) count = 0;
      lastbtnstate = HIGH;
      Serial.print("Taster2->");
      Serial.println (count);
    }
    if (!btnstate) lastbtnstate = LOW;
  }
  // TASTER1
  {
    schaltzustand = !digitalRead(Taster1); //Taster lesen
    delay(20); // entprellen

    // Motor dreht Rechts
    if ( zaehler == 0) {
      Serial.println(F("D67"));
      digitalWrite(Relais, HIGH);
      digitalWrite(Relais1, HIGH);
      if (!digitalRead(Endschalter1)) zaehler = 1; // Wenn Endschalter gelesen - setze Zähler auf 1
    }

    // Motor Stop
    if (zaehler == 1) {
      Serial.println(F("D75"));
      digitalWrite(Relais, LOW);
      digitalWrite(Relais1, LOW);
    }

    if (schaltzustand & !letzterschaltzustand) { // Schalterzustand abfragen
      zaehler++;
      if (zaehler == 2) zaehler = 0;
      letzterschaltzustand = HIGH;
      Serial.print("Taster1->");
      Serial.println (zaehler);
    }
    if (!schaltzustand) letzterschaltzustand = LOW;
  }
}

du hast ein paar konkurrierende IF-Bedingungen und schaltest in bestimmten Situationen die Ausgänge ständig aus und ein. Konkret in die Ifs nach D67 und D46

heißt; es liegt nicht wie vermutet am Delay, sondern an den konkurrierenden Bedingungen?

Danke für den Code, wenn ich ihn auf meinen Arduino Spiele kommen in den Seriellen Monitor leider nur noch '?????????'

Wie kann ich den Fehler beheben? Ich habe leider noch nie mit zwei 'bools' programmiert.. (Ist es überhaupt nötig?)

Serial umgestellt auf`?

 Serial.begin(115200);

Klar doch...

Wozu?
Du drückst auf die Taste - der Antrieb läuft.
Ob das für 5ms flattert, ist vollkommen egal - Dein relais schaltet nicht so schnell.

Du versperrst Dir aber mit dem delay() die Abfrage der Endschalter - das halte ich für gefährlicher.

Du verriegelst zudem die Taster nicht gegenseitig.
Wer zuletzt dran ist, hat gewonnen....

Soll der Schlitten solange fahren, bis der Endschalter ereicht ist, oder soll bei loslassen der taste auch angehalten werden?
Das wäre dann die Aufgabe.

Danke :see_no_evil:

Ziel ist das wenn der Taster das erste mal gedrückt wurde der Motor losfährt bis; entweder der Taster ein zweites mal gedrückt wird oder er am Endschalter anschlägt.

so funktioniert der Code wie er soll, leider halt nur in eine Richtung mit einem Endschalter:

const byte Taster = A0;
const byte Endschalter = 2;
const byte Relais = 13;
const byte Relais1 = 12;
bool btnstate, lastbtnstate;
int count = 0;


void setup() {
 
  pinMode(Taster, INPUT_PULLUP);
  pinMode(Endschalter,INPUT_PULLUP);
  pinMode(Relais, OUTPUT);
 
  Serial.begin(9600);

}

void loop() {
  btnstate = !digitalRead(Taster); //Taster lesen
  
  delay(20); // entprellen 

  // Motor dreht Links
  if ( count == 0) {
    digitalWrite(Relais, HIGH);
    digitalWrite(Relais1, LOW);
   if (!digitalRead(Endschalter)) count=1;  // Wenn Endschalter gelesen - setze Count auf 1
  }


 // Motor Stop
  if (count == 1) { 
    digitalWrite(Relais, LOW);
    digitalWrite(Relais1, LOW);
  }


  
  if (btnstate & !lastbtnstate) { // Schalterzustand abfragen
    count++;
    if (count == 2) count = 0;
    lastbtnstate = HIGH;
    Serial.println (count);
  }


  if (!btnstate) lastbtnstate = LOW;

}

Du solltest pin D13 nicht für Relais verwenden da dieses vom Bootloader verwendet wird und beim Einschalten einige male komutiert wird.
Grüße Uwe

Danke, tausch ich dann noch aus!

Ok,
aber nicht gegenseitig verriegelt :wink:

Ich hab mal was gebaut.
Nicht schick, aber es sollte tun.

const byte kreise = 2;
const byte Taster[kreise] = {A0, A1};
const byte Endschalter[kreise] = {2, 3};
const byte Relais[kreise] = {13, 12};
unsigned long ausloeseMerker[kreise] = {0, 0}; // fuers debounce
enum {an, aus};
enum {gedrueckt, losgelassen};
bool tastenMerker[kreise] = {losgelassen, losgelassen};
void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start... "));
  for (byte b = 0; b < kreise; b++)
  {
    digitalWrite(Relais[b], LOW);
    pinMode(Relais[b], OUTPUT);
    digitalWrite(Relais[b], aus);
    pinMode(Taster[b], INPUT_PULLUP);
    pinMode(Endschalter[b], INPUT_PULLUP);
  }
}

void endschalter()
{
  for (byte b = 0; b < kreise; b++)
  {
    if (digitalRead(Endschalter[b]) == an)
    {
      digitalWrite(Relais[b], aus);
      Serial.println(F("Endschalter ausgelöst!"));
    }
  }
}
void taster(const byte sperrkreis, const byte tastkreis)
{
  unsigned long ausloeseMerker[kreise] = {0, 0};        // fuers debounce
  if (digitalRead(Relais[sperrkreis]) == aus)           // Nur wenn Gegenrichtung nicht ausgelöst
  {
    if (digitalRead(Taster[tastkreis]) == gedrueckt &&  // Taste gedrückt?
        (tastenMerker[tastkreis] == losgelassen))       // und vorher nicht?
    {
      digitalWrite(Relais[tastkreis], !digitalRead(Relais[tastkreis])); // Wechsel Zustand
      tastenMerker[tastkreis] = gedrueckt;
      ausloeseMerker[tastkreis] = millis();
      Serial.print(F("Taster : ")); Serial.print(tastkreis); Serial.println(F(" ausgelöst"));
    }
  }
  if (tastenMerker[tastkreis] == gedrueckt &&
      millis() - ausloeseMerker[tastkreis] > 20)
    tastenMerker[tastkreis] = losgelassen;
  Serial.print(F("Taster : ")); Serial.print(tastkreis); Serial.println(F(" debuonce"));
}

void loop()
{
  endschalter(); // die müssen immer abgefragt werden
  taster(0, 1);
  taster(1, 0);
}

ich habe mir deine Relais nicht wirklich genau angesehen, aber ich würde es in einer State machine machen.

Was du in den einzelnen Status machst, kannst ja selber bestimmten.

so in der Art:

const byte Taster = A0;
const byte Endschalter = 2;

const byte Taster1 = A1;
const byte Endschalter1 = 3;

const byte Relais = 13;
const byte Relais1 = 12;

bool btnstate, lastbtnstate = true;
int count = 0;

uint32_t debounceTaster = 0;

bool schaltzustand, letzterschaltzustand;
int zaehler = 0;

enum State {LEFT,       // Endposition Links
            RIGHT,      // Endposition Rechts
            LEFT_GO,    // Bewegung nach Links
            RIGHT_GO,   // Bewegung nach Rechts
            LEFT_HALT,  // Nothalt während Bewegung nach Links
            RIGHT_HALT  // Nothalt während Bewegung nach Rechts
           };
State state;

bool tasterWasPressed()
{
  btnstate = !digitalRead(Taster); //Taster lesen
  bool result = false;
  if (btnstate != lastbtnstate)
  {
    delay(50);
  }
  if (btnstate == true && btnstate != lastbtnstate)
  {
    Serial.println(F("pressed"));
    result = true;
  }
  lastbtnstate = btnstate;
  return result;
}

void stop()
{
  digitalWrite(Relais, LOW);
  digitalWrite(Relais1, LOW);
}
void goRight()
{
  digitalWrite(Relais, HIGH);
  digitalWrite(Relais1, LOW);
}

void goLeft()
{
  digitalWrite(Relais, LOW);
  digitalWrite(Relais1, HIGH);
}

void setup() {
  Serial.begin(115200);
  pinMode(Taster, INPUT_PULLUP);
  pinMode(Endschalter, INPUT_PULLUP);

  pinMode(Taster1, INPUT_PULLUP);
  pinMode(Endschalter1, INPUT_PULLUP);

  pinMode(Relais, OUTPUT);
  pinMode(Relais1, OUTPUT);
}

void loop()
{
  switch (state)
  {
    case LEFT:
      if (tasterWasPressed())
      {
        Serial.println(F("start RIGHT_GO"));
        state = RIGHT_GO;
        goRight();
      }
      break;
    case LEFT_GO:
      if (digitalRead(Endschalter1) == LOW)
      {
        Serial.println(F("End LEFT"));
        state = LEFT;
        stop();
      }
      if (tasterWasPressed())
      {
        Serial.println(F("LEFT halted"));
        state = LEFT_HALT;
        stop();
      }
      break;
    case LEFT_HALT:
      if (tasterWasPressed())
      {
        Serial.println(F("restart LEFT"));
        state = LEFT_GO;
        goLeft();
      }
      break;
    case RIGHT:
      if (tasterWasPressed())
      {
        Serial.println(F("start LEFT"));
        state = LEFT_GO;
        goLeft();
      }
      break;
    case RIGHT_GO:
      if (digitalRead(Endschalter) == LOW)
      {
        Serial.println(F("End RIGHT"));
        state = RIGHT;
        stop();
      }
      if (tasterWasPressed())
      {
        Serial.println(F("RIGHT halted"));
        state = RIGHT_HALT;
        stop();
      }
      break;
    case RIGHT_HALT:
      if (tasterWasPressed())
      {
        Serial.println(F("restart RIGHT"));
        state = RIGHT_GO;
        goRight();
      }
      break;
  }
}

im prinzip könntest bei einem "Nothalt" auch in die andere Richtung fahren, je nach dem was benötigt wird...

Was passiert in der Zeit, wenn sich der Antrieb bewegt?

DANKE! :heart_eyes: - Grundsätzlich Funktioniert alles wie es soll, jedoch schalten die Relais wenn die Taster gedrückt sind ganz wild hin und her, hört sich an wie ein vibrieren - ich hoffe du weißt was ich mein, wie kann man so einen Fehler beheben?

Cooles Prinzip, danke dafür - jedoch wird in dem Sketch momentan nur ein Taster ausgelesen, rechts funktioniert perfekt, aber genau das ist mein Problem noch den zweiten Taster, in dem fall für Links einzubinden..

Copy und Paste wird mir hier ja wieder den gleichen Fehler wie am Anfang bringen..

Kannst du mir das zeigen?

Dan werfe ich eine Frage in Raum, was für Relais sind das? wie wird das Versorgt? nicht das die an unter Spannung leiden. Kam schon vor.

2 Kanal Relais - nichts besonderes, einfach über den 5V pin - sobald ich den Taster los lasse ist das flackern auch weg, nur im 'Schaltzustand' flackerts.

erstze:

void taster(const byte sperrkreis, const byte tastkreis)
{
  if (digitalRead(Relais[sperrkreis]) == aus)           // Nur wenn Gegenrichtung nicht ausgelöst
  {
    if (digitalRead(Taster[tastkreis]) == gedrueckt)    // Taste gedrückt?
    {
      if  (tastenMerker[tastkreis] == losgelassen)     // und vorher nicht?
      {
        digitalWrite(Relais[tastkreis], !digitalRead(Relais[tastkreis])); // Wechsel Zustand
        tastenMerker[tastkreis] = gedrueckt;
        ausloeseMerker[tastkreis] = millis();
        Serial.print(F("Taster : ")); Serial.print(tastkreis); Serial.println(F(" ausgelöst"));
      }
    }
    else
    {
      if (tastenMerker[tastkreis] == gedrueckt &&
          millis() - ausloeseMerker[tastkreis] > 20)
      {
        tastenMerker[tastkreis] = losgelassen;
        Serial.print(F("Taster : ")); Serial.print(tastkreis); Serial.println(F(" debuonce"));
      }
    }
  }
}

naja wenn du das Prinzip durchschaut hast: ... mach dir eine zweite wasPressed Funktion für den anderen Taster und reagiere in den einzelnen States auf den anderen Taster.

Ich glaube nicht dass du da wirklich meine Hilfe brauchst oder?

edit,
oder vieleicht doch:

const byte Taster = A0;
const byte Endschalter = 2;

const byte Taster1 = A1;
const byte Endschalter1 = 3;

const byte Relais = 13;
const byte Relais1 = 12;

enum State {LEFT,       // Endposition Links
            RIGHT,      // Endposition Rechts
            LEFT_GO,    // Bewegung nach Links
            RIGHT_GO,   // Bewegung nach Rechts
            LEFT_HALT,  // Nothalt während Bewegung nach Links
            RIGHT_HALT  // Nothalt während Bewegung nach Rechts
           };
State state;

bool tasterWasPressedLeft()
{
  int btnstate = !digitalRead(Taster1); //Taster lesen
  static bool lastbtnstate = true;
  bool result = false;
  if (btnstate != lastbtnstate)
  {
    delay(50);
  }
  if (btnstate == true && btnstate != lastbtnstate)
  {
    Serial.println(F("pressed A"));
    result = true;
  }
  lastbtnstate = btnstate;
  return result;
}

bool tasterWasPressedRight()
{
  int btnstate = !digitalRead(Taster); //Taster lesen
  static bool lastbtnstate = true;
  bool result = false;
  if (btnstate != lastbtnstate)
  {
    delay(50);
  }
  if (btnstate == true && btnstate != lastbtnstate)
  {
    Serial.println(F("pressed B"));
    result = true;
  }
  lastbtnstate = btnstate;
  return result;
}

void stop()
{
  digitalWrite(Relais, LOW);
  digitalWrite(Relais1, LOW);
}
void goRight()
{
  digitalWrite(Relais, HIGH);
  digitalWrite(Relais1, LOW);
}

void goLeft()
{
  digitalWrite(Relais, LOW);
  digitalWrite(Relais1, HIGH);
}

void setup() {
  Serial.begin(115200);
  pinMode(Taster, INPUT_PULLUP);
  pinMode(Endschalter, INPUT_PULLUP);

  pinMode(Taster1, INPUT_PULLUP);
  pinMode(Endschalter1, INPUT_PULLUP);

  pinMode(Relais, OUTPUT);
  pinMode(Relais1, OUTPUT);
}

void loop()
{
  switch (state)
  {
    case LEFT:
      if (tasterWasPressedRight())
      {
        Serial.println(F("start RIGHT_GO"));
        state = RIGHT_GO;
        goRight();
      }
      break;
    case LEFT_GO:
      if (digitalRead(Endschalter1) == LOW)
      {
        Serial.println(F("End LEFT"));
        state = LEFT;
        stop();
      }
      if (tasterWasPressedLeft())
      {
        Serial.println(F("LEFT halted"));
        state = LEFT_HALT;
        stop();
      }
      break;
    case LEFT_HALT:
      if (tasterWasPressedLeft())
      {
        Serial.println(F("restart LEFT"));
        state = LEFT_GO;
        goLeft();
      }
      if (tasterWasPressedRight())
      {
        Serial.println(F("reverse RIGHT"));
        state = RIGHT_GO;
        goRight();
      }
      break;
    case RIGHT:
      if (tasterWasPressedLeft())
      {
        Serial.println(F("start LEFT"));
        state = LEFT_GO;
        goLeft();
      }
      break;
    case RIGHT_GO:
      if (digitalRead(Endschalter) == LOW)
      {
        Serial.println(F("End RIGHT"));
        state = RIGHT;
        stop();
      }
      if (tasterWasPressedRight())
      {
        Serial.println(F("RIGHT halted"));
        state = RIGHT_HALT;
        stop();
      }
      break;
    case RIGHT_HALT:
      if (tasterWasPressedRight())
      {
        Serial.println(F("restart RIGHT"));
        state = RIGHT_GO;
        goRight();
      }
      if (tasterWasPressedLeft())
      {
        Serial.println(F("reverse Left"));
        state = LEFT_GO;
        goLeft();
      }
      break;
  }
}

Danke, ich hatte gerade eine nicht funktionierende Variante hochladen wollen..

Hast du noch ein Tutorial für mich für diese 'State Machines'?
Würde mich da gerne noch genauer mit beschäftigen!