Because i need high resolution (0.5µs) i wrote a sketch using TIMER4/5 with extern trigger on ICP-pin 48/49 evaluating the signal. That works really great for itself on a MEGA.
This is the sketch:
// Arduino CookBook 18.0
// https://www.inkling.com/read/arduino-cookbook-michael-margolis-2nd/chapter-18/recipe-18-8
// ICP1-Pin for UNO & Timer1: Pin 8
// ICP5-Pin for Mega & Timer5: Pin 48
#define NUM_OF_CHL 8 // we are working with an 8-ch-Transmitter
#define NUM_OF_AVG 3 // 3 added values for average
const int inputCapturePin = 48; // input pin fixed to internal Timer
const int prescale = 8; // prescale factor (each tick 0.5 us @16MHz)
const byte prescaleBits = B010; // pecision scale factor 8
const long precision = (1000000/(F_CPU/1000)) * prescale; // time per counter tick in ns
volatile int overflows = 0;
volatile long valuesInt[9] = {0};
volatile long valuesUse[9] = {0};
volatile byte counter = NUM_OF_CHL;
volatile byte average = NUM_OF_AVG;
volatile boolean ready = false;
long timelastloop;
/* Overflow interrupt vector */
ISR(TIMER5_OVF_vect) // here if no input pulse detected
{
overflows++; // increment overflow count
}
/* ICR interrupt vector */
ISR(TIMER5_CAPT_vect)
{
TCNT5 = 0; // reset the counter
if( bitRead(TCCR5B ,ICES5) == true) // wait for rising edge
{
long time = ICR5 + (overflows * 65536); // save the input capture value
overflows = 0;
time = time * precision / 1000; // time in ms
if (time > 2500) // this is a gap between set of pulses
{
valuesInt[8] = valuesInt[8] + time;
counter = 0;
if (average == NUM_OF_AVG)
{ for (int i = 0; i < NUM_OF_CHL + 1; i++)
{
valuesUse[i] = (valuesInt[i] + 0.5) / average;
valuesInt[i] = 0;
}
average = 0;
ready = true;
}
average++;
}
else
{ if (counter < NUM_OF_CHL)
{
valuesInt[counter] = valuesInt[counter] + time;
counter++;
}
}
}
}
void setup()
{
Serial.begin(115200);
Serial.println(F("Start reading PPM-Signal from Remote-Control"));
Serial.print( precision); // report duration of each tick in nanoseconds
Serial.println(F(" nanoseconds per tick"));
pinMode(inputCapturePin, INPUT_PULLUP); // ICP pin (digital pin 8 on Arduino/48 on Mega) as input
TCCR5A = 0 ; // Normal counting mode
TCCR5B = prescaleBits ; // set prescale bits
TCCR5B |= _BV(ICES1); // enable input capture
TIMSK5 = _BV(ICIE1); // enable input capture interrupt for timer 1
TIMSK5 |= _BV(TOIE1); // enable overflow interrupt
timelastloop = micros(); // measure loop-time with "standard" micros()
}
void loop()
{
if (ready)
{
long timenew = micros();
Serial.print(timenew - timelastloop); Serial.print(F(" | "));
for (int i = 0; i < NUM_OF_CHL + 1; i++)
{
Serial.print(valuesUse[i]);
if (i < 8) Serial.print(F(" - "));
}
Serial.println();
ready = false;
timelastloop = timenew;
}
}
These are the resulting timings:
Start reading PPM-Signal from Remote-Control
496 nanoseconds per tick
1356 | 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 11127
67464 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67412 | 1384 - 1388 - 1505 - 1402 - 940 - 1505 - 1500 - 1501 - 11120
67416 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67424 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67424 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67432 | 1384 - 1390 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11119
67416 | 1384 - 1388 - 1505 - 1402 - 940 - 1505 - 1501 - 1501 - 11120
67424 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67416 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67424 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67424 | 1384 - 1389 - 1505 - 1402 - 940 - 1505 - 1500 - 1501 - 11120
67424 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11118
67420 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67424 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67420 | 1384 - 1390 - 1505 - 1401 - 940 - 1505 - 1500 - 1501 - 11120
67424 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67412 | 1384 - 1388 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67432 | 1383 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67424 | 1384 - 1390 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67424 | 1384 - 1388 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67416 | 1384 - 1386 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67416 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
67424 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1500 - 1501 - 11120
67424 | 1384 - 1389 - 1505 - 1401 - 940 - 1505 - 1501 - 1501 - 11120
and so forth
Afterwards i want to drive a servo with that readed values and used simple code like shown in servo-demo shown here:
http://arduino.cc/en/Tutorial/Knob or http://arduino.cc/en/Tutorial/Sweep
Stand alone it works as expected - when i combine the demo-code with my sketch, servo is also driven as wanted.
But some curious behaviour occurs:
The servo is dithering, shaking ! Looks like as it is supplied with AC with approx. 10-20 Hz.
This behaviour remains until i disconnect the PPM-signal from Pin 48/49.
Remember: Driving the servo alone with the Demo works fine.
I commented out serval lines in the servo-lib so that only timer5 or 4 used and that its not the same used by the reading-routine.
No change.
Also i can use the simple demo-code alone with none of my code above:
Soon as i connect the PPM-signal to pin 48 or 49, the servo is rambling over the desk ....
Doesn't matter what i try .... problem of dithering, shaking servo still remains.
Does anyone have a solution or idea why this happens ?