Küsimus:
Kas funktsiooni saab automaatselt kutsuda, kui sisend muutub?
Peter Bloomfield
2014-02-20 06:42:53 UTC
view on stackexchange narkive permalink

Praegu kontrollib minu visand sisendnõela iga kord, kui põhisilmus ümardatakse. Kui see tuvastab muutuse, kutsub see sellele reageerimiseks kohandatud funktsiooni. Siin on kood (trimmitud hädavajalikuni):

  int pinValue = LOW; void pinChanged () {//...}void setup () {pinMode (2, INPUT);} void loop () {// Loe praegust sisendit int newValue = digitalRead (2); // Kas sisend on muutunud? if (newValue! = pinValue) {pinValue = newValue; pinChanged (); }}  

Kahjuks ei toimi see alati sisendi väga lühikeste muudatuste korral (nt lühike impulss), eriti kui loop () töötab natuke aeglaselt.

Kas on võimalus panna Arduino tuvastama sisendi muutust ja kutsuma minu funktsiooni automaatselt?

See, mida otsite, on selle väline katkestus
Kolm vastused:
#1
+26
Peter Bloomfield
2014-02-20 06:42:53 UTC
view on stackexchange narkive permalink

Seda saate teha väliste katkestustega. Enamik Arduinosid toetab seda siiski piiratud arvul tihvtidel. Lisateavet leiate dokumendist saidi attachInterrupt () kohta.

Eeldades, et kasutate Unot, võiksite seda teha järgmiselt:

  void pinChanged () {//...}väldi seadistamist () {pinMode (2, INPUT); attachInterrupt (0, pinChanged, CHANGE);} void loop () {}  

See kutsub pinChanged () alati, kui välisel katkestusel 0 tuvastatakse muudatus. Uno-s vastab GPIO pin 2-le. Väline katkestuste numeratsioon on teistel tahvlitel erinev, seetõttu on oluline kontrollida asjakohast dokumentatsiooni.

Sellel lähenemisel on siiski piiranguid. Kohandatud funktsiooni pinChanged () kasutatakse katkestusteenusena (ISR). See tähendab, et ülejäänud kood (kõik koodis loop () ) on kõne sooritamise ajal ajutiselt peatatud. Olulise ajastuse katkestamise vältimiseks peaksite püüdma teha ISR-id võimalikult kiiresti.

Samuti on oluline märkida, et teie ISR-i ajal ei toimu muid katkestusi. See tähendab, et kõik, mis tugineb katkestustele (nt põhifunktsioonid delay () ja millis () ), ei pruugi selle sees korralikult töötada.

Lõpuks kui teie ISR peab visandis muutma mõnda globaalset muutujat, tuleks need tavaliselt deklareerida kui volatile , nt:

  volatile int someNumber;  

See on oluline, sest see ütleb kompilaatorile, et väärtus võib ootamatult muutuda, seega peaks olema ettevaatlik ja ärge kasutage selle aegunud koopiaid / vahemälusid.

küsimuses mainitud "lühikeste impulsside" osas, kas on minimaalne aeg, millal tihvt peab olema katkestuse käivitamiseks olekus? (ilmselt on see palju väiksem kui küsitlus, mis sõltub sellest, mis tsüklis veel toimub)
@sachleen See töötab seni, kuni seda ei juhtu ISR-funktsiooni täitmise ajal (nagu on selgitatud vastuses); sellepärast peaks `pinChanged ()` olema võimalikult lühike. Seetõttu peaks minimaalne aeg olema funktsiooni `pinChanged ()` käivitamise aeg.
+1 selle väga üksikasjaliku vastuse eest, mis sisaldab kõiki olulisi asju, millest katkestuste kasutamisel tuleb hoolida!
Lisaks jagatud globaalide muutumatuks kuulutamisele peate ka juhul, kui globaalne muutuja on laiem kui 1 bait, nagu mõniNumber, kaitsta programmi poolt baidipääsude vahel toimuva pin-change-katkestuse eest. Avaldus nagu "someNumber + = 5;" hõlmab madalate baitide ja kõrgete baitide lisamist koos kaasamisega. Neid kahte (laiemate muutujate puhul rohkem) ei tohi katkestusega jagada. Piisab katkestajate väljalülitamisest ja taastamisest enne ja pärast operatsiooni (vastavalt).
@sachleen - impulsi minimaalse suuruse osas. Andmelehelt on raske kindlat vastust leida, kuid otsustades tihvtivahetuse katkestuste ajastuse järgi, lukustatakse need poole kellaaja jooksul. Kui katkestus on "meelde jäänud", jääb see meelde, kuni ISR ​​alustab ja sellega tegeleb.
#2
+5
mpflaga
2014-02-24 20:36:06 UTC
view on stackexchange narkive permalink

Mis tahes digitaalse sisendina konfigureeritud tihvti muutmise olek võib katkestuse tekitada. Erinevalt INT1 või INT2 katkestuste põhjuste ainulaadsetest vektoritest kasutab funktsioon PinChangeInt ühist vektorit ja seejärel peab selle vektori jaoks teenuse katkestamise rutiin (ISR) määrama, millist tihvti muudeti.

Õnneks teeb PinChangeInt Library selle lihtsaks.

  PCintPort :: attachInterrupt (PIN, burpcount, RISING); // kinnitage PinChange Interrupt meie tihvti tõusvas servas // (selle teegiga töötavad kõik RISING, FALLING ja CHANGE) // ja käivitage funktsioon burpcount, kui see tihvt muutub  
#3
  0
Nick Gammon
2015-07-01 07:27:55 UTC
view on stackexchange narkive permalink

Kui soovite tuvastada pinge, mis ületab läve , selle asemel, et olla lihtsalt KÕRGE või MADAL, võite kasutada analoogvõrdurit. Näide visandist:

  volatile boolean triggered; ISR (ANALOG_COMP_vect) {triggered = true; } void setup () {Serial.begin (115200); Serial.println ("Alustatud."); ADCSRB = 0; // (Keela) ACME: Analoog-komparaatori multiplekser Luba ACSR = bit (ACI) // (Kustuta) Analoog-komparaatori katkestuslipp | bit (ACIE) // Analoogvõrdleja katkestuse lubamine | bitti (ACIS1); // ACIS1, ACIS0: Analoogvõrdleja katkestusrežiimi valimine (päästik langeva serva korral)} // seadistuse lõpp väldi tsüklit () {if (käivitatud) {Serial.println ("Käivitatud!"); käivitatud = vale; }} // tsükli lõpp  

See võib olla kasulik näiteks valgusdetektorite puhul, kus peate võib-olla tuvastama sisendis muutuse (näiteks) 1 V asemel 2 V.

Vooluringi näide:

enter image description here

Samuti saate protsessoril kasutada sisendhõive seadet, mis mäletab teatud sisendite täpset aega, salvestades Taimeri / loenduri praegune loendus 1. See võimaldab teil salvestada täpse (hästi, peaaegu täpse) hetke, mil huvipakkuv sündmus aset leidis, selle asemel, et sisestada viivitus (tõenäoliselt mõnest mikrosekundist), enne kui ISR-i saab kasutada voolu salvestamiseks aeg.

Ajakriitiliste rakenduste korral võib see täpsust mõnevõrra suurendada.

Rakenduse näide: muutke oma Arduino kondensaatori testeriks



See küsimus ja vastus tõlgiti automaatselt inglise keelest.Algne sisu on saadaval stackexchange-is, mida täname cc by-sa 3.0-litsentsi eest, mille all seda levitatakse.
Loading...