Prozess an der richtigen Stelle pausieren

Ein Antrieb fährt auf und ab.(heben,senken)
An den Endpunkten wird durch Taster die Laufrichtung umgeschaltet.(oben,unten)
Wenn die Temperatut des Motors kritisch wird, soll dieser pausieren.(MAXtemp)
Die Pause soll am unteren Umschaltpunkt eingelegt werden.
Ist die Temperatur unkritisch setzt sich der Prozess fort.(MAXtemt - HYSTtemp)
Leider gelingt es mir nicht, bei Erreichen des unteren Tasters eine Pause zu programmieren, der Prozess stoppt aktuell, wenn die Maximaltemperatur erreicht wird.


float MAXtemp = 23; //in °C
float HYSTtemp = 2; //in °C
float tempKorrektur = 2.0; //in °C
float Motortemp;

bool kalt_warm = true;
bool heben_senken = false;

int oben = 10;//Endschalter oben
int unten = 12;//Endschalter unten
int heben = 5;//Relais heben
int senken = 7;//Relais senken

//Temperatur-Sensor NTC
int ntc_pin = A0; //Pin für NTC
float R1 = 10000; //10K Resistor

void setup()
{
  Serial.begin(9600);
  delay( 200 );

  pinMode(heben, OUTPUT);//Relais heben
  pinMode(senken, OUTPUT);//Relais senken
  pinMode(oben, INPUT_PULLUP);//Endschalter oben
  pinMode(unten, INPUT_PULLUP);//Endschalter unten
  pinMode(A0, INPUT);//Temperatur Motor ANALOG-PIN

  if  (digitalRead(oben) == LOW)
    !heben_senken;// = false
  if  (digitalRead(unten) == LOW)
    heben_senken;// = true
  if  ((oben) &&  (unten))
    !heben_senken;// = false;
}

void loop() {

  if  (digitalRead(oben) == LOW)
    heben_senken = false;
  if  (digitalRead(unten) == LOW)// NUR WENN DER ANTRIEB UNTEN IST, SOLL PAUSIERT WEREN!!??
    heben_senken = true;
  digitalWrite(senken, !heben_senken);

  do {
    //Temperaturmessung//////////////////////////////////////////////////////////////////////////
    float ain = analogRead(ntc_pin);
    float R2 = R1 * (1023.0 / (float)ain - 1.0);
    float lgr = log(R2);
    float tmp = (1.0 / (1.009249522e-03 + 2.378405444e-04 * lgr + 2.019202697e-07 * lgr * lgr * lgr));
    Motortemp = tmp - 273.15 + tempKorrektur;
    ///////////////////////////////////////////////////////////////////////////////////////////////
    Serial.print("Temperatur: ");
    Serial.print(Motortemp);
    Serial.print(" °C \t");
    Serial.print("warm: ");
    Serial.print(kalt_warm);
    Serial.print("\t heben: ");
    Serial.println(heben_senken);
    delay(50);
    if (Motortemp >= MAXtemp)
      kalt_warm = false;
    if (Motortemp <= MAXtemp - HYSTtemp)
      kalt_warm = true;
  }
  while (!kalt_warm); //Systempause bei Erreichen der maximal zulässigen Motortemperatur

  digitalWrite(heben, heben_senken);
}

Ich würde auf „do while“ verzichten. Außerdem würde ich in den If-Abfragen die Abfrage „!kalt_warm“ per UND (&&) verknüpfen.

Hier kommst du nicht mehr raus!
Es sei denn: kalt_warm wird in einer ISR geändert
Aber das sehe ich bei dir nicht.

1 Like

Mahlzeit!

Da Du zwei Bedingungen hast, musst Du auch beide abfragen.
Dein Konstrukt ist mir auch nicht ganz geheuer.
Die 3 bedingungen im Setup() machen nichts:

  if  (digitalRead(oben) == LOW)
    !heben_senken;// = false

Was mal zum testen - ich hab es durchkommentiert.
Eigentlich müsste das anders aufgebaut werden, ich will nur wissen, ob die Logik dahinter verstanden wird.

float MAXtemp = 23; //in °C
float HYSTtemp = 2; //in °C
float tempKorrektur = 2.0; //in °C
float Motortemp;

bool warm = false;

const byte oben = 10;//Endschalter oben
const byte unten = 12;//Endschalter unten
const byte heben = 5;//Relais heben
const byte senken = 7;//Relais senken

//Temperatur-Sensor NTC
const byte ntc_pin = A0; //Pin für NTC
float R1 = 10000; //10K Resistor

void setup()
{
  Serial.begin(9600);
  delay( 200 );
  pinMode(heben, OUTPUT);//Relais heben
  pinMode(senken, OUTPUT);//Relais senken
  pinMode(oben, INPUT_PULLUP);//Endschalter oben
  pinMode(unten, INPUT_PULLUP);//Endschalter unten
  pinMode(A0, INPUT);//Temperatur Motor ANALOG-PIN
}

