Eksterne interrupts kan brukes til å reagere på et elektrisk signal som kommer inn på en bestemt pinne på Arduino. Når signalet endrer tilstand (fra høy til lav, eller fra lav til høy), vil et interrupt utløses og ISR vil bli kalt. Du kan velge hvilken pinne du vil bruke for interrupt, og du kan også velge om du vil at interruptet skal utløses når signalet går fra høy til lav, eller omvendt.
Timer interrupts brukes til å utføre en funksjon med jevne mellomrom, for eksempel å måle tid eller å oppdatere en skjerm. Når timeren når et bestemt antall tellinger, vil interruptet utløses og ISR vil bli kalt.
For å bruke interrupts i Arduino, må du først konfigurere pinne eller timer som du vil bruke for interrupt. Deretter kan du definere ISR-funksjonen din og knytte den til riktig interrupt ved å bruke en "attachInterrupt" funksjon. Du kan også deaktivere interrupt ved å bruke "detachInterrupt" funksjonen.
Det er viktig å merke seg at når ISR-funksjonen kjører, vil Arduino ikke kunne utføre andre oppgaver eller interrupts. Derfor bør ISR-funksjonen din være så kort som mulig og ikke bruke for mye tid.
I det første eksempelet tar vi utgangspunkt i Arduino Uno. Her er det bare pinne 2 og 3 som kan brukes til eksterne interrupt. En oversikt over pinner som kan brukes på noen av de forskjellige Arduino-typene kan du finne her: https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
Eksterne interrupt
Enkelt eksempel: const int interruptPinne = 2; // Definer hvilken pinne som skal brukes for interrupt I dette eksemplet vil interruptet utløses hver gang signalet på interruptPin endrer tilstand (fra høy til lav eller omvendt). Når interruptet utløses, vil ISR-funksjonen "handleInterrupt" bli kalt, og interruptCount vil øke med en. I loop-funksjonen vil antall ganger interruptet har blitt utløst skrives til seriell monitor hvert sekund. Merk at "volatile" nøkkelordet brukes i deklarasjonen av interruptCount-variabelen. Dette forteller Arduino at interruptCount kan endre seg utenfor hovedprogrammet, i ISR-funksjonen. Uten dette nøkkelordet kan det oppstå uforutsigbare feil når interruptCount endres i ISR-funksjonen. Som du ser når du kjører koden (med en knapp tilkoblet pinne 2), er det en del å ta tak i. Se oppgave 1 under "Oppgaver"-fliken. |
Oppgaver:
Oppgave 1: Oppgave 2: |
Løsningsforslag:
Oppgave 1: Så lenge vi er inne i ISR'en, vil ikke funksjoner som delay() og millis() fungere, dvs. verdiene blir ikke oppdatert. Vi kan likevel kalle millis() i starten for å registere når knappen er trykt inn. Denne verdien har jeg lagret i variabelen "sisteTrykk" i løsningsforslaget. Neste gang ISR'en kjøres sammenlignes denne med const int interruptPinne = 2; // Definer hvilken pinne som skal brukes for interrupt //Alle variabler som kan endres inne i en ISR må deklareres som "volatile" volatile int interruptTeller = 0; // Variabel for å telle antall ganger interruptet har blitt utløst volatile long sisteTrykk = 0; void setup() { pinMode(interruptPinne, INPUT_PULLUP); // Konfigurer interruptPin som input attachInterrupt(digitalPinToInterrupt(interruptPinne), knapp1Interrupt, FALLING); // Koble interrupt til interruptPin og kall ISR-funksjonen "handleInterrupt" Serial.begin(115200); // Start seriell kommunikasjon med PC } void loop() { Serial.print("Interrupt teller: "); // Skriv antall ganger interruptet har blitt utløst til seriell monitor Serial.println(interruptTeller); delay(1000); } // ISR-funksjonen som blir kalt når interruptet utløses void knapp1Interrupt() { long naa = millis(); if (naa > sisteTrykk + 200) { //Sjekker om det har gått 200 millisekunder siden siste trykk Oppgave 2: const int knapp1 = 2; // Definer hvilken pinne som skal brukes for interrupt
const int knapp2 = 3; // Definer hvilken pinne som skal brukes for interrupt
//Alle variabler som kan endres inne i en ISR må deklareres som "volatile"
volatile int interruptTeller = 0; // Variabel for å telle antall ganger interruptet har blitt utløst
volatile long sisteTrykkKnapp1 = 0;
volatile long sisteTrykkKnapp2 = 0;
void setup() {
pinMode(knapp1, INPUT_PULLUP); // Konfigurer interruptPin som input
pinMode(knapp2, INPUT_PULLUP); // Konfigurer interruptPin som input
attachInterrupt(digitalPinToInterrupt(knapp1), knapp1Interrupt, FALLING); // Koble interrupt til interruptPin og kall ISR-funksjonen "handleInterrupt"
attachInterrupt(digitalPinToInterrupt(knapp2), knapp2Interrupt, FALLING); // Koble interrupt til interruptPin og kall ISR-funksjonen "handleInterrupt"
Serial.begin(115200); // Start seriell kommunikasjon med PC
}
void loop() {
Serial.print("Interrupt teller: "); // Skriv antall ganger interruptet har blitt utløst til seriell monitor
Serial.println(interruptTeller);
delay(1000);
}
// ISR-funksjonen som blir kalt når interruptet utløses
void knapp1Interrupt() {
long naa = millis();
if (naa > sisteTrykkKnapp1 + 200) { //Sjekker om det har gått 200 millisekunder siden siste trykk
sisteTrykkKnapp1 = naa; //Lagrer tiden første gang ISR'en kjøres etter knappe-trykk
interruptTeller++; // Øk interruptCount med en hver gang interruptet utløses
}
}
void knapp2Interrupt() {
long naa = millis();
if (naa > sisteTrykkKnapp2 + 200) { //Sjekker om det har gått 200 millisekunder siden siste trykk
sisteTrykkKnapp2 = naa; //Lagrer tiden første gang ISR'en kjøres etter knappe-trykk
interruptTeller--; // Øk interruptCount med en hver gang interruptet utløses
}
}
|