- Was ist Multitasking?
- Warum Verzögerung () in Arduino überspringen?
- Warum Millis () verwenden?
- Erforderliche Komponenten
- Schaltplan
- Programmieren von Arduino UNO für Multitasking
Das Multitasking hat die Computer zu einer Revolution geführt, bei der ein oder mehrere Programme gleichzeitig ausgeführt werden können, was die Effizienz, Flexibilität, Anpassungsfähigkeit und Produktivität erhöht. In eingebetteten Systemen können Mikrocontroller auch Multitasking verarbeiten und zwei oder mehr Aufgaben gleichzeitig ausführen, ohne die aktuellen Anweisungen anzuhalten.
Hier in diesem Tutorial erfahren Sie, wie Arduino Multitasking mit der Arduino Millis-Funktion ausführt. Im Allgemeinen wird in Arduino eine delay () - Funktion für eine periodische Aufgabe wie das Blinken der LED verwendet, aber diese delay () - Funktion stoppt das Programm für eine bestimmte Zeit und lässt keine anderen Operationen zu. In diesem Artikel wird erläutert, wie wir die Verwendung der Funktion delay () vermeiden und durch millis () ersetzen können, um mehr als eine Aufgabe gleichzeitig auszuführen und den Arduino zu einem Multitasking-Controller zu machen. Bevor wir ins Detail gehen, beginnen wir mit dem Verständnis von Multitasking.
Was ist Multitasking?
Multitasking bedeutet einfach, mehrere Aufgaben oder Programme gleichzeitig auszuführen. Fast alle Betriebssysteme verfügen über Multitasking. Diese Art von Betriebssystemen wird als MOS (Multitasking-Betriebssystem) bezeichnet. Der MOS kann ein mobiles oder Desktop-PC-Betriebssystem sein. Das gute Beispiel für Multitasking auf Computern ist, wenn Benutzer die E-Mail-Anwendung, den Internetbrowser, den Media Player und die Spiele gleichzeitig ausführen und wenn Benutzer die Anwendung nicht verwenden möchten, wird sie im Hintergrund ausgeführt, wenn sie nicht geschlossen wird. Der Endbenutzer verwendet alle diese Anwendungen gleichzeitig, aber das Betriebssystem sieht dieses Konzept etwas anders. Lassen Sie uns diskutieren, wie das Betriebssystem Multitasking verwaltet.
Wie in der Abbildung zu sehen ist, teilt die CPU die Zeit in drei gleiche Teile auf und ordnet jeden Teil jeder Aufgabe / Anwendung zu. So wird das Multitasking in den meisten Systemen durchgeführt. Das Konzept wird für das Arduino Multitasking fast gleich sein, außer dass die Zeitverteilung etwas anders sein wird. Da der Arduino im Vergleich zu Laptop / Mobile / PC mit niedriger Frequenz und RAM betrieben wird, ist auch die für jede Aufgabe angegebene Zeit unterschiedlich. Arduino hat auch eine delay () - Funktion, die weit verbreitet ist. Bevor wir beginnen, wollen wir diskutieren, warum wir die delay () - Funktion in keinem Projekt verwenden sollten.
Warum Verzögerung () in Arduino überspringen?
Wenn die Referenzdokumentation von Arduino berücksichtigt wird, gibt es zwei Arten von Verzögerungsfunktionen: die erste ist delay () und die zweite ist delayMicroseconds (). Beide Funktionen sind hinsichtlich der Erzeugungsverzögerung identisch. Der einzige Unterschied besteht darin, dass in der Funktion delay () die übergebene Parameter-Ganzzahl in Millisekunden angegeben wird, dh wenn wir die Verzögerung (1000) schreiben, beträgt die Verzögerung 1000 Millisekunden, dh 1 Sekunde. In ähnlicher Weise wird in der Funktion delayMicroseconds () der übergebene Parameter in Mikrosekunden angegeben. Wenn wir also delayMicroseconds (1000) schreiben, beträgt die Verzögerung 1000 Mikrosekunden, dh 1 Millisekunde.
Hier kommt der Punkt, beide Funktionen pausieren das Programm für die in der Verzögerungsfunktion verstrichene Zeit. Wenn wir also eine Verzögerung von 1 Sekunde angeben, kann der Prozessor erst nach Ablauf von 1 Sekunde zum nächsten Befehl übergehen. Wenn die Verzögerung 10 Sekunden beträgt, stoppt das Programm für 10 Sekunden und der Prozessor lässt die nächsten Anweisungen erst nach Ablauf der 10 Sekunden zu. Dies beeinträchtigt die Leistung des Mikrocontrollers in Bezug auf Geschwindigkeit und Ausführung der Anweisungen.
Das beste Beispiel, um den Nachteil der Verzögerungsfunktion zu erklären, ist die Verwendung von zwei Drucktasten. Stellen Sie sich vor, wir möchten zwei LEDs mit zwei Drucktasten umschalten. Wenn also ein Druckknopf gedrückt wird, sollte die entsprechende LED 2 Sekunden lang leuchten. Wenn der zweite gedrückt wird, sollte die LED 4 Sekunden lang leuchten. Wenn wir jedoch delay () verwenden, wenn der Benutzer die erste Taste drückt, stoppt das Programm für 2 Sekunden und wenn der Benutzer die zweite Taste vor 2 Sekunden Verzögerung drückt, akzeptiert der Mikrocontroller die Eingabe nicht wie das Programm ist in der Haltestufe.
In der offiziellen Dokumentation von Arduino wird dies in der Funktionsbeschreibung Notes and Warnings of delay () deutlich erwähnt. Sie können dies überprüfen, um es klarer zu machen.
Warum Millis () verwenden?
Um das durch die Verwendung von Verzögerung verursachte Problem zu lösen, sollte ein Entwickler die millis () -Funktion verwenden, die einfach zu verwenden ist, sobald Sie sich daran gewöhnt haben, und die 100% ige CPU-Leistung verwendet, ohne dass die Ausführung der Anweisungen verzögert wird. millis () ist eine Funktion, die nur die Anzahl der Millisekunden zurückgibt, die vergangen sind, seit das Arduino-Board das aktuelle Programm ausgeführt hat, ohne das Programm einzufrieren. Diese Zeitnummer läuft nach ungefähr 50 Tagen über (dh geht zurück auf Null).
Genau wie Arduino delayMicroseconds () hat, hat es auch die Mikroversion von millis () als micros (). Der Unterschied zwischen Mikros und Millis besteht darin, dass die Mikros () nach ungefähr 70 Minuten überlaufen, verglichen mit Millis (), das 50 Tage beträgt. Je nach Anwendung können Sie also millis () oder micros () verwenden.
Verwenden von millis () anstelle von delay ():
Um millis () für Timing und Verzögerung zu verwenden, müssen Sie die Zeit aufzeichnen und speichern, zu der die Aktion zum Starten der Zeit stattgefunden hat, und dann in Intervallen prüfen, ob die definierte Zeit abgelaufen ist. Speichern Sie also wie angegeben die aktuelle Zeit in einer Variablen.
unsigned long currentMillis = millis ();
Wir benötigen zwei weitere Variablen, um herauszufinden, ob die erforderliche Zeit verstrichen ist. Wir haben die aktuelle Zeit in der Variablen currentMillis gespeichert, müssen aber auch wissen, wann und wie lange die Zeitperiode begonnen hat. Also wird das Intervall und die vorherige Millis deklariert. Das Intervall gibt die Zeitverzögerung an und previosMillis speichert das letzte Mal, als das Ereignis aufgetreten ist.
unsigned long previousMillis; vorzeichenlose lange Periode = 1000;
Um dies zu verstehen, nehmen wir ein Beispiel einer einfachen blinkenden LED. Die Periode = 1000 zeigt an, dass die LED 1 Sekunde oder 1000 ms lang blinkt.
const int ledPin = 4; // die angeschlossene LED-Pin-Nummer int ledState = LOW; // wird verwendet, um den LED-Status ohne Vorzeichen zu setzen long previousMillis = 0; // speichert das letzte Mal, als die LED blinkte const long period = 1000; // Zeitraum, in dem in ms void flash () zu blinken ist { pinMode (ledPin, OUTPUT); // Ledpin als Ausgabe setzen } void loop () { unsigned long currentMillis = millis (); // speichere die aktuelle Zeit if (currentMillis - previousMillis> = period) {// überprüfe ob 1000ms bestanden previousMillis = currentMillis; // speichere das letzte Mal, als du die LED blinkst if (ledState == LOW) {// wenn die LED aus ist, schalte sie ein und umgekehrt ledState = HIGH; } else { ledState = LOW; }} digitalWrite (ledPin, ledState); // LED mit ledState so einstellen, dass sie wieder blinkt } }
Hier die Aussage
Interrupts in Arduino funktionieren genauso wie in anderen Mikrocontrollern. Die Arduino UNO-Karte verfügt über zwei separate Pins zum Anschließen von Interrupts an GPIO-Pin 2 und 3. Wir haben dies im Arduino Interrupts Tutorial ausführlich behandelt, in dem Sie mehr über Interrupts und deren Verwendung erfahren können.
Hier zeigen wir Arduino Multitasking, indem wir zwei Aufgaben gleichzeitig erledigen. Die Aufgaben umfassen das Blinken von zwei LEDs mit unterschiedlicher Zeitverzögerung sowie einen Druckknopf, mit dem der EIN / AUS-Zustand der LED gesteuert wird. Es werden also drei Aufgaben gleichzeitig ausgeführt.
Erforderliche Komponenten
- Arduino UNO
- Drei LEDs (beliebige Farbe)
- Widerstände (470, 10k)
- Jumper
- Steckbrett
Schaltplan
Das Schaltbild zur Demonstration der Verwendung der Arduino Millis () -Funktion ist sehr einfach und enthält nicht viele Komponenten, die wie unten gezeigt angebracht werden müssen.
Programmieren von Arduino UNO für Multitasking
Für die Programmierung von Arduino UNO für Multitasking ist nur die oben erläuterte Logik zur Funktionsweise von millis () erforderlich. Es wird empfohlen, die Blink-LED immer wieder mit Millis zu üben , um die Logik zu verdeutlichen und sich mit Millis () vertraut zu machen, bevor Sie mit der Programmierung von Arduino UNO für Multitasking beginnen. In diesem Tutorial wird der Interrupt auch mit millis () gleichzeitig für Multitasking verwendet. Die Schaltfläche wird ein Interrupt sein. Wenn also ein Interrupt generiert wird, dh ein Druckknopf gedrückt wird, wechselt die LED in den EIN- oder AUS-Zustand.Die Programmierung beginnt mit der Angabe der Pin-Nummern, an denen LEDs und Push Button angeschlossen sind.
int led1 = 6; int led2 = 7; int toggleLed = 5; int pushButton = 2;
Als nächstes schreiben wir eine Variable, um den Status von LEDs für die zukünftige Verwendung zu speichern.
int ledState1 = LOW; int ledState2 = LOW;
Wie oben im Blinkbeispiel erläutert, werden die Variablen für Periode und vorherige Millis zum Vergleichen und Erzeugen einer Verzögerung für LEDs deklariert. Die erste LED blinkt alle 1 Sekunde und eine weitere LED blinkt nach 200 ms.
unsigned long previousMillis1 = 0; const long period1 = 1000; unsigned long previousMillis2 = 0; const long period2 = 200;
Eine andere Millis-Funktion wird verwendet, um die Entprellverzögerung zu erzeugen, um das mehrfache Drücken des Druckknopfs zu vermeiden. Es wird einen ähnlichen Ansatz wie oben geben.
int debouncePeriod = 20; int debounceMillis = 0;
Die drei Variablen werden verwendet, um den Status des Druckknopfs als Interrupt, Umschalt-LED und Druckknopfstatus zu speichern.
bool buttonPushed = false; int ledChange = LOW; int lastState = HIGH;
Definieren Sie die Aktion des Pins, welcher Pin als INPUT oder OUTPUT fungiert.
pinMode (led1, OUTPUT); pinMode (led2, OUTPUT); pinMode (toggleLed, OUTPUT); pinMode (pushButton, INPUT);
Definieren Sie nun den Interrupt-Pin, indem Sie den Interrupt mit der Definition von ISR und Interrupt-Modus anhängen. Beachten Sie, dass empfohlen wird, digitalPinToInterrupt (pin_number) zu verwenden, wenn Sie die Funktion attachInterrupt () deklarieren, um den tatsächlichen digitalen Pin in die spezifische Interrupt-Nummer zu übersetzen.
attachInterrupt (digitalPinToInterrupt (pushButton), pushButton_ISR, CHANGE);
Das Interrupt-Unterprogramm wird geschrieben und ändert nur das buttonPushed- Flag. Beachten Sie, dass die Interrupt-Subroutine so kurz wie möglich sein sollte. Versuchen Sie daher, sie zu schreiben und die zusätzlichen Anweisungen zu minimieren.
void pushButton_ISR () { buttonPushed = true; }}
Die Schleife beginnt mit dem Speichern des Millis-Werts in einer currentMillis-Variablen, in der der Wert der verstrichenen Zeit bei jeder Iteration der Schleife gespeichert wird.
unsigned long currentMillis = millis ();
Beim Multitasking gibt es insgesamt drei Funktionen: Blinken Sie eine LED bei 1 Sekunde, Blinken Sie die zweite LED bei 200 ms und schalten Sie die LED aus, wenn der Druckknopf gedrückt wird. Wir werden also drei Teile schreiben, um diese Aufgabe zu erledigen.
Der erste ist das Umschalten des LED-Status nach jeweils 1 Sekunde durch Vergleichen der verstrichenen Millis.
if (currentMillis - previousMillis1> = period1) { previousMillis1 = currentMillis; if (ledState1 == LOW) { ledState1 = HIGH; } else { ledState1 = LOW; } digitalWrite (led1, ledState1); }}
In ähnlicher Weise wird die LED zum zweiten Mal alle 200 ms durch Vergleichen der verstrichenen Millis umgeschaltet. Die Erklärung wurde bereits weiter oben in diesem Artikel erläutert.
if (currentMillis - previousMillis2> = period2) { previousMillis2 = currentMillis; if (ledState2 == LOW) { ledState2 = HIGH; } else { ledState2 = LOW; } digitalWrite (led2, ledState2); }}
Zuletzt wird das buttonPushed- Flag überwacht und nach dem Erzeugen einer Entprellverzögerung von 20 ms wird nur der Status der LED umgeschaltet, der dem als Interrupt angebrachten Druckknopf entspricht.
if (buttonPushed = true) // prüfe, ob ISR aufgerufen wird { if ((currentMillis - debounceMillis)> debouncePeriod && buttonPushed) // 20 ms Entprellverzögerung erzeugen, um Mehrfachdrücke zu vermeiden { debounceMillis = currentMillis; // speichere die letzte Entprellverzögerungszeit, wenn (digitalRead (pushButton) == LOW && lastState == HIGH) // die LED ändern, nachdem der Druckknopf gedrückt wurde { ledChange =! ledChange; digitalWrite (toggleLed, ledChange); lastState = LOW; } else if (digitalRead (pushButton) == HIGH && lastState == LOW) { lastState = HIGH; } buttonPushed = false; } }
Damit ist das Arduino millis () Tutorial beendet. Beachten Sie, dass Sie diese Logik nur in einigen anderen Anwendungen implementieren müssen, um sich an millis () zu gewöhnen. Sie können es auch erweitern, um Motoren, Servomotoren, Sensoren und andere Peripheriegeräte zu verwenden. Im Zweifelsfall schreiben Sie bitte in unser Forum oder kommentieren Sie unten.
Der vollständige Code und das Video zur Demonstration der Verwendung der Millis-Funktion in Arduino finden Sie unten.