JasonP 5 Posted April 16, 2016 Share Posted April 16, 2016 Hello Everyone, I am working with the MSP432 launchpad in Energia and I can't seem to use digitalRead() in and ISR? I'm hoping that someone can give me some indication as to why or find the bug in my code This is for a rotary encoder and the interrupts must fire on both Rising and Falling Edges. This Is why I try to determine the state of the pin that was just interrupted. The ISR's will be a bit more complex for the actual encoding but first I need to be able to read the state of the pins. Thanks Guys! const int encoder0PinA = 11; const int encoder0PinB = 31; volatile int pinACount = 0; volatile int pinBCount = 0; volatile bool Aflag = false; volatile bool Bflag = false; /////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// S E T U P ////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// void setup(){ Serial.begin(9600); Serial.println("COUNTER STARTING UP"); pinMode(11,INPUT); pinMode(31,INPUT); attachInterrupt(encoder0PinA, doEncoderA, CHANGE); attachInterrupt(encoder0PinB, doEncoderB, CHANGE); } /////////////////////////////////////////////////////////////////////////////////// //////////////////////////////// L O O P ////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// void loop(){ // SANITY CHECK Serial.println(digitalRead(11)); // Here to see that the pin does change states Serial.println(digitalRead(31)); // Here to see that the pin does change states Serial.print("A Flag: "); Serial.print(Aflag); // I never see either of these get set to 1. Serial.print(" B Flag: "); Serial.println(Bflag); ; Serial.println(); delay(500); } void doEncoderA(){ Aflag = digitalRead(encoder0PinA); } void doEncoderB(){ Bflag = digitalRead(encoder0PinB); } Quote Link to post Share on other sites
energia 484 Posted April 16, 2016 Share Posted April 16, 2016 It seems that you have stumbled on a bug. I was able to reproduce it. Odd thing is that I am able to read a pin that has not seen attachedInterrupt() and see the flag change if I digitalRead() that pin in the interrupt routine. I'll look into it. Robert JasonP 1 Quote Link to post Share on other sites
energia 484 Posted April 16, 2016 Share Posted April 16, 2016 Would you please be so kind to file an issue on github here: https://github.com/energia/Energia/issues Thanks! Robert JasonP 1 Quote Link to post Share on other sites
JasonP 5 Posted April 16, 2016 Author Share Posted April 16, 2016 Would you please be so kind to file an issue on github here: https://github.com/energia/Energia/issues Thanks! Robert Robert, I have created the new issue found here: https://github.com/energia/Energia/issues/873 Also I was wondering if you can think of a workaround in the meantime? We are trying to have a working prototype by next week. Thank You. Quote Link to post Share on other sites
Fmilburn 445 Posted April 17, 2016 Share Posted April 17, 2016 I modified the code to use the buttons so that I didn't have to hook up an encoder. Something in Energia doesn't process "CHANGE" from the attachInterrupt() function properly either. It works as expected on a F5529 and catches rising and falling edges but not on the MSP432. @@JasonP - The following "works" but will only catch one edge const int encoder0PinA = PUSH1; const int encoder0PinB = PUSH2; volatile int pinACount = 0; volatile int pinBCount = 0; volatile bool Aflag = false; volatile bool Bflag = false; /////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// S E T U P ////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// void setup(){ Serial.begin(115200); Serial.println("COUNTER STARTING UP"); pinMode(encoder0PinA,INPUT_PULLUP); pinMode(encoder0PinB,INPUT_PULLUP); attachInterrupt(encoder0PinA, doEncoderA, CHANGE); attachInterrupt(encoder0PinB, doEncoderB, CHANGE); } /////////////////////////////////////////////////////////////////////////////////// //////////////////////////////// L O O P ////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// void loop(){ // SANITY CHECK Serial.println(digitalRead(encoder0PinA)); // Here to see that the pin does change states Serial.println(pinACount); Serial.println(digitalRead(encoder0PinB)); // Here to see that the pin does change states Serial.println(pinBCount); Serial.print("A Flag: "); Serial.print(Aflag); // I never see either of these get set to 1. Serial.print(" B Flag: "); Serial.println(Bflag); ; Serial.println(); delay(500); } void doEncoderA(){ pinACount++; if (Aflag == 0) { Aflag = 1; } else { Aflag = 0; } } void doEncoderB(){ pinBCount++; if (Bflag == 0) { Bflag = 1; } else { Bflag = 0; } } JasonP 1 Quote Link to post Share on other sites
JasonP 5 Posted April 17, 2016 Author Share Posted April 17, 2016 @@Fmilburn, Thanks for mentioning that. That explains what I have been seeing but I did not pick up on that. I was going insane here trying to figure out why my arduino based code that has worked flawlessly isn't working at all. I hope these issues can get resolved soon. @@energia, Has an issue been created for the attachInterrupt(CHANGE) problem that @@Fmilburn just mentioned? Quote Link to post Share on other sites
Fmilburn 445 Posted April 17, 2016 Share Posted April 17, 2016 @@JasonP I added it to your issue JasonP 1 Quote Link to post Share on other sites
JasonP 5 Posted April 18, 2016 Author Share Posted April 18, 2016 @@energia, @@Fmilburn Ryan Brown over at TI has given a workaround for the digitalRead(). It is found here: https://e2e.ti.com/support/microcontrollers/msp430/f/166/p/506515/1838064#1838064 I'm not quite sure how this works but it does seem to. Quote Link to post Share on other sites
chicken 630 Posted April 18, 2016 Share Posted April 18, 2016 I think the proposed Aflag ^= 1 workaround does not really solve your problem. You still only get an interrupt on one of the transitions (high-low or low-high), but instead of reading the current pin state, you simply inverse the current state of the variable. From reading the e2e thread and without reading at the datasheet, it looks like the MSP432 hardware only supports configuring the interrupt for one of the transitions at a time, i.e. no native support of CHANGE. It could be worked around by re-configuring within the interrupt. E.g. if currently high, trigger on going low; if currently low, trigger on going high. Calling attachInterrupt within the interrupt probably won't work, so you'd have to go to the register level to implement that. Maybe there's already an Energia library for reading quadrature encoders that takes care of those low-level details. tripwire, JasonP and Fmilburn 3 Quote Link to post Share on other sites
JasonP 5 Posted April 19, 2016 Author Share Posted April 19, 2016 @@chicken, Your'e right. It doesn't really solve the problem. I posted a followup over there after I pulled my head out and realized that is not an actual workaround. Re-establishing the interrupt within the interrupt might work. I know detaching and reattaching inside an interrupt does work on my arduino. I might have to try that. I really didn't want to have to refresh on C but maybe I will have to... Or revert back to arduino. Quote Link to post Share on other sites
abecedarian 330 Posted April 19, 2016 Share Posted April 19, 2016 A little wasteful of GPIO and code space perhaps, but could you not send the encoder's signals to two pins each and attach rising and falling interrupt handlers / functions to those pins separately? JasonP 1 Quote Link to post Share on other sites
abecedarian 330 Posted April 19, 2016 Share Posted April 19, 2016 Okay... put something together... a little simplified, but using the EMT abilities... and "CHANGE". One part eschews using Serial for debugging and sets up the "Aflag" variable and configures pin 11 as in input with an interrupt handler using CHANGE, the handler does a "NOT" on the Aflag variable when called, and loop() sets the RED LED to the Aflag state. The other is a "thread" which sets up another pin (12) to automatically turn on and off every 1/10 second. So, create new sketch in Energia and put the following in it: const int encoder0PinA = 11; volatile bool Aflag; void setup(){ pinMode(encoder0PinA,INPUT); Aflag = digitalRead(encoder0PinA); attachInterrupt(encoder0PinA, doEncoderA, CHANGE); pinMode(78, OUTPUT); // RED single LED on board } void loop(){ digitalWrite(78, Aflag); } void doEncoderA(){ Aflag = !Aflag; }Then make a new tab, name it "blink", then paste the following code in: void setupBlink() { pinMode(12, OUTPUT); digitalWrite(12,HIGH); } void loopBlink() { delay(100); digitalWrite(12, LOW); delay(100); digitalWrite(12,HIGH); }Then, connect a jumper between pins 11 and 12 and upload the program. "CHANGE" does in fact work... this way at least. Makes me wonder if using a physical switch without debouncing, or something with Serial might be culprit...? *edit: changed the value in the delay() in "blink" to a few different values and couldn't see any issues. *edit-2: tried to do digitalRead() in the interrupt and that still does not work. Fmilburn and JasonP 2 Quote Link to post Share on other sites
JasonP 5 Posted April 19, 2016 Author Share Posted April 19, 2016 @@abecedarian, Thanks for the Idea of using two pins for the interrupt rising and falling. This actually would solve most of my issues as I would then truly know the state of the pin.... I think. Also thanks for this little sample sketch I will try running it later today.. HA I was going to ask if you tried different delays since 100mS vs 200mS might be hard to tell, but I see in your edit you did that The GPIO thing isn't really an issue for us. Thanks again. Quote Link to post Share on other sites
abecedarian 330 Posted April 19, 2016 Share Posted April 19, 2016 After waking up this morning, I put a blink sketch on a G2553 LP in order to emulate the signal a Hall effect sensor or similar might output to the system. I connected that to the 432 and the LED on the 432 toggles on only one edge. So I need to correct myself: "CHANGE" is not working in the sketch I posted above. Must've been an illusion. Anyhow, I tried the two-pin, two-interrupt thing, and kept the G2553LP as a "signal generator"- On the 432: const int encoder0PinA1 = 11; const int encoder0PinA2 = 12; volatile bool Aflag; /////////////////////////////////////////////////////////////////////////////////// ////////////////////////////// S E T U P ////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// void setup(){ pinMode(78, OUTPUT); // RED single LED on board pinMode(encoder0PinA1,INPUT); pinMode(encoder0PinA2,INPUT); // set Aflag to whatever state the pin is in on start up // in case the interrupts don't trigger early enough Aflag = digitalRead(encoder0PinA1); attachInterrupt(encoder0PinA1, doRisingEncoderA, RISING); attachInterrupt(encoder0PinA2, doFallingEncoderA, FALLING); } /////////////////////////////////////////////////////////////////////////////////// //////////////////////////////// L O O P ////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////// void loop(){ digitalWrite(78, Aflag); } void doRisingEncoderA(){ Aflag = true; } void doFallingEncoderA(){ Aflag = false; }On the G2553LP: void setup() { pinMode(RED_LED,OUTPUT); digitalWrite(RED_LED,HIGH); } void loop() { delay(100); digitalWrite(RED_LED, LOW); delay(100); digitalWrite(RED_LED, HIGH); }On the G2553LP, I left the RED LED jumper on.I ran a jumper from the G2553LP pin 2(LED1) to a row on a breadboard, then ran two jumpers from that row to the 432's pins 11 and 12. Essentially: G2553 pin 2 ------+------ pin 11 432LP +------ pin 12 432LPThe RED LED's on both boards blink together, at the same rate, so the 432 is catching both the rising and falling edges of the single output from the G2553. Fmilburn 1 Quote Link to post Share on other sites
JasonP 5 Posted April 20, 2016 Author Share Posted April 20, 2016 @@abecedarian, Ha ha I was just writing to say thank you to everyone that has pitched in and helped me, especially you! Honestly I don't see a better workaround for the time being and things are actually working flawless. Spitting the two interrupts into two is actually nice as each interrupt is much simpler. Thanks again. ////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// I N T E R R U P T //////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// void risingA(){ // Must be a low-to-high on channel A Ahigh = true; // The pin must be high to get here. // check channel B to see which way encoder is turning if (!Bhigh) { encoder0Pos++; // CW direction = 1; } else { encoder0Pos--; // CCW direction = 2; } } ////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// I N T E R R U P T //////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// void fallingA(){ // must be a high-to-low edge on channel A Ahigh = false; // check channel B to see which way encoder is turning if (Bhigh) { encoder0Pos++; // CW direction = 1; } else { encoder0Pos--; // CCW direction = 2; } } ////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// I N T E R R U P T //////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// void risingB(){ // Must be a low-to-high on channel B Bhigh = true; // check channel A to see which way encoder is turning if (Ahigh) { encoder0Pos++; // CW direction = 1; } else { encoder0Pos--; // CCW direction = 2; } } ////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////// I N T E R R U P T //////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////// void fallingB(){ Bhigh = false; // must be a high-to-low on channel B sensblast = false; // check channel B to see which way encoder is turning if (!Ahigh) { encoder0Pos++; // CW direction = 1; } else { encoder0Pos--; // CCW direction = 2; } } abecedarian 1 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.