Go Down

Topic: Interrupt -> cli() -> Wireless Serial Transmission -> sei() (Read 1 time) previous topic - next topic

sprowan

I have an Arduino Nano 328 which communicates wirelessly via XBEE with a C# program. The Arduino only sends data when an interrupt occurs on digital pin 2, due to an infrared sensor. The unique pulse-width of the infrared interrupt is determined, and a 2 character notification of the details of the interrupt is sent to the PC.

Sometimes random characters such as %$ etc. get added to the intended string when being sent to the PC. I haven't yet used cli() and sei(). My question is this: Is the placement/use of cli() and sei() as shown below correct and likely to increase the reliability of wireless string transmission?

Thank you for your time.

Code: [Select]
attachInterrupt(0, IRInterruptOccurs, RISING);//(Digital Pin 2, Function, Rising Voltage)
...
void IRInterruptOccurs()
{
      IR_INTERRUPT = 1;
}
...
void Send()//Gets called in the loop if IR_INTERRUPT=1
{
      while(digitalRead(IR_PIN)){}//Do nothing, we want to start out with a fresh pulse
      int ir_duration = pulseIn(IR_PIN, HIGH);
      cli();
      ....Decide what message to print
      Serial.println(message);
      IR_INTERRUPT = 0;//Reset interrupt
      sei();//Resumes normal interrupt
}

el_supremo

Using cli/sei like that is probably not going to help. When you disable interrupts you should only do it for very brief periods.
But your Send function seems to have other problems. It is entered from loop() when IR_INTERRUPT has been set which means that IR_PIN is now high. The while loop then waits for IR_PIN to go low. The pulseIn statement is going to measure the length of the next high pulse but as soon as IR_PIN goes high there will be another interrupt, which is going to confuse things.
I think what you have to do in Send() is first detach the interrupt so that it can't occur while pulseIn is measuring the next pulse. Remove cli/sei. Then attach the interrupt again at the end of Send().

Pete
Don't send me technical questions via Private Message.

Tom Carpenter

When you call cli() you disable interrupts which means this statement won't send anything until interrupts are reenabled:
Code: [Select]
Serial.println(message);
Furthermore, if your message doesn't fit into the remaining space in the serial buffer, you will cause a deadlock whereby the Serial.print is in a while() loop waiting for free space, but the interrupts are disabled meaning no free space is made available.
~Tom~

sprowan

Thanks for responding, here is the updated code then:

Code: [Select]
void Send()
{
      detachInterrupt(0);
      while(digitalRead(IR_PIN)){}//Do nothing, we want to start out with a fresh pulse
      int ir_duration = pulseIn(IR_PIN, HIGH);
     
      String location = BUGGY_NUM + Detection(ir_duration);   

      Wait(1, 200);//Turn on the LED, waste 200 milliseconds
      Serial.println(location + " ");//Notification to PC

      IR_INTERRUPT = 0;//Reset interrupt
      attachInterrupt(0, IRInterruptOccurs, RISING);
}

el_supremo

Don't use String. It will eventually cause a mysterious crash.
Use null-terminated C strings instead.

Pete
Don't send me technical questions via Private Message.

Go Up