void loop()
{
  //Temperaturmessung//////////////////////////////////////////////////////////////////////////
  float ain = analogRead(ntc_pin);
  float R2 = R1 * (1023.0 / (float)ain - 1.0);
  float lgr = log(R2);
  float tmp = (1.0 / (1.009249522e-03 + 2.378405444e-04 * lgr + 2.019202697e-07 * lgr * lgr * lgr));
  Motortemp = tmp - 273.15 + tempKorrektur;
  ///////////////////////////////////////////////////////////////////////////////////////////////
  Serial.print("Temperatur: ");
  Serial.print(Motortemp);
  Serial.print(" °C \t");
  Serial.print("warm: ");
  Serial.print(warm);
  Serial.print("\t heben: ");
  Serial.println(heben);
  delay(50);
  if  (!digitalRead(oben))          // Oben angeschlagen?
  {
    digitalWrite(heben, HIGH);      // Heben aus
    digitalWrite(senken, LOW);      // senken an
  }
  else if (!digitalRead(unten))     // unten angeschlagen
  {
    digitalWrite(senken, HIGH);     // Senken aus
    if (Motortemp >= MAXtemp)       // Motor warm (und unten angeschlagen)
    {
      warm = true;                  // Merke, das es warm ist
    }
    //  // solange warm ist - ABER ACHTUNG! Hier bist Du gefangen und kannst nichts anderes machen!
    if (warm)
    {
      if (Motortemp <= MAXtemp - HYSTtemp) // Warte darauf, das kalt wird
        warm = false;               // und komm wieder zurück
    }
    else
    {
      //  // Hier kommst Du nur hin, wenn Motor kalt
      digitalWrite(heben, LOW);       // heben an
    }
  }
}

Warum nicht?
im do wird kalt_warm je nach Temp gesetzt und damit ein Austritt ermöglicht.

Weil die von mir angeprangerte while Schleife eine Endlosschleife ist.
Läuft sie einmal, hilft nur noch der Resetknopf.

Was da in einer niemals an die Reihe kommenden do Schleife getan werden soll, interessiert in dem Zusammenhang überhaupt nicht.

Deine while Schleife hat übrigens genau das gleiche Problem.

1 Like

Jetzt wo es sagst.
Bei mir ist der Fehler drin.

Bei ihm aber nicht denn er misst während des do {} while() die Temperatur erneut und bekommt somit seine Abbruchbedingung.

Wo misst er in der von mir zitierten endlos Schleife die Temperatur?
Nirgendwo!
Also auch kein Ausgang.

Tipp:
Eine Endlosschleife führt dazu, dass nix anderes, außer ISR, da noch ausgeführt wird.

1 Like

zwischen do{
und
} while (!kalt_warm)

Ich ziehe zurück! Falsches Pferd - er kommt da nicht raus ohne Vergleichsbedingung. Die hat er mit dem Anstoß. des do.

Ich mach das sonst auch nicht.

Also alles gut.

Oh!

Natürlich, da hast du wahr!

Da habe ich das while doch glatt als eigenständig gesehen, und das vorherige do nicht zugeordnet.

Also, behaupte ich ab jetzt das Gegenteil!
Beim TO tritt "das" Problem nicht auf.
Ein Irrtum meinerseits.

1 Like

Hallo Leute, vielen Dank für Eure Hilfe.
Das Setup benötige ich, um den Vorgang zu starten, da beide Endschalter nicht ausgelöst sein könnten, und dann der Antrieb in eine definierte Richtung starten soll.
Ich hatte zuvor auch eine reine wihle Schleife verwendet und innerhalb dieser die Temperatur abgefragt, das funktioniert auch. Der sketch funktioniert auch soweit und hängt sich nicht auf, nur das Problem mit der Pause an der richtigen Stelle fehlt.
Ich hatte do{...} while (!kalt_warm && (unten) == LOW) versucht, aber ohne Erfolg.

Das ist in den aller meisten Fällen die falsche Vorgehensweise. Du hast in loop() eine Schleife die ständig laufen sollte. Da kann man auch einfach nichts tun, statt irgendwo wortwörtlich zu warten. Und je nach Zustand des Systems macht man dann was man braucht

Hmm, also alles noch mal verwerfen und neu aufbauen?

Na das ist das geringste Übel, nur machst Du das nicht.

Ich würde im setup() einmal eine Fahrt nach unten machen und dann von dort aus starten. Hat den Vorteil, das Du bei einem möglichen reset sofort merkst, ob der Motor warm gelaufen ist und nicht erst kurz überm Endschalter startest und nach oben und dann wieder nach unten fährst.

Und dann nicht alles in loop() schreiben sondern nach Funktion aufteilen.

In etwa so:

float MAXtemp = 23; //in °C
float HYSTtemp = 2; //in °C
float tempKorrektur = 2.0; //in °C
float Motortemp;

bool warm = false;

const byte oben = 10;//Endschalter oben
const byte unten = 12;//Endschalter unten
const byte heben = 5;//Relais heben
const byte senken = 7;//Relais senken

