Reading servo pulses, RC plane lights, arduino runs slow when no signal present

I'm using a sparkfun arduino pro micro (programs as a leoardo board) and a home made mosfet 'shield'

The mosfets connect to high-ish power 5mm led's, that are to be fitted into a model airplane im making, and they will be the navigation and anti collision lights, as well as switchable landing lights,

The sketch simply turns a few led's on when the board is powred up (nav lights)

as well as flashing some led's at 200mA to mimic strobes (led's run at 70mA constant on, and they are pulsed at 50ms intervals twice every 2 seconds... so should survive)

It also fades a red led up and down with a bright flash, to mimic a revolving anti colision light found on the belly of planes,

And finally it monitors the servo pulses from the reciever, and turns 3 led's on or off depending on the pulse count (relating to a switch on the transmitter being on or off)

The problem i have is that with the transmitter turned off, and hence no pulses going in the input pin, it seems to overload the arduino and make it run slow... so the 50mS pulses of the strobes become more like 1 second pulses.

I tried putting a 10k resistor from the input pin to ground (same as is done with all the mosfets.. thankyou groundFungus for telling me how to use mosfets instead of transistors and the need for the pull down resistor... i used '2N7002KT1G' surface mount mosfets, and 0805 size SMT resistors... my first ever build using SMT components)

But it makes no difference to the arduino if i use a pull down or pull up resistor,

also it doesnt always do it, sometimes the sketch runs at the normal speed with nothing connected to pin 3, other times it runs slow the second the reciever is turned off.

i am wondering if i need some code that listens for the pulses, but when it gets none it stops the board running slow?

//Read PPM from one channel and use to switch landing lights on and off (usualy using flaps chanel)
//Flash strobe led's in a seni random manner, double flash for wingtips, single flash for tail strobe
//Mimic revolving anti collision light by fading led up, flashing bright then fading down
//Nav lights (red - port, green - starboard, white - facing rear) on when board powered up

const byte LightSwitch = 3;  //Turns on or off Landing lights via TX
unsigned int LightSwitchValue; //Decides if landing lights on or off
unsigned long currentTime = 0; //Timing for everything


//Navigation Lights
const byte NavLights = 9;  // Port, Starboard and Rear constant on Nav Lights


//Revolving Belly Light
const byte RevolvingLight = 10;  //Replicates revolving light
int RevolvingLightInterval = 0; //Sets initial start of sequence?
boolean RevolvingLightDirection = HIGH; //Sets initial 'direction' the led fades

//LandingLights
const byte LandingLightFront = 5;  //White nose mounted light, Turned on with TX
const byte LandingLightWing1 = 14;  //White wing mounted light, Turned on with TX
const byte LandingLightWing2 = 7;  //White wing mounted light, Turned on with TX

//WingTipStrobe 1
const byte WingTipStrobe1 = A3; //Flashes twice every second or so
unsigned long WingTipStrobeTimer1 = millis();
unsigned long WingTipStrobeInterval1 = 2000; //Time off after double flash
int WingTipStrobePhase1 = 1;

//WingTipStrobe 2
const byte WingTipStrobe2 = 15; //Flashes twice every second or so
unsigned long WingTipStrobeTimer2 = millis();
unsigned long WingTipStrobeInterval2 = 2100; //Time off after double flash, slightly different to strobe 1 for randomness
int WingTipStrobePhase2 = 1;

//Tail strobe
const byte TailStrobe = 2; //Flashes once a second or so
unsigned long TailStrobeTimer = millis();
unsigned long TailStrobeInterval = 1500; //Time strobe off
int TailStrobePhase = 1;


void setup()
{


  currentTime = millis();
  // Setting up pin functions
  pinMode(LandingLightFront, OUTPUT); //30000mcd white led @ 70mA
  pinMode(LandingLightWing1, OUTPUT); //30000mcd white led @ 70mA
  pinMode(LandingLightWing2, OUTPUT);//30000mcd white led @ 70mA
  pinMode(NavLights, OUTPUT); //25000mcd red, green and white led's @ 55mA
  pinMode(WingTipStrobe1, OUTPUT); //30000mcd white led @ 200mA pulsed
  pinMode(WingTipStrobe2, OUTPUT); //30000mcd white led @ 200mA pulsed
  pinMode(TailStrobe, OUTPUT); //30000mcd white led @ 200mA pulsed
  pinMode(RevolvingLight, OUTPUT); //25000mcd red led @ 70mA
  pinMode(LightSwitch, INPUT); //Connected to reciever channel 5 (landing gear)


  //Turn on NavLights when board is powered up
  digitalWrite(NavLights, HIGH);
}

//Functions for landing lights
void LandingLightsOn()
{
  digitalWrite(LandingLightFront, HIGH); //Lights on
  digitalWrite(LandingLightWing1, HIGH);
  digitalWrite(LandingLightWing2, HIGH);
}
void LandingLightsOff()
{
  digitalWrite(LandingLightFront, LOW); //Lights off
  digitalWrite(LandingLightWing1, LOW);
  digitalWrite(LandingLightWing2, LOW);
}

void pulse() //Read servo pulses from reciever
{
  LightSwitchValue = pulseIn(LightSwitch, HIGH);


  if (LightSwitchValue > 1400) //landing lights on
  {
    LandingLightsOn();

  }
  if (LightSwitchValue < 1200) //landing lights off
  {
    LandingLightsOff();

  }
}

void loop()
{

  pulse();  //Check Radio Receiver switch position.
  
  currentTime = millis();

  {
    //Revolving Belly Light
    {
      int revolvingIncrement = 5;
      static unsigned long revolvingTimer = 0;
      unsigned long revolvingInterval = 90;
      if (currentTime - revolvingTimer >= revolvingInterval)
      {
        revolvingTimer = currentTime;
        analogWrite(RevolvingLight, RevolvingLightInterval);
        if (RevolvingLightDirection == HIGH)
          RevolvingLightInterval = RevolvingLightInterval + revolvingIncrement;
        else
          RevolvingLightInterval = RevolvingLightInterval - revolvingIncrement;
        if (RevolvingLightInterval > 80 && RevolvingLightDirection == HIGH )
          RevolvingLightInterval = 255; //Jump for the flash
        if (RevolvingLightInterval > 200 && RevolvingLightDirection == LOW )
          RevolvingLightInterval = 80; //Dump from the flash

        if (RevolvingLightInterval == 255)
          RevolvingLightDirection = LOW;
        if (RevolvingLightInterval == 5)
          RevolvingLightDirection = HIGH;
      }
    }


    //WingTip Strobe 1
    if (currentTime - WingTipStrobeTimer1 > WingTipStrobeInterval1 )
    {
      switch (WingTipStrobePhase1)
      {
        case 1:
          //strobe on first
          digitalWrite(WingTipStrobe1, HIGH);
          WingTipStrobeInterval1 = 50; //Pulse the led for 50ms
          WingTipStrobePhase1 = 2;
          break;
        case 2:
          //strobe off first cycle
          digitalWrite(WingTipStrobe1, LOW);
          WingTipStrobeInterval1 = 100; //Pause for 100ms
          WingTipStrobePhase1 = 3;
          break;
        case 3:
          //strobe on second cycle
          digitalWrite(WingTipStrobe1, HIGH);
          WingTipStrobeInterval1 = 50; //Pulse again for 50ms
          WingTipStrobePhase1 = 4;
          break;
        case 4:
          //strobe off second cycle
          digitalWrite(WingTipStrobe1, LOW);
          WingTipStrobeInterval1 = 2000; //Pause for 2 seconds
          WingTipStrobePhase1 = 1;
          break;
      }
      WingTipStrobeTimer1 = millis();
    }


    //WingTip Strobe 2
    if (currentTime - WingTipStrobeTimer2 > WingTipStrobeInterval2 )
    {
      switch (WingTipStrobePhase2)
      {
        case 1:
          //strobe on first
          digitalWrite(WingTipStrobe2, HIGH);
          WingTipStrobeInterval2 = 50; //Pulse the led for 50ms
          WingTipStrobePhase2 = 2;
          break;
        case 2:
          //strobe off first cyclerevolving
          digitalWrite(WingTipStrobe2, LOW);
          WingTipStrobeInterval2 = 110; //Pause for 110ms
          WingTipStrobePhase2 = 3;
          break;
        case 3:
          //strobe on second cycle
          digitalWrite(WingTipStrobe2, HIGH);
          WingTipStrobeInterval2 = 50; //Pulse again for 50ms
          WingTipStrobePhase2 = 4;
          break;
        case 4:
          //strobe off second cycle
          digitalWrite(WingTipStrobe2, LOW);
          WingTipStrobeInterval2 = 2300; //Pause for 2.3 seconds (results in the realistic random flash rates)
          WingTipStrobePhase2 = 1;
          break;
      }
      WingTipStrobeTimer2 = millis();
    }


    //Tail Strobe
    if (currentTime - TailStrobeTimer > TailStrobeInterval )
    {
      switch (TailStrobePhase )
      {
        case 1:
          //strobe on
          digitalWrite(TailStrobe, HIGH);
          TailStrobeInterval = 70; //Pulse for 70ms
          TailStrobePhase = 2;
          break;
        case 2:
          //strobe off
          digitalWrite(TailStrobe, LOW);
          TailStrobeInterval = 1800; //Pause for 1.8 seconds.. again for some randomness with other strobes
          TailStrobePhase = 1;
          break;
      }
      TailStrobeTimer = millis();
    }

  }
}

You're probably going to find that if you comment this line:

LightSwitchValue = pulseIn(LightSwitch, HIGH);

your speed will return. pulseIn is a blocking function that, by default, will wait up to 1-second for a pulse.

You can try adding a shorter timeout, such as 60-milliseconds:

LightSwitchValue = pulseIn(LightSwitch, HIGH, 60000ul); //60000 microseconds == 60mS

or change to using a pin-change interrupt and time the relatively slow RC input yourself.

Brilliant, thanks for that, done the trick.

Is a pin change interupt the only other way of reading servo pulses without blocking?

gazz292:
Is a pin change interupt the only other way of reading servo pulses without blocking?

Only way I know of.

Check out this thread: submarine

It was started by a user looking for help with his RC submarine. IIRC, he had adapted some existing code which lets an Arduino intercept PPM servo signals and then pass them on to the servos. You might find it useful.

i am not sure if this will work... but i'm thinking, i have 8 unused pins on the arduino, and with a simple pin re-route 2 of them can be pins 1 and 2 (tx and rx, the i2c port too i believe)

i'd like some telemetry data from the plane on the ground, so i was thinking of using some sort of transievers (some use Xbee's, others use i think NRF24L01's, and other similar ones) and getting some basic data... battery pack voltage (11.1v) motor current, speed controller temperature, and maybe air speed and altitude.

Would this be possible with the script that runs the nav lights? of would i have to use another arduino just for the telemetry?

gazz292:
i'd like some telemetry data from the plane on the ground, so i was thinking of using some sort of transievers (some use Xbee's, others use i think NRF24L01's, and other similar ones) and getting some basic data... battery pack voltage (11.1v) motor current, speed controller temperature, and maybe air speed and altitude.

This is very possible, but I'd use 3DR 915MHz radios instead of NRF modules IMHO - you'll get a lot better range and are much more straightforward to use.

I do telemetry reporting with my Arduino Research RC plane project "ArdUAV". You should check out the build logs for airplane #1 and airplane #2 (in progress). The code can be found here at GitHub and a full API/website is here.