Arduino ir mygtukai: pertraukimai

Posted: 2013-06-12 in Darbeliai
Žymos:,

Truputį papasakojau apie Arduino ir mygtukus bei jų nuskaitymą paprastuoju būdu: kartas nuo karto pagrindiniame programos cikle patikrinant reikšmes. Tačiau programa gali būti labai didelė, daug dirbanti, o ir kodą gali norėtis tiesiog gražesnį parašyti. Tad jeigu planuojate kokią nors apsaugos sistemą ar kažką panašaus, kur kai kuriuos procesus būtina apdoroti tuoj pat, nedelsiant, būtina naudoti pertraukimus.

ATMega168/328 procesoriai turi du išorinius pertraukimus INT0 ir INT1, kurie gali būti susieti su Arduino 2 ir 3 elektrodais (PD2 ir PD3 ATMega procesoriuose). Arduino kodo bibliotekoje apskritai visas programavimas yra supaprastintas iki negalėjimo ir tuos pertraukimus panaudoti savo projekte yra labai paprasta.

Pertraukimai gali būti iššaukiami keliais atvejais:

  • LOW: pertraukimas vykdomas visada, kai elektrodo reikšmė yra loginis nulis.
  • RISING: pertraukimas vykdomas, kai elektrodas keičia būseną iš loginio nulio į loginį vienetą.
  • FALLING: atvirkščiai, nei RISING.
  • CHANGE: pertraukimas vykdomas tiesiog elektrodui keičiant būseną.
  • Arduino Due dar turi ir HIGH pertraukimą, vykdomą visuomet, kai elektrodo reikšmė yra loginis vienetas.

Kaip minėjau praėjusį kartą, taupant detales geriausia išnaudoti vidinį pull up rezistorių ir mygtukais elektrodą trumpinti į „žemę“. Jei prie tokio mygtuko paspaudimo norime prikabinti pertraukimą, tai reikia FALLING tipo pertraukimo, ar ne?

Arduino bibliotekoje yra tokia funkcija attachInterrupt(…). Ja galime susieti norimą pertraukimą su savo parašyta funkcija. Pavyzdukas labai paprastas. Tarkime, kad paspaudę mygtuką norime įjungti arba išjungti prie 13 elektrodo prilituotą šviesos diodą. Kodas būtų labai paprastas:

volatile int diodas = LOW;

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(2, INPUT); // Antrajam elektrodui nustatom įvesties režimą (nebūtina)
  digitalWrite(2, HIGH); // Įjungiam pull up rezistorių
  attachInterrupt(0, perjungti, FALLING); // Prikabinam pertraukimo funkciją „perjungti()“
}

void loop()
{
  // Į 13-ą elektrodą siunčiam signalą „diodas“
  digitalWrite(13, diodas);
}

// Mūsų pačių pertraukimo vykdymo funkcija
void perjungti()
{
  diodas = !diodas;
}

 

Va ir viskas. Matote, kas čia darosi? Pagrindinis programos ciklas nuolat į 13 elektrodą siunčia loginį signalą pavadinimu diodas. Jis iš pradžių nustatomas į loginį nulį. O kai mygtukas nuspaudžiamas, šio signalo reikšmė yra apverčiama (loginis neigimas su šauktuko operatoriumi). Bet signalo reikšmė keičiama tik įvykus pertraukimui. Kaip matote, setup() funkcijoje prie nulinio pertraukimo (t.y. antrojo Arduino elektrodo) „prikabinama“ mūsų pačių parašyta funkcija perjungti(). Ir prikabinama prie FALLING tipo, t.y. kai mygtukas užtrumpina elektrodą į „žemę“. Taigi pertraukimo funkcija pakeičia signalo reikšmę, o kai tai įvykdoma, pagrindinis programos ciklas įrašinėja į elektrodą jau naująją reikšmę.

