I have an arduino project I am working on that involves reading a ppm stream from a receiver and spitting out servo control.
In between there is some GPS goodness to act as a RTH.
This is a personal project I'm doing for fun, I already have OSDs I like and don't fell like spending $200+ for a full OSD RTH fancy thing when all I want to something very simple. For use in rc cars, gliders etc that only require steering or the rudder to turn, things like that.
Anywho the reason I have come and asked for help, I have ppm decoding (using timer 1) and I was planning on using the servotimer2 library for driving my servos but these 2 bits of code don't play nice together. Although it works, every ~30s or so all the outputs glitch (I suspect they all drop to 1000 or 0, ether way the throttle cuts for a moment and servos twitch.) which makes it non usable (on servos the effect is almost unnoticeable but on esc's/motors the effect is rather dramatic). All the ppm decoding code I have found uses timer 1 so that can't change, the servo library built into arduino can't be used as it uses timer 1 and software servo is less then ideal as well.
I'm trying to stick with using a 328 as I have a number of them and they are cheap, I could use a 2560 as it has extra timers that could be used to drive servos with the default library but this is a lazy method and costs considerably more. I also fly multicopters and as shown by multiwii 328s are capable of doing the above job + alot more so it is possible, but maybe not with such simple code.....
I have tried multiple sets of hardware so can rule that out.
I have also constructed this very minimal code snipit to test the bare ppm in servo out functions together, before this I thought it could have been the GPS code casing the issues.
Talking to a friend he suspects that there is a clash between the 2 timers that cases this issue.
Looking at the inputs and outputs with serial prints shows nothing out of the ordinary, without getting the scope out it is otherwise hard to narrow the problem down more, I have reached the limit of my skill set for the time.
If anyone has run into something similar or has an idea of whats happening that'd be great.
Thanx Hadley
// libraries
#include <ServoTimer2.h>
// pins for servos
#define rollPin 3
#define throttlePin 7
// declare variables for servos
ServoTimer2 servoRoll;
ServoTimer2 servoThrottle;
//*************ppm capture variables*****************
#define ICP_PIN 8 // this interrupt handler must use pin 8
#define TICKS_PER_uS 2 // counter increments by two counts each microsecond (at 16mhz)
#define SYNC_GAP_LEN 3000 // synch gap 3000 microseconds long
volatile unsigned int pulses[9]; // array holding channel pulses width value in microseconds
volatile uint8_t channel = 1; // number of channels detected so far in the frame (first channel is 1)
//*********************timer for ppm stream receiving*************************************
ISR(TIMER1_CAPT_vect){
if( bit_is_set(TCCR1B ,ICES1)){ //rising edge detected because bit ICES1=1
}
else{ //falling edge detected]
TCNT1 = 0; // reset the counter
if(ICR1 > SYNC_GAP_LEN*TICKS_PER_uS){
channel = 1;
}
else{
pulses[channel++] = ICR1/TICKS_PER_uS;
}
}
TCCR1B ^= _BV(ICES1); // toggle bit ICES1 to trigger on the other edge
}
//*********************************************************************************************
void setup(){
Serial.begin(38400);
//Comfigure ppm stream in on pin 8
pinMode(ICP_PIN,INPUT);
TCCR1A = 0x00; // COM1A1=0, COM1A0=0 => Disconnect Pin OC1 from Timer/Counter 1 -- PWM11=0,PWM10=0 => PWM Operation disabled
TCCR1B = B00000010; //0x02; // 16MHz clock with prescaler means TCNT1 increments every .5 uS (cs11 bit set
TIMSK1 = _BV(ICIE1); // enable input capture interrupt for timer 1
// attach a pin to the servos and they will start pulsing
servoRoll.attach(rollPin);
servoThrottle.attach(throttlePin);
}
//************************************************************************************************
void loop(){
//Write values to outputs
servoRoll.write(pulses[1]);
servoThrottle.write(pulses[2]);
}