RC Panzer mit Airsoftgun

Guten Abend die Herren,

Ich habe ein RC Panzer gebastelt, Arduino empfängt die PWM Signale. Wird die Bedingung erfüllt wir eine Funktion/Methode schuss(); aufgerufen. Diese Funktion beinhaltet einen sheduler welches ein Relai ansteuert. Wird der Stromkreis geschlossen feuert eine Airsoftgun eine Kugel ab.

Anbei habe ich noch ein Bild hochgeladen.

Der Code funktioniert zwar hat jedoch seine Schwachstellen. Irgendwie Blockiere ich mich selber.
Die Mechanik der Airsoftgun braucht ca. 300ms für einen Vorgang. Die Funktion schuss(); wird aufgerufen wenn Knopf auf dem RC Controller gedrückt wird zwar aufgerufen. Jedoch der Sheduler in dieser Funktion funktioniert ja eigentlich so nicht.
Das Intervall ist zwar 300ms, jedoch läuft sie ja nicht durch, weil nach dem der Knopf 1x « if(channel[0]<=1005 && channel[0]>950) » gedrückt wurde. Wird die Funktion 1x aufgerufen und danach nicht mehr.

Kann mir jemand weiterhelfen? Ich möchte das die Funktion schuss(); aufgerufen wird, Relai für 350ms den Stromkreis schliesst und er danach den Relai auf LOW schaltet ausser ich bleibe am Knopf?
Besten Dank!

*
 Dieses Arduino Programm wertet die PWM Signale aus, vom Carlson 2.4Ghz Remote Controller
 Es werden keine delays verwendet.
 PulseIn Funktion hat jedoch selber ein Timer. Ansonsten wird der eigene Sheduler verwendet.
 */

//PINs für LEDs
int pin13=13;

//PINs für Channel
int pin2=2;
int pin3=3;


//Variablen für PWM SIgnale
double channel[2]; //Zum auswerten von 2 Signal Eingängen
                   //0=Channel 8 =>Arduino Pin 3, 1=Channel 11 0=>Arduino Pin 2
//Röle Pin
int pin11=11;

//LED Status
int ledState=LOW;

//Varianlen für Sheduler
unsigned long previousMillis=0; // um ziet zu speichere wie viel sekunde nach de letschte änderig vergange isch
unsigned long interval=300; //interval zwischen zwei änderige in millisekunde

void setup()
{
  //Channel Eingänge
  pinMode(pin2, INPUT);
  pinMode(pin3, INPUT);

  //LED Eingang
  pinMode(pin13, OUTPUT);

  //Röle Pin
  pinMode(pin11, OUTPUT);

  //LED Standart aus
  digitalWrite(pin13, LOW); 
  
  Serial.begin(9600);
}

void loop()
{
  channel[0] = pulseIn(pin2, HIGH); // Der übergeben Wert ist "HIGH". Es wird gewartet bis PIN auf HIGH gezogen ist. Startet Timer bis wieder LOW ist. Pulse länge in us wird retour gegeben. Möglich ist auch ein Timer mitzugeben  10 microseconds to 3 minutes, pulseIn(pin, value, timeout)
  channel[1] = pulseIn(pin3, HIGH);

  //Ausgabe in Serial Monitor
  Serial.print("CH 8: ");  
  Serial.print(channel[0]);
  Serial.print(" ===== ");
  Serial.print("CH 11: ");   
  Serial.println(channel[1]);

  if(channel[1]<=1007) //Sicherheitsknopf on
  {
    if(channel[0]<=1005 && channel[0]>950) //Airsoftgun soll nur schiessen wenn PWM Periode stimmt
    {
      schuss(); 
    }

     digitalWrite(pin13, LOW);
    // digitalWrite(pin11, LOW);       
  }
  else
  {
     digitalWrite(pin11, LOW);
  }

  //Sicherheitsabfrage soll Automatisch off schalten, wenn PWM Signale nicht mehr stimmen oder gestört sind.
  if(channel[1]>1400 || channel[1]<950 || channel[0]>1400 ||  channel[0]<950) 
  {
      digitalWrite(pin13, LOW);
      digitalWrite(pin11, LOW); 
  }
}