Viena pastaba: visi kintamieji, kurie naudojami ne tik pertraukimo, bet ir kituose programos gabaluose, turi būti volatile tipo. Tai reiškia, kad jie išskirtinai saugomi atmintyje, o ne procesoriaus registruose ir tuo užtikrinamas jų reikšmių teisingumas. Kitaip su pertraukimas labai nesunku prisižaisti.

Tokį patį pertraukimą, tik su numeriuku 1 galite prikabinti ir prie trečiojo elektrodo.

Viskas čia gerai ir gražu, ale va — nu kažkaip gaila, kad tik du elektrodai gali būti tokie galingi, t.y. sukelti pertraukimus. O jeigu projekte yra kokie penki-šeši ar daugiau mygtukų? Ir jie visi labai svarbūs? Nesijaudinkite, išeitis yra ir tokiems atvejams.

Be išorinių (external) pertraukimų AVR procesoriuose yra dar įgyvendinti tokie PCINT (Pin Change Interrupt) pertraukimai. Juos gali sukelti bet kuris iš Arduino įvesties/išvesties elektrodų, įskaitant ir analoginius. Viena problemėlė: šie pertraukimai yra suskirstyti prievadais ir jie iššaukiami elektrodams keičiant būseną: o va iš kokios į kokią — neaišku.

Jei dar nežinojote apie Arduino prievadus, tai čia toks vidinis AVR procesoriaus suskirstymas. Tarkime, analoginiai elektrodai priklauso vienam prievadui PORTA, 0–7 elektrodai priklauso prievadui PORTD, o 8–13 — prievadui PORTB. PCINT sudaro trys pertraukimai, kiekvienas apimantis visus vieno prievado elektrodus: PCISR0 => PORTB, PCISR1 => PORTA, PCISR2 => PORTD.

Kaip visą šitą dalyką suvaldyti? Paprasčiausia nelendant ir nesigilinant į AVR navarotus — pasinaudoti PinChangeInt biblioteka. Ji išsisaugo esamas elektrodų reikšmes ir netgi leidžia prikabinti pertraukimus prie RISING ir FALLING tipų, kurių AVR procesorius pats nepalaiko — tai padaroma programiškai pačioje bibliotekoje. Tad su šia biblioteka galime išnaudoti pertraukimus su visais Arduino elektrodais ir parašyti kodą, kuris, tarkime, reaguoja į mygtuką, prikabintą prie analoginio elektrodo nr. 1. Tiesa, verta žinoti, kad Arduino terminais skaičiukai 0–13 atitinka skaitmeninius Arduino elektrodus, o analoginių numeriai yra 14–21 (pradedant nuo Analog 0). Jiems Arduino bibliotekoje yra konstantos pavadintos A0–A7:

#include <PinChangeInt.h>
#include <PinChangeIntConfig.h>

volatile int diodas = LOW;

void setup()
{
  pinMode(13, OUTPUT);
  pinMode(A1, INPUT); // Analog 1 (arba 15-am elektrodui) nustatom įvesties režimą
  digitalWrite(A1, HIGH); // Įjungiam pull up rezistorių
  PCintPort::attachInterrupt(A1, perjungti, FALLING); // Prikabinam savo pertraukimą.
}

void loop()
{
  digitalWrite(13, diodas);
}

void perjungti()
{
  diodas = !diodas;
}

 

Štai šitaip galime kabinti mygtukus ir pertraukimus prie visų Arduino elektrodų 🙂 Paprasta, ar ne?

Advertisements

Parašykite komentarą

Įveskite savo duomenis žemiau arba prisijunkite per socialinį tinklą:

WordPress.com Logo

Jūs komentuojate naudodamiesi savo WordPress.com paskyra. Atsijungti / Keisti )

Twitter picture

Jūs komentuojate naudodamiesi savo Twitter paskyra. Atsijungti / Keisti )

Facebook photo

Jūs komentuojate naudodamiesi savo Facebook paskyra. Atsijungti / Keisti )

Google+ photo

Jūs komentuojate naudodamiesi savo Google+ paskyra. Atsijungti / Keisti )

Connecting to %s