Arduino Controlled IR Helicopter

Hello all,

I’m using a UDOO quad with an on-board Arduino DUE for this project.

I’ve been working on modified version of the link below[1] to control a S107G 2-channel helicopter. The code I’m using is [2]. The initial code works as intended with little delay from serial input to output at LED. The modified code has a significant delay (~1 sec) that would make this unusable in practice.

I’ve attempted to turn up the serial port to its maximum baud rate which reduced the lag slightly, but still would be unusable.

The only thoughts i have that would make this occur is the disabling of interrupts during transmission of the signal but allowing interrupts would destroy the integrity of the transmitted signal. Is there a way to set priority of the incoming serial unsigned-dint to execute immediately after transmission end?

[1]

http://www.avergottini.com/2011/05/arduino-helicopter-infrared-controller.html

[2]

//Arduino code to control a helicotper.
int IRledPin =  8;    

int pulseValue=0;
int pulseLength = 0;
byte yawCmd=0;
byte throttleCmd=0;
byte trimCmd=0;
byte pitchCmd=0;

int incomingByte = 0;


void setup()   {                
  // initialize the IR digital pin as an output:
  pinMode(IRledPin, OUTPUT);      
  pinMode(13, OUTPUT);  
  Serial.begin(115200);
 }
 
void loop()                    
{
  SendCode();
}
 
 
void pulseIR(long microsecs) {
  noInterrupts();  // this turns off any background interrupts
 
  while (microsecs > 0) {
    // 38 kHz is about 13 microseconds high and 13 microseconds low
    digitalWrite(IRledPin, HIGH);  // this takes about 3 microseconds to happen
    delayMicroseconds(10);         // hang out for 10 microseconds
    digitalWrite(IRledPin, LOW);   // this also takes about 3 microseconds
    delayMicroseconds(10);         // hang out for 10 microseconds
 
    // so 26 microseconds altogether
    microsecs -= 26;
 
  }
 
  interrupts();  // this turns interrupts back on
}
 
void Zero()
{  
  pulseIR(300);
  delayMicroseconds(300);
  pulseLength += 600;
}
 
void One()
{
  pulseIR(300);
  delayMicroseconds(600);
  pulseLength += 900;
}
 
void sendPulseValue(int pulseValue)
{

  char bob='0';
  Zero();
  for (int i=1; i<32; i++){
   bob=String(pulseValue,BIN).charAt(i);
   if (bob == '1')
    One();
   else
    Zero();   
  }
  
}
 
void checkPulseChanges(){
  
  if (Serial.available() > 0){

  incomingByte = Serial.parseInt();
  //Serial.println(incomingByte);
  throttleCmd=incomingByte;
  
  pitchCmd=63;
  yawCmd=63;

pulseValue=0;
pulseValue=trimCmd;
pulseValue+=throttleCmd<<8;
pulseValue+=pitchCmd<<16;
pulseValue+=yawCmd<<24;
pulseValue+=1<<31;

}
 
void SendCode() {
 
 while (true)
  {
    checkPulseChanges();
 
    pulseIR(2000);
    delayMicroseconds(2000);
    pulseLength=6000;
 
    sendPulseValue(pulseValue);

    //Footer
    pulseIR(360);
    delayMicroseconds( (118000 - pulseLength) );
   }

    }

Krush: The initial code works as intended with little delay from serial input to output at LED. The modified code has a significant delay (~1 sec) that would make this unusable in practice.

I think your question should be, why does this happen? Since you admit you don't know. Before leaping to solutions.

Interrupt-based programming has left me in this position on time-critical applications. I have a phase-control regulator with a similar issue that I overcame with an overclock and no-op delays.

I'm looking for clarification on my understanding to start, not be accused of jumping to conclusions.

Clarification would at least give me a basis to restructure the code in such a way that I can limit the amount of time interrupts are disabled.

Oh I see now. You have already disabled interrupts, rather than wondering if that would solve your problem. Well, I guess the point I'm leading to is, since the original code worked well without it, why you are compelled to do it? Because it may indeed be the source of your problem. How did the original program deal with transmission, in order to avoid that?

I haven't delved deeply into the code, but I see a lot of instances of delay() used in generating the pulse train. Is it blocking serial input? Likely. Perhaps there is a better way.

The delay() function usually affects real time applications, sort of the way green kryptonite affects Superman.

The old code used an identical transmission method but only changed one bit at a time in the transmission signal. The only modifications to the code is how the unsigned dint for transmission is formed.

The DUE is supposed to pass a 32-bit signal through serial but (this is the part I'm not sure about) I'm not sure why there is a delay if the data is being ignored. The transmission signal should be unchanged and the input discarded, not a lag in input.

The noInterrupts() page reads:

Some functions will not work while interrupts are disabled, and incoming communication may be ignored.

As far as I can see the "transmitter" is sending pulses to the helicopter - rather like a traditional R/C system.

If you have an Arduino on the helicopter and another in the transmitter why use such a primitive system? Why not send numbers or characters, or even binary bytes? See this IR Thread, for example

...R

If you have an Arduino on the helicopter and another in the transmitter why use such a primitive system?

The Arduino is replacing the need for the controller. The end result of this project is to pass a 32-bit signal generated on the Linux side of the UDOO to the Arduino for operation.

Krush: The Arduino is replacing the need for the controller. The end result of this project is to pass a 32-bit signal generated on the Linux side of the UDOO to the Arduino for operation.

What form does the 32 bit signal take - that sounds like 4 bytes? Did you write the Linux program?

...R

Did you write the Linux program?

Yes I wrote the code.

I'm using the serial monitor currently before I add the additional complexity of another program. The serial port should be plenty fast to write 4 bytes worth of data in between transmission at 115k baud rate.

Krush: The serial port should be plenty fast to write 4 bytes worth of data in between transmission at 115k baud rate.

I'm confused. I thought the 4 bytes would be the transmission, not something "between" transmissions.

I don't think you can do 115k baud with IR. Many IR transmissions uses a crrier frequency of 38Khz which allows a baud rate of about 2400 baud. That would transmit 4 bytes in 133 millisecs. I don't think the next higher standard baud rate (4800) will work, but some intermediate non standard may be possible.

...R