millis() in einer Unterfunktion

Guten Morgen ,

ich habe folgendes Problem:
In einer Unterfunktion sollen zwei Motoren angesprochen werden. Der erste soll nach dem Aufrufen des Codeteiles nach dem Abfragen von 2 Sensorständen sofort loslaufen, bis einer der Sensoren von Low auf High wechselt. Und wenn dieser Motor läuft soll der 2.Motor mit einer Zeitverzögerung von 2 sec auch anlaufen und 2 Sekunden später sofort wieder ausgehen.

Der Code kommt aber nur bis zum Anlaufen des 1. Motors ...das war`s und ich komme nicht drauf, weshalb. Hat jemand eine Idee ?Hier ist mal der Code:

    void fuellen()
         
   { 
    if ( (digitalRead(Sensor1Pin) == LOW ) && (digitalRead(Sensor2Pin) == LOW ))  // Abfrage der Bedingungen..Sensor 1 u 2
         
  
        {
          //start2 = millis();  // hier beginn eine 2.Zeit, welche nur in diesem Codeteil verwendet werden soll
          
          Pumpe2->setSpeed(200);  // Pumpe 2 beginnt zu laufen wenn Sensor1 und Sensor 2 kein Wasser am Sensor erkannt
          Pumpe2->run(FORWARD);
          
          Serial.println("Fuellen beginnt jetzt ");
          Serial.println("Pumpe 2 startet");
          
          
        }
        
            if ( millis() - start2 > 2000 ) // erst 2 Sekunden nach Beginn von dieser Sequenz soll hier Pumpe 1  für 1,5 Sekunden)
                {
                    Pumpe1->setSpeed(150);
                    Pumpe1->run(FORWARD);
                    Serial.println(" Pumpe 1 startet 2 sekunden spaeter ");
                 } 
          else if ( millis() - start2 > 4000 )
                {
                   Pumpe1->setSpeed(0);
                   Serial.println(" Pumpe 1 stoppt nach 2 Sekunden ");
                }
        
      else
        { 
          if  (digitalRead(Sensor1Pin) == HIGH)
           
            {
              Pumpe2->setSpeed(0);               // wenn der Sensor erkennt, das der Füllstand 5 ml erreicht ist, soll Pumpe 2 wieder stoppen
              Serial.println("Pumpe 2 stoppt wenn Sensor 1");
              Zustand = MESSEN;                      //Weiterschaltbedingung:  Wenn die Befülling erfolgt ist, kann mit dem eigentlichen Messvorgang gestartet werden
              Serial.println("Fuellvorgang beendet");  
             }
        }
  }

Das ist nur eine Funktion, bitte poste den ganzen Sketch, evtl. haben ja andere Teile noch Einfluss, aber das wird nicht sofort ersichtlich.

In der geposteten Funktion fällt auf, dass start2 gar nicht gesetzt wird, somit die Zeitfunktion nicht gestartet.

Zudem testest Du

if ( millis() - start2 > 2000 )

nur auf >2000, also wird

else if ( millis() - start2 > 4000 )

nicht auch nur geprüft werden, weil millis() - start2 grösser 2000 sein muss, wenn es grösser 4000 werden sollte.

hier ist der gesamte Sketch…
( einen Art Notaus fehlt übrigens auch noch…allerdings hab ich da noch keine Idee)

//letzte Aktualisierung : 26.3.2014  11:24 Uhr 
//Stand: spülen fkt.; messen fkt. ; Füllen fehlerhaft; Einbau und LCD fehlt,evt. mit Wartezeiten und einigen LED; Notaus fehlt


#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"

Adafruit_MotorShield AFMS = Adafruit_MotorShield();

Adafruit_DCMotor *Pumpe1 = AFMS.getMotor(1);   // dient dem Transport der Indikatorflüssigkeit
Adafruit_DCMotor *Pumpe2 = AFMS.getMotor(2);   // dient dem Zulauf von Probenflüssigkeit / Spülwasser
Adafruit_DCMotor *Pumpe3 = AFMS.getMotor(3);   // dient dem Absaugen des Wasser/Probenflüssigkeit

const int Sensor1Pin = 2;
const int Sensor2Pin = 3;
//const int Sensor3Pin = 1;

  const int SPUELEN = 1;
  const int FUELLEN = 2;
  const int MESSEN = 3;
  const int FERTIG = 0;
  const int startbuttonPin = 9;     // connect to Pulldown + Button to 5V
  
  int Zustand;        // Variable für den jeweiligen Zustand 
  float Messergebnis;  // global deklarierte Variable zum Aufnehmen des Messergebnisses
  
  int Sensor1State = 0;   //Status des Füllstandes in der Messkammer direkt--- sorgt dafür, das max. 5 ml in der Messkammer sind 
  int Sensor2State = 0;   // Status des Füllstandssensors unterhalb der Messkammer und vor dem Abfallbehälter
  
  int voltPin = 0;    // Festlegung, das A0 als Eingang für die Spannungswerte verwendet wird
  float Vref = 1.10; // verwendete Referenzspannung , die beim Arduino verwendet wird
  float R1 = 220;    // Widerstand R1 = 220 Ohm 
  float R2 = 100;    // Widerstand R2 = 100 Ohm
  float cal = 0.99288*(R1+R2)/R2;  // Kalibrationsfaktor, hierdurch werden u.a.Ungenauigkeiten und Fertigungstoleranzen der Bauteile ausgeglichen 
  
  int Messungen = 20;          // Anzahl der Messungen, die durchgeführt werden
  int Messwartezeit = 500;    // Wartezeit zwischen den einzelnen Messungen
  
  float valVolt;
  float tempV;
  float tempVtotal;
  float tempVmittel;   //global deklarierte Variable vom Typ float für den Mittelwert der 20 Spannungsmessungen
  
  
  boolean active; // während programm läuft, kein neuer Start

  unsigned long start1;   // Variable für die Zeit in der Spülsequenz
  unsigned long start2;   // Variable für die Zeit in der Füllsequenz
  

void setup()
 {
   
   
   analogReference(INTERNAL);   // Festlegung, das mit der internen Referenzspannung gearbeitet werden soll
   AFMS.begin();                 // Initialisierung des Adafruit Motorshield`s
   Serial.begin(9600);
   while(!Serial);     // startet die Anzeige erst beim Aufrufen des Serial Monitor
 }
  
  

