ESC und Motor ansteuern mit millis()

Hallo liebe Community!

Für ein kleines Projekt habe ich 3 Taster an einem Sender, mit denen ich 3 verschiedene Geschwindigkeiten an einem Motor über einen Empfänger+ ESC einstellen möchte.

  1. Taster (1. Funktion): Motor dreht mit 0 RPM
  2. Taster (2. Funktion): Motor dreht mit kleiner RPM
  3. Taster (3. Funktion): Motor soll für 5 Sekunden mit maximaler RPM drehen, und dann auf die kleine RPM umschalten. 1 Minute muss vergehen, bis der 3. Taster wieder aktiviert werden kann.

Das funktioniert soweit, bis auf Taster 3. Ich habe das mit der millis() Funktion probiert, allerdings bisher ohne Erfolg.

Könnt ihr mir bitte dabei helfen, die Funktion vom 3. Taster zu erfüllen?
Auch die "Sperre" für eine Minute, nachdem der 3. Taster gedrückt wurde, bringt mich zum verzweifeln. Ich bin für jede Hilfe sehr dankbar, da ich noch nicht viel Erfahrung habe.

Anbei der Code:

#include <RCSwitch.h>
#include <Servo.h>
Servo servo;
RCSwitch mySwitch = RCSwitch();

unsigned long previousMillis = 0; 
const long interval = 5000;

void setup() 
{
  Serial.begin(9600);
  mySwitch.enableReceive(0);  // Empfänger ist an Interrupt-Pin "0" - Das ist am NANO der Pin2
  servo.attach(3,1000,2000);
  
}

void loop() {
  
  if (mySwitch.available()) // Wenn ein Code Empfangen wird...
  {
  
  int value = mySwitch.getReceivedValue(); 

  if (value == 5680)   //Verarbeitung: Wenn der Arduino die Zahl "5680" empfängt, dann... 
        {  
    aus ();
        }

  else  if (value == 5679) //Verarbeitung: Wenn der Arduino die Zahl "5679" empfängt, dann... 
         {
          langsam ();    
         }

  else  if (value == 5678)   //Verarbeitung: Wenn der Arduino die Zahl "5678" empfängt, dann... 
        {  
           unsigned long currentMillis = millis();
           if (currentMillis - previousMillis >= interval) {
           langsam ();
           previousMillis = currentMillis;
          }

            else {
            schnell ();
           
          }    
      }
  }
}

  void langsam () {
        servo.writeMicroseconds(1800);
        mySwitch.resetAvailable(); // Hier wird der Empfänger "resettet"  
  }

  void aus () {
         servo.writeMicroseconds(1500);
            mySwitch.resetAvailable(); // Hier wird der Empfänger "resettet"  
  }

  void schnell (){
      servo.writeMicroseconds(2000);
      mySwitch.resetAvailable();// Hier wird der Empfänger "resettet"   
  }



 

Wenn du in der Arduino IDE STRG+T drückst, formatiert die IDE dein Sketch automatisch und rückt die Zeilen richtig ein. So wie dein Sketch im Moment formatiert ist, sieht man schlecht welcher Code in welchen Block gehört. Bitte änder dies.

unsigned long currentMillis

Deklariert die Variable currentMillis vom Typ unsigned long. Dies sollte man pro Variable nur einmal im Sketch machen. Du machst das einmal vor dem Setup (global) und einmal in einer if-Abfrage (lokal). Global würde bei dir gut sein. In deiner If-Abfrage reicht dann ein Aufruf der Variable, dein Code weis dann welcher Typ die Variable ist.

currentMillis = millis();

Und du meinst bestimmt ESP und nicht ESC. Da gibt es aber auch verschiedene. Welchen nutzt du?

Nicht schön, aber zum Kurztest:

// ungetestet kompiliert fehlerfrei
void loop()
{
  static bool merker = false; // Merker fuer Status "Start" des LangsamModus
  static bool minutenSperre = false;
  const unsigned long minutenInterval = 1000UL * 60; // zeit in ms
  if (mySwitch.available()) // Wenn ein Code Empfangen wird...
  {
    int value = mySwitch.getReceivedValue();
    if (value == 5680)   //Verarbeitung: Wenn der Arduino die Zahl "5680" empfängt, dann...
    {
      aus ();
    }
    else  if (value == 5679) //Verarbeitung: Wenn der Arduino die Zahl "5679" empfängt, dann...
    {
      langsam ();
    }
    else  if (value == 5678 && minutenSperre == false) //Verarbeitung: Wenn der Arduino die Zahl "5678" empfängt, dann...
    {
      if (merker == false)
      {
        previousMillis = millis();
        merker = true;
        schnell();
      }
      else if (millis() - previousMillis >= interval)
      {
        merker = false;
        langsam();
        minutenSperre = true;
        // Wenn ein "Restart" nicht gewollt ist, musst Du hier value mit einem anderen Wert ueberschreiben
      }
    }
  }
  if (millis() - previousMillis >= minutenInterval && minutenSperre == true)
  {
    minutenSperre = false;
  }
}

Zum testen solltest das minutenInterval verkürzen.

Danke für die Hilfe! Ich probiere das heute noch aus.

Ich tippe auf ESC = Electronic Speed Controller, siehe Brushlessmotor mit ESC ansteuern.

Hallo my_xy_projekt,

