Kysymys:
Voiko toimintoa kutsua automaattisesti, kun tulo muuttuu?
Peter Bloomfield
2014-02-20 06:42:53 UTC
view on stackexchange narkive permalink

Tällä hetkellä luonnokseni tarkistaa syöttötapin joka kerta pääpiirin ympäri. Jos se havaitsee muutoksen, se kutsuu mukautetun toiminnon vastaamaan siihen. Tässä on koodi (leikattu olennaiseen):

  int pinValue = LOW; void pinChanged () {//...}void setup () {pinMode (2, INPUT);} void loop () {// Lue nykyinen tulo int newValue = digitalRead (2); // Onko tulo muuttunut? if (newValue! = pinValue) {pinValue = newValue; tappiMuutettu (); }}  

Valitettavasti tämä ei aina toimi oikein hyvin lyhyissä muutoksissa (esim. lyhyet pulssit), varsinkin jos loop () on käynnissä vähän hitaasti.

Onko Arduinolla tapa havaita tulomuutos ja kutsua toimintoni automaattisesti?

Mitä etsit sen ulkoisesta keskeytyksestä
Kolme vastused:
#1
+26
Peter Bloomfield
2014-02-20 06:42:53 UTC
view on stackexchange narkive permalink

Voit tehdä tämän käyttämällä ulkoisia keskeytyksiä. Useimmat Arduinot tukevat tätä kuitenkin vain rajoitetulla määrällä nastoja. Katso lisätietoja attachInterrupt () -oppaasta.

Olettaen, että käytät Unoa, voit tehdä sen näin:

  void pinChanged () {//...}void setup () {pinMode (2, INPUT); attachInterrupt (0, pinChanged, CHANGE);} void loop () {}  

Tämä kutsuu pinChanged () aina, kun ulkoisen keskeytyksen 0 havaitaan muutos. Unossa, joka vastaa GPIO-nastaa 2. Ulkoinen keskeytysnumerointi on erilainen muilla levyillä, joten on tärkeää tarkistaa asiaankuuluvat asiakirjat.

Tällä lähestymistavalla on kuitenkin rajoituksia. Mukautettua pinChanged () -toimintoa käytetään keskeytyspalvelurutiinina (ISR). Tämä tarkoittaa, että loput koodista (kaikki loop () -kohdassa) pysäytetään väliaikaisesti puhelun suorittaessa. Estääksesi tärkeän ajoituksen keskeyttämisen, sinun on pyrittävä tekemään ISR: stä mahdollisimman nopeasti.

On myös tärkeää huomata, että muita keskeytyksiä ei suoriteta ISR: n aikana. Tämä tarkoittaa, että kaikki, joka luottaa keskeytyksiin (kuten ydin delay () ja millis () -toiminnot) ei välttämättä toimi oikein sen sisällä.

Viimeiseksi, jos ISR: n on muutettava luonnoksessa yleisiä muuttujia, ne on yleensä ilmoitettava volatile -näytteinä, esimerkiksi:

  volatile int someNumber;  

Se on tärkeää, koska se kertoo kääntäjälle, että arvo voi muuttua odottamattomasti, joten sen tulisi olla varovainen, ettei siitä käytetä vanhentuneita kopioita / välimuisteja.

kysymyksessä mainittujen "lyhyiden pulssien" suhteen, onko nastan oltava vähimmäisaika, jotta se voi käynnistää keskeytyksen? (tietysti se on paljon vähemmän kuin äänestys, joka riippuu siitä, mitä muuta silmukassa tapahtuu)
@sachleen Se toimii niin kauan kuin sitä ei tapahdu ISR-toiminnon suorittamisen aikana (kuten vastauksessa selitetään); siksi `` pinChanged () '' tulee olla mahdollisimman lyhyt. Siksi tyypillisesti vähimmäisajan pitäisi olla aika suorittaa itse `` pinChanged () '' -toiminto.
+1 tästä erittäin yksityiskohtaisesta vastauksesta, joka sisältää kaikki tärkeät asiat, joista on huolehdittava keskeytyksiä käytettäessä!
Jaetun globaalin julistamisen lisäksi, jos globaali muuttuja on leveämpi kuin 1 tavu, kuten jotkutNumero on, sinun on suojattava ohjelman tavuisten pääsyjen välillä tapahtuvalta pin-change-keskeytykseltä. Lauseke kuten "someNumber + = 5;" sisältää pienten tavujen lisäämisen ja korkeiden tavujen lisäämisen, kun mukana on kantoaika. Näitä kahta (enemmän, laajemmille muuttujille) ei saa jakaa keskeytyksellä. Keskeytysten kytkeminen pois päältä ja palauttaminen ennen toimintoa (vastaavasti) on riittävä.
@sachleen - pulssin vähimmäiskoon suhteen. Datalehdestä on vaikea löytää tarkkaa vastausta, mutta tapinvaihdon keskeytysten ajoituksen perusteella ne lukittuvat puolen kellojakson kuluessa. Kun keskeytys "muistetaan", se pysyy muistettuna, kunnes ISR aloittaa ja käsittelee sitä.
#2
+5
mpflaga
2014-02-24 20:36:06 UTC
view on stackexchange narkive permalink

Mikä tahansa digitaalituloksi määritetyn nastan muutostila voi aiheuttaa keskeytyksen. Toisin kuin INT1: n tai INT2: n keskeytysten aiheuttajien ainutlaatuiset vektorit, PinChangeInt-ominaisuus käyttää yhteistä vektoria ja sitten tämän vektorin keskeytyspalvelurutiini (alias ISR) on määritettävä sitten, mikä tappi on muuttunut.

Onneksi PinChangeInt-kirjasto tekee tämän helpoksi.

  PCintPort :: attachInterrupt (PIN, burpcount, RISING); // kiinnitä PinChange-keskeytys nastallemme nousevalla reunalla // (RISING, FALLING and CHANGE all work with this library) // ja suorita funktio burpcount, kun tappi muuttuu  
#3
  0
Nick Gammon
2015-07-01 07:27:55 UTC
view on stackexchange narkive permalink

Jos haluat havaita kynnyksen ylittävän jännitteen eikä olla vain KORKEA tai MATALA, voit käyttää analogista vertailua. Esimerkki luonnoksesta:

  volatile boolean triggered; ISR (ANALOG_COMP_vect) {triggered = true; } void setup () {Sarja.alku (115200); Serial.println ("Aloitettu."); ADCSRB = 0; // (Poista käytöstä) ACME: Analogisen vertailijan multiplekseri Ota käyttöön ACSR = bitti (ACI) // (Tyhjennä) Analogisen vertailijan keskeytyslippu | bitti (ACIE) // Analogisen vertailijan keskeytys käytössä | bitti (ACIS1); // ACIS1, ACIS0: Analogisen vertailijan keskeytystilan valinta (laukaisu putoavalla reunalla)} // asennuksen loppu välttää silmukan () {if (laukaistuna) {Serial.println ("Triggered!"); laukaisi = väärä; }} // silmukan loppu  

Tästä voi olla hyötyä esimerkiksi valoilmaisimissa, joissa saatat joutua havaitsemaan tulon muutoksen (esimerkiksi) 1 V: n ja 2 V: n välillä.

Esimerkki piiristä:

enter image description here

Voit myös käyttää prosessorin tulonsiirtoyksikköä, joka muistaa tiettyjen tulojen tarkan ajan, tallentamalla ajastimen / laskurin 1. nykyinen määrä. Tämän avulla voit tallentaa tarkan (hyvin, melkein tarkan) hetken, jolloin kiinnostava tapahtuma tapahtui, sen sijaan, että otettaisiin käyttöön viive (todennäköisesti muutaman mikrosekunnin) ennen kuin ISR: ää voidaan käyttää nykyisen aikaa.

Ajoituskriittisissä sovelluksissa tämä voi lisätä jonkin verran tarkkuutta.

Esimerkkisovellus: Tee Arduinosta kondensaattoritesteri



Tämä Q & A käännettiin automaattisesti englanniksi.Alkuperäinen sisältö on saatavilla stackexchange-palvelussa, jota kiitämme cc by-sa 3.0-lisenssistä, jolla sitä jaetaan.
Loading...