void loop()
{
  static boolean active;
  if ( (digitalRead(startbuttonPin) == HIGH) && ( Zustand == FERTIG)) 
  
         Zustand=SPUELEN;
    if ( Zustand==SPUELEN ) spuelen();
    if ( Zustand==FUELLEN ) fuellen();
    if ( Zustand==MESSEN  ) messen(); 
}   
  
void spuelen()   // in dieser Sequenz sollen die Pumpe 2 (= Zulauf) und Pumpe 3 (= Ablauf) unterschiedlich schnell für genau 20 Sekunden laufen.
                 // Ziel soll es sein, dafür zu sorgen das weder in der Messkammer Flüssigkeit aus einer vorangegangen Messung vorliegt,noch das die Kammer überlaufen kann und 
                 // Schmutzpartikel weggespült werden 
                 // Im selben Zeitraum wird der Indikator im Schlauch sicher von der Vorratskammer bis an die Messkammer vorgelegt
{
         if  ( active == false)
  {
     start1 = millis();  
     active = true;    
       Serial.println("Beginn spuelen");
       Pumpe3->setSpeed(200);
       Pumpe3->run(FORWARD);
       Serial.println("Pumpe3 startet");
       Pumpe2->setSpeed(200);
       Pumpe2->run(FORWARD);
       Serial.println("Pumpe2 startet");
              
    }
   
   if  (active && (millis() - start1 < 5000) ) // Während die Pumpen laufen ... 5 Sekunden
   {
         if (millis() - start1 < 2000) //  0.3 Sekunden
              {  
                 Pumpe1->setSpeed(150);// Pumpe1 an
                 Pumpe1->run(FORWARD);
                 Serial.println("Pumpe1 startet");
           
               }
                 
         else if ( millis() - start1 > 2000) //ab 3 Sekunden Pumpe 1 aus
              {
              Pumpe1->setSpeed(0) ; // Pumpe 1 aus
              Serial.println("Pumpe 1 stoppt");
              }
         
   
   
   
   
         
    }
   else
   {
       if (active) 
       {    // Zeit gerade abgelaufen
           Pumpe2->setSpeed(0);   // ???
           Pumpe3->setSpeed(0);
           
           Serial.println("Pumpe2 und 3 stoppen");
           Zustand = FUELLEN;                                      // hier ist die Sprungmarke zum nächsten Teilabschnitt -> in diesem Fall soll das Befüllen starten
           Serial.println("Spuelen fertig");
           
       } 
   }

}

