Arduino pertraukia kiekvieną sekundę. Kontaktų apdorojimas

Ir čia yra Arduino funkcijos naudojimo pavyzdys attachInterrupt().

Pertraukimas yra signalas, pranešantis procesoriui, kad įvyko įvykis, į kurį reikia nedelsiant atkreipti dėmesį. Procesorius turi reaguoti į šį signalą nutraukdamas esamų komandų vykdymą ir perduodamas valdymą pertraukimų tvarkytojui (ISR, Interrupt Service Routine). Daiktuvas yra įprasta funkcija, kurią rašome patys ir įdedame kodą, kuris turėtų reaguoti į įvykį.

Aptarnavus ISR pertraukimą, funkcija baigia savo darbą ir procesorius su džiaugsmu grįžta prie nutrauktos veiklos – tęsia kodo vykdymą nuo ten, kur baigė. Visa tai vyksta automatiškai, todėl mūsų užduotis yra tik parašyti pertraukų tvarkyklę, nieko nesulaužant ir pernelyg dažnai neblaškant procesoriaus. Jums reikės supratimo apie grandinę, prijungtų įrenginių veikimo principus ir supratimą, kaip dažnai gali atsirasti pertraukimas ir kokios yra jo atsiradimo ypatybės. Visa tai yra pagrindinis sunkumas dirbant su pertraukomis.

Aparatinės ir programinės įrangos pertrūkiai

„Arduino“ pertraukimus galima suskirstyti į keletą tipų:

  • Aparatinė įranga pertraukia. Pertraukimas mikroprocesoriaus architektūros lygiu. Pats įvykis gali įvykti produktyviu momentu iš išorinio įrenginio – pavyzdžiui, paspaudus klaviatūros mygtuką, judant kompiuterio pelę ir pan.
  • Programinė įranga pertraukia. Jie paleidžiami programos viduje naudojant specialias instrukcijas. Naudojamas pertraukimų tvarkytojui iškviesti.
  • Vidiniai (sinchroniniai) pertraukimai. Vidinis pertraukimas įvyksta dėl programos vykdymo pakeitimo ar pažeidimo (pavyzdžiui, kai pasiekiate netinkamą adresą, netinkamą operacijos kodą ir pan.).

Kodėl reikalingi aparatinės įrangos pertraukimai?

Aparatinės įrangos pertraukimai atsiranda reaguojant į išorinį įvykį ir atsiranda iš išorinio aparatūros įrenginio. „Arduino“ siūlo 4 tipų aparatinės įrangos pertraukimus. Jie visi skiriasi signalu pertraukimo kaištyje:

  • Kontaktas traukiamas į žemę. Pertraukimų tvarkytuvas vykdomas tol, kol pertraukimo kaištyje yra LOW signalas.
  • Signalo keitimas ant kontakto. Tokiu atveju „Arduino“ vykdo pertraukimų tvarkyklę, kai pasikeičia signalas pertraukimo kaištyje.
  • Signalo keitimas iš LOW į HIGH ant kaiščio – keičiant iš žemo signalo į aukštą, bus vykdomas pertraukimų tvarkytuvas.
  • Signalo keitimas iš HIGH į LOW ant kaiščio – pakeitus aukštą signalą į žemą signalą, bus vykdoma pertraukimų tvarkytuvė.

Pertraukimai yra naudingi Arduino programose, nes padeda išspręsti laiko nustatymo problemas. Pavyzdžiui, dirbant su UART, pertraukimai leidžia išvengti kiekvieno simbolio atvykimo. Išorinis aparatūros įrenginys duoda pertraukimo signalą, procesorius iš karto iškviečia pertraukimų tvarkytuvą, kuris laiku užfiksuoja simbolį. Tai sutaupo CPU laiko, kuris kitu atveju būtų sugaištas tikrinant UART būseną be pertraukimų, o visus būtinus veiksmus atlieka pertraukimų tvarkytuvas, nepaveikdamas pagrindinės programos. Iš aparatūros įrenginio nereikia jokių specialių galimybių.

Pagrindinės priežastys, kodėl reikia iškviesti pertraukimą, yra šios:

  • Išvesties būsenos pasikeitimo aptikimas;
  • Laikmačio pertraukimas;
  • Duomenų pertraukimai per SPI, I2C, USART;
  • konvertavimas iš analoginio į skaitmeninį;
  • Noras naudoti EEPROM, flash atmintį.

Kaip „Arduino“ įdiegiami pertraukimai

Kai gaunamas pertraukimo signalas, veikimas sustabdomas. Prasideda funkcijos, kuri paskelbta vykdoma nutraukus, vykdymas. Deklaruota funkcija negali priimti įvesties verčių ir grąžinti vertes, kai ji išeina. Pertraukimas neturi įtakos pačiam kodui pagrindinėje programos cikle. Norint dirbti su pertraukimais Arduino, naudojama standartinė funkcija attachInterrupt().

Pertraukų diegimo skirtumai įvairiose „Arduino“ plokštėse

Priklausomai nuo konkretaus mikrovaldiklio modelio aparatinės įrangos įgyvendinimo, yra keletas pertraukimų. „Arduino Uno“ plokštė turi 2 pertraukimus ant antrojo ir trečiojo kaiščių, tačiau jei reikia daugiau nei dviejų išėjimų, plokštė palaiko specialų „pin-keitimo“ režimą. Šis režimas veikia keičiant visų kontaktų įvestį. Skirtumas tarp įvesties keitimo pertraukimo režimo yra tas, kad pertraukimus galima generuoti bet kuriame iš aštuonių kontaktų. Tokiu atveju apdorojimas bus sunkesnis ir ilgesnis, nes turėsite sekti naujausią kiekvieno kontakto būseną.

Kitose plokštėse pertraukimų skaičius didesnis. Pavyzdžiui, plokštė turi 6 kaiščius, kurie gali valdyti išorinius pertraukimus. Visoms „Arduino“ plokštėms, kai dirbama su „AttaxInterrupt“ funkcija (pertraukimas, funkcija, režimas), „Inerrupt 0“ argumentas yra susietas su skaitmeniniu kaiščiu 2.

Pertraukimai Arduino kalba

Dabar pakalbėkime apie tai, kaip projektuose naudoti pertraukimus.

Sintaksė attachInterrupt()

Funkcija attachInterrupt naudojama darbui su pertraukimais. Jis skirtas prijungti išorinį pertraukimą prie tvarkyklės.

Skambučių sintaksė: attachInterrupt (pertraukimas, funkcija, režimas)

Funkcijos argumentai:

  • pertraukimas – iškviečiamo pertraukimo numeris (standartinis 0 – 2-ajam kaiščiui, Arduino Uno plokštės 1 – 3-iajam kaiščiui),
  • funkcija – funkcijos, kuri bus iškviečiama nutraukus, pavadinimas (svarbu – funkcija neturi nei priimti, nei grąžinti jokių reikšmių),
  • režimas – pertraukimo įjungimo sąlyga.

