Yritän käyttää porttikäsittelyä keskeytyksissä kiertokooderin lukemiseen. Löysin koodin Unolle, joten nastojen 2 ja 3 porttikutsu on erilainen. Mielestäni Megassa ne ovat PORTH3 ja PORTH4. Koodini ei toimi. Onko porttini väärässä? Olen yrittänyt lukea tämän ja en ymmärrä täysin Bxxxxxxxx-osaa. Luulen, että tämä saattaa olla väärin. Tässä on osa koodiani, johon kuuluu yksi keskeytyksistä.
static int pinA = 2; // Our first hardware interrupt pin is digital pin 2 static int pinB = 3; // Our second hardware interrupt pin is digital pin 3 volatile byte aFlag = 0; // let us know when we"re expecting a rising edge on pinA to signal that the encoder has arrived at a detent volatile byte bFlag = 0; // let us know when we"re expecting a rising edge on pinB to signal that the encoder has arrived at a detent (opposite direction to when aFlag is set) volatile byte encoderPos = 0; //this variable stores our current value of encoder position. Change to int or uin16_t instead of byte if you want to record a larger range than 0-255 volatile byte oldEncPos = 0; //stores the last encoder position value so we can compare to the current reading and see if it has changed (so we know when to print to the serial monitor) volatile byte reading = 0; void setup () { pinMode(pinA, INPUT); // set pinA as an input, pulled HIGH to the logic voltage (5V or 3.3V for most cases) pinMode(pinB, INPUT); attachInterrupt(0, PinA, RISING); // set an interrupt on PinA, //looking for a rising edge signal and executing the "PinA" Interrupt Service Routine (below) attachInterrupt(1, PinB, RISING); // set an interrupt on PinB, //looking for a rising edge signal and executing the "PinB" Interrupt Service Routine (below) } void PinA() { //CCW cli(); //stop interrupts happening before we read pin values reading = PORTH & 0xC; // read all eight pin values then strip away all but pinA and pinB"s values if (reading == B00001100 && aFlag) { //check that we have both pins at detent (HIGH) and that we are expecting detent on this pin"s rising edge encoderPos --; //decrement the encoder"s position count bFlag = 0; //reset flags for the next turn aFlag = 0; //reset flags for the next turn } else if (reading == B00000100) bFlag = 1; //signal that we"re expecting pinB to signal the transition to detent from free rotation sei(); //restart interrupts }
Kommentit
- Saitko koskaan tämän toimivan? Minäkin olen halunnut käyttää Arduino Megaa seurataksesi 3 keskeytyksellä varustetun Omron-kooderin kulma-asemaa. Yksi keskeytyksistä, jotta Indeksi palautuu nollaan joka kerta se suorittaa yhden kierroksen. Haluan käyttää sitä pyörivän maston jäljittämiseen suunnan löytämiseen. Koodipaloja on, mutta mikään ei ole täydellinen. Onko sinun täydellinen? [email protected]
Vastaus
Re ”nastat 2 ja 3 ovat erilaisia. Mielestäni Megassa ne ovat PORTH3 ja PORTH4”, on totta, että Arduinon digitaaliset nastat 2 ja 3 kuuluvat Uno vs Mega2560 -taulujen eri portteihin.
Mega2560: lla on kuusi INTx-nastaa, verrattuna kahteen sellaiseen Unon. Megalla INT0 … INT3 ovat PD0 … PD3 ja INT4, INT5 ovat PE4, PE5. Unossa INT0, INT1 ovat PD2, PD3. Huomaa, että vastauksessa osoitteeseen Voivatko ulkoiset keskeytykset olla TAI ”d yhdessä” 328 (Uno) -ohjelmassa? Näytän pari rutiinia, jotka näyttävät sopivat maskit nastat eri Arduinosissa. Katso kohdat ”Muiden nastojen käyttäminen PCI: ssä” ja ”ISR-kehyksen luominen luonnos”.
Tässä on muutama ongelma kysymyksessä esitetyssä koodissa:
-
aFlag
alustetaan nollaksi, eikä sitä koskaan aseteta nollaksi näytetyssä koodissa. Joten ensimmäinenif
-ehtoPinA()
-kohdassa ei koskaan täyty. -
PinA()
on keskeytyskäsittelijä, joka on kytketty keskeytyksiinattachInterrupt()
-puheluillasi. Koska laitteisto poistaa keskeytykset käytöstä ennen kuin se tulee keskeytyskäsittelijään, keskeytyskäsittelijän ei tarvitse sammuttaa keskeytyksiä. Toisin sanoen poistacli()
kohdastaPinA()
. Poista samalla tavallasei()
kohdanPinA()
lopussa, koska laitteisto palauttaa keskeytystilan, kun RETI-käsky suoritetaan. -
Arduino-ohjelmistoympäristö määrittelee vakiot, kuten
B00001100
, binääriarvoilla, jotka vastaavat nimeä. Toisin sanoen vakioB00001100
on Arduino-ohjelmistoympäristössä arvo0B00001100
. Mielestäni tämä on tyhmä ja tarpeeton ominaisuus; ehdotan, että käytät koodissasi tavallista C-merkintää, kuten0B00001100
, kun haluat käyttää binaarivakioarvoja. -
Pidän
encoderPos --
-kentän kirjoittamistaencoderPos--
-kuvan sijaan vääristymänä ja ehdotan tarpeettoman tilan poistamista. -
Kun et ole osoittanut
PinB()
keskeytyskäsittelijää, en tiedä miten aiot käsitelläencoderPos++
-tapa. Näytetystä koodista päätellen käytät menetelmää, joka ei käsittele oikein palautumis- ja ajoittaisia virheitä. Ehdotan pin-change-keskeytysten ja tilakone-menetelmän käyttöä, kuten vastaukset osoittavat:
• Lukeminen KY-040-pyörivästä enkooderista Digisparkin kanssa
• Kuinka lukea RPS nopeaa kiertämistä varten tilanvaihtomenetelmällä Arduinossa?
• Lue RC-vastaanottimen kanavat käyttämällä keskeytystä PulseInin sijaan
• Voivatko ulkoiset keskeytykset olla TAI ”d” yhdessä ”328 (Uno) -laitteessa?
Vastaa
Megassa luit nastat PINE: lla.
Joten PINA-koodisi muuttuisi:
reading = PINE & 0b00110000; if(reading == 0b00110000 && aFlag) { encoderPos --; bFlag = 0; aFlag = 0; } else if (reading == 0b00010000) bFlag = 1;
I löysi suuren keskustelun, joka puhui täältä vaaditusta peittämisestä: https://forum.arduino.cc/index.php?topic=561741.0