void fuellen ()                                 
          
{
    
    if ( (digitalRead(Sensor1Pin) == LOW ) && (digitalRead(Sensor2Pin) == LOW ))  // 
                                                                                                    
         
        {
          //start2 = millis();  // hier beginn eine 2.Zeit, welche nur in diesem Codeteil verwendet werden soll
          
          Pumpe2->setSpeed(200);  // Pumpe 2 beginnt zu laufen wenn Sensor1 und Sensor 2 kein Wasser am Sensor erkennen---> heißt hier ist alles leer---> Befüllung mit Wasser und Indikator kann starten
          Pumpe2->run(FORWARD);
          
          Serial.println("Fuellen beginnt jetzt ");
          Serial.println("Pumpe 2 startet");
          
        }
        
            if ( millis() - start2 > 2000 ) // erst 2 Sekunden nach Beginn von dieser Sequenz soll hier Pumpe 1  für 1,5 Sekunden anlaufen ) 
                {
                    Pumpe1->setSpeed(150);
                    Pumpe1->run(FORWARD);
                    Serial.println(" Pumpe 1 startet 2 sekunden spaeter ");
                 } 
          else if ( millis() - start2 > 4000 )
                {
                   Pumpe1->setSpeed(0);
                   Serial.println(" Pumpe 1 stoppt nach 2 Sekunden ");
                }
        
      else
        { 
          if  (digitalRead(Sensor1Pin) == HIGH)
           
            {
              Pumpe2->setSpeed(0);               // wenn der Sensor erkennt, das der Füllstand 5 ml erreicht ist, soll Pumpe 2 wieder stoppen
              Serial.println("Pumpe 2 stoppt wenn Sensor 1");
              Zustand = MESSEN;                      //Weiterschaltbedingung:  Wenn die Befülling erfolgt ist, kann mit dem eigentlichen Messvorgang gestartet werden
              Serial.println("Fuellvorgang beendet");  
             }
        }
  }


void messen()                     
          
         { 
           tempVtotal = 0;
           tempV = 0;
           tempVmittel;
           
           for (int i=0; i<Messungen;i++)
             {
               valVolt = analogRead(voltPin);      // einlesen des Werte an A0
               tempV = (valVolt*Vref/1023*cal);    // Umrechnung auf realen Wert 
               tempVtotal = tempVtotal+tempV;     // hier werden die aktuell gemesssenen Spannungswerte dem vorhergehenden dazuaddiert
               Serial.println(tempV,3);          //Anzeige des Gesamtspannungswertes mit 3 Nachkommastellen
             }
             
             Messergebnis =  tempVtotal/Messungen;
             
             Serial.println("Ende der 20 Messungen");
             
             Serial.println("gemessener Wert: "),Serial.print(Messergebnis,3),Serial.print("  Volt");  // Anzeige des gemittelten Spannungswertes
             
           if ( (Messergebnis >= 1.9)  && ( Messergebnis <= 1.99 ) )  // ist nur eine der noch zu ergänzenden if Anweisungen für die Zuordnung der pH Werte zu den ermittelten Spannungen
          
             
           Serial.println("z.B. Ph Wert liegt bei 6.2");  // Anzeige des pH Wertes 
           
           Zustand = FERTIG;
           

         }

Ist zwar nicht das Problem hier, aber du hast sehr viele String Literale. Anders als du wahrscheinlich denkst, landen die allem im RAM!

Mach das mal so:

Serial.println(F("Text"));

Mit dem F()-Makro bleiben die dann im Flash. Das geht aber nur mit der Arduino print/ln() Methode