Galima nustatyti šias paleidimo sąlygas:

  • LOW – atliekama, kai signalo lygis žemas, kai kontaktas turi nulinę reikšmę. Pertraukimas gali būti kartojamas cikliškai – pavyzdžiui, paspaudus mygtuką.
  • CHANGE – pakraštyje, signalui pasikeitus iš aukšto į žemą arba atvirkščiai, atsiranda pertrūkis. Vykdoma vieną kartą bet kokiam signalo pakeitimui.
  • RISING – vieną kartą atlikite pertraukimą, kai signalas pasikeičia iš LOW į HIGH.
  • FALLING – vieną kartą vykdyti pertraukimą, kai signalas pasikeičia iš HIGH į LOW.4

Svarbios pastabos

Dirbant su pertraukimais, reikia atsižvelgti į šiuos svarbius apribojimus:

  • Prižiūrėtojo funkcija neturėtų veikti per ilgai. Reikalas tas, kad „Arduino“ negali apdoroti kelių pertraukimų vienu metu. Kol veikia tvarkyklės funkcija, visi kiti pertraukimai bus ignoruojami ir galite praleisti svarbius įvykius. Jei jums reikia padaryti ką nors didelio, tiesiog perkelkite įvykių apdorojimą į main loop() kilpą. Valdytoje galite nustatyti tik įvykio vėliavėlę, o cikle galite patikrinti vėliavėlę ir ją apdoroti.
  • Su kintamaisiais turite būti labai atsargūs. Išmanusis C++ kompiliatorius gali „iš naujo optimizuoti“ jūsų programą – pašalinti kintamuosius, kurie, jo nuomone, yra nereikalingi. Kompiliatorius tiesiog nematys, kad kai kuriuos kintamuosius nustatėte vienoje dalyje ir naudojate juos kitoje. Norėdami pašalinti šią galimybę pagrindinių duomenų tipų atveju, galite naudoti nepastovų raktinį žodį, pavyzdžiui: nepastovi loginė būsena = 0. Tačiau šis metodas neveiks su sudėtingomis duomenų struktūromis. Taigi jūs visada turite būti budrūs.
  • Nerekomenduojama naudoti daug pertraukimų (stenkitės nenaudoti daugiau nei 6-8). Daugybė skirtingų įvykių reikalauja rimtų kodo komplikacijų, todėl gali atsirasti klaidų. Be to, turite suprasti, kad sistemose, kuriose yra daug pertraukimų, negali būti nė kalbos apie jokį laikiną vykdymo tikslumą - niekada tiksliai nesuprasite, koks yra intervalas tarp jums svarbių komandų iškvietimų.
  • Griežtai draudžiama naudoti delay() tvarkyklėse. Vėlavimo intervalo nustatymo mechanizmas naudoja laikmačius, be to, jie veikia su pertraukimais, kuriuos jūsų tvarkytojas blokuos. Dėl to visi lauks visų ir programa sustings. Dėl tos pačios priežasties negalima naudoti pertrūkiais pagrįstų ryšio protokolų (pavyzdžiui, i2c).

AttattaInterrupt naudojimo pavyzdžiai

Pradėkime praktiką ir pažvelkime į paprastą pertraukimų naudojimo pavyzdį. Pavyzdyje apibrėžiame tvarkyklės funkciją, kuri, pasikeitus Arduino Uno 2 kaiščio signalui, perjungs 13 kaiščio, prie kurio tradiciškai jungiame šviesos diodą, būseną.

#define PIN_LED 13 nepastovus loginis actionState = LOW; void setup() ( pinMode(PIN_LED, OUTPUT); // Nustatyti pertraukimą // Funkcija myEventListener bus iškviesta, kai // ant 2 kaiščio (pertraukimas 0 prijungtas prie 2 kaiščio) // pasikeičia signalas (nesvarbu, kuriame kryptis) attachInterrupt (0, myEventListener, CHANGE); ; // / / Atlikite kitus veiksmus, pavyzdžiui, įjunkite arba išjunkite šviesos diodą digitalWrite(PIN_LED, actionState )

Pažvelkime į keletą sudėtingesnių pertraukimų ir jų tvarkyklių pavyzdžių: laikmačiams ir mygtukams.

Pertraukia paspaudus mygtuką su apsaugos nuo atšokimo funkcija

Nutrūkus tai įvyksta – kol kontaktai glaudžiai nesusiliečia paspaudus mygtuką, jie svyruos, generuodami keletą operacijų. Yra du būdai, kaip susidoroti su atšokimu: techninė įranga, tai yra, kondensatoriaus litavimas prie mygtuko ir programinė įranga.

Galite atsikratyti plepėjimo naudodami funkciją – ji leidžia išmatuoti laiką, praėjusį nuo pirmojo mygtuko paspaudimo.

