Megpróbálom használni a port manipulációt a megszakításokban egy forgó kódoló olvasására. Találtam egy Uno kódját, ezért a 2. és a 3. érintkezõ porthívása eltérõ. Szerintem a Megán PORTH3, illetve PORTH4. A kódom nem működik. Rosszul vannak a portjaim? Megpróbáltam elolvasni ezt, és nem értem teljesen a Bxxxxxxxx részt. Azt hiszem, ez lehet az, ami hibás. Itt van a kódom része az egyik megszakítással.
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 }
Megjegyzések
- Valaha is működött ez? Én is Arduino Mega-t akartam követni egy Omron Encoder szögpozíciójának 3 megszakítással. Az egyik megszakítás, hogy az Index minden alkalommal 0-ra álljon egy fordulatot teljesít. Egy forgó árboc nyomon követésére akarom használni az iránykereséshez. Vannak kódrészek, de semmi sem teljes. A tiéd teljes? [email protected]
Válasz
A “2 és 3 csap különbözik. Úgy gondolom, hogy a Megán PORTH3, illetve PORTH4”, igaz, hogy az Arduino digitális csapok 2 és 3 az Uno vs Mega2560 táblák különböző portjaihoz tartozik.
A Mega2560-nak hat INTx csapja van, szemben két ilyen Uno-val. A Megán az INT0 … INT3 PD0 … PD3 és az INT4, INT5 PE4, PE5. Az Uno-n INT0, INT1 PD2, PD3. Ne feledje, hogy a címen adott válaszban a külső megszakítások VAGY “d” együtt lehetnek a “328 (Uno)?” -On? mutatok pár olyan rutint, amelyek megfelelő maszkokat jelenítenek meg csapok a különböző Arduinos-on. Lásd: „Más csapok használata PCI-khez” és „ISR-keretet generáló vázlat”.
Íme néhány probléma a kérdésben látható kóddal:
-
aFlag
nullára inicializálódik, és soha nem lesz nulla a beállított kódban. Tehát az elsőif
feltétel soha nem teljesül aPinA()
mezőben. -
PinA()
egy megszakításkezelő, amelyetattachInterrupt()
hívásai kapcsolódnak a megszakításokhoz. Mivel a hardver letiltja a megszakításokat, mielőtt belépne egy megszakításkezelőbe, nincs szükség arra, hogy a megszakításkezelő kikapcsolja a megszakításokat. Vagyis törölje azcli()
elemet aPinA()
fájlból. Hasonlóképpen törölje asei()
-t aPinA()
végén, mert a hardver visszaállítja a megszakítási állapotot, amikor egy RETI utasítás végrehajtódik. -
Az Arduino szoftverkörnyezet olyan konstansokat határoz meg, mint a
B00001100
, a névnek megfelelő bináris értékekkel. Vagyis az Arduino szoftverkörnyezetben aB00001100
állandó értéke0B00001100
. Véleményem szerint ez “hülye és felesleges szolgáltatás; azt javaslom, hogy a kódjában használjon szabványos C jelölést, például0B00001100
, ha bináris állandó értékeket szeretne használni. -
A
encoderPos --
írást aencoderPos--
helyett perverziónak tekintem, és javaslom a felesleges szóköz törlését. -
Amint nem mutatta meg a
PinB()
megszakításkezelőt, nem tudom, hogy fogta kezelni aencoderPos++
eset. A bemutatott kódból ítélve olyan módszert használ, amely nem fogja helyesen kezelni a visszafordulási és szakaszos hibákat. Javaslom a pin-change megszakítások és az állam-gép módszer használatát, amint azt a következő válaszok szemléltetik:
• Olvasás KY-040 rotációs kódolóból a Digisparkkal
• Hogyan olvasható az RPS gyors forgatáshoz állapotváltoztatási módszerrel az Arduino-ban?
• Olvassa el az RC vevőcsatornákat a PulseIn helyett a megszakítással
• Lehetnek-e külső megszakítások VAGY “d” együtt a “328 (Uno)?
Válasz
A megán a PINE-t olvastad el a csapokkal.
Tehát a PINA kódja a következőre változik:
reading = PINE & 0b00110000; if(reading == 0b00110000 && aFlag) { encoderPos --; bFlag = 0; aFlag = 0; } else if (reading == 0b00010000) bFlag = 1;
I nagyszerű vitát talált az itt szükséges maszkolásról: https://forum.arduino.cc/index.php?topic=561741.0