Abgesehen von den zwei Problemen, die ich bereits im letzten Post erwähnte, werden bei Dir die meisten Variablen nicht initialisiert (Zustand, start1, start2, etc.). Auch wenn die in den meisten Fällen auf 0 sind, wenn das Programm startet, darfst Du Dich darauf nicht verlassen. Dann solltest Du dringend die Einrückungen richtig machen, damit der Programmfluss deutlicher wird. start2 wird z.B. schon mit millis() verglichen, bevor es auf einen vernünftigen Wert gesetzt wurde (was auch nur geschieht, wenn Du den Kommentar entfernst).

pylon:
Abgesehen von den zwei Problemen, die ich bereits im letzten Post erwähnte, werden bei Dir die meisten Variablen nicht initialisiert (Zustand, start1, start2, etc.). Auch wenn die in den meisten Fällen auf 0 sind, wenn das Programm startet, darfst Du Dich darauf nicht verlassen

Doch darauf kann man sich 100% verlassen. Man muss nur lokale nicht-statische Variablen initialisieren!

Lokale statische und Globale Variablen werden vom Compiler (nach C Standard) automatisch auf 0 initialisiert. Es wird sogar empfohlen solche Variablen nicht per Hand auf 0 zu initialisieren:
http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_varinit

Was sich aber hier wirklich anbietet ist Variablen die nicht global sein müssen lokal in der Funktion als "static" zu definieren. Das würde das wesentlich übersichtlicher machen. Static Variablen behalten ihren Wert von einem Aufruf der Funktion zum nächsten bei. Sie verhalten sich also wie globale Variablen aber haben lokalen Scope/Gültigigkeitsbereich

Doch darauf kann man sich 100% verlassen.

Das stimmt zwar, aber da ein sketch ewig läuft, sollte die “Füllen” Prozedur sicher mehrfach nach einen Reset laufen können.

Während des Füllens wird die Funktion fuellen() zigtausendmal aufgerufen. Einmal davon ist das erste Mal, das muss die Software irgendwie erkennen und genau dann einmal
start2 = millis();
aufrufen, damit die weitere Zeitmessung funktionieren kann.

Um diesen Start zu erkennen, kann man ( etwas unsauber ) start2 == 0 abfragen. Dann muss man natürlich am Ende des Füllens start2 = 0 setzen um sicher zu sein, dass der nächste Aufruf von fuellen() den Start einer neuen Füll-Prozedur signalisiert.

“etwas unsauber” nur, weil – äusserst unwahrscheinlich – millis() auch im laufenden Betrieb einmal alle 49 Tage den Wert 0 hat.
Alternativ geht natürlich auch eine extra Variable boolean fuellenAktiv, die als Kennzeichen für einen Neustart des Füllens dienen kann.

Eine Extra-Funktion fuellen() mit lokalen Variablen ist prinzipiell gut, um das Ganze übersichtlich zu halten.
millis() innerhalb einer solchen Funktion verhält sich natürlich genau gleich wie in loop(). Dein eigentliches Problem ist etwas unklar…

Ein Dummy, nur um die Struktur zu sehen:

const int FUELLEN = 2;
const int MESSEN = 3;
int Zustand; // fuellen() wird in loop nur aufgerufen, wenn Zustand == FUELLEN
             // fuellen signalisiert fertig durch setzen von Zustand auf MESSEN
void fuellen () 
{
   static unsigend long start; // Startzeitpunkt, 0 als Kennzeichen
   static int Phase;
   if (start == 0)
   {
      start = millis(); // Startzeitpunkt
      Serial.println(F("Füllen startet"));
      Phase = 1; 
      // Aktionen, die am Anfang gemacht werden, z.B. Pumpe 1 ein
   }
   if (millis() - start > 2000)
   { 
      if (Phase == 1)
      {
          Serial.println(F(" Füllen Phase 2 ( Pumpe 2 für 2 Sekunden dazu"));
          Phase = 2;  // damit der Text nur einmal, bei Übergang von Phase 1 nach 2, ausgeseben wird
      }
      if ( millis() - start < 4000) digitalWrite(Pumpe2Pin, HIGH);
      else digitalWrite(Pumpe2Pin, LOW);
   }
   if ( digitalRead( FüllstandsSensor) == HIGH ) // dummy: Software erkennt das Ende des Füllens
   {  
        // alle Pumpen aus
        digitalWrite(Pumpe1Pin, LOW);
        digitalWrite(Pumpe2Pin, LOW);
        
        // Füllen Ende
        start = 0; // intern
        Zustand = MESSEN; // global: fuellen() wird erst wieder für einen neuen Füll-Vorgang aufgerufen
   } 
}

