Millis mit While in einem Switch Case :)

Hallo zusammen,

ich habe ein Problem.

Ich habe ESP 32 mit einem STM 32 per i2c verbunden.

An dem STM ist ein DC Motor angesteckt.

Dieser soll je nach dem, was vom ESP kommt den Motor für jeweils 3,5 oder 7 Sekunden laufen lassen.

void empfangeProgramm() {
  switch (c) {
    case 1 :
      while ((aktuelleZeit - vergangeneZeit) < pause_s) { // pause s sind unsigned long 5000
        StempelRunterfahren();
      }
      StempelStopp();
      vergangeneZeit = aktuelleZeit;
      break;
    case 2 :
      while ((aktuelleZeit - vergangeneZeit) < pause_m) { // pause s sind unsigned long 8000
        StempelRunterfahren();
      }
      vergangeneZeit = aktuelleZeit;
      StempelStopp();
      break;

  }

}

Er geht nicht mehr aus der Schleife raus :o
Wo muss vergangeneZeit = aktuelleZeit hin?

Was macht Dein StempelRunterfahren()?
Du brauchst keine eigenen Schleifen, Du hast doch loop.

Gruß Tommy

void StempelRunterfahren() {
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  Serial.println("Fahre Runter");
}

fährt meine 2 Motoren runter.

Die Motoren sollen aber nur dann runter fahren wenn der ESP per i2c etwas schickt.

Also ein Aufruf fährt komplett runter?

Gruß Tommy

habe mich glaub falsch ausgedrückt^^.

Ich will z.B dass 5 Sekunden nach dem die Methode StempelRunterfahren () aufgerufen wurde die Methode StempelStopp() aufgerufen wird. Delay kommt nicht in frage weil ich noch einen Interrupt eingebaut hab.

Das würde ich gerne in einer extra Methode drin haben und nicht in der Loop.

Deine Beschreibung ist etwas verworren. Gib uns mal den kompletten Sketch und lies Dir mal BlinkWitoutDelay in den Beispielen der IDE durch. Auch die Nachtwächtererklärung könnte Dir helfen.

Gruß Tommy

Hi

Einen Interrupt stört delay() nihct wirklich - aber ich bezweifel, daß Du einen Interrupt brauchst (wofür?).
Auch brauchst Du kein delay() oder ein While-Konstrukt, Welches das Gleiche macht.
Lies Dich in die Nachtwächtererklärung hier im Forum ein.

MfG

balocollu:
Delay kommt nicht in frage weil ich noch einen Interrupt eingebaut hab.

Interrupts und delay() haben eigentlich nichts miteinander zu tun. Vielleicht meinst Du mit Interrupt aber etwas Anderes. Wie Tommy schon meint: Zeig am besten mal den ganzen Sketch.

Gruß

Gregor

Ok dann beschreibe ich mal alles :smiley:

Ich habe eine Software auf dem Raspberry Pi. Dort habe ich ein Display angeschlossen auf dem 4 Buttons sind. Small Medium Large und STOP. Vom RPI wird ein Byte an den ESP geschickt. Der schickt es dann per i2c weiter an den STM.

Dort wo der Motor arbeitet gibt es 3 Taster. Wenn einer dieser Taster betätigt wird sollen alle Motoren stoppen.

Ich will jetzt wenn ich auf dem RPI auf S drück dass die Motoren 5 Sekunden lang runterfahren. Ich habe das auch schon mal hinbekommen. Der Motor läuft aber langsamer als sonst.

Ich poste mal den kompletten Code

#include <Wire_slave.h>        //Bibliothek für I2C-Kommunikation


// Definition STM32 PINs
//Antrieb
#define IN1 PB9                //Steuerung Motor A
#define IN2 PB8                //Steuerung Motor A
#define IN3 PB10               //Steuerung Motor B
#define IN4 PB11               //Steuerung Motor B
#define abfuellTaster PA0      //Taster für Bediener (LOW auf HIGH)
#define sicherheitskreis PB0   //wird Sicherheitskreis unterbrochen, Antriebe abschalten! mehrere Anschlagtaster angeschlossen
#define freigabeTaster PA6     //nach Neustart drücken, damit Antriebe überhaupt laufen können