wow! Danke! Damit bin ich dem Ziel schon deutlich näher gekommen.
Allerdings macht der Motor beim switchen der Tasten nicht immer was er soll.
Ich habe die Sperre gerade auf 10 sec zum Testen eingestellt.
Zum Beispiel:

  1. schnell()-Taste drücken. Motor geht auf schnell(), nach interval (5sec) auf langsam().
    Wenn ich dann die aus()-Taste drücke und dann sofort wieder die schnell()-Taste:
    Dann wartet das Programm 5 sekunden (nicht 10) und der Motor geht wieder auf schnell(), bleibt jedoch auf schnell() und wechselt nicht wieder nach interval auf langsam().

  2. schnell()-Taste drücken. Motor geht auf schnell(). Während schnell() auf die aus()-Taste drücken. Dann wieder auf schnell()-Taste drücken: Motor geht nach 5 sekunden in den langsam() modus.

Hoffe das ist einigermaßen anschaulich erklärt. Ich denke wir sind sehr nah an der Lösung dran, allerdings "spinnt" das System noch etwas, wenn ich schnell zwischen den Tastern switche.

Meintest du das vllt mit dem Kommentar: "// Wenn ein "Restart" nicht gewollt ist, musst Du hier value mit einem anderen Wert ueberschreiben"?

Viele Grüße

Das ist klar. Schaltest in der Zeit, wo die merker noch aktiv sind, kommt Dir mit Ablauf der Zeit die dann erfüllende Bedingung dazwischen.
Also musst Du die Merker löschen, wenn Du manuell eingreifst.

Nur zusätzlich in die Abfragezweige von Value 5680 und 5679 die Zeilen rein:

minutenSperre = false;
merker = false;

Damit werden die gelöscht und fummeln nicht mehr rein.

Danke für deine Antwort.
Habe die Merker auf false gesetzt in die Abfragen von 5680 und 5679.
Alles funktioniert nun richtig sauber, bis auf die Minutensperre. Das heißt ich kann gleich wieder in den schnell() Modus nachdem ich auf aus() gedrückt habe.
Habe versucht jeweils die Minutensperre auf true zu setzen und nur den merker auf false, aber damit hat es nicht funktioniert.

Hast du noch eine Idee wie man die Minutensperre wieder reinbekommt?

Danke

Mooment.
Im Ausgangspost:

In der Zeit, wo 3. Funktion aktiviert ist, machst Du mit der FB entweder 1. Funktion und/oder 2. Funktion.

Und jetzt kommt:

Das heisst, Du willst 1. und 2. Funktion mit der Hand aktivieren, während eigentlich 3. Funktion aktiv ist und ein erneutes aktivieren von 3. Funktion verhindern?
Das heisst, 3. Funktion bleibt gesperrt, obwohl 1. oder 2. manuell aktiviert?
Das wäre was ganz anderes....

Genau! Das war so gedacht. Sry, habe es nicht exakt beschrieben in meinem Ausgangspost.

Das hört man nicht so gerne. Heißt deutlich mehr Aufwand für den Code?

...Der Code funktioniert abgesehen von der Minutensperre so gut! Kein Unterbrechungen, alles reagiert zackig. Einfach perfekt.

Hi my_xy_projekt,

kannst du mir bitte noch einen Tipp geben, wie ich die Minutensperre einprogrammieren kann?
Muss ich den ganzen Code umgestalten oder reicht eine neue Merker variable für die Taster aus() und langsam() eventuell?

Viele Grüße

Nicht wirklich.
Irgendwie bekomme ich die Aufgabenstellung nicht abgebildet.
Eigentlich ist der Code aus #3 doch das, was Du suchst.
value 5680 macht aus
value 5679 macht langsam
value 5678 macht Takt und sperrt sich selbst.
Wenn Du jetzt 5680 machst, ist der aus.
Oder wenn Du 5679 machst ist der langsam.
Die 5678 kannst erst wieder aktivieren, wenn die minutenSperre gelöscht ist.
Ich hab mir jetzt was zusammengereimt.
Ob das funktioniert? Keine Ahnung.
Beschreibe genau, was Du willst.

void loop()
{
  static bool merker = false; // Merker fuer Status "Start" des LangsamModus
  static bool minutenSperre = false;
  const unsigned long minutenInterval = 1000UL * 60; // zeit in ms
  if (mySwitch.available()) // Wenn ein Code Empfangen wird...
  {
    unsigned int value = mySwitch.getReceivedValue();
    if (value == 5680)   //Verarbeitung: Wenn der Arduino die Zahl "5680" empfängt, dann...
    {
      aus ();
    }
    else  if (value == 5679) //Verarbeitung: Wenn der Arduino die Zahl "5679" empfängt, dann...
    {
      langsam ();
    }
    else  if (value == 5678 && minutenSperre == false) //Verarbeitung: Wenn der Arduino die Zahl "5678" empfängt, dann...
    {
      minutenSperre = true;
    }
  }
  if ((minutenSperre) && ((value != 5680) || (value != 5679)))
  {
    if (merker == false)
    {
      previousMillis = millis();
      merker = true;
      schnell();
    }
    else if (millis() - previousMillis >= interval)
    {
      merker = false;
      langsam();
      minutenSperre = true;
    }
  }
  if (millis() - previousMillis >= minutenInterval && minutenSperre == true)
  {
    minutenSperre = false;
  }
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.