Alternativ wird auch gern mit einem Rückgabewert gearbeitet:
z.b. boolean fuellen() statt void fuellen()
wenn fuellen false zurückliefert, ist es noch nicht fertig, bei true ist das Füllen komplett.
fuellen überlässt es dann dem Aufrufer, sich um die Zustand Variable zu kümmern.
Statt Zustand = MESSEN; stünde dann return true;
Das Ende von fuellen sähe dann so aus:

boolean fuellen () 
{

   //    ... wie oben

   return false;
}

Habe jetzt den Code einmal direkt im kompletten Sketch umgesetzt…
Fazit: Es ist noch immer so, dass der zweite Motor für 2 Sekunden angeschaltet wird, als ob er quasi gar nicht existiert. Das ist das größte Problem…das kann doch nicht unmöglich sein.
Abgesehen davon schaltet der Motor 1 im Testlauf sofort aus, obwohl der der Sensor physikalische gar kein HIGH Signal liefern kann. Der Versuchsaufbau wird nämlich zu Testzwecken noch ohne die Flüssigkeiten betrieben…
Hat hier jemand noch einen super Idee für das Problem???

Hänge den eingefügten Codesschnipsel direkt mal ran:

   void fuellen() 
{
    static unsigned long start;
    static int Phase;
    
    
    if  ( ( start == 0 )  && ( digitalRead(Sensor1Pin) == LOW ) && ( digitalRead(Sensor2Pin) == LOW )) 
    
            {
              start = millis();
              Serial.print(F("Fuellvorgang Phase 1 wird jetzt gestartet und Pumpe 2 startet"));
              Phase = 1;
              Pumpe2->setSpeed(200);  // Pumpe 2 beginnt zu laufen wenn Sensor1 und Sensor 2 kein Wasser am Sensor erkennen---> heißt hier ist alles leer---> Befüllung mit Wasser und Indikator kann starten
              Pumpe2->run(FORWARD);
              Serial.println(F("Status Sensor 1 :   ")),Serial.print(digitalRead(Sensor1Pin));
              Serial.println(F("Status Sensor  :   ")),Serial.print(digitalRead(Sensor2Pin));
              
            }
              
                if ( millis() - start > 2000 ) 
                    { 
                       if (Phase == 1)
                         {
                          Serial.println(F("Fuellen Phase 2 beginnt jetzt  -->   Pumpe 1 startet jetzt für 2 sec"));
                          Phase == 2;
                         }
                      
                       if ( millis() - start < 4000 )
                         {
                          Pumpe1->setSpeed(150);
                          Pumpe1->run(FORWARD);
                         }
                       else
                         { 
                          Pumpe1->setSpeed(0);
                          }
                          
                 if (digitalRead (Sensor1Pin ) == HIGH )
                  {
                         Pumpe2->setSpeed(0);
                         start = 0;
                         Zustand = MESSEN;
                   }     
            

                         
                          
                     } 
                 else if ( millis() - start2 > 4000 )
                     {
                      Pumpe1->setSpeed(0);
                      Serial.println(" Pumpe 1 stoppt nach 2 Sekunden ");
                      }

          else
           {  
             if    (digitalRead(Sensor1Pin) == HIGH)
           
                 {
                   Pumpe2->setSpeed(0);               // wenn der Sensor erkennt, das der Füllstand 5 ml erreicht ist, soll Pumpe 2 wieder stoppen
                   Serial.println("Pumpe 2 stoppt wenn Sensor 1 den gewünschten Füllstand erreicht hat");
      
                   Zustand = MESSEN;                      //Weiterschaltbedingung:  Wenn die Befülling erfolgt ist, kann mit dem eigentlichen Messvorgang gestartet werden
                   Serial.println("Fuellvorgang beendet");  
                 }
           } 
 
}

dass der zweite Motor für 2 Sekunden angeschaltet wird, als ob er quasi gar nicht existiert

