- Hva er multitasking?
- Hvorfor hoppe over forsinkelse () i Arduino?
- Hvorfor bruke millis ()?
- Komponenter kreves
- Kretsdiagram
- Programmering av Arduino UNO for multitasking
Den fleroppgave har ført datamaskinene til en omdreining hvor en eller flere programmer som kan kjøres samtidig øker effektivitet, fleksibilitet, tilpasningsevne og produktivitet. I innebygde systemer kan mikrokontrollere også håndtere multitasking og utfører to eller flere oppgaver samtidig uten å stoppe gjeldende instruksjoner.
Her i denne opplæringen vil vi lære hvordan Arduino utfører multitasking med Arduino millis-funksjonen. Vanligvis brukes en forsinkelsesfunksjon () i Arduino for en periodisk oppgave som LED Blinking, men denne forsinkelsesfunksjonen () stopper programmet i en viss periode og tillater ikke andre operasjoner. Så denne artikkelen forklarer hvordan vi kan unngå bruk av delay () -funksjonen og erstatte den med millis () for å utføre mer enn én oppgave samtidig og gjøre Arduino til en multitasking-kontroller. Før vi går i detalj, la oss starte med å undervurdere Multitasking.
Hva er multitasking?
Multitasking betyr ganske enkelt å utføre mer enn én oppgave eller et program samtidig. Nesten alle operativsystemer har multitasking. Denne typen operativsystemer er kjent som MOS (multitasking operativsystem). MOS kan være operativsystem for mobil eller stasjonær PC. Det gode eksemplet på multitasking på datamaskiner er når brukere kjører e-postprogrammet, nettleseren, mediaspilleren, spill, samtidig, og hvis brukerne ikke vil bruke applikasjonen, kjører den i bakgrunnen hvis den ikke er lukket. Sluttbrukeren bruker alle disse applikasjonene samtidig, men OS tar dette konseptet litt annerledes. La oss diskutere hvordan OS administrerer multitasking.
Som vist på bildet, deler CPU tiden i de tre like delene og tilordner hver del til hver oppgave / applikasjon. Slik gjøres multitasking i de fleste systemene. Konseptet vil være nesten det samme for Arduino Multitasking, bortsett fra tidsfordelingen vil være litt annerledes. Siden Arduino kjører i lav frekvens og RAM sammenlignes med bærbar PC / mobil / PC, så tiden som blir gitt til hver oppgave vil også være forskjellig. Arduino har også en forsinkelsesfunksjon () som brukes mye. Men før vi begynner, la oss diskutere hvorfor vi ikke skal bruke delay () -funksjonen i noe prosjekt.
Hvorfor hoppe over forsinkelse () i Arduino?
Hvis referansedokumentasjonen til Arduino blir vurdert, er det to typer forsinkelsesfunksjoner, den første er forsinkelse () og den andre er forsinkelse Mikrosekunder (). Begge funksjonene er identiske når det gjelder å generere forsinkelse. Den eneste forskjellen er at, i forsinkelse () -funksjonen, er parameteren heltall som går, i millisekunder, dvs. hvis vi skriver forsinkelse (1000), vil forsinkelsen være på 1000 millisekunder, dvs. 1 sekund. Tilsvarende i funksjonen delayMicroseconds (), er parameteren som sendes i mikrosekunder, dvs. hvis vi skriver delayMicroseconds (1000), vil forsinkelsen være på 1000 mikrosekunder, dvs. 1 millisekunder.
Her kommer poenget, begge funksjonene stopper programmet i løpet av tiden som er gått i forsinkelsesfunksjonen. Så hvis vi gir en forsinkelse på 1 sekund, kan ikke prosessoren gå til neste instruksjon før 1 sekund har gått. Tilsvarende hvis forsinkelsen er 10 sekunder, vil programmet stoppe i 10 sekunder, og prosessoren vil ikke la de neste instruksjonene gå før de 10 sekundene har gått. Dette hindrer ytelsen til mikrokontrolleren når det gjelder hastighet og utføring av instruksjonene.
Det beste eksemplet for å forklare ulempen med forsinkelsesfunksjonen er å bruke to trykknapper. Tenk på at vi vil bytte to lysdioder ved hjelp av to trykknapper. Så hvis en trykknapp trykkes, skal den tilsvarende lysdioden lyse i 2 sekunder, på samme måte hvis den andre trykkes, skal lysdioden lyse i 4 sekunder. Men når vi bruker forsinkelse (), hvis brukeren trykker på den første knappen, vil programmet stoppe i 2 sekunder, og hvis brukeren trykker på den andre knappen før 2 sekunders forsinkelse, vil ikke mikrokontrolleren godta inngangen slik programmet er i stopp-etappe.
Den offisielle dokumentasjonen til Arduino nevner dette tydelig i sin beskrivelse og advarsler om forsinkelse (). Du kan gå gjennom og sjekke dette for å gjøre det mer tydelig.
Hvorfor bruke millis ()?
For å overvinne problemet forårsaket av bruk av forsinkelse, bør en utvikler bruke millis () -funksjonen som er enkel å bruke når du har blitt vanlig, og den vil bruke 100% CPU-ytelse uten å generere noen forsinkelser i å utføre instruksjonene. millis () er en funksjon som bare returnerer mengden millisekunder som har gått siden Arduino-styret begynte å kjøre det nåværende programmet uten å fryse programmet. Dette tidstallet vil flyte over (dvs. gå tilbake til null), etter omtrent 50 dager.
Akkurat som Arduino har delayMicroseconds (), har den også mikroversjonen av millis () som micros (). Forskjellen mellom mikro og millis er at mikroene () vil renne over etter ca. 70 minutter, sammenlignet med millis () som er 50 dager. Så avhengig av applikasjonen kan du bruke millis () eller micros ().
Bruker millis () i stedet for forsinkelse ():
For å bruke millis () for timing og forsinkelse, må du registrere og lagre tidspunktet da handlingen fant sted for å starte tiden, og deretter sjekke med intervaller om den definerte tiden har gått. Så som sagt, lagre gjeldende tid i en variabel.
usignert langstrømMillis = millis ();
Vi trenger to variabler til for å finne ut om den nødvendige tiden har gått. Vi har lagret gjeldende tid i currentMillis- variabelen, men vi må også vite at når begynte tidsperioden og hvor lang er perioden. Så intervallet og forrige Millis er erklært. Intervallet vil fortelle oss tidsforsinkelsen, og previosMillis lagrer sist gang hendelsen har skjedd.
usignert lenge tidligereMillis; usignert lang periode = 1000;
For å forstå dette, la oss ta et eksempel på en enkel blinkende LED. Perioden = 1000 vil fortelle oss at LED-lampen vil blinke i 1 sekund eller 1000 ms.
const int ledPin = 4; // LED-pin-nummeret koblet til int ledState = LAV; // brukes til å sette LED-tilstand usignert lenge forrige Millis = 0; // lagrer sist gang LED ble blinket const lang periode = 1000; // periode for å blinke i ms ugyldig oppsett () { pinMode (ledPin, OUTPUT); // set ledpin as output } void loop () { unsigned long currentMillis = millis (); // lagre gjeldende tid hvis (currentMillis - previousMillis> = periode) {// sjekk om 1000 ms passerte previousMillis = currentMillis; // lagre sist gang du blinket lysdioden hvis (ledState == LAV) {// hvis lysdioden er av, slå den på og omvendt ledState = HØY; } annet { ledState = LAV; } digitalWrite (ledPin, ledState); // sett LED med ledState til å blinke igjen } }
Her, uttalelsen
Avbrudd i Arduino fungerer som i andre mikrokontrollere. Arduino UNO-kortet har to separate pinner for å feste avbrudd på GPIO pin 2 og 3. Vi har dekket det i detalj i Arduino Interrupts Tutorial, hvor du kan lære mer om Interrupts og hvordan du bruker dem.
Her vil vi vise Arduino Multitasking ved å håndtere to oppgaver samtidig. Oppgavene vil omfatte blinking av to lysdioder i forskjellig tidsforsinkelse sammen med en trykknapp som vil bli brukt til å kontrollere PÅ / AV-tilstanden til LED. Så tre oppgaver vil bli utført samtidig.
Komponenter kreves
- Arduino UNO
- Tre lysdioder (hvilken som helst farge)
- Motstand (470, 10k)
- Gensere
- Brettbrett
Kretsdiagram
Kretsskjemaet for å demonstrere bruken av Arduino Millis () -fuksjon er veldig enkelt og har ikke så mange komponenter å feste som vist nedenfor.
Programmering av Arduino UNO for multitasking
Programmering av Arduino UNO for multitasking vil bare kreve logikken bak hvordan millis () fungerer som forklart ovenfor. Det anbefales å øve på blinkende LED ved å bruke millis igjen og igjen for å gjøre logikken tydelig og gjøre deg komfortabel med millis () før du begynner å programmere Arduino UNO for multitasking. I denne opplæringen brukes avbruddet også med millis () samtidig for multitasking. Knappen blir avbrutt. Så når det genereres et avbrudd, dvs. trykk på knappen, vil lysdioden skifte til PÅ eller AV-tilstand.Programmeringen starter med å erklære pin-nummer der lysdioder og trykknapp er koblet til.
int led1 = 6; int led2 = 7; int toggleLed = 5; int trykknapp = 2;
Deretter skriver vi en variabel for å lagre statusen til lysdioder for fremtidig bruk.
int ledState1 = LAV; int ledState2 = LAV;
Akkurat som forklart ovenfor i blinkeksemplet, erklæres variablene for periode og tidligere millis for å sammenligne og generere forsinkelse for lysdioder. Den første LED-lampen blinker etter hvert sekund og en annen LED blinker etter 200 ms.
usignert lang forrige Millis1 = 0; const lang periode1 = 1000; usignert lang forrige Millis2 = 0; const lang periode2 = 200;
En annen millis-funksjon vil bli brukt til å generere utsettelsesforsinkelsen for å unngå flere trykk på trykknappen. Det vil være en lignende tilnærming som ovenfor.
int debouncePeriod = 20; int debounceMillis = 0;
De tre variablene vil bli brukt til å lagre statusen på trykknappen som avbrudd, veksle LED og trykknapptilstand.
bool buttonPushed = false; int ledChange = LAV; int lastState = HØY;
Definer handlingen til pin som pin vil fungere som INPUT eller OUTPUT.
pinMode (led1, OUTPUT); pinMode (led2, OUTPUT); pinMode (toggleLed, OUTPUT); pinMode (trykknapp, INNGANG);
Definer nå avbruddspinnen ved å feste avbrudd med definisjon av ISR og avbrytingsmodus. Merk at det anbefales å bruke digitalPinToInterrupt (pin_number) når du erklærer attachInterrupt () -funksjonen for å oversette den faktiske digitale pin til det spesifikke interruptnummeret.
attachInterrupt (digitalPinToInterrupt (pushButton), pushButton_ISR, CHANGE);
Avbryt subrutinen skrives, og den vil bare endre knappen Pushed flagg. Merk at avbryt subrutinen skal være så kort som mulig, så prøv å skrive den og minimer de ekstra instruksjonene.
ugyldig pushButton_ISR () { buttonPushed = true; }
Sløyfe starter med å lagre millisverdien i en gjeldende Millis-variabel som lagrer verdien av tiden som har gått hver gang sløyfen gjentas.
usignert langstrømMillis = millis ();
Det er totalt tre funksjoner i multitasking, blink en LED på 1 sekund, Blink sekund LED på 200 ms, og trykk på knappen, og slå deretter AV / PÅ LED. Så vi vil skrive tre deler for å gjøre denne oppgaven.
Den første er å bytte LED-tilstand etter hvert 1 sekund ved å sammenligne forløpne millis.
if (currentMillis - previousMillis1> = period1) { previousMillis1 = currentMillis; hvis (ledState1 == LAV) { ledState1 = HØY; } annet { ledState1 = LAV; } digitalWrite (led1, ledState1); }
Tilsvarende for det andre det veksler LED etter hvert 200ms ved å sammenligne de gått Millis. Forklaringen er allerede forklart tidligere i denne artikkelen.
if (currentMillis - previousMillis2> = period2) { previousMillis2 = currentMillis; hvis (ledState2 == LAV) { ledState2 = HØY; } annet { ledState2 = LAV; } digitalWrite (led2, ledState2); }
Til slutt, den buttonPushed blir flagget overvåkes og etter generering av en demper forsinkelse på 20 ms det bare veksler tilstand av LED svarer til trykknappen festet som avbruddet.
if (buttonPushed = true) // sjekk om ISR kalles { if ((currentMillis - debounceMillis)> debouncePeriod && buttonPushed) // genererer 20 ms avvisningsforsinkelse for å unngå flere trykk { debounceMillis = currentMillis; // lagre den siste forsinkelsestiden hvis (digitalRead (trykknapp) == LAV && lastState == HØY) // endre LED etter at trykknappen er trykket på { ledChange =! ledChange; digitalWrite (toggleLed, ledChange); lastState = LAV; } annet hvis (digitalRead (trykknapp) == HIGH && lastState == LOW) { lastState = HIGH; } buttonPushed = false; } }
Dette avslutter veiledningen til Arduino millis (). Merk at for å bli vanlig med millis (), er det bare å øve på å implementere denne logikken i noen andre applikasjoner. Du kan også utvide den til å bruke motorer, servomotorer, sensorer og andre eksterne enheter. Hvis du er i tvil, kan du skrive til forumet eller kommentere nedenfor.
Komplett kode og video for å demonstrere bruken av millis-funksjonen i Arduino er gitt nedenfor.