Problems coding PCINTs for Sharp IR sensors

Hello –

I am having mixed success with pin change interrupts for some Sharp 10Z0F digital IR sensors in an obstacle avoiding robot sketch. The MCU is a 1284P-PU @ 16MHz programmed with the Arduino IDE. I can get the following tester sketch to run OK, best I can tell.

//Pin defines on 1284P-PU
//PORTA pins
#define LEFTIR A5    //PA5, PCINT5
#define RIGHTIR A4   //PA4, PCINT4

void setup(){
  Serial.begin(115200);
  Serial.println("**** Sharp IR pin change ints tests ****");
  
  pinMode(LEFTIR, INPUT);
  pinMode(RIGHTIR, INPUT);
  
  //enable pin change interrupts, mask for specific pins
  PCICR |= (1<<PCIE0); //enable group interrupts on PORTA PCINT[7:0]
  PCMSK0 |= (1<<PCINT5); //mask to enable interrupt on A5 for LEFTIR
  PCMSK0 |= (1<<PCINT4); //mask to enable interrupt on A4 for RIGHTIR
}

void loop(){
  Serial.println("HIGH");
  delay(100);
}

ISR (PCINT0_vect) //handle pin change interrupt for group A0-A7, triggered by A5 & A4
{
  if ( bitRead (PINA,5) == LOW)
  {
    veerRight();
  }
  if ( bitRead (PINA,4) == LOW)
  {
    veerLeft();
  }
  if ( bitRead (PINA,5) == LOW && bitRead (PINA,4) == LOW)
  {
    backUp();
  }
}

void veerRight(){
  Serial.println("Veer Right");
}
void veerLeft(){
  Serial.println("Veer Left");
}
void backUp(){
  Serial.println("Back Up");
}

This is my first foray into pin change interrupts, referencing some recent posts on forum.pololu and forum.arduino. Those posts regarded wheel encoders, which was the original focus of my research. I modified some found code to address the Sharp IRs, and the above seemed to work.

I dropped the above code into the bot’s sketch (attached file) and encountered some problems. First, in the future I am wanting to switch from motor control durations with delay()'s to encoder wheel counts, so there was a conflict with the PCINT0_vect (and it’s aliases) already used in the PololuWheelEncoders library. I commented the encoder library and init out. This will need to be resolved later.

The second problem is in the ISR and it’s function calls. In the attached sketch, course changes of very brief durations are had when the IRs detect, though not to the desired degree. I think my problem relates to the IR sensor going from HIGH to LOW, and then LOW to HIGH, which is two changes on the pin, the second change cutting the ISR short.

If forum members might offer some guidance in regard my second problem that would be great. In regard my first problem, of conflicts with the PCINT vectors in the wheel encoder library, advice for resolving that is appreciated. I am unsure which of these two problems should be tackled fist.

Thank you!
Mark
New6x2problem.ino (8.15 KB)

Hello, Mark.

I am sorry you are having problems implementing interrupts with your AVR. Lets look at the ISR issue first. I noticed that in your code you are calling Serial.println() within the ISRs, which might be causing your problem. In general, ISRs should return to the code as soon as possible. Instead of calling Serial.println() in your ISR, you might consider raising a flag and having your main loop check the flag and call the appropriate function.

- Jeremy

Aloha Jeremy, and thank you the support.

So, because veerRight() is contained within the ISR, so to is the Serial print? If so, I have totally gotten this all wrong. I have read Serial prints, delays, and other timer related stuff does not work well in an ISR, and thought I was avoiding these issues by calling the function, and thereby bailing out of the ISR.

When a function is called from an ISR, it does not exit the ISR; it simply executes the function and returns to the ISR, just as it would if you called the function from any other part of your code.

- Jeremy

Interrupts are disabled while executing an interrupt routine (including execution of routines called from within an interrupt).

So, not only is it generally a bad idea to do something slow (like printing) from an interrupt, in the Arduino environment, Serial.print(ln) depends on interrupts and won’t work at all in that situation.

Jim, Jeremy – Aloha!

Thank you for your gracious support. Bouncing some of my misunderstandings off the forum always returns a valuable lesson.

'Ae Pololu no ka oi.
Me ka mahalo,
Mark

OK folks, I think I made some progress here, in spite of some of the bunk info out there on the webernet.

Following code seems to work, and over Serial can see the sensors’ bits go down and up.

#define LEFTIR A5    //Port A, PCINT 5
#define RIGHTIR A4   //Port A, PCINT 4

volatile byte portAStatus;
volatile byte eventFlag;

void setup(){
  Serial.begin(115200);
  
  pinMode(LEFTIR, INPUT);
  pinMode(RIGHTIR, INPUT);
  digitalWrite(LEFTIR, HIGH);
  digitalWrite(RIGHTIR, HIGH);
  
  PCICR |= (1<<PCIE0); //enable group interrupts on PORTA PCINT[7:0]
  PCMSK0 |= (1<<PCINT5); //mask to enable interrupt on A5 for LEFTIR
  PCMSK0 |= (1<<PCINT4); //mask to enable interrupt on A4 for RIGHTIR
}

void loop(){
  if (eventFlag == 1){
    Serial.println(portAStatus, BIN);
    
    if (bitRead(PINA,5) == LOW){
      Serial.println("LEFT");
    }
    if (bitRead(PINA,4) == LOW){
      Serial.println("RIGHT");
    }
    if (bitRead(PINA,5) == LOW && bitRead(PINA,4) == LOW){
      Serial.println("BACKUP");
    }
   
    eventFlag = 0;
  }
}
    
ISR (PCINT0_vect) //handle pin change interrupt for group A0-A7, triggered by A5 & A4
{
  portAStatus=PINA;
  
  eventFlag=1;
}

See any problems with what I am doing here?

Thank you,
Mark

Your code seems fine; I do not see any problems with it. I am glad you got it working.

- Jeremy