kann jemand das verstehen ?

michael_x:

dass der zweite Motor für 2 Sekunden angeschaltet wird, als ob er quasi gar nicht existiert

kann jemand das verstehen ?

Und wenn dieser Motor läuft soll der 2.Motor mit einer Zeitverzögerung von 2 sec auch anlaufen und 2 Sekunden später sofort wieder ausgehen.

war im ersten Beitrag zu lesen.

Ich glaube, der OP sollte nochmals im Detail erklären, was in welcher Reihenfolge passiert, wenn der Sketch läuft.
Die Einrückungen sind immer noch so schrecklich, dass Zusammenhänge vorgegaukelt werden, die gar nicht vorhanden sind.

Hallo und Guten Morgen,

ich fasse mal den gewünschten Ablauf zusammen:
Mein Programm besteht aus einem Loop der die einzelnen Unterfunktion ( 1. void spuelen ; 2. void fuellen ; 3. void (messen) nacheinander aufrufen soll. Heißt...ich starte den gesamten Vorgang per Tastendruck und es wird mit dem Spülen( zeitgesteuert) angefangen. Wenn das Spülen beendet ist soll es mit dem Befüllen weitergehen. Dafür sollen zwei Motoren verwendet werden. Der 1.Motor soll nach Aufrufen dieser Funktion "void spuelen" und einer zusätzlichen Abfrage eines Füllstandssensors ( dieser soll ein LOW Signal liefern, wenn der Behälter leer ist ) beginnen. Das klappt soweit auch. Der 2.Motor soll allerdings erst 2 Sekunden nach dem Start von Motor 1 starten, und nach 2 Sekunden wieder stoppen. Motor 1 läuft währenddessen solange weiter bis der bereits genannte Sensor ein HIGH Signal liefert. Am Ende soll dann der Aufruf für die Funktion "MESSEN" erfolgen.

Problem ist aber nach wie vor, das der Motor 2 ebend nicht für die kurze Zeit zum Motor 1 dazugeschaltet wird.

Und noch eine Frage: Ich lasse im Serial Monitor die Meldung ( z.B, Motor 1 startet ...usw.) anzeigen,aber dieser werden ja durch die ständigen Wdh. immer und immer wieder angezeigt. Mit dem Syntax Serial.println(F("Text")) sollte das doch eigentlich nur noch einmal angezeigt werden, nämlich beim ersten Aufruf...
Leider wird der "Text" noch immer solange aufgerufen, wie die Anweisung dauert und das trotz des obigen Syntax...

Was kann man anders machen ??

Und noch eine Frage: Ich lasse im Serial Monitor die Meldung ( z.B, Motor 1 startet ...usw.) anzeigen,aber dieser werden ja durch die ständigen Wdh. immer und immer wieder angezeigt. Mit dem Syntax Serial.println(F("Text")) sollte das doch eigentlich nur noch einmal angezeigt werden, nämlich beim ersten Aufruf...
Leider wird der "Text" noch immer solange aufgerufen, wie die Anweisung dauert und das trotz des obigen Syntax...

Dies Syntax (das F() Makro) sorgt nur dafür, dass für die konstanten Zeichenketten nicht unnötig RAM verschwendet wird. Damit werden die Strings im Flash gehalten und direkt von dort ausgegeben und der Compiler braucht nicht eine Kopie im RAM vorzuhalten.

Im geposteten Code ist noch ein Durcheinander mit start und start2. Wenn Du sonst nichts am Code geändert hast, dürfte dies für das sofortige Abschalten der Pumpe 1 verantwortlich sein.

HELP !

Habe im Codeschnipsel für das Befüllen das "start 2 " in ein nur "start " abgeändert...aber das Phänomen bleibt..
Der Motor für die Pumpe 1 läuft nicht, wie gewünscht, 2 Sekunden nach Start von Pumpe 2 an und geht folglich auch nicht aus..

Ein kleiner Fortschritt:

Im Programmteil für das Spülen wird der 2. Motor zumindest schon erkannt , allerdings auch sofort mit dem Eintritt in dieses void füllen wieder ausgeschaltet…Wenn man es jetzt noch schafft, diesen Motor auch noch kurz loslaufen zu lassen — dann wären alle Probleme gelöst. Irgendwo ist noch ein Fehler bei dem Aufruf von millis() — leider steh ich wie der Ochse vor dem Berg und bin für Ideen und Anregungen sehr dankbar:

Hier noch mal der Codeteil:

void fuellen()
{
    static unsigned long start;
    static int Phase;
    start == 0;
    Sensor1State = digitalRead(Sensor1Pin);
    //start = millis();
    if  (   ( digitalRead(Sensor1Pin) == LOW ) && ( digitalRead(Sensor2Pin) == LOW )) 
    
            { 
              start = millis();
              Serial.print(F(" Fuellvorgang Phase 1 beginnt - Pumpe 2 startet "));
              //Phase = 1;
              Pumpe2->setSpeed(200);  // Pumpe 2 beginnt zu laufen wenn Sensor1 und Sensor 2 kein Wasser am Sensor erkennen---> heißt hier ist alles leer---> Befüllung mit Wasser und Indikator kann starten
              Pumpe2->run(FORWARD);
              Serial.println(F("   Status Sensor1:   ")),Serial.print(digitalRead(Sensor1Pin));
              //Serial.println(F("Status Sensor2  :   ")),Serial.print(digitalRead(Sensor2Pin));
              
            
              
                  if ( millis() - start > 2000 )
                  
                         {
                           
                          Pumpe1->setSpeed(150);
                          Pumpe1->run(FORWARD);  
                          Serial.println(F(" Pumpe 1 startet jetzt für 2 sec"));
                          
                         }
                      
                   else if ( millis() - start < 4000 )
                         {
                          Pumpe1->setSpeed(0);
                          Serial.println(" Pumpe 1 wieder aus ");
                         }
                              
            }
            
         else 
           {
               if (digitalRead (Sensor1Pin ) == HIGH )
                  {
                         Pumpe2->setSpeed(0);
                         
                         Serial.println(digitalRead(Sensor1Pin));
                         Serial.println(" Pumpe 2 stoppt - Becher voll ");
                         
                         start = 0;
                         Zustand = MESSEN;
                   }     
            

                         
                          
         }       

            }

Im Programmteil für das Spülen wird der 2. Motor zumindest schon erkannt , allerdings auch sofort mit dem Eintritt in dieses void füllen wieder ausgeschaltet....Wenn man es jetzt noch schafft, diesen Motor auch noch kurz loslaufen zu lassen --- dann wären alle Probleme gelöst. Irgendwo ist noch ein Fehler bei dem Aufruf von millis()

Du hast ja auch keinen Code drin, der wieder abstellen würde. Der else-Teil wird nur aufgerufen, wenn weniger als 2 Sekunden vergangen sind, dann aber natürlich immer ausgeführt. Dies ist aber nach Deinem Bekunden nicht Deine Absicht.

Das Einrücken ist jetzt besser, aber immer noch nicht sauber. Die IDE hat eine Funktion, die automatisch "richtig" einrückt, vielleicht probierst Du die mal aus.

Danke für den Tip mit der Übersichtlichkeit. Habe das direkt ausprobiert ( siehe unten )
Ich denke, das ich mein Anliegen nicht deutlich genug beschrieben habe.
Mit dem Aufruf von void fuellen () soll die Pumpe 2 starten und weiter laufen bis der Sensor 1 diese wieder abschaltet.
Ca. 2 Sekunden nach dem Start von Pumpe 2 soll nun auch Pumpe 1 starten/anlaufen … aber ebend nur für rd. 2 Sekunden.
Ergo soll also Pumpe 2 mit dem Sensorstand HIGH ausgeschaltet werden, und Pumpe 1 zeitversetzt starten und zeitgesteuert abgeschaltet werden…
Ist wahrscheinlich ganz banal, aber bisher habe ich ( incl. der bisher hier genannten Tips ) dieses Problem noch nicht lösen können. :~ :drooling_face: :roll_eyes:

void fuellen ()                                   // in dieser Sequenz soll die Pumpe 2 ( = Zulauf Wasser(ist das selbe wie das Probenmaterial)) genau sooolange laufen, bis Sensor1Pin mit einem HIGH Signal 
// den geforderten Füllstand von 5 ml in der Messkammer anzeigt und die Pumpe 2 entsprechend ausschaltet.
// Bedingung soll aber sein, das weder Wasser an Sensor 1 und Sensor 2 detektiert wird und die Spülsequenz soll zuvor beendet sein )
// Ca. 2 Sekunden nach dem Start von Pumpe 2 soll auch die Pumpe 1 ( = Indikator wird jetz mit einer superkurzen Laufsequenz tropfenweise dem Wasser  
// beigemischt, Wichtig ist hierbei die deutlich geringere Zeit und Geschwindigkeit)



{
  static unsigned long start;
  static int Phase;
  start == 0;
  Sensor1State = digitalRead(Sensor1Pin);
  //start = millis();
  if  (   ( digitalRead(Sensor1Pin) == LOW ) && ( digitalRead(Sensor2Pin) == LOW )) 

  { 
    start = millis();
    Serial.print(F(" Fuellvorgang Phase 1 beginnt - Pumpe 2 startet "));
    //Phase = 1;
    Pumpe2->setSpeed(200);  // Pumpe 2 beginnt zu laufen wenn Sensor1 und Sensor 2 kein Wasser am Sensor erkennen---> heißt hier ist alles leer---> Befüllung mit Wasser und Indikator kann starten
    Pumpe2->run(FORWARD);
    Serial.println(F("   Status Sensor1:   ")),Serial.print(digitalRead(Sensor1Pin));
    //Serial.println(F("Status Sensor2  :   ")),Serial.print(digitalRead(Sensor2Pin));



    if ( millis() - start > 2000 )

    {

      Pumpe1->setSpeed(150);
      Pumpe1->run(FORWARD);  
      Serial.println(F(" Pumpe 1 startet jetzt für 2 sec"));

    }

    else if ( millis() - start < 4000 )
    {
      Pumpe1->setSpeed(0);
      Serial.println(" Pumpe 1 wieder aus ");
    }

  }

  else 
  {
    if (digitalRead (Sensor1Pin ) == HIGH )
    {
      Pumpe2->setSpeed(0);

      Serial.println(digitalRead(Sensor1Pin));
      Serial.println(" Pumpe 2 stoppt - Becher voll ");

      start = 0;
      Zustand = MESSEN;
    }     




  }       

}

Am Anfang

  start == 0;

ist nur sinnlos, und daher verwirrend.
( start = 0; wäre zwar syntaxmässig richtig, aber das willst du ja gerade nicht. )

In deiner jetzigen Version startet das Füllen immer wieder neu ( incl. Serial.print - Ausschrieb …)
bis einer der beiden Sensoren ( vermutlich Sensor2) HIGH liefert, ist das deine Absicht ??

Nehmen wir das mal auseinander:

    if ( millis() - start > 2000 )

    {
        // Code Teil 1
    }

    else if ( millis() - start < 4000 )
    {
        // Code Teil 2
    }

Ich hoffe, wir gehen einig, dass Code-Teil 1 immer ausgeführt wird, wenn millis() grösser ist als start + 2000. Code-Teil 2 wird nur ausgeführt, wenn millis() kleiner ist als start + 2000 (da ist ja so ein “else” dabei). Ich glaube aber, dass Du Code-Teil 2 eigentlich dann ausführen wolltest, wenn millis() grösser wird als start + 4000. Liege ich da falsch?

Ja mehr oder weniger, das kommt auf die Definition an.

Definieren wir mal Pumpe Nr. 2 als Code 1.
Dann soll Code 1 sofort nach dem Programmaufruf starten, wenn zusätzlich zum Programmaufruf "Sensor 1" ein LOW-Signal ( Füllstand = leer ) liefert.

Definieren wir Pumpe Nr. 1 als Code 2:
Dann soll Code 2 erst 2 Sekunden nach dem Start von Code 1 starten ( also Pumpe 1 läuft erst 2 Sekunden nach Pumpe 2 los ), und ca. 2 Sekunden später wieder stoppen.

Auch nach dem Stoppen von Code 2 läuft Code 1 noch so lange weiter, bis Sensor 1 ( Füllstand = voll ) Pumpe Nr. 2 wieder abschaltet..

Ist das so verständlicher ??