Wie pausiere ich einen teil eines sketches?

Hallo,
Ich möchte einen teil meines sketches pausieren und fortführen können.
Hier der sketch:

#include <Bounce.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>


#define ONE_WIRE_BUS 30  // Temperatursensor pin 30
LiquidCrystal lcd(22, 23, 24, 25, 26, 27, 28);
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

DeviceAddress Sensor[] = {{0x28, 0xCD, 0x9B, 0xDA, 0x03, 0x00, 0x00, 0xF2},
                          {0x28, 0x1F, 0xA3, 0xDA, 0x03, 0x00, 0x00, 0xE2},
                          {0x28, 0x2D, 0xB9, 0xDA, 0x03, 0x00, 0x00, 0xA0},
                          {0x28, 0x37, 0x88, 0xDA, 0x03, 0x00, 0x00, 0x7D}};

int backLight = 29;
uint8_t k[] = {31, 32, 33, 35};   //relais HIGH = Aus; LOW = An

uint8_t knopf1 = 34;
uint8_t buttonState = 0; //knopf
Bounce bouncer = Bounce( knopf1, 5 );

uint32_t previousMillis = 0;


int   mpxPin =  5; //drucksensor
int   mpx;
float pkPa;

uint8_t ledPin = 9; // (kemo)
uint8_t fade;
uint8_t status;

 uint32_t nextMillis = 0;
 uint32_t thresholdMillis = 0;

void setup() {
  pinMode(backLight, OUTPUT);
  digitalWrite(backLight, HIGH);
  lcd.begin(20, 4);
  sensors.begin();
  uint8_t i;
  for (i = 0; i < 4; i++) {
    pinMode(k[i], OUTPUT);
    digitalWrite(k[i], HIGH);
  }
  pinMode(knopf1, INPUT);
  
  status=20; // 20 = aus
  sensors.setWaitForConversion(false);
  sensors.requestTemperatures();
}

void loop(){
  // check if conversion is done
  if (oneWire.read_bit()) {
    
    uint8_t i;
    for (i = 0; i < 4; i++) {
      lcd.setCursor(0, i);
      lcd.print("T");
      lcd.print(i+1, DEC);
      lcd.print(":");
      if (sensors.isConnected(Sensor[i])) {
        lcd.print(sensors.getTempC(Sensor[i]));
        lcd.print("C");
      } else {
        lcd.print("AUS   ");
      }
    }
    // start next conversion
    sensors.requestTemperatures();
  
    mpx = analogRead(mpxPin);
    pkPa = (mpx/1023.0-0.04)/0.0018;
    lcd.setCursor(10, 0);
    lcd.print(pkPa);
    lcd.print("mb   ");
    lcd.setCursor(10, 1);
    lcd.print(fade);
  }
    
  
  
  if ( bouncer.update() ) {
     if ( bouncer.read() == HIGH) {
       if ( buttonState == LOW ) {
         uint8_t i;
         for (i = 0; i < 4; i++) {
          digitalWrite(k[i], HIGH);
          }
         analogWrite(ledPin, 0);
         thresholdMillis = 0;
         nextMillis = 0;
         
         status = 0;
         
         buttonState = HIGH;
       } else {
         
         status = 20; // programm1 aus
         uint8_t i;
         for (i = 0; i < 4; i++) {
          digitalWrite(k[i], HIGH);
          }
         analogWrite(ledPin, 0);
         thresholdMillis = 0;
         nextMillis = 0;
    
         buttonState = LOW;
      }
    }
  }
  programm1();
} // endklammer des loops

void programm1() {
  
 if (status == 0){
    digitalWrite(k[0], LOW);
    status = 1;
  } else if (sensors.getTempC(Sensor[0]) >= 23.0 && status == 1) {
    digitalWrite(k[0], HIGH);
    status = 2;
    nextMillis = millis() + 30000L;
  } else if (status == 2 && millis() > nextMillis) {
    digitalWrite(k[1], LOW);
    digitalWrite(k[2], LOW);
    digitalWrite(k[3], LOW);
    fade = 0;
    analogWrite(ledPin, fade);
    fade = 51;
    analogWrite(ledPin, fade);
  
		status = 3;
		nextMillis = millis() + 30000L;
	
  } else if (status == 3 && millis() > nextMillis) {
    fade = 102;
    analogWrite(ledPin, fade);
      status = 4;
      nextMillis = millis() + 30000L;
  } else if (status == 4 && millis() > nextMillis) {
    fade = 153;
    analogWrite(ledPin, fade);
  
      status = 5;
      nextMillis = millis() + 30000L;
    
  } else if (status == 5 && millis() > nextMillis) {
    fade = 255;
      status = 6;
    
  }
  if (sensors.getTempC(Sensor[0]) >= 25.0 && thresholdMillis == 0) {
    digitalWrite(k[1], HIGH);
    thresholdMillis = millis() + 30000L;
  } else if (thresholdMillis && millis() > thresholdMillis) {
    digitalWrite(k[2], HIGH);
    digitalWrite(k[3], HIGH);
    analogWrite(ledPin, 0);
    thresholdMillis = 0;
    nextMillis = 0;
    fade = 0;
    
    status = 20;
  }   
}

Von diesem sketch möchte ich programm1 (wenn es gerade an ist) an einer beliebigen stelle anhalten können und ab dem punkt auch wieder fortfahren können.
Dazu möchte ich dem sketch einen "pausenknopf" hinzufügen, der bei kurzem drücken das nur programm1 anhällt sich genau die stelle merkt und von dort aus bei weiterem knopfdruck fortsetzt.
Mir ist, aber noch keine idee gekommen wie ich den plan umsetzen kann.
Kann mir bitte jemand helfen?Vorschläge,Tipps?