If(digitalRead(2)==HIGH) ( //kai paspaudžiamas mygtukas //Jei nuo ankstesnio paspaudimo praėjo daugiau nei 100 milisekundžių if (millis() - ankstesnisMillis >= 100) ( //Pirmojo paspaudimo laikas operacija prisimenama previousMillis = millis( if (led==oldled) ( //patikra, ar nepasikeitė mygtuko būsena led=!led; )

Šis kodas leidžia pašalinti debounce ir neblokuoja programos vykdymo, kaip yra delsos funkcijos atveju, kuri neleidžiama pertraukimų metu.

Laikmatis pertraukia

Laikmatis yra tam tikru dažniu skaičiuojantis skaitiklis, gaunamas iš 16 MHz procesoriaus. Dažnio daliklis gali būti sukonfigūruotas taip, kad gautų norimą skaičiavimo režimą. Taip pat galite sukonfigūruoti skaitiklį, kad generuotų pertraukimus, kai pasiekiama nustatyta vertė.

O laikmačio pertraukimas leidžia nutraukti kartą per milisekundę. Arduino turi 3 laikmačius – Timer0, Timer1 ir Timer2. Timer0 naudojamas generuoti pertraukimus kartą per milisekundę, o tai atnaujina skaitiklį ir perduoda jį funkcijai millis (). Šis laikmatis yra aštuonių bitų ir skaičiuoja nuo 0 iki 255. Kai reikšmė pasiekia 255, generuojamas pertraukimas. Pagal numatytuosius nustatymus 65 laikrodžio daliklis naudojamas norint gauti artimą 1 kHz dažnį.

Palyginimo registrai naudojami norint palyginti laikmačio būseną ir saugomus duomenis. Šiame pavyzdyje kodas sugeneruos pertraukimą, kai skaitiklis pasieks 0xAF.

TIMSK0 |= _BV(OCIE0A);

Turite apibrėžti pertraukimų tvarkyklę laikmačio pertraukimo vektoriui. Pertraukimo vektorius yra komandos, kuri bus vykdoma iškvietus pertraukimą, vietos adresą. Keli pertraukimų vektoriai sujungiami į pertraukimo vektorių lentelę. Šiuo atveju laikmatis bus vadinamas TIMER0_COMPA_vect. Šis tvarkytuvas atliks tuos pačius veiksmus kaip ir loop().

SIGNALAS(TIMER0_COMPA_vect) ( nepasirašyta ilga srovėMillis = milis(); sweeper1.Update(currentMillis); if(digitalRead(2) == HIGH) ( sweeper2.Update(currentMillis); led1.Update(currentMillis); ) led2.Update currentMillis); void loop () ( )

Apibendrinant

Pertraukimas Arduino yra gana sudėtinga tema, nes reikia galvoti apie visą projekto architektūrą iš karto, įsivaizduoti, kaip vykdomas kodas, kokie įvykiai galimi, kas nutinka, kai nutrūksta pagrindinis kodas. Mes nesiekėme atskleisti visų darbo su šia kalbos konstrukcija ypatybių, pagrindinis tikslas buvo pristatyti pagrindinius naudojimo atvejus. Kituose straipsniuose pokalbį apie trukdžius tęsime plačiau.

Vykdant projektą gali prireikti kelių pertraukimų, tačiau jei kiekvienas iš jų turi didžiausią prioritetą, tai iš tikrųjų jo neturės nė viena funkcija. Dėl tos pačios priežasties nerekomenduojama naudoti daugiau nei tuziną pertraukimų.

Valdikliai turėtų būti taikomi tik tiems procesams, kurių jautrumas laiko intervalams yra didžiausias. Nepamirškite, kad kol programa yra pertraukimų tvarkyklėje, visi kiti pertraukimai yra išjungti. Dėl didelio pertrūkių skaičiaus pablogėja jų reakcija.

Tuo metu, kai vienas pertraukimas yra aktyvus, o kiti išjungti, iškyla du svarbūs niuansai, į kuriuos grandinės projektuotojas turi atsižvelgti. Pirma, pertraukimo laikas turėtų būti kuo trumpesnis.

Tai užtikrins, kad nepraleisite jokių kitų suplanuotų pertraukimų. Antra, tvarkant pertraukimą, programos kodas neturėtų reikalauti veiklos iš kitų pertraukimų. Jei tai nebus užkirstas kelias, programa tiesiog užšaldys.

Nenaudokite ilgalaikio apdorojimo kilpa () , geriau sukurti pertraukimų tvarkyklės kodą, kai kintamasis nustatytas kaip nepastovus. Jis praneš programai, kad tolesnio apdorojimo nereikia.

Jei funkcijos skambutis Atnaujinti () vis tiek būtinas, pirmiausia turėsite patikrinti būsenos kintamąjį. Tai leis jums nustatyti, ar reikalingas tolesnis apdorojimas.

Prieš konfigūruodami laikmatį, turėtumėte patikrinti kodą. Anduino laikmačius reikėtų priskirti prie ribotų išteklių, nes jų yra tik trys, o jie naudojami įvairioms funkcijoms atlikti. Jei susipainiosite su laikmačių naudojimu, kai kurios operacijos gali tiesiog nustoti veikti.

Kokias funkcijas veikia tas ar kitas laikmatis?

„Arduino Uno“ mikrovaldikliui kiekvienas iš trijų laikmačių turi savo operacijas.

Taigi Laikmatis0 atsakingas už PWM penktajame ir šeštajame kontaktuose, funkcijas milis () , mikros () , delsimas() .

Kitas laikmatis - 1 laikmatis, naudojamas su PWM devintame ir dešimtajame kontaktuose, su bibliotekomis WaveHC ir servo.

Laikmatis 2 veikia su PWM 11 ir 13 kaiščiuose, taip pat Tonas.

Grandinės projektuotojas turi pasirūpinti saugiu bendrai naudojamų duomenų naudojimu. Juk pertraukimas milisekundei sustabdo visas procesoriaus operacijas ir duomenų mainus tarp kilpa () ir pertraukimų tvarkytojai turi būti patvarūs. Gali susidaryti situacija, kai kompiliatorius pradeda optimizuoti kodą, kad pasiektų maksimalų jo našumą.

Šio proceso rezultatas bus pagrindinių kodo kintamųjų kopijavimas registre, kuris užtikrins maksimalų prieigos prie jų greitį.

Šio proceso neigiama pusė gali būti ta, kad tikrosios vertės pakeičiamos saugomomis kopijomis, todėl gali būti prarastos funkcijos.

Kad taip neatsitiktų, turite naudoti kintamąjį nepastovūs , o tai padės išvengti nereikalingo optimizavimo. Kai naudojate didelius masyvus, kuriems atnaujinti reikia ciklų, šių naujinimų metu turite išjungti pertraukimus.

Įdiegę šią programą nustebsite, kokia ji panaši į Arduino IDE. Nenustebkite, abi programos sukurtos tuo pačiu varikliu.

Programa turi daug funkcijų, įskaitant biblioteką Serijinis, todėl galime susieti duomenų perdavimą tarp plokštės ir .

Paleiskite Arduino IDE ir pasirinkite paprasčiausią duomenų išvesties pavyzdį Nuoseklusis prievadas:

Void setup() ( Serial.begin(9600); ) void loop() ( Serial.println("Hello Kitty!"); // Palaukite 500 milisekundžių prieš siųsdami kitą delsą (500); )

Paleiskite pavyzdį ir įsitikinkite, kad kodas veikia.

Duomenų gavimas

Dabar norime gauti tą patį tekstą . Pradėkime naują projektą ir parašykime kodą.

Pirmasis žingsnis yra importuoti biblioteką. Eime Eskizas | Importuoti biblioteką | Serijinis. Eskize atsiras eilutė:

Importo apdorojimas.serial.*; Serijinis serialas; // sukurti nuosekliojo prievado objektą String Gauta; // duomenys gauti iš nuosekliojo prievado void setup() ( String port = Serial.list(); serial = new Serial(this, port, 9600); ) void draw() ( if (serial.available() > 0) ( // jei yra duomenų, gauta = serial.readStringUntil("\n"); // skaityti duomenis ) println(received // rodyti duomenis konsolėje )

Norint užtikrinti, kad duomenys būtų gaunami iš nuosekliojo prievado, mums reikia klasės objekto Serijinis. Kadangi siunčiame String tipo duomenis su Arduino, eilutę turime gauti procese Processing.

Pagal metodą setup () jums reikia gauti laisvą nuoseklųjį prievadą. Paprastai tai yra pirmasis prieinamas prievadas sąraše. Po to galime konfigūruoti objektą Serijinis, nurodant prievadą ir duomenų perdavimo greitį (pageidautina, kad greičiai sutaptų).

Belieka vėl prijungti plokštę, paleisti eskizą iš apdorojimo ir stebėti gaunamus duomenis programos konsolėje.

Apdorojimas leidžia dirbti ne tik su konsole, bet ir kurti standartinius langus. Perrašykime kodą.

Importo apdorojimas.serial.*; Serijinis serialas; // sukurti nuosekliojo prievado objektą String Gauta; // duomenys gauti iš nuosekliojo prievado void setup() ( dydis(320, 120); String port = Serial.list(); serial = new Serial(this, port, 9600); ) void draw() ( if (serijinis .available() > 0) ( // jei yra duomenų, // perskaityti ir įrašyti į gautą kintamąjį Gauta = serial.readStringUntil("\n"); ) // Teksto textSize(24) nustatymai (); if (gauta != null) ( tekstas (gautas, 10, 30); ) )

Paleiskite pavyzdį dar kartą ir pamatysime langą su vienoje vietoje perbraižytu užrašu.

Taip išmokome gauti duomenis iš Arduino. Tai leis mums nubraižyti gražius grafikus arba sukurti jutiklių rodmenų stebėjimo programas.

Duomenų siuntimas

Mes galime ne tik gauti duomenis iš plokštės, bet ir siųsti duomenis į plokštę, priversti ją vykdyti komandas iš kompiuterio.

Tarkime, siunčiame simbolį „1“ iš „Apdorojimas“. Kai plokštė aptinka išsiųstą simbolį, įjunkite LED 13 prievade (įtaisyta).

Eskizas bus panašus į ankstesnį. Pavyzdžiui, sukurkime nedidelį langą. Kai spustelėsite lango sritį, išsiųsime „1“ ir pakartosime jį konsolėje, kad būtų galima patikrinti. Jei nėra paspaudimų, siunčiama komanda „0“.

Importo apdorojimas.serial.*; Serijinis serialas; // sukurti nuosekliojo prievado objektą String Gauta; // duomenys gauti iš nuosekliojo prievado void setup() ( dydis(320, 120); String port = Serial.list(); serial = new Serial(this, port, 9600); ) void draw() ( if (mousePressed) == true) (//jei spustelėjome pelę lange serial.write("1"); //send 1 println("1"); ) else ( //jei nebuvo spustelėti serial.write ("0" ); //siųsti 0 )

Dabar parašykime Arduino eskizą.

Char commandValue; // duomenys, gaunami iš nuosekliojo prievado int ledPin = 13; // įtaisytasis šviesos diodas void setup() ( pinMode(ledPin, OUTPUT); // duomenų išvesties režimas Serial.begin(9600); ) void loop() ( if (Serial.available())) ( commandValue = Serial.read ( ) if (commandValue == "1") ( digitalWrite(ledPin, HIGH); // įjungti LED ) else ( digitalWrite(ledPin, LOW); // kitu atveju išjungti ) delay(10); skaitymas)

Atlikime abu eskizus. Paspaudžiame lango viduje ir pastebime, kad užsidega šviesos diodas. Jums net nereikia spustelėti, o laikykite nuspaudę pelės mygtuką – šviesos diodas užsidegs nuolat.

Keitimasis duomenimis

Dabar pabandykime sujungti abu būdus ir keistis pranešimais tarp lentos ir programos dviem kryptimis.

Siekdami maksimalaus efektyvumo, pridėkime Būlio kintamąjį. Dėl to mums nebereikia nuolat siųsti 1 arba 0 iš Processing ir nuoseklusis prievadas yra iškraunamas ir neperduoda nereikalingos informacijos.

Kai plokštė aptinka išsiųstą vienetą, mes pakeičiame Būlio reikšmę į priešingą, palyginti su dabartine būsena ( MAŽASįjungta AUKŠTAS ir atvirkščiai). IN Kitas Mes naudojame eilutę „Hello Kity“, kurią išsiųsime tik tuo atveju, jei neaptiksime „1“.

Funkcija nustatytiContact() siunčia eilutę, kurią tikimės gauti apdorojant. Jei gaunamas atsakymas, apdorojimas gali gauti duomenis.

Char commandValue; // duomenys, gaunami iš nuosekliojo prievado int ledPin = 13; loginis ledState = LOW; //valdykite šviesos diodo būseną void setup() ( pinMode(ledPin, OUTPUT); Serial.begin(9600); createContact(); // siųsti kontakto baitą, kol imtuvas atsako) void loop() ( / / jei duomenis galima nuskaityti if (Serial.available() > 0) ( // skaityti duomenis commandValue = Serial.read(); if (commandValue == "1") ( ledState = !ledState; digitalWrite(ledPin, ledState ); ) delay(100) ; else ( // Siųsti atgal Serial.println("Hello Kitty"); ) delay(50 ) void createContact() ( while (Serial.available());<= 0) { Serial.println("A"); // отсылает заглавную A delay(300); } }

Pereikime prie apdorojimo eskizo. Mes naudosime metodą serialevent(), kuri bus iškviečiama kiekvieną kartą, kai buferyje aptinkamas tam tikras simbolis.

Pridėkime naują Būlio kintamąjį pirmasis Susisiekite, kuri leidžia nustatyti, ar yra ryšys su „Arduino“.

Pagal metodą setup () pridėti eilutę serial.bufferUntil("\n");. Tai leidžia mums saugoti gaunamus duomenis buferyje, kol susidursime su konkrečiu simboliu. Šiuo atveju grąžiname (\n), nes siunčiame Serial.println() iš Arduino. "\n" pabaigoje reiškia, kad suaktyvinsime naują eilutę, ty tai bus paskutiniai duomenys, kuriuos matysime.

Kadangi nuolat siunčiame duomenis, metodas serialevent() atlieka kilpos užduotis piešti (), tada galite palikti tuščią.

Dabar pažvelkime į pagrindinį metodą serialevent(). Kiekvieną kartą įvedus naują eilutę (\n), šis metodas iškviečiamas. Ir kiekvieną kartą atliekama tokia veiksmų seka:

  • Nuskaitomi gaunami duomenys;
  • Patikrinama, ar jose yra kokių nors reikšmių (tai yra, ar mums buvo perduotas tuščias duomenų masyvas, ar „nulis“);
  • Pašalinti tarpus;
  • Jei reikiamus duomenis gavome pirmą kartą, keičiame Būlio kintamojo reikšmę pirmasis Susisiekite ir pasakykite Arduino, kad esame pasirengę priimti naujus duomenis;
  • Jei tai ne pirmas reikiamo tipo duomenų gavimas, rodome juos pulte ir siunčiame mikrovaldikliui duomenis apie atliktą paspaudimą;
  • Informuojame Arduino, kad esame pasirengę gauti naują duomenų paketą.
importo apdorojimas.serial.*; Serijinis serialas; // sukurti nuosekliojo prievado objektą String Gauta; // duomenys gauti iš nuosekliojo prievado // Tikrinama, ar nėra duomenų, gautų iš Arduino loginio pirmojoContact = false; void setup() ( dydis(320, 120); String port = Serial.list(); serial = new Serial(this, port, 9600); serial.bufferUntil("\n"); ) void draw() ( ) void serialEvent(Serial myPort) ( //suformuokite eilutę iš gaunamų duomenų // "\n" - skyriklis - gauto duomenų paketo pabaiga = myPort.readStringUntil("\n"); //įsitikinkite, kad mūsų duomenys nėra tuščias prieš kaip tęsti if (received != null) ( //pašalinti tarpus gavo = trim(received); println(received); //ieškokite mūsų eilutės "A", kad pradėtumėte rankos paspaudimą //jei rasta, išvalykite buferį ir išsiųsti duomenų užklausą if (firstContact == false) ( if (received.equals("A")) (serial.clear(); firstContact = true; myPort.write("A"); println("contact "); ) ) else ( //jei kontaktas užmegztas, mes gauname ir analizuojame duomenis println(gauta); if (mousePressed == true) (//jei spustelėjome langą serial.write("1 "); //išsiųsti 1 println(" 1"); ) // kai turėsite visus duomenis, pateikite užklausą dėl naujo paketo serial.write("A"); ) ) )

Prijungus ir paleidus konsolėje turėtų pasirodyti frazė „Hello Kitty“. Kai spustelėsite pelę apdorojimo lange, 13 kaiščio šviesos diodas įsijungs ir išsijungs.

Be apdorojimo, galite naudoti „PuTTy“ programas arba rašyti savo programą C#, naudodami paruoštas klases darbui su prievadais.

04. Ryšys: Dimmer

Pavyzdys parodo, kaip duomenis galima siųsti iš kompiuterio į plokštę, kad būtų galima valdyti šviesos diodo ryškumą. Duomenys pateikiami atskirų baitų nuo 0 iki 255 forma. Duomenys gali būti gaunami iš bet kurios kompiuterio programos, turinčios prieigą prie nuosekliojo prievado, įskaitant apdorojimą.

Pavyzdžiui, jums reikės standartinės grandinės su rezistoriumi ir šviesos diodu prie 9 kaiščio.

Arduino eskizas.

Const int ledPin = 9; // 9 kaiščio šviesos diodas void setup() ( Serial.begin(9600); // nustatykite režimą į pinMode(ledPin, OUTPUT); ) void loop() (baitų ryškumas; // patikrinkite, ar yra duomenų iš kompiuteris if (Serial.available()) ( // nuskaityti paskutinius gautus baitus nuo 0 iki 255 brightness = Serial.read(); // nustatyti LED ryškumą analogWrite(ledPin, brightness); ) )

Apdorojimo kodas

Importo apdorojimas.serial.*; Nuoseklusis prievadas; void setup() ( dydis(256, 150); println("Galimi nuoseklieji prievadai:"); println(Serial.list()); // Naudoja pirmąjį šio sąrašo prievadą (skaičius 0). Pakeiskite, kad pasirinktumėte prievadas //, atitinkantis jūsų Arduino plokštę. Paskutinis parametras (pvz., 9600) yra // ryšio greitis. (this, Serial.list(), 9600 // Jei žinote Arduino plokštės naudojamo prievado pavadinimą, tada aiškiai nurodykite //port = new Serial(this, "COM1", 9600 ) void draw() (); // nubrėžkite gradientą nuo juodos iki baltos (int i = 0; i

Paleiskite jį ir perkelkite pelės žymeklį virš sukurto lango bet kuria kryptimi. Judant į kairę, šviesos diodo ryškumas sumažės, judant į dešinę – padidės.

04. Ryšys: „PhysicalPixel“ (pele apšvieskite šviesos diodą)

Šiek tiek pakeiskime problemą. Perkelsime pelę ant kvadrato ir išsiųsime simbolį „H“ (aukštas), kad lentoje užsidegtų šviesos diodas. Kai pelė paliks kvadratinį plotą, mes išsiųsime simbolį „L“ (žemas), kad išjungtume šviesos diodą.

Arduino kodas.

Const int ledPin = 13; // 13 kaištis LED int incomingByte; // kintamasis duomenims gauti void setup() ( Serial.begin(9600); pinMode(ledPin, OUTPUT); ) void loop() ( // jei yra duomenų if (Serial.available() > 0) ( // skaityti baitą buferyje incomingByte = Serial.read( // jei tai simbolis H (ASCII 72), tada įjunkite šviesos diodą if (incomingByte == "H") ( digitalWrite(ledPin, HIGH); ) / / jei tai simbolis L (ASCII 76), tada išjunkite šviesos diodą if (incomingByte == "L") ( digitalWrite(ledPin, LOW); ) ) )

Apdorojimo kodas.

Importo apdorojimas.serial.*; plūdinė dėžėX; plūdinė dėžutėY; int boxDydis = 20; boolean mouseOverBox = klaidinga; Nuoseklusis prievadas; void setup () ( dydis (200, 200); boxX = plotis / 2.0; boxY = aukštis / 2.0; rectMode (RADIUS); println (Serial.list ()); // Atidarykite prievadą, prie kurio prijungta Arduino plokštė (šiuo atveju #0) // Įsitikinkite, kad atidarote prievadą tuo pačiu greičiu, kurį naudoja Arduino (9600 bps) port = new Serial(this, Serial.list(), 9600 ) void draw() ( background(0); // Jei žymeklis yra virš kvadrato if (mouseX > boxX - boxSize && mouseX boxY - boxSize && mouseY

04. Bendravimas: grafikas (grafiko braižymas)

Jei ankstesniame pavyzdyje siuntėme duomenis iš kompiuterio į plokštę, tai dabar atliksime priešingą užduotį – gausime duomenis iš potenciometro ir parodysime juos grafiko pavidalu.


Aparatinė įranga pertraukia

Neradau juokingo paveiksliuko šiai pamokai, radau tik paskaitą apie programavimą, o pati šios paskaitos pradžia mums puikiai paaiškina, kas nutraukti. Pertraukimą Arduino galima apibūdinti lygiai taip pat: mikrovaldiklis „viską numeta“, persijungia į funkcijų bloko vykdymą pertraukimų tvarkyklėje, jas vykdo ir tada grįžta tiksliai į pagrindinio kodo vietą, kur sustojo.

Nutrūkimų būna įvairių, tai yra ne patys pertrūkiai, o jų priežastys: sutrikimą gali sukelti analoginis-skaitmeninis keitiklis, laikmatis-skaitiklis arba tiesiog mikrovaldiklio kaištis. Šie pertraukimai vadinami išoriniais pertraukimais. aparatūra, ir apie tai šiandien kalbėsime.

Išorinės aparatinės įrangos pertraukimas yra pertraukimas, kurį sukelia mikrovaldiklio kaiščio įtampos pasikeitimas. Svarbiausia yra tai, kad mikrovaldiklis (kompiuterio branduolys) neapklauso kaiščio Ir nešvaisto tam laiko, kaištį tvarko kita techninė įranga. Kai tik pasikeičia įtampa ant kaiščio (turi galvoje skaitmeninį signalą, +5 įdėtas/+5 pašalintas), mikrovaldiklis gauna signalą, viską numeta, apdoroja pertraukimą ir grįžta į darbą. Kodėl tai būtina? Dažniausiai pertraukimai naudojami aptikti trumpus įvykius – impulsus ar net suskaičiuoti jų skaičių, neįkeliant pagrindinio kodo. Aparatinės įrangos pertraukimas gali sugauti trumpą mygtuko paspaudimą arba jutiklio paleidimą atliekant sudėtingus ilgus skaičiavimus arba kodo uždelsimus, t.y. grubiai tariant, smeigtukas yra apklausiamas lygiagrečiai pagrindiniam kodui. Pertraukimai taip pat gali pažadinti mikrovaldiklį iš energijos taupymo režimų, kai beveik visi išoriniai įrenginiai yra išjungti. Pažiūrėkime, kaip dirbti su aparatinės įrangos pertraukimais Arduino IDE.

Pertraukia Arduino

Pradėkime nuo to, kad ne visi kaiščiai „gali“ pertraukti. Taip, yra toks dalykas kaip pinChangeInterrupts, bet apie tai kalbėsime išplėstinėse pamokose. Dabar turime suprasti, kad aparatinės įrangos pertraukimai gali generuoti tik tam tikrus kaiščius:

MK / pertraukimo numeris INT 0 INT 1 INT 2 INT 3 INT 4 INT 5
ATmega 328/168 (Nano, UNO, Mini) D2 D3
ATmega 32U4 („Leonardo“, „Micro“) D3 D2 D0 D1 D7
ATmega 2560 (Mega) D2 D3 D21 D20 D19 D18

Kaip suprantate iš lentelės, pertraukimai turi savo numerį, kuris skiriasi nuo PIN numerio. Beje, yra patogi funkcija skaitmeninisPinToInterrupt (pin), kuris paima PIN kodą ir grąžina pertraukimo numerį. Į Arduino nano įvedę šią funkciją skaičių 3, gauname 1. Viskas pagal aukščiau esančią lentelę, funkcija tinginiams.

Pertrauka prijungiama naudojant funkciją addInterrupt (smeigtukas, tvarkytuvė, režimas):

  • smeigtukas– pertraukimo numeris
  • prižiūrėtojas– pertraukimų tvarkyklės funkcijos pavadinimas (ją reikia susikurti patiems)
  • režimu– pertraukimo veikimo „režimas“:
    • MAŽAS(žemas) – suveikia signalas MAŽAS ant kaiščio
    • KILDAMAS(augimas) – suveikia, kai pasikeičia c kaiščio signalas MAŽASįjungta AUKŠTAS
    • KRINTAS(drop) – suveikia, kai pasikeičia signalas ant kaiščio AUKŠTASįjungta MAŽAS
    • PAKEISTI(keisti) – suveikia, kai pasikeičia signalas (su MAŽASįjungta AUKŠTAS ir atvirkščiai)

Pertraukimą taip pat galima išjungti naudojant funkciją detachInterrupt (smeigtukas), kur pin – vėl pertraukimo numeris.

Taip pat galite visame pasaulyje išjungti pertraukimus naudodami funkciją no Interrupts () ir išspręskite juos dar kartą naudodami pertraukia (). Būkite atsargūs su jais! no Interrupts () taip pat sustabdys laikmačio pertraukimus ir nutrūks visos laiko funkcijos ir PWM generavimas.

Pažiūrėkime į pavyzdį, kuriame mygtukų paspaudimai skaičiuojami pertraukoje, tačiau pagrindinėje kilpoje jie išvedami su 1 sekundės uždelsimu. Dirbant su mygtuku įprastu režimu, tokios grubios išvesties neįmanoma derinti su vėlavimu:

Nepastovus tarpinis skaitiklis = 0; // skaitiklio kintamasis void setup() ( Serial.begin(9600); // atidarė prievadą ryšiui // prijungė mygtuką D2 ir GND pinMode(2, INPUT_PULLUP); \ // D2 yra pertraukimas 0 // tvarkytojas - Funkcijos mygtukasTick // FALLING - paspaudus mygtuką bus signalas 0, pagauname jį attachInterrupt(0, buttonTick, FALLING) void buttonTick() ( counter++; // + pressing ) void loop() ( Serial.println (skaitiklis) // išvesties delsa (1000 // laukti);

Taigi, mūsų kodas skaičiuoja klavišų paspaudimus net delsimo metu! Puiku. Bet kas yra nepastovios? Mes paskelbėme visuotinį kintamąjį skaitiklis, kuriame bus išsaugotas mygtuko paspaudimų skaičius. Jei pertraukimo metu pasikeičia kintamojo reikšmė, turite apie tai informuoti mikrovaldiklį naudodami specifikaciją nepastovios, kuris rašomas prieš nurodant kintamojo duomenų tipą, antraip darbas bus neteisingas. Tai tiesiog reikia atsiminti: jei kintamasis pasikeičia pertraukimo metu, padarykite tai nepastovios.

Dar keli svarbūs punktai:

  • Pertraukyje modifikuoti kintamieji turi būti deklaruojami kaip nepastovios
  • Tokios uždelsos neveikia pertrūkių atveju delsimas()
  • Pertraukimo metu jo reikšmė nekeičiama milis () Ir mikros ()
  • Pertraukimo metu išvestis į prievadą neveikia tinkamai ( Serial.print()), taip pat neturėtumėte jo naudoti - jis įkelia branduolį
  • Pertraukdami turėtumėte pabandyti atlikti kuo mažiau skaičiavimų ir apskritai „ilgų“ veiksmų - tai sulėtins MC darbą su dažnais pertraukimais! Ką daryti? Skaitykite apačioje.

Jei pertraukimas užfiksuoja kokį nors įvykį, kurio nereikia nedelsiant apdoroti, dirbti su pertraukimu geriau naudoti šį algoritmą:

  • Pertraukimų tvarkyklėje mes tiesiog pakeliame vėliavėlę
  • Pagrindinėje programos kilpoje patikriname vėliavėlę, jei ji pakelta, iš naujo nustatome ir atliekame reikiamus veiksmus
nepastovus loginis intFlag = false; // pažymėkite void setup() ( Serial.begin(9600); // atidarė prievadą ryšiui // prijungė mygtuką prie D2 ir GND pinMode(2, INPUT_PULLUP); // D2 yra pertraukimas 0 // tvarkytojas - funkcijos mygtukasTick // FALLING - paspaudus mygtuką bus signalas 0, pagauname jį attachInterrupt(0, buttonTick, FALLING) void buttonTick() ( intFlag = true; // pakėlė pertraukimo vėliavėlę ) void loop() ( if (intFlag) ( intFlag = false; // atstatyti // atlikti kai kuriuos veiksmus Serial.println("Nutraukti!");

Iš esmės tai viskas, ką jums reikia žinoti apie pertraukimus, mes nagrinėsime konkretesnius atvejus išplėstinėse pamokose.

Vaizdo įrašas

Išmokime dirbti su laikmačio pertraukimais. Parašykime paprastą programą su lygiagrečiais procesais.

Realioje programoje vienu metu turi būti atliekama daug veiksmų. Įžangoje pateikiau pavyzdį. Išvardysiu kokius veiksmus ji atlieka:

Operacija

Pasivažinėjimo dviračiu laikas
Perklauso 3 mygtukus, apdoroja jų signalus, kad pašalintų atšokimą 2 ms
Atkuria duomenis iš septynių segmentų LED indikatorių 2 ms
Generuoja valdymo signalus 2 DS18B20 temperatūros jutikliams ir nuskaito iš jų duomenis. Jutikliai turi 1 laido nuosekliąją sąsają. 100 µs kiekvienam bitui,
1 sek. visas skaitymo ciklas
Analoginių Peltier elemento srovės ir įtampos verčių skaitymas, maitinimo įtampa 100 µs
Skaitmeninis analoginių srovės ir įtampos verčių filtravimas 10 ms
Peltier elemento galios skaičiavimas 10 ms
PID (proporcinis integralinis diferencialas) srovės ir įtampos stabilizavimo valdiklis 100 µs
Galios reguliatorius 10 ms
Temperatūros reguliatorius 1 sekundė
Apsaugos funkcijos, duomenų vientisumo stebėjimas 1 sekundė
Valdymas, bendroji sistemos veikimo logika 10 ms

Visos šios operacijos atliekamos cikliškai, kiekviena su skirtingais ciklo periodais. Nė vienas iš jų negali būti sustabdytas. Bet koks, net ir trumpalaikis, veikimo laikotarpio laiko pasikeitimas sukels bėdų: didelę matavimo paklaidą, netinkamą stabilizatorių veikimą, mirksinčius indikatorius, nestabilią mygtukų paspaudimų reakciją ir kt.

Šaldytuvo valdiklio programoje yra keletas lygiagrečių procesų, kurie atlieka visus šiuos veiksmus, kiekvienas ciklas su savo laikotarpio trukme. Lygiagretūs procesai yra procesai, kurių veiksmai atliekami vienu metu.

Ankstesnėse pamokose kūrėme mygtuko objekto klasę. Mes sakėme, kad tai yra signalo apdorojimo lygiagrečiame procese klasė. Kad normaliam jos veikimui reikia iškviesti signalo apdorojimo funkciją (metodą) cikle su reguliariu periodu (laiką pasirinkome 2 ms). Tada bet kurioje programos vietoje yra ženklai, rodantys esamą mygtuko ar signalo būseną.

Į vieną kilpą įdėjome mygtukų būsenos apdorojimo ir šviesos diodų valdymo kodą. Ir ciklo pabaigoje nustatome delsos funkcijos uždelsimą (2). Tačiau laikas, kurio reikia programai vykdyti cikle, keičia bendrą ciklo laiką. Ir ciklo laikotarpis aiškiai nėra lygus 2 ms. Be to, vykdant uždelsimo() funkciją, programa užstringa ir negali atlikti kitų veiksmų. Sudėtinga programa sukels visišką chaosą.

Išeiti – iškvieskite mygtuko būsenos apdorojimo funkciją, kai pertraukiamas aparatūros laikmatis. Kas 2 ms pagrindinė programos kilpa turi būti nutraukta, mygtuko signalas apdorojamas ir valdymas grįžta į pagrindinę kilpą prie kodo, kuriame buvo nutrauktas. Trumpas mygtuko signalo apdorojimo laikas neturės didelės įtakos pagrindinės kilpos vykdymui. Tie. Mygtukų apdorojimas vyks lygiagrečiai, nepastebėdamas pagrindinės programos.

Aparatinės įrangos laikmačio pertraukimas.

Aparatinės įrangos pertraukimas yra signalas, pranešantis apie kokį nors įvykį. Jai atėjus, programos vykdymas sustabdomas ir valdymas perduodamas pertraukimų tvarkytuvui. Po apdorojimo valdymas grįžta į pertrauktą programos kodą.

Programos požiūriu pertraukimas yra funkcijos iškvietimas dėl išorinio įvykio, kuris nėra tiesiogiai susijęs su programos kodu.

Laikmačio pertraukimo signalas generuojamas cikliškai, tam tikru periodu. Jį generuoja aparatūros laikmatis – skaitiklis su logika, kuris iš naujo nustato savo kodą, kai pasiekiama tam tikra reikšmė. Programiškai nustatę atstatymo logikos kodą, galime nustatyti laikmačio pertraukimo laikotarpį.

„Arduino“ laikmačio režimo ir laiko nustatymas atliekamas per mikrovaldiklio aparatinės įrangos registrus. Jei norite, galite išsiaiškinti, kaip tai padaryti. Bet aš siūlau paprastesnį variantą – naudoti MsTimer2 biblioteką. Be to, laikmačio režimas nustatomas retai, o tai reiškia, kad bibliotekos funkcijų naudojimas nesustabdys programos.

Biblioteka MsTimer2.

Biblioteka skirta konfigūruoti aparatinės įrangos pertraukimą iš mikrovaldiklio 2 laikmačio. Jis turi tik tris funkcijas:

  • MsTimer2::set(nepasirašytas ilgas ms, galiojantis (*f)())

Ši funkcija nustato pertraukimo laikotarpį ms. Su šiuo laikotarpiu bus iškviestas pertraukimų tvarkytuvas f. Jis turi būti paskelbtas negaliojančiu (nieko negrąžina) ir be argumentų. * f yra funkcijos rodyklė. Vietoj to turite parašyti funkcijos pavadinimą.

  • MsTimer2::start()

Ši funkcija įgalina laikmačio pertraukimus.

  • MsTimer2::stop()

Funkcija išjungia laikmačio pertraukimus.

Prieš funkcijų pavadinimą reikia parašyti MsTimer2::, nes Biblioteka parašyta naudojant vardų erdvės direktyvą.

Norėdami įdiegti biblioteką, nukopijuokite MsTimer2 katalogą į bibliotekų aplanką Arduino IDE darbiniame aplanke. Tada paleiskite Arduino IDE programą, atidarykite Eskizas -> Prijungti biblioteką ir pamatysite, kad MsTimer2 biblioteka yra bibliotekų sąraše.

MsTimer2 biblioteką galite atsisiųsti ZIP archyve. Norėdami jį įdiegti, turite jį išpakuoti.

Paprasta programa su lygiagrečiu mygtuko signalo apdorojimu.

Dabar parašykime paprastą programą su vienu mygtuku ir LED iš 6 pamokos. Vienas mygtukas prijungtas prie Arduino plokštės pagal schemą:

Tai atrodo taip:

Kiekvieną kartą paspaudus mygtuką, šviesos diodas Arduino plokštėje keičia savo būseną. Būtina, kad būtų įdiegtos MsTimer2 ir Button bibliotekos:

MsTimer2

Ir mokėti. Tik 40 rub. per mėnesį, kad gautumėte prieigą prie visų svetainės išteklių!

// eskizas_10_1 10 pamoka
// Paspaudus mygtuką pasikeičia šviesos diodo būsena

#įtraukti
#įtraukti

#define LED_1_PIN 13 //
#define BUTTON_1_PIN 12 // mygtukas prijungtas prie 12 kaiščio

Mygtuko mygtukas1(BUTTON_1_PIN, 15); // objekto kūrimas – mygtukas

negaliojantis nustatymas () (

MsTimer2::set(2, timerInterupt); // nustatykite laikmačio pertraukimo laikotarpį į 2 ms
MsTimer2::start(); //
}

void loop() (

// LED valdymas
if (button1.flagClick == true) (
// mygtukas buvo paspaustas



}
}

// pertraukų tvarkytojas
void timerInterrupt() (
mygtukas1.scanState(); // iškviečiamas būdas laukti stabilios mygtuko būsenos
}

Funkcijoje setup() nustatome laikmačio pertraukimo ciklo laiką į 2 ms ir nurodome pertraukimo tvarkyklės pavadinimą timerInterrupt . Mygtuko signalo apdorojimo funkcija button1.scanState() iškviečiama laikmačio pertraukimo tvarkyklėje kas 2 ms.

Taigi mygtuko būseną apdorojame lygiagrečiu procesu. O pagrindinėje programos kilpoje patikriname mygtuko paspaudimo ženklą ir keičiame LED būseną.

Nepastovus kvalifikatorius.

Modifikuokime kilpą loop() ankstesnėje programoje.

void loop() (

kol (tiesa) (
if (button1.flagClick == true) break;
}

// mygtukas buvo paspaustas
button1.flagClick= false; // iš naujo nustatykite ženklą
digitalWrite(LED_1_PIN, ! digitalRead(LED_1_PIN)); // LED inversija
}

Logiška, kad niekas nepasikeitė.

  • Pirmojoje versijoje programa perėjo kilpą iki galo ir išanalizavo joje esančią vėliavėlę button1.flagClick.
  • Antroje parinktyje programa analizuoja vėliavėlę button1.flagClick begalinėje while ciklo metu. Kai vėliavėlė tampa aktyvi, ji išeina iš while ciklo per pertrauką ir apverčia šviesos diodo būseną.

Vienintelis skirtumas yra tai, kuriame cikle programa veikia cikle arba while.

Bet jei paleisime naujausią programos versiją, pamatysime, kad šviesos diodas nereaguoja į mygtukų paspaudimus. Pašalinkime klasę ir supaprastinkime programą.

#įtraukti
#define LED_1_PIN 13 // LED prijungtas prie 13 kaiščio
int count=0;

negaliojantis nustatymas () (
pinMode(LED_1_PIN, IŠVESTIS); // apibrėžti LED kaištį kaip išvestį
MsTimer2::set(500, timerInterupt); // nustatykite laikmačio pertraukimo laikotarpį iki 500 ms
MsTimer2::start(); // įjungti laikmačio pertraukimą
}

void loop() (

kol (tiesa) (
if (skaičiuoti != 0) pertrauka;
}

skaičius = 0;
digitalWrite(LED_1_PIN, ! digitalRead(LED_1_PIN)); // LED būsenos inversija
}

// pertraukų tvarkytojas
void timerInterrupt() (
skaičiuoti++;
}

Šioje programoje skaičiavimo skaitiklis pertraukimų tvarkyklėje didinamas 1 kas 500 ms. Nors cikle jis analizuojamas, su pertrauka išeiname iš kilpos ir apverčiame šviesos diodo būseną. Neįsivaizdavote paprastesnės programos, bet ir ji neveikia.

Faktas yra tas, kad C++ kalbos kompiliatorius optimizuoja programą pagal jos intelektą. Kartais tai nesiseka gerai. Kompiliatorius mato, kad jokios operacijos su skaičiavimo kintamuoju while cikle neatliekamos. Todėl jis mano, kad pakanka tik vieną kartą patikrinti skaičiavimo būklę. Kam tikrinti tai, kas niekada negali pasikeisti. Kompiliatorius pataiso kodą, optimizuodamas jį vykdymo laikui. Paprasčiau tariant, jis pašalina kintamojo tikrinimo kodą iš ciklo. Kompiliatorius negali suprasti, kad skaičiaus kintamasis keičia savo būseną pertraukimų tvarkyklėje. Dėl to mes įstringame ciklą, kai.

Programos versijose, kuriose ciklas vykdomas iki galo, kompiliatorius daro prielaidą, kad visi kintamieji gali keistis, ir palieka tikrinimo kodą. Jei į while kilpą įterpiate bet kurios sistemos funkcijos iškvietimą, kompiliatorius taip pat nuspręs, kad kintamieji gali keistis.

Jei, pavyzdžiui, įtrauksite iškvietimą į delay() funkciją prie while ciklo, programa veiks.

kol (tiesa) (
if (skaičiuoti != 0) pertrauka;
delsimas(1);
}

Geras stilius yra kurti programas, kuriose ciklas vykdomas iki galo ir programa niekur neužstringa. Kitoje pamokoje bus vienintelis kodas, kuris analizuoja vėliavėles nesibaigiančiomis while kilpomis. Toliau planuoju visose programose atlikti ciklą iki galo.

Kartais tai nėra lengva ar veiksminga. Tada jums reikia naudoti nepastovų kvalifikatorių. Jis nurodomas, kai deklaruojamas kintamasis, ir nurodo kompiliatoriui nemėginti optimizuoti jo naudojimo. Tai neleidžia kompiliatoriui daryti prielaidas apie kintamojo reikšmę, nes kintamasis gali būti pakeistas kitame programos vienete, pavyzdžiui, lygiagrečiame procese. Be to, kompiliatorius įdeda kintamąjį į RAM, o ne į bendrosios paskirties registrus.

Programoje deklaruojant skaičių užtenka parašyti

nepastovus int count=0;

ir visos parinktys veiks.

Programai, kuri valdo mygtuką, turite deklaruoti, kad mygtukų klasės egzemplioriaus ypatybės gali keistis.

nepastovus 1 mygtukas (BUTTON_1_PIN, 15); // objekto kūrimas – mygtukas

Mano pastebėjimais, nepastovios kvalifikatoriaus naudojimas niekaip nepailgina programos kodo ilgio.

Mygtuko signalo apdorojimo metodo palyginimas su Bounce biblioteka.

Yra paruošta biblioteka „Bounce“ mygtukų atšaukimui. Mygtuko būsena tikrinama, kai iškviečiama funkcija update(). Šioje funkcijoje:

  • nuskaitomas mygtuko signalas;
  • palyginti su būsena per ankstesnį kvietimą atnaujinti ();
  • patikrina, kiek laiko praėjo nuo ankstesnio skambučio, naudojant funkciją millis();
  • priimamas sprendimas, ar pasikeitė mygtuko būsena.
  • Bet tai nėra lygiagretus signalo apdorojimas. Funkcija update() paprastai iškviečiama pagrindinėje, asinchroninėje programos cikle. Jei nebus skambinama ilgiau nei tam tikrą laiką, mygtuko signalo informacija bus prarasta. Nereguliarūs skambučiai lemia neteisingą algoritmo veikimą.
  • Pati funkcija turi gana daug kodo ir jos vykdymas užtrunka daug ilgiau nei Button() bibliotekos funkcijos.
  • Iš viso nėra skaitmeninio signalų filtravimo pagal vidutinę vertę.

Sudėtingose ​​programose šios bibliotekos geriau nenaudoti.

Kitoje pamokoje parašysime sudėtingesnę programą su lygiagrečiais procesais. Išmoksime realizuoti programos blokų vykdymą kilpomis su skirtingais laiko intervalais nuo vieno laikmačio pertraukimo.

Kategorija: . Galite pažymėti jį.