/*
Diese Funktion beinhaltet einen kleinen Sheduler. Der Sheduler setzt den Röle PIN eine Zeit auf HIGH.
Relai Stromkreis wird für diese Periode geschlossen 
*/
 void schuss()
 {    
      Serial.println("");
      Serial.println("Schuss");
  
      if(millis()-previousMillis >= interval)
      {
        previousMillis = millis(); //aktuelli zeit speichere    

        if(ledState==LOW)
        {
          ledState=HIGH; 
        }
            digitalWrite(pin13, ledState); 
            digitalWrite(pin11, HIGH);
      }
 }

Hier noch das Bild (siehe Attached File)

Zu diesem Projekt möchte ich nichts beitragen.

Ich denke, der Punkt ist, dass die Funktion "Schuss()" nur aufgerufen wird, wenn der Knopf der Fernbedienung gedrückt wurde.

damit "if(millis()-previousMillis >= interval)" funktionier, muss die Funktion aber ständig in der loop() aufgerufen werden.

ich würde eine globale Variable bool SchussAusloesen einführen.
die wird gesetzt, wenn der Knopf gedrückt wird, und von der Funktion Schuss() ausgewertet wird.

z.B. so:

void schuss()
{
  if (SchussAusloesen)                        // Wenn Schuss angefordert
  {
    previousMillis = millis();                  //aktuelli zeit speichere
    Serial.println("");
    Serial.println("Schuss");
    digitalWrite(pin13, HIGH);                  // Kontroll-LED ein
    digitalWrite(pin11, HIGH);                  // Relais ein
  }
  if (millis() - previousMillis >= interval)  // Wenn Zeit für Relais abgelaufen
    SchussAusloesen = false;                    // Schussanforderung löschen
    digitalWrite(pin13, LOW);                   // Kontroll-LED aus
    digitalWrite(pin11, LOW);                   // Relais aus
  }
}

Super vielen Dank für das Feedback 

Ich werde es am Mittwoch ausprobieren. Bin erst jetzt von der Arbeit gekommen.

@ElEspanol: Sorry ich wollte niemandem zu nahetreten. Wusste nicht das solche Sachen unerwünscht sind. Die Idee habe ich von den Amis https://www.youtube.com/watch?v=rDQ8IhDB5jM
Und fand es Lustig. Wollte mit einem Kollegen was Ähnliches machen. Bin jetzt aber mal im Alleingang dran.
Keine Angst ich werde es nie in der nähe von Menschen und Tieren testen.

Ob es hier unerwünscht ist, kann ich nicht sagen und auch nicht bestimmen.
Jedoch möchte ich auf ausdrücklich darauf hinweisen, das dein Projekt sehr einfach nachgebaut werden kann, mit FPV drauf und anstatt Airsoft etwas anderes darauf gebaut wird.
Ich möchte mir nicht vorstellen, wenn sowas dann in einer Grosstadt in der Fußgängerzone losgelassen wird. Schon schlimm genug, das DJIs zum Granaten abwerfen genommen werden können.

Hi

Jeder simple, sogar mit delay() gefütterte Arduino, kann nach zuvor bestimmter Zeit einen Ausgang schalten.
Eigentlich ist Das genau Seine Bestimmung.

Was an dem Ausgang dran hängt, hängt nun eher von Dem ab, Der den Arduino benutzt.

Und ob ich nun - verbotener Weise - einer Silvester-Rakete aber so was von exakt 0:00:00 zum Start verhelfe, oder dort doch 'etwas Anderes' auf das 'Spannung anlegen' reagiert, macht der Programmierung keinen Unterschied.

Klar kann ich mittels Arduino wesentlich komplexere Szenarien abdecken - aber das 'Bumm' am Ende geht genau so auch mit einer simplen Batterie.
Und wenn Du den Leuten zuvor lange genug einredest, daß eh Alles nur Sünder sind, brauchst Du den Arduino auch nicht mehr!

MfG

Da hast du vollkommen recht. Ich finde es trotzdem nicht gut, das das Projekt in diesem Forum in „Klartext“ erwähnt wird und u.U. technische Lösungen zu vorhandenen Problemen von uns diskutiert/gefunden werden.
Da helfe ich lieber bei KFZ Modifikationen im Südsudan, welche in der EU zum Erlöschen der ABE führen würden.

Im endeffekt kann jeded RC Fahr,- und Flugzeug zur Bombe/Waffe umgerüstet werden.

Nur das man hier halt einen Trigger zum Auslösen eines Schusses und Ketten an Board hat.

