- Vad är multitasking?
- Varför hoppa över fördröjning () i Arduino?
- Varför använda millis ()?
- Komponenter krävs
- Kretsschema
- Programmering av Arduino UNO för multitasking
Den multitasking har lett datorerna till en revolution där ett eller flera program kan köras samtidigt som ökar effektiviteten, flexibilitet, anpassningsförmåga och produktivitet. I inbäddade system kan mikrokontroller också hantera multitasking och utför två eller flera uppgifter samtidigt utan att de nuvarande instruktionerna stoppas.
Här i den här handledningen lär vi oss hur Arduino utför multitasking med Arduino millis-funktion. Generellt används en fördröjning () -funktion i Arduino för en periodisk uppgift som LED Blinking men denna fördröjning () -funktion stoppar programmet under en viss slutgiltig tid och tillåter inte andra operationer att utföra. Så den här artikeln förklarar hur vi kan undvika att använda fördröjningsfunktionen () och ersätta den med millis () för att utföra mer än en uppgift samtidigt och göra Arduino till en multitasking-styrenhet. Innan vi går i detalj låt oss börja med att underskatta Multitasking.
Vad är multitasking?
Multitasking betyder helt enkelt att utföra mer än en uppgift eller ett program samtidigt. Nästan alla operativsystem har multitasking. Denna typ av operativsystem kallas MOS (multitasking operativsystem). MOS kan vara operativsystem för mobila eller stationära datorer. Det goda exemplet med multitasking på datorer är när användare kör e-postapplikationen, webbläsaren, mediaspelaren, spel samtidigt och om användarna inte vill använda applikationen körs den i bakgrunden om den inte är stängd. Slutanvändaren använder alla dessa applikationer samtidigt men OS tar detta koncept lite annorlunda. Låt oss diskutera hur OS hanterar multitasking.
Som framgår av bilden delar CPU tiden i de tre lika delarna och tilldelar varje del till varje uppgift / applikation. Så här görs multitasking i de flesta systemen. Konceptet kommer att vara nästan samma för Arduino Multitasking, förutom att tidsfördelningen kommer att vara lite annorlunda. Eftersom Arduino körs med låg frekvens och RAM jämförs med bärbar dator / mobil / PC så kommer tiden för varje uppgift också att vara annorlunda. Arduino har också en fördröjningsfunktion () som används i stor utsträckning. Men innan vi börjar ska vi diskutera det varför vi inte ska använda delay () -funktionen i något projekt.
Varför hoppa över fördröjning () i Arduino?
Om referensdokumentationen för Arduino beaktas finns det två typer av fördröjningsfunktioner, den första är fördröjning () och den andra är fördröjning Mikrosekunder (). Båda funktionerna är identiska när det gäller att generera fördröjning. Den enda skillnaden är att, i fördröjningsfunktionen () är parametern heltal som passeras i millisekunder, dvs. om vi skriver fördröjning (1000) så kommer fördröjningen att vara 1000 millisekunder, dvs 1 sekund. På samma sätt i funktionen delayMicroseconds () är den överförda parametern i mikrosekunder, dvs. om vi skriver delayMicroseconds (1000), då kommer fördröjningen att vara på 1000 mikrosekunder, dvs. 1 millisekunder.
Här kommer poängen, båda funktionerna pausar programmet under den tid som gått i fördröjningsfunktionen. Så om vi ger en fördröjning på 1 sekund kan inte processorn gå till nästa instruktion förrän 1 sekund passerat. På samma sätt om fördröjningen är 10 sekunder kommer programmet att stoppa i 10 sekunder och processorn tillåter inte att gå till nästa instruktioner förrän de 10 sekunderna gått. Detta hindrar mikrokontrollerns prestanda när det gäller hastighet och utförande av instruktionerna.
Det bästa exemplet för att förklara nackdelen med fördröjningsfunktionen är att använda två tryckknappar. Tänk på att vi vill byta två lysdioder med två tryckknappar. Så om en tryckknapp trycks in ska motsvarande lysdiod lysa i 2 sekunder, på samma sätt om sekund trycks in ska lysdioden lysa i 4 sekunder. Men när vi använder fördröjning (), om användaren trycker på den första knappen, kommer programmet att stoppa i 2 sekunder och om användaren trycker på den andra knappen innan 2 sekunder fördröjer, accepterar inte mikrokontrollen ingången eftersom programmet är i stoppsteg.
Den officiella dokumentationen för Arduino nämner detta tydligt i dess beskrivning av anteckningar och varningar om fördröjning (). Du kan gå igenom och kolla in detta för att göra det tydligare.
Varför använda millis ()?
För att övervinna problemet som orsakas av att använda fördröjning, bör en utvecklare använda millis () -funktionen som är lätt att använda när du har blivit vanligt och den kommer att använda 100% CPU-prestanda utan att generera någon fördröjning när instruktionerna utförs. millis () är en funktion som bara returnerar mängden millisekunder som har gått sedan Arduino-kortet började köra det aktuella programmet utan att frysa programmet. Detta tidsnummer kommer att rinna över (dvs. gå tillbaka till noll) efter cirka 50 dagar.
Precis som Arduino har delayMicroseconds (), har den också mikroversionen av millis () som micros (). Skillnaden mellan micros och millis är att micros () kommer att rinna över efter cirka 70 minuter, jämfört med millis () vilket är 50 dagar. Så beroende på applikation kan du använda millis () eller micros ().
Använda millis () istället för fördröjning ():
För att använda millis () för timing och fördröjning måste du registrera och lagra den tid då åtgärden ägde rum för att starta tiden och sedan kontrollera med intervaller om den definierade tiden har gått. Så som sagt, lagra aktuell tid i en variabel.
osignerad långströmMillis = millis ();
Vi behöver ytterligare två variabler för att ta reda på om den erforderliga tiden har gått. Vi har lagrat aktuell tid i currentMillis- variabel men vi måste också veta att när började tidsperioden och hur lång är perioden. Så Intervall och tidigare Millis förklaras. Intervallet anger tidsfördröjningen och previosMillis lagrar den senaste gången händelsen inträffade.
osignerad lång tidigare Millis; osignerad lång period = 1000;
För att förstå detta, låt oss ta ett exempel på en enkel blinkande lysdiod. Perioden = 1000 kommer att tala om för oss att lysdioden blinkar i 1 sekund eller 1000 ms.
const int ledPin = 4; // LED-pin-numret anslutet int ledState = LOW; // används för att ställa in LED-tillståndet osignerat långt tidigareMillis = 0; // kommer att lagra förra gången lysdioden blinkade const lång period = 1000; // period för att blinka i ms tomrumsinställning () { pinMode (ledPin, OUTPUT); // set ledpin as output } void loop () { unsigned long currentMillis = millis (); // lagra aktuell tid om (currentMillis - previousMillis> = period) {// kontrollera om 1000 ms passerat previousMillis = currentMillis; // spara sista gången du blinkade lysdioden om (ledState == LOW) {// om lysdioden är av, slå på den och vice versa ledState = HIGH; } annat { ledState = LÅG; } digitalWrite (ledPin, ledState); // ställ in LED med ledState för att blinka igen } }
Här uttalandet
Avbrott i Arduino fungerar på samma sätt som i andra mikrokontroller. Arduino UNO-kortet har två separata stift för att fästa avbrott på GPIO-stift 2 och 3. Vi har täckt det detaljerat i Arduino Interrupts Tutorial, där du kan lära dig mer om Interrupts och hur du använder dem.
Här visar vi Arduino Multitasking genom att hantera två uppgifter samtidigt. Uppgifterna kommer att inkludera att två lysdioder blinkar i olika tidsfördröjning tillsammans med en tryckknapp som används för att styra PÅ / AV-tillståndet för LED. Så tre uppgifter kommer att utföras samtidigt.
Komponenter krävs
- Arduino UNO
- Tre lysdioder (valfri färg)
- Motstånd (470, 10k)
- Tröjor
- Bakbord
Kretsschema
Kretsschemat för att demonstrera användningen av Arduino Millis () -funktion är väldigt enkelt och har inte mycket komponenter att fästa som visas nedan.
Programmering av Arduino UNO för multitasking
Programmering av Arduino UNO för multitasking kräver bara logiken bakom hur millis () fungerar som förklaras ovan. Det rekommenderas att öva blink-LED med millis om och om igen för att göra logiken tydlig och göra dig bekväm med millis () innan du börjar programmera Arduino UNO för multitasking. I denna handledning används avbrottet också med millis () samtidigt för multitasking. Knappen blir ett avbrott. Så när ett avbrott genereras, dvs tryckknappen trycks in, kommer lysdioden att växla till PÅ eller AV-läge.Programmeringen börjar med att deklarera stiftnummer där lysdioder och tryckknapp är anslutna.
int led1 = 6; int led2 = 7; int toggleLed = 5; int tryckknapp = 2;
Därefter skriver vi en variabel för att lagra status för lysdioder för framtida bruk.
int ledState1 = LÅG; int ledState2 = LÅG;
Precis som förklarats ovan i blinkningsexemplet förklaras variablerna för period och tidigare millis för att jämföra och generera fördröjning för lysdioder. Den första lysdioden blinkar efter var 1 sekund och en annan lysdiod blinkar efter 200 ms.
osignerad lång föregående Millis1 = 0; const lång period1 = 1000; osignerad lång tidigareMillis2 = 0; const lång period2 = 200;
En annan millis-funktion kommer att användas för att generera avstängningsfördröjningen för att undvika att trycka på knappen flera gånger. Det kommer att finnas liknande tillvägagångssätt som ovan.
int debouncePeriod = 20; int debounceMillis = 0;
De tre variablerna används för att lagra tryckknappens status som avbrott, växla lysdiod och tryckknappstillstånd.
bool buttonPushed = false; int ledChange = LOW; int lastState = HÖG;
Definiera åtgärden för stift som vilken stift som fungerar som INPUT eller OUTPUT.
pinMode (led1, OUTPUT); pinMode (led2, OUTPUT); pinMode (toggleLed, OUTPUT); pinMode (tryckknapp, INPUT);
Definiera nu avbrottsstiftet genom att fästa avbrott med definition av ISR och avbrottsläge. Observera att det rekommenderas att använda digitalPinToInterrupt (pin_number) när deklarera attachInterrupt () -funktionen för att översätta den faktiska digitala pin till det specifika interruptnumret.
attachInterrupt (digitalPinToInterrupt (pushButton), pushButton_ISR, CHANGE);
Avbrottsrutinen skrivs och den kommer bara att ändra knappenPushed flagga. Observera att avbryt subrutinen ska vara så kort som möjligt, så försök att skriva den och minimera de extra instruktionerna.
ogiltigt pushButton_ISR () { buttonPushed = true; }
Loop börjar med att lagra millisvärdet i en currentMillis-variabel som lagrar värdet av den förflutna tiden varje gång slingan upprepas.
osignerad långströmMillis = millis ();
Det finns totalt tre funktioner i multitasking, blinka en lysdiod på 1 sekund, blinka andra lysdiod vid 200 ms och om tryckknappen trycks in, slå sedan AV / PÅ LED. Så vi kommer att skriva tre delar för att göra denna uppgift.
Den första växlar LED-tillståndet efter var 1 sekund genom att jämföra förflutna millis.
if (currentMillis - previousMillis1> = period1) { previousMillis1 = currentMillis; if (ledState1 == LOW) { ledState1 = HIGH; } annat { ledState1 = LÅG; } digitalWrite (led1, ledState1); }
Likaså andra det växlar lysdioden efter varje 200 ms genom att jämföra de förflutna millis. Förklaringen förklaras redan tidigare i den här artikeln.
if (currentMillis - previousMillis2> = period2) { previousMillis2 = currentMillis; if (ledState2 == LOW) { ledState2 = HIGH; } annat { ledState2 = LÅG; } digitalWrite (led2, ledState2); }
Slutligen, den buttonPushed är flaggan övervakas och efter generering av en studsfördröjning på 20 ms det bara växlar tillståndet hos LED motsvarar tryckknapp bifogas som avbrott.
if (buttonPushed = true) // kontrollera om ISR kallas { if ((currentMillis - debounceMillis)> debouncePeriod && buttonPushed) // generera 20 ms debounce delay för att undvika flera tryckningar { debounceMillis = currentMillis; // spara den sista debounce-fördröjningstiden om (digitalRead (pushButton) == LOW && lastState == HIGH) // byt led efter att tryckknappen trycks in { ledChange =! ledChange; digitalWrite (toggleLed, ledChange); lastState = LÅG; } annat om (digitalRead (pushButton) == HIGH && lastState == LOW) { lastState = HIGH; } buttonPushed = false; } }
Detta avslutar självstudien Arduino millis (). Observera att för att bli vanligt med millis (), öva bara på att implementera denna logik i vissa andra applikationer. Du kan också utöka den för att använda motorer, servomotorer, sensorer och andra kringutrustning. Om du är osäker, vänligen skriv till vårt forum eller kommentera nedan.
Komplett kod och video för att demonstrera användningen av millis-funktionen i Arduino finns nedan.