Mfg

strohhirn

Gab's das nicht schon am Ende von:
http://arduino.cc/forum/index.php/topic,122789.15.html

Wie willst Du es angehen?

Das einzige, das mir einfällt ist ein Interrupt auslösen und die Rücksprungaddresse verbiegen, damit der µC nach dem Interrupt anderen Code ausführt. Das ist aber alles andere als trivial. Ich kann mir eigentlich nicht vorstellen, dass du das nicht auch anderst lösen kannst. Beschreib doch mal ein bisschen großzügiger, was du machen möchtest und wieso es notwendig ist den Code an der stelle zu pausieren das kann man bestimmt einfacher erledigen.

Auch mir eschließt sich nicht der Sinn Deiner Frage.
Bitte erklär uns besser was Du machen willst. Vieleicht finden wir eine bessere Lösung.

Ich kenne keine einfache Lösung außer jede 2. Zeile einen Funktionsaufruf zu machen und in der Funktion den Taster zu kontrollieren. Falls dieser das erste mal gedrückt wurde startest Due ine Schleife die nichts weiter mache als den Taster abzufragen und herauszuspringen wenn der Taster ein zweites mal gedrückt wurde. Damit will ich aber nicht sagen, auch nicht indirekt, daß diese Programmlogik sinnvoll ist.

Grüße Uwe

Ich habe die Frage auch nicht genau verstanden.

Was genau willst Du erreichen? Sind Programm 1 und 2 logisch sowas wie 2 unabhängige Threads und Du willst einen Thread pausieren können? Oder sind das 2 Unterprogramm und solange 1 steht kommt überhaupt nichts mehr dran?

Beides halte ich für relativ einfach zu realisieren. Vor allem dann wenn Du bei Programm 1 damit leben kannst nur an gewissen vordefinierten Stellen zu halten.

Ja jurs das thema habe ich schon mal angesprochen.

Hier einmal ne zusammenfassung was der sketch macht :

loop:

  • Temperaturen messen
  • Druck messen
  • Messwerte Temperatur und Druck auf LCD anzeigen
  • Fadewert anzeigen
  • Startknopf (knopf1) abfragen:
    -startet programm1
    -resetet und verlässt es wenn es läuft

programm1:
1.relais k0 einschalten (LOW = an)
2.wenn Sensor1 25.8 °C erreicht/überschreitet soll k1 aus gehen (HIGH = aus)
3.nachdem k0 aus ist soll eine minute gewartet werden(ohne delay),nach dieser minute sollen relais k1 , k2 und k3 angehen (also LOW)
4.gleichzeitig soll mit den relais k1 und k2 und k3 eine LED mit einem PWM signal von 51 aufleuchten, denn sollen 2min gewartet werden(ohne delay)
5.nach diesen 2 min soll die LED leuchtkraft auf ein PWM signal von 102 steigen,denn sollen 3 min gewartet werden(ohne delay)
6.nach diesen 3 min soll die LED leuchtkraft auf ein PWM signal von 153 steigen,denn sollen 4 min gewartet werden(ohne delay)
7.nach diesen 4 min soll die LED leuchtkraft auf ein PWM signal von 255 steigen und so bleiben bis das programm beendet ist
8.wenn Sensor1 27°C ereicht/überschreitet soll k1 ausgehen (HIGH)
9.denn sollen 5 min gewartet werden(ohne delay)
10.nach diesen 5 min soll k2 und k3 ausgehen(HIGH)
11.wenn nach diesen 5 min k2 un k3 aus sind soll das Programm1 verlassen werden und wiederverwendbar sein

(die zeiten temp.werte und fadewerte sind nur testwerte und beispiele)

Jetzt will ich noch einen pausenknopf hinzufügen, der ,wenn programm1 gerade läuft, bei kurzem drücken es anhält (LCD soll sich weiterhin aktualisieren) und bei wiederholtem drücken es genau von der angehaltenen stelle weiterlaufen lässt.

Die einfachste Lösung wäre es die Teile als Zustandsautomat abzubilden. Für die Haltedauer würde man dann einfach beim "Programm 1 Automat" die Zustandsübergänge unterbinden.

Alternativ könntest Du auch die durchlaufenden Sachen per Interrupt treiben und "Programm 1" im Loop lassen. Den Loop könnte man mit einer unterbrechbaren Interruptroutine stoppen und wieder starten. Diese Lösung ist allerdings nicht ohne Nebenwirkungen. In der Regel schiessen sich Anfänger mit sowas ins Knie.

Die dritte Lösung wäre um jede Zeile von Programm 1 ein If zu packen. also so:

int16_t line = 1;
void loop() {  
    if (line == 1) {
        // Zeile 1
        line = 2;
    }
    if (line == 2) {
      // Zeile 2
      line = 3;
    }

...


    if (line == 4711) {
      // letzte Zeile
      line = 1;
    }
}

Wenn der Code aussetzen soll würde ich dann einfach

line = -line;

setzen und zum starten ebenfalls

line = -line;

Genaugenommen ist das ein Zustandsautomat wie ich ihn oben beschrieben habe.

Da programm1 ja eigentlich nur aus Pausen besteht, die ja zudem bereits ohne delay realisiert sind, musst Du bei "Pause" doch eigentlich nur jeweils immer die nextMillis nach hinten verschieben, oder?

  • Interrupt in dem der Pausezustand gesetzt wird.
  • function loop { if (pause) { nextMillis += MillisekundenDieDerLoopdurchlaufBenötigt; } }

Danke für die ideen und anregungen.