unsigned long pause_s = 5000;
unsigned long pause_m = 8000;
unsigned long pause_l = 24000;
unsigned long vergangeneZeit = 0;
unsigned long vergangeneZeit2 = 0;
unsigned long intervall = 2000;
unsigned long aktuelleZeit;
bool freigabe = false;
byte c;

void setup() {
  Serial.begin(115200);
  Wire.begin(8);                 // join i2c bus with address #4
  Wire.onReceive(receiveEvent);  // register event

  pinMode(IN1, OUTPUT);
  digitalWrite(IN1, LOW);
  pinMode(IN2, OUTPUT);
  digitalWrite(IN2, LOW);
  pinMode(IN3, OUTPUT);
  digitalWrite(IN3, LOW);
  pinMode(IN4, OUTPUT);
  digitalWrite(IN4, LOW);

  pinMode(abfuellTaster, INPUT);
  pinMode(sicherheitskreis, INPUT);
  pinMode(freigabeTaster, INPUT);

  attachInterrupt(sicherheitskreis, erkenneAnschlag, FALLING);   // HIGH zu LOW
}

void loop() {
  checkeFreigabe();
  aktuelleZeit = millis();
  if (freigabe == true) {
    Wire.onReceive(receiveEvent);
    empfangeProgramm();
     
    starteAbfuellung();
  }
}

void receiveEvent(int howMany) {
  vergangeneZeit = aktuelleZeit;
  while (Wire.available()) {
    c = Wire.read();
    Serial.println(c);
  
  }
}
void checkeFreigabe() {
  if (digitalRead(freigabeTaster) == HIGH && digitalRead(sicherheitskreis) == HIGH) {
    freigabe = true;
  }
}
void erkenneAnschlag() {
  freigabe = false;
  digitalWrite(IN1, LOW);         //Schalte alle Motoren ab
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
}
void StempelRunterfahren() {
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  Serial.println("FAHRERUNTER");
}

void StempelHochfahren() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);

}

void StempelStopp() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);

}

void starteAbfuellung() {
  // abfuellTaster gedrückt
  if (digitalRead(abfuellTaster) == HIGH && digitalRead(sicherheitskreis) == HIGH) {
    StempelRunterfahren();;
  }
  // abfuellTaster wird losgelassen
  else if (digitalRead(abfuellTaster) == LOW || digitalRead(sicherheitskreis) == LOW) {
      StempelStopp();
    //TODO: Drehe x Sekunden nach oben um den Stempel zu entlasten,
    // danach muss der Stempel gestoppt werden
  }

}
void empfangeProgramm() {
  switch (c) {
    case 1:
      StempelRunterfahren();
      if ((aktuelleZeit - vergangeneZeit) >= pause_s) {
        StempelStopp();
        c = 0;
        break;

      }
    case 2:
      StempelRunterfahren();
      if ((aktuelleZeit - vergangeneZeit) >= pause_m) {
        StempelStopp();
        c = 0;
        break;

      }
  }
}

Deine while-Schleifen hast Du ja schon raus gebaut.
Wo klemmt es denn noch?

Gruß Tommy

Tommy56:
Deine while-Schleifen hast Du ja schon raus gebaut.
Wo klemmt es denn noch?

Gruß Tommy

So würde es funktionieren, der Motor läuft so aber langsamer.

Ich will die Methode empfangeProgramm() in receiveEvent reintun damit sie nicht mehr in der Loop durchgehend läuft.
Nur dann bekomm ich die Zeitsteuerung nicht mehr hin :frowning:

MfG

Die sollte im loop bleiben.

Du brauchst noch eine Variable, die Dir sagt, dass der Stempel runter fährt.
Dann brauchst Du das Runterfahren nicht laufend aufzurufen und auch nur dann macht die Zeitabfrage Sinn.

Gruß Tommy

Tommy56:
Die sollte im loop bleiben.

Du brauchst noch eine Variable, die Dir sagt, dass der Stempel runter fährt.
Dann brauchst Du das Runterfahren nicht laufend aufzurufen und auch nur dann macht die Zeitabfrage Sinn.

Gruß Tommy

Soll ich dann ein Bool auf True setzen wenn der Stempel runter fährt oder wie?

Vielen Dank noch für die ganze Hilfe ! :slight_smile:

Zum Beispiel. das Zurücksetzen beim Hochfahren nicht vergessen.

Gruß Tommy

Ich komm nicht weiter :frowning:

void StempelRunterfahren() {
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  fahrerunter = true;

}
void StempelStopp() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
  fahrerunter = false;

}

Wie soll ich in der Loop jetzt das zeitlich steuern?

Erst mal richtig lesen:

Tommy56:
das Zurücksetzen beim Hochfahren nicht vergessen.

Gruß Tommy

Tommy56:
Erst mal richtig lesen:
Gruß Tommy

Ich will doch erst mal dass er stoppt und noch nicht hochfährt.

Das Stoppen erledigst Du doch nach meinem Verständnis mit einer eigenen Funktion, die wohl auf Position oder Ahnliches reagiert. Das wirst Du schlecht per Zeit abfangen können. Was passiert, wenn er länger runter fährt? Zerlegt sich dann was?

Irgendwie stimmt Deine Beschreibung nicht.

#include <Wire_slave.h>        //Bibliothek für I2C-Kommunikation


// Definition STM32 PINs
//Antrieb
#define IN1 PB9                //Steuerung Motor A
#define IN2 PB8                //Steuerung Motor A
#define IN3 PB10               //Steuerung Motor B
#define IN4 PB11               //Steuerung Motor B
#define abfuellTaster PA0      //Taster für Bediener (LOW auf HIGH)
#define sicherheitskreis PB0   //wird Sicherheitskreis unterbrochen, Antriebe abschalten! mehrere Anschlagtaster angeschlossen
#define freigabeTaster PA6     //nach Neustart drücken, damit Antriebe überhaupt laufen können

unsigned long pause_s ;
unsigned long pause_m = 8000;
unsigned long pause_l = 24000;
unsigned long vergangeneZeit = 0;
unsigned long vergangeneZeit2 = 0;
unsigned long intervall = 2000;
unsigned long aktuelleZeit;
bool freigabe = false;
bool fahrerunter;
byte c;

void setup() {
  Serial.begin(115200);
  Wire.begin(8);                 // join i2c bus with address #4
  Wire.onReceive(receiveEvent);  // register event

  pinMode(IN1, OUTPUT);
  digitalWrite(IN1, LOW);
  pinMode(IN2, OUTPUT);
  digitalWrite(IN2, LOW);
  pinMode(IN3, OUTPUT);
  digitalWrite(IN3, LOW);
  pinMode(IN4, OUTPUT);
  digitalWrite(IN4, LOW);

  pinMode(abfuellTaster, INPUT);
  pinMode(sicherheitskreis, INPUT);
  pinMode(freigabeTaster, INPUT);

  attachInterrupt(sicherheitskreis, erkenneAnschlag, FALLING);   // HIGH zu LOW
}

void loop() {
  checkeFreigabe();
  Wire.onReceive(receiveEvent);
  if (fahrerunter == true) {
    StempelRunterfahren();
    Serial.println("FahreRunter");
    Serial.println(aktuelleZeit);
    Serial.println(vergangeneZeit);
    if ((aktuelleZeit - vergangeneZeit) > pause_s) {
      StempelHochfahren();
      Serial.println("FahreHoch");
      delay(1000);
      StempelStopp();
      fahrerunter = false;
    }
  }
  aktuelleZeit = millis();
}

void receiveEvent(int howMany) {

  while (Wire.available()) {
    vergangeneZeit = aktuelleZeit;
    c = Wire.read();
    Serial.println(c);
    empfangeProgramm();
    Serial.println(pause_s);

  }
}
void checkeFreigabe() {
  if (digitalRead(freigabeTaster) == HIGH && digitalRead(sicherheitskreis) == HIGH) {
    freigabe = true;
  }
}
void erkenneAnschlag() {
  freigabe = false;
  digitalWrite(IN1, LOW);         //Schalte alle Motoren ab
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);
}
void StempelRunterfahren() {
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);

}

void StempelHochfahren() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);


}

void StempelStopp() {
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);


}

void empfangeProgramm() {
  switch (c) {
    case 1:
      fahrerunter = true;
      pause_s = 4000;
      break;
    case 2:
      fahrerunter = true;
      pause_s = 10000;
      break;
  }
}

Ich glaube ich konnte mein Problem lösen :slight_smile:

Ob es Deinen Ansprüchen genügt, kannst nur Du wissen. Wolltest Du nicht delay vermeiden?

Gruß Tommy