Falls das Teil auf einem Privaten Airsoftgelände benutzt wird, finde ich es cool.

Genug OT. Ich lese mal weiter mit.

Liebe Leute,

Das Programm funktioniert :slight_smile:
Danke!

Wenn ich mal länger Zeit habe versuche ich es noch genauer zu verstehen. Ich mache im Moment noch ein Überlegungsfehler.

Jetzt habe ich noch eine weitere Funktion eingebaut.

automatischAus();

Damit nicht alles im loop(); steht.

Ich übergeben jetzt die Werte channel[0] und channel[1] an die Funktion

automatischAus(channel[0], channel[1]);
Erduino bring jedoch ein Error (redefinition of double* channel) bei:

void automatischAus(double channel[0], double channel[1])

LG
hoju

/*
 Dieses Arduino Programm wertet die PWM Signale aus, vom Carlson 2.4Ghz Remote Controller
 Es werden keine delays verwendet.
 PulseIn Funktion hat jedoch selber ein Timer. Ansonsten wird der eigene Sheduler verwendet.
 */

//PINs für LEDs
int pin13=13;

//PINs für Channel
int pin2=2;
int pin3=3;


//Variablen für PWM SIgnale
double channel[2]; //Zum auswerten von 2 Signal Eingängen
                   //0=Channel 8 =>Arduino Pin 3, 1=Channel 11 0=>Arduino Pin 2
//Röle Pin
int pin11=11;

//LED Status
int ledState=LOW;

//Varianlen für Sheduler
unsigned long previousMillis=0; // um ziet zu speichere wie viel sekunde nach de letschte änderig vergange isch
unsigned long interval=300; //interval zwischen zwei änderige in millisekunde

//Auswerten
bool SchussAusloesen=false;

void setup()
{
  //Channel Eingänge
  pinMode(pin2, INPUT);
  pinMode(pin3, INPUT);

  //LED Eingang
  pinMode(pin13, OUTPUT);

  //Röle Pin
  pinMode(pin11, OUTPUT);

  //LED Standart aus
  digitalWrite(pin13, LOW); 
  
  Serial.begin(9600);
}

void loop()
{

  
  channel[0] = pulseIn(pin2, HIGH); // Der übergeben Wert ist "HIGH". Es wird gewartet bis PIN auf HIGH gezogen ist. Startet Timer bis wieder LOW ist. Pulse länge in us wird retour gegeben. Möglich ist auch ein Timer mitzugeben  10 microseconds to 3 minutes, pulseIn(pin, value, timeout)
  channel[1] = pulseIn(pin3, HIGH);
  
  automatischAus(channel[0], channel[1]);
  
  //Ausgabe in Serial Monitor
  /*OFF
  Serial.print("CH 8: ");  
  Serial.print(channel[0]);
  Serial.print(" ===== ");
  Serial.print("CH 11: ");   
  Serial.println(channel[1]);
  */

  if(channel[1]<=1007) //Sicherheitsknopf on
  {
    if(channel[0]<=1005 && channel[0]>950) //Airsoftgun soll nur schiessen wenn PWM Periode stimmt
    {
      SchussAusloesen = true;
    }     
  }
  else
  {
     digitalWrite(pin13, LOW);
     digitalWrite(pin11, LOW);
  }

  schuss(); 
}

/*
Diese Funktion beinhaltet einen kleinen Sheduler. Der Sheduler setzt den Röle PIN eine Zeit auf HIGH.
Relai Stromkreis wird für diese Periode geschlossen 
*/
 void schuss()
 {    
      if(SchussAusloesen)
      {
        previousMillis = millis();
        Serial.println("");
        Serial.println("Schuss>>");
        digitalWrite(pin13, HIGH); 
        digitalWrite(pin11, HIGH);
      }
  
      if(millis()-previousMillis >= interval)
      {
        previousMillis = millis();  //aktuelli zeit speichere    
        SchussAusloesen = false;    //Schussanforderung löschen
        digitalWrite(pin13, LOW); 
        digitalWrite(pin11, LOW);

      }
 }

 void automatischAus(double channel[0], double channel[1])
 {
  //Sicherheitsabfrage soll Automatisch off schalten, wenn PWM Signale nicht mehr stimmen oder gestört sind.
  if(channel[1]>1400 || channel[1]<950 || channel[0]>1400 ||  channel[0]<950) 
  {
      Serial.println("!!! Achtung PWM Signal Falsch !!!"); 
      digitalWrite(pin13, LOW);
      digitalWrite(pin11, LOW); 
  }
 }