//Temperatur-Sensor NTC
const byte ntc_pin = A0; //Pin für NTC
float R1 = 10000; //10K Resistor

void setup()
{
  Serial.begin(9600);
  pinMode(heben, OUTPUT);//Relais heben
  digitalWrite(heben, HIGH); // aus
  pinMode(senken, OUTPUT);//Relais senken
  pinMode(oben, INPUT_PULLUP);//Endschalter oben
  pinMode(unten, INPUT_PULLUP);//Endschalter unten
  pinMode(A0, INPUT);//Temperatur Motor ANALOG-PIN
  digitalWrite(senken, LOW); //  treibt nach unten
}

void loop()
{
  getTemp();
  bewegung();
  ausgabe(500);  // schreibt im Abstand von xxx ms auf dem SerMon.
}
void getTemp()
{
  //Temperaturmessung
  float ain = analogRead(ntc_pin);
  float R2 = R1 * (1023.0 / (float)ain - 1.0);
  float lgr = log(R2);
  float tmp = (1.0 / (1.009249522e-03 + 2.378405444e-04 * lgr + 2.019202697e-07 * lgr * lgr * lgr));
  Motortemp = tmp - 273.15 + tempKorrektur;
}

void bewegung()
{
  if  (!digitalRead(oben))          // Oben angeschlagen?
  {
    digitalWrite(heben, HIGH);      // Heben aus
    digitalWrite(senken, LOW);      // senken an
  }
  else if (!digitalRead(unten))     // unten angeschlagen
  {
    digitalWrite(senken, HIGH);     // Senken aus
    if (Motortemp >= MAXtemp)       // Motor warm (und unten angeschlagen)
    {
      warm = true;                  // Merke, das es warm ist
    }
    //  // solange warm ist 
    if (warm)
    {
      if (Motortemp <= MAXtemp - HYSTtemp) // Warte darauf, das kalt wird
        warm = false;               // und komm wieder zurück
    }
    else
    {
      //  // Hier kommst Du nur hin, wenn Motor kalt
      digitalWrite(heben, LOW);       // heben an
    }
  }
}

void ausgabe(const uint32_t pause)
{
  static uint32_t lastmillis = 0;
  if (millis() - lastmillis >= pause)
  {
    Serial.print("Temperatur: ");
    Serial.print(Motortemp);
    Serial.print(" °C \t");
    Serial.print("warm: ");
    Serial.print(warm);
    Serial.print("\t heben: ");
    Serial.println(digitalRead(heben));
    lastmillis = millis();
  }
}

kein einziges while drin und kein delay() und trotzdem gehts :wink:

1 Like

:clap: :clap: :clap: Sehr cool gemacht, schon fast amüsant, wie Du mit der Programmierlogik "spielst". Es funktioniert auch mit der HW. Jedoch ist die Reaktion auf die Temperaturänderung extrem langsam geworden, woran könnte das liegen?

Naja. Die Motertemperatur wird ja nur verglichen und dementsprechend gesetzt wenn:

    if (Motortemp >= MAXtemp)       // Motor warm (und unten angeschlagen)
    {
      warm = true;                  // Merke, das es warm ist
    }

Erreicht wird. Und das passiert nur wenn:

if (!digitalRead(unten))

Vorher wahr ist.

Das sage ich Dir, wenn Du hier gelsen hast: Wie man dieses Forum benutzt - bitte lesen

Im Seriellen Monitor einfach strg-a + strg-c machen und dann in codetags (steht auch da drin wie es geht) an Stelle des Bildes einfügen.

:wink:

Das ist nicht sein alleiniges Problem.
Bei 23° ist MaxTemp erreicht.
Der hebenPin ist vorher schon HIGH.
Ihm fehlt die Information was wann mit dem senkenPin passiert.
Das ginge so:

    Serial.print(warm);
    Serial.print("\t heben: ");
    Serial.println(digitalRead(heben));
    Serial.print("\t senken: ");
    Serial.println(digitalRead(senken));

Und mir fehlt die Info, ob direkt auf die maxTemp beim hochfahren angehalten und sofort nach unten gefahren werden soll, oder ob erst oben angeschlagen und der Zyklus beendet werden muss.

Ja, Was wann genau passieren soll, muss natürlich geklärt werden.

Ich wollte nur darauf hinweisen, das die Variable 'warm' ihren zustand nicht ändert sobald die MaxTemperatur überschritten wird, sondern erst, wenn unten angechlagen wird und die MaxTemperatur überschritten wird.

Die Variable 'warm' ist so wie es bisher ist nur ein Merker ob die Hochfahrt wieder gestartet werden kann. Nicht ein Merker dafür das die Maximale Temperatur überschritten ist.

:frowning: Ja, ich weiss das. Hab das ja so geschrieben... Nur verraten wollte ich es später. Siehe oben.
Na gut. War vielleicht nicht so eindeutig rauszulesen... :wink: