Code

/*Date: 2014-06-13Author: Jean-Christophe Heger <jcheger*at*ordinoscope*net>License: GPLv3 (http://www.gnu.org/copyleft/gpl.html)Project desciption------------------Play with LEDs for RC (PPM). This project handles one PPM input, and triggers different typesof LED (or switch) behaviors. Each one can be triggered at a givven level of PPM length.Warning-------This circuit use some PWM, which creates interferences with RC receivers. Take care of:- never run such circuit without a capacitor in parallel of the battery (1uF or 2x 470uF / 50V is a good choice)- use a separate battery is better- do never run a model without a serious testingRequirements------------- download the Timer1 library (https://code.google.com/p/arduino-timerone/)- unzip it and copy the folder in sketchbook/libraries- restart the Arduino IDEPins----2 - PPM input3 - LED glow output4 - LED flash output5 - LED switch output (1)6 - LED switch output (2)13 - onboard LED PPM monitorLimitations------------ the maximum current per pin is 40mA - use a MOSFET for upper current- the PPM reading has quite a high jitter of about 50usPWM considerations------------------Pins 3 and 11 use the timer2.Pins 5 and 6 use the timer0, conflicting with delay(), millis() and micros()Pins 9 and 10 use the timer1, conflicting with timerIsr()Electronic components---------------------- Arduino (Atmega 328p)- MOSFETS IRL3705-N - actually any NPN transistor of MOSFET-N is allright. The IRL3705-N handles high currents, is cheap (~ 1€ / eBay) and is a "Logic Gate". This means the MOSFET is either ON or OFF, and not in a intermediate state. - 10k pulldown resistor per MOSFET- 2x 470 uF or 1x 1000 uF capacitor (good for ~5A @ 12V) */#include<TimerOne.h>// Pins settings#define PPMIN_PIN 2 // must be an interrupt pin - do not change !#define GLOW_PIN 3 // must be a timer2 PWM pin - do not change !#define FLASH_PIN 4 // any digital pin#define SWITCH1_PIN 5 // any digital pin#define SWITCH2_PIN 6 // any digital pin#define RXLED_PIN 13 // monitors the PPM readings (onboard LED)// PPM settings#define DEADBAND 50 // around 50us#define FLASH_PPM 1900 // PPM length (1000-2000 us)#define GLOW_PPM 1900 // PPM length (1000-2000 us)#define SWITCH1_PPM 1400 // PPM length (1000-2000 us)#define SWITCH2_PPM 1900 // PPM length (1000-2000 us)// Delays and lengths#define FLASH_DELAY 2000 // flash delay in us (OFF)#define FLASH_LENGTH 100 // flash length in us (ON)#define GLOW_DELAY 5 // delay between change in us#define GLOW_MIN -100 // minimum PWM is 0 - a value below 0 will delay the glow at 0#define GLOW_MAX 300 // maximum PWM is 255 - a value above 255 will delay the glow at 255// Globalsvolatilebooleanflash_enable=0;volatilebooleanglow_enable=0;volatilebooleanswitch1_enable=0;volatilebooleanswitch2_enable=0;volatileunsignedlongpulse;voidsetup(){pinMode(PPMIN_PIN,INPUT);pinMode(FLASH_PIN,OUTPUT);pinMode(GLOW_PIN,OUTPUT);pinMode(SWITCH1_PIN,OUTPUT);pinMode(SWITCH2_PIN,OUTPUT);pinMode(RXLED_PIN,OUTPUT);attachInterrupt(0,pulseInIsr,CHANGE);// monitor PWM inputTimer1.initialize(1000);// set timer once per msTimer1.attachInterrupt(timerIsr);}voidloop(){}/** * Output loop. * Only Timer1 is used, based on a 1ms behavior (Timer1.initialize (1000)). */voidtimerIsr(){staticunsignedintflash_delay=0;// flash OFF incrementstaticunsignedintflash_length=0;// flash ON incrementstaticunsignedintglow_delay=0;// glow increment before next valuestaticbooleanglow_dir=0;// 0 = up, 1 = downstaticsignedintglow_pwm=0;// glow PWM value// FLASHif(flash_enable){if(flash_length>0){// flash is ONif(flash_length>=FLASH_LENGTH){// turn flash OFFdigitalWrite(FLASH_PIN,LOW);flash_length=0;flash_delay=0;}else{flash_length++;}}else{// flash is OFFflash_delay++;if(flash_delay>=FLASH_DELAY){// turn flash ONdigitalWrite(FLASH_PIN,HIGH);flash_length++;flash_delay=0;}}}else{flash_delay=0;flash_length=0;digitalWrite(FLASH_PIN,LOW);}// GLOWif(glow_enable){if(glow_delay>=GLOW_DELAY){// glow increase/decrease PWMglow_delay=0;if(glow_dir){glow_pwm--;}else{glow_pwm++;}if(glow_pwm<=GLOW_MIN)glow_dir=0;if(glow_pwm>=GLOW_MAX)glow_dir=1;if(glow_pwm<0){// delay the glow at 0analogWrite(GLOW_PIN,0);}elseif(glow_pwm>255){// delay the glow at 255analogWrite(GLOW_PIN,255);}else{analogWrite(GLOW_PIN,glow_pwm);// normal PWM}}else{// glow wait (increment)glow_delay++;}}else{analogWrite(GLOW_PIN,0);glow_delay=0;glow_pwm=0;}// SWITCH1if(switch1_enable){digitalWrite(SWITCH1_PIN,HIGH);}else{digitalWrite(SWITCH1_PIN,LOW);}// SWITCH2if(switch2_enable){digitalWrite(SWITCH2_PIN,HIGH);}else{digitalWrite(SWITCH2_PIN,LOW);}}/** * Monitor the incoming PPM and set global variables if change is detected. * The pulse measure is not quite precise, and may jitter by about 20us. * The DEADBAND value is an anti flicker, but you should be advised to * set the trigger values about 100us below the real value. */voidpulseInIsr(){unsignedlongt=micros();// current time in usstaticunsignedlongs;// previous time in usstaticbooleanrx_led=0;// monitors the valid PPM pulsespulse=t-s;// pulse length is usif(digitalRead(PPMIN_PIN)==LOW){if(pulse<500||pulse>2500)return;// error - out of valuerx_led=!rx_led;digitalWrite(RXLED_PIN,rx_led);if(pulse>=SWITCH1_PPM)switch1_enable=1;if(pulse>=SWITCH2_PPM)switch2_enable=1;if(pulse>=FLASH_PPM)flash_enable=1;if(pulse>=GLOW_PPM)glow_enable=1;if(pulse<=SWITCH1_PPM-DEADBAND)switch1_enable=0;if(pulse<=SWITCH2_PPM-DEADBAND)switch2_enable=0;if(pulse<=FLASH_PPM-DEADBAND)flash_enable=0;if(pulse<=GLOW_PPM-DEADBAND)glow_enable=0;}else{s=t;}}