Hi

Normal müsste der Compiler meckern, daß in der loop() kein Rückgabetyp für die Funktion automatischAus(..,..); angegeben ist.

Die eigentliche Funktion wird mit
void automatischAus(double channel[0], double channel[1]) {
angelegt.
In loop() rufst Du bereits eine Funktion auf, Die gar nicht existiert.
Ohne ein void davor musste der Compiler meckern, mit void wäre es die Ankündigung, also das Bekannt machen.

Schreibe am Anfang des Programm, noch vor setup();
void automatischAus(double channel[0], double channel[1]);

Also ohne geschweifte Klammer - damit kündigst Du die Funktion an.
Dadurch sucht der Compiler, ob Er die Funktion irgendwo findet.

MfG

Hi,

Ich habe den Code angepasst.

Leider habe ich jetzt einen weiteren Fehler: Alpha_V5:33: error: variable or field ‘automatischAus’ declared void.
Nur um es genauer zu verstehen. Müsste ich also Theoretisch gesehen die Funktion schuss(); Auch vor setup() anlegen?

LG

/*
 Dieses Arduino Programm wertet die PWM Signale aus, vom Carlson 2.4Ghz Remote Controller
 Es werden keine delays verwendet.
 PulseIn Funktion hat jedoch selber ein Timer. Ansonsten wird der eigene Sheduler verwendet.
 */

//PINs für LEDs
int pin13=13;

//PINs für Channel
int pin2=2;
int pin3=3;


//Variablen für PWM SIgnale
double channel[2]; //Zum auswerten von 2 Signal Eingängen
                   //0=Channel 8 =>Arduino Pin 3, 1=Channel 11 0=>Arduino Pin 2
//Röle Pin
int pin11=11;

//LED Status
int ledState=LOW;

//Varianlen für Sheduler
unsigned long previousMillis=0; // um ziet zu speichere wie viel sekunde nach de letschte änderig vergange isch
unsigned long interval=300; //interval zwischen zwei änderige in millisekunde

//Auswerten
bool SchussAusloesen=false;

void automatischAus(channel[0],channel[1]);

void setup()
{
  //Channel Eingänge
  pinMode(pin2, INPUT);
  pinMode(pin3, INPUT);

  //LED Eingang
  pinMode(pin13, OUTPUT);

  //Röle Pin
  pinMode(pin11, OUTPUT);

  //LED Standart aus
  digitalWrite(pin13, LOW); 
  
  Serial.begin(9600);
}

void loop()
{

  channel[0] = pulseIn(pin2, HIGH); // Der übergeben Wert ist "HIGH". Es wird gewartet bis PIN auf HIGH gezogen ist. Startet Timer bis wieder LOW ist. Pulse länge in us wird retour gegeben. Möglich ist auch ein Timer mitzugeben  10 microseconds to 3 minutes, pulseIn(pin, value, timeout)
  channel[1] = pulseIn(pin3, HIGH);
  
  automatischAus(channel[0], channel[1]);
  
  //Ausgabe in Serial Monitor
  /*OFF
  Serial.print("CH 8: ");  
  Serial.print(channel[0]);
  Serial.print(" ===== ");
  Serial.print("CH 11: ");   
  Serial.println(channel[1]);
  */

  if(channel[1]<=1007) //Sicherheitsknopf on
  {
    if(channel[0]<=1005 && channel[0]>950) //Airsoftgun soll nur schiessen wenn PWM Periode stimmt
    {
      SchussAusloesen = true;
    }     
  }
  else
  {
     digitalWrite(pin13, LOW);
     digitalWrite(pin11, LOW);
  }

  schuss(); 
}

/*
Diese Funktion beinhaltet einen kleinen Sheduler. Der Sheduler setzt den Röle PIN eine Zeit auf HIGH.
Relai Stromkreis wird für diese Periode geschlossen 
*/
 void schuss()
 {    
      if(SchussAusloesen)
      {
        previousMillis = millis();
        Serial.println("");
        Serial.println("Schuss>>");
        digitalWrite(pin13, HIGH); 
        digitalWrite(pin11, HIGH);
      }
  
      if(millis()-previousMillis >= interval)
      {
        previousMillis = millis();  //aktuelli zeit speichere    
        SchussAusloesen = false;    //Schussanforderung löschen
        digitalWrite(pin13, LOW); 
        digitalWrite(pin11, LOW);

      }
 }

 void automatischAus(double channel[0], double channel[1])
 {
  //Sicherheitsabfrage soll Automatisch off schalten, wenn PWM Signale nicht mehr stimmen oder gestört sind.
  if(channel[1]>1400 || channel[1]<950 || channel[0]>1400 ||  channel[0]<950) 
  {
      Serial.println("!!! Achtung PWM Signal Falsch !!!"); 
      digitalWrite(pin13, LOW);
      digitalWrite(pin11, LOW); 
  }
 }

Versuche, Zeiger zu übergeben:

  automatischAus(channel);
void automatischAus(double * chan)
{
  //Sicherheitsabfrage soll Automatisch off schalten, wenn PWM Signale nicht mehr stimmen oder gestört sind.
  if (chan[1] > 1400 || chan[1] < 950 || chan[0] > 1400 ||  chan[0] < 950)
  {
    Serial.println("!!! Achtung PWM Signal Falsch !!!");
    digitalWrite(pin13, LOW);
    digitalWrite(pin11, LOW);
  }
}

Geht das?

hoju:
Hi,

Ich habe den Code angepasst.

Leider habe ich jetzt einen weiteren Fehler: Alpha_V5:33: error: variable or field ‘automatischAus’ declared void.
Nur um es genauer zu verstehen. Müsste ich also Theoretisch gesehen die Funktion schuss(); Auch vor setup() anlegen?

Deklarieren und Definieren…
mal ein kurzer Überblick:

Deklarieren: du musst dem Kompiler sagen, dass es eine Funktion gibt:
void TestFunk(int a);
damit weiß der Kompiler, dass es eine Funktion Testfunk gibt, die einen interwert als Parameter erwartet und keinen Rückgabewert hat.
die Deklaration sollte üblicherweise vor setup stehen, die Arduino-IDE akzeptiert es, wenn es in der gleichen Datei steht.

und dann musst du noch die Funktion definieren, also, was soll die Funktion denn tun?

void TestFunk(int a){
  Serial.println("Zahlen und ihre Quadrate");
  for(int i = 0; i<=a; i++){
    int quadrat = i*i;
    Serial.print(i);
    Serial.print(":\t");
    Serial.println(quadrat);
}

Das kann dann irgendwo im Code stehen, gerne auch in anderen Dateien. Du kannst auf die Deklaration verzichten, wenn die Definition (bei Arduino) im gleichen File ist wie der Rest vom Code.

In deinem Falle passt die Deklaration von void automatischAus(channel[0],channel[1]) nicht, weil der Variablentyp fehlt.

Ausserdem passen deine Übergabeparameter nicht.

entweder, du übergibst einen double Wert (oder zwei), dann muss das so gehen:
Definition: void automatischAus(double c1, double c2){…}; // definition mit 2 double Werten als Übergabewert
Aufruf: automatischAus(channel[0], channel[1]); // Beim Aufruf werden 2 double Werte übergeben.

Oder du übergibst gleich das ganze Array:
Definition: void automatischAus(double channel[2]){…}; // definition mit einem Array als Übergabewert
Aufruf: automatischAus(channel); // Beim Aufruf wird das ganze Array übergeben.

Guten Abend alle,

So ich habe mich etwas mehr eingearbeitet/eingelesen. Damit ich das mit den Funktionen etwas besser verstehe.
Dazu habe ich aber noch eine Frage. Im Arduino Buch wird Methode statt Funktion verwendet.
Heisst es nun Funktion oder Methode?
Der Code funktioniert soweit, muss es aber noch etwas ausbessern. Weil die Funktionen im gleichen File stehen habe ich die Deklaration weggelassen.


Bei der Funktion Schuss wurde vorgeschlagen das ich millis noch speichere. Wenn ich das mache ist der Stromkreis vom Relai immer geschlossen. Ich möchte den Stromkreis aber für eine bestimmte Zeit schliessen.
Das zweite Problem ist, dass der Arduino Controller wenn ich auf dem RC Controller den Knopf betätige und loslasse mehrmals SchussAusloesen = true; ausgelöst wird.
Irgendwie muss ich sagen können SchussAusloesen = true; nur wenn 500ms vergangen sind. Wenn ich es in denn Sheduler packe kann ich den Knopf nicht auslösen oder muss es in der 500ms erwischen.


/*
 Dieses Arduino Programm wertet die PWM Signale aus, vom Carlson 2.4Ghz Remote Controller
 Es werden keine delays verwendet.
 PulseIn Funktion hat jedoch selber ein Timer. Ansonsten wird der eigene Sheduler verwendet.
 */

//PINs für LEDs
int pin13=13;

//PINs für Channel
int pin2=2;
int pin3=3;


//Variablen für PWM SIgnale
double channel[2]; //Zum auswerten von 2 Signal Eingängen
                   //0=Channel 8 =>Arduino Pin 3, 1=Channel 11 0=>Arduino Pin 2
//Röle Pin
int pin11=11;

//LED Status
int ledState=LOW;

//Varianlen für Sheduler
unsigned long previousMillis=0; // um ziet zu speichere wie viel sekunde nach de letschte änderig vergange isch
unsigned long interval=600; //interval zwischen zwei änderige in millisekunde

//Auswerten
bool SchussAusloesen=false;

void setup()
{
  //Channel Eingänge
  pinMode(pin2, INPUT);
  pinMode(pin3, INPUT);

  //LED Eingang
  pinMode(pin13, OUTPUT);

  //Röle Pin
  pinMode(pin11, OUTPUT);

  //LED Standart aus
  digitalWrite(pin13, LOW); 
  
  Serial.begin(9600);
}

void loop()
{

  channel[0] = pulseIn(pin2, HIGH); // Schuss | Der übergeben Wert ist "HIGH". Es wird gewartet bis PIN auf HIGH gezogen ist. Startet Timer bis wieder LOW ist. Pulse länge in us wird retour gegeben. Möglich ist auch ein Timer mitzugeben  10 microseconds to 3 minutes, pulseIn(pin, value, timeout)
  channel[1] = pulseIn(pin3, HIGH); //Sicherheit
  
  automatischAus(channel[1]);
  
  //Ausgabe in Serial Monitor
  /*OFF
  Serial.print("CH 8: ");  
  Serial.print(channel[0]);
  Serial.print(" ===== ");
  Serial.print("CH 11: ");   
  Serial.println(channel[1]);
  */

  if(channel[1]<=1007) //Sicherheits-Knopf on
  {
    if(channel[0]<=1005 && channel[0]>950) //Schuss-Knopf
    {
      SchussAusloesen = true;
    }     
  }
  else
  {
     digitalWrite(pin13, LOW);
     digitalWrite(pin11, LOW);
  }

  schuss(); 
}

/* Definition
Diese Funktion beinhaltet einen kleinen Sheduler. Der Sheduler setzt den Röle PIN eine Zeit auf HIGH.
Relai Stromkreis wird für diese Periode geschlossen 
*/
 void schuss()
 {    
      if(SchussAusloesen)
      {
        //previousMillis = millis();
        digitalWrite(pin13, HIGH); 
        digitalWrite(pin11, HIGH);
        int anzahl;
        anzahl=anzahl++;
        Serial.print("Schuss>> ");
        Serial.println(anzahl);
      }
  
      if(millis()-previousMillis >= interval)
      {
        previousMillis = millis();  //aktuelli zeit speichere    
        SchussAusloesen = false;    //Schussanforderung löschen
        digitalWrite(pin13, LOW); 
        digitalWrite(pin11, LOW);

      }
 }

/* Definition
 * channel_2 Sicherheits-Knopf
 * channel_1 Schuss
 */
 void automatischAus(double channel_1)
 {
  //Sicherheitsabfrage soll Automatisch off schalten, wenn PWM Signale nicht mehr stimmen oder gestört sind.
  if(channel_1>1007 || channel_1<993) 
  {
        digitalWrite(pin13, LOW);
        digitalWrite(pin11, LOW); 
       
        Serial.println("!!! Achtung PWM Signal Falsch !!!"); 
  }
 }

Es wurde, glaube ich, schonmal erwähnt, aber schau dir mal den Fred an:
BlinkwithoutDelay - Die Nachtwächtererklärunghttps://forum.arduino.cc/index.php?topic=423688.0

Hier wird sehr anschaulich erklärt, wie du einen "Scheduler", wie du ihn nennst, aufbaust, und wie du damit auch zwei unabhängige Ereignisse behandeln kannst.