Hello,
I'm using a teensy 2.0 board( amtel MEGA32U4) to receive 4 channels signals from a 40Mhz futaba RC receiver. I've tried pulsein and interrupt methods which are working great but in both cases, my values are jittering.
I've read many subjects on this forum but did not find the clue. For the moment I've put an averaging algorythm in place but it slow down a lot my program as I need several valid inputs to average. And with that it still jittering !
Any help would be really appreciated
Here is an example of the input values that I get on Channel 1 (other are jittering the same and are always multiple of 4) :
rc1_val raw: 1540
rc1_val raw: 1540
rc1_val raw: 1540
rc1_val raw: 1512
rc1_val raw: 1512
rc1_val raw: 1512
rc1_val raw: 1512
rc1_val raw: 1512
rc1_val raw: 1512
rc1_val raw: 1512
rc1_val raw: 1536
rc1_val raw: 1536
rc1_val raw: 1536
rc1_val raw: 1536
rc1_val raw: 1536
rc1_val raw: 1536
rc1_val raw: 1536
rc1_val raw: 1520
rc1_val raw: 1520
rc1_val raw: 1520
rc1_val raw: 1520
rc1_val raw: 1520
Here is the code I use with the 4 interrupt pins (found on this forum) :
//read PPM signals from 2 channels of an RC reciever and convert the values to PWM in either direction.
// digital pins 5 & 9 control motor1, digital pins 6 & 10 control motor2. DP 12 and 13 are neutral indicator lights. DP 2 and 3 are inputs from the R/C receiver. All analog pins are open. When motor pin is HIGH, bridge is open. All mosfets are pulled up/down to stay closed unless told to open.
unsigned long time; // variable de mémorisation du temps écoulé
unsigned long timeold ;// au cycle précédent; // variable de mémorisation du temps écoulé
float timediff; //temps du cycle écoulé
int motor1_a = 7;
int motor1_b = 8;
int motor2_a = 9;
int motor2_b = 10;
//Neutral indicator LED's (FWD and REV LED's are on the motor driver board.
int ledPin1 = 12;
int ledPin2 = 13;
int ppm1 = 5; // connect the desired channel (PPM signal) from your RC receiver to digital pin 2 on Arduino.
int ppm2 = 6;
int ppm3 = 7; // connect the desired channel (PPM signal) from your RC receiver to digital pin 2 on Arduino.
int ppm4 = 8;
unsigned long rc1_PulseStartTicks;
volatile int rc1_val; // store RC signal pulse length
int lastgood1;
int adj_val1; // mapped value to be between 0-511
int rc1_InputReady;
unsigned long rc2_PulseStartTicks;
volatile int rc2_val; // store RC signal pulse length
int lastgood2;
int adj_val2; // mapped value to be between 0-511
int rc2_InputReady;
unsigned long rc3_PulseStartTicks;
volatile int rc3_val; // store RC signal pulse length
int lastgood3;
int adj_val3; // mapped value to be between 0-511
int rc3_InputReady;
unsigned long rc4_PulseStartTicks;
volatile int rc4_val; // store RC signal pulse length
int lastgood4;
int adj_val4; // mapped value to be between 0-511
int rc4_InputReady;
int deadband_high = 265; // set the desired deadband ceiling (ie. if adj_val is above this, you go forward)
int deadband_low = 245; // set deadband floor (ie. below this, go backward)
int pwm_ceiling = 256; // adjusts speed of PWM signal at turn-on
int pwm_floor = 254;
int delta_val = 400; //this value sets the range for discarding unwanted signals.
void setup() {
Serial.begin(9600);
//led's
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
//PPM inputs from RC receiver
pinMode(ppm1, INPUT); //Pin 2 as input
pinMode(ppm2, INPUT); //Pin 3 as input
pinMode(ppm3, INPUT); //Pin 2 as input
pinMode(ppm4, INPUT); //Pin 3 as input
attachInterrupt(0, rc1, CHANGE); // catch interrupt 0 (digital pin 2) going HIGH and send to rc1()
attachInterrupt(1, rc2, CHANGE); // catch interrupt 1 (digital pin 3) going HIGH and send to rc2()
attachInterrupt(2, rc3, CHANGE); // catch interrupt 0 (digital pin 2) going HIGH and send to rc1()
attachInterrupt(3, rc4, CHANGE); // catch interrupt 1 (digital pin 3) going HIGH and send to rc2()
lastgood1 = 255;
lastgood2 = 255;
lastgood3 = 255;
lastgood4 = 255;
}
void rc1()
{
// did the pin change to high or low?
if (digitalRead( ppm1 ) == HIGH)
{
// store the current micros() value
rc1_PulseStartTicks = micros();
}
else
{
// Pin transitioned low, calculate the duration of the pulse
rc1_val = micros() - rc1_PulseStartTicks; // may glitch during timer wrap-around
// Set flag for main loop to process the pulse
rc1_InputReady = true;
}
}
void rc2()
{
// did the pin change to high or low?
if (digitalRead( ppm2 ) == HIGH)
{
// store the current micros() value
rc2_PulseStartTicks = micros();
}
else
{
// Pin transitioned low, calculate the duration of the pulse
rc2_val = micros() - rc2_PulseStartTicks; // may glitch during timer wrap-around
// Set flag for main loop to process the pulse
rc2_InputReady = true;
}
}
void rc3()
{
// did the pin change to high or low?
if (digitalRead( ppm3 ) == HIGH)
{
// store the current micros() value
rc3_PulseStartTicks = micros();
}
else
{
// Pin transitioned low, calculate the duration of the pulse
rc3_val = micros() - rc3_PulseStartTicks; // may glitch during timer wrap-around
// Set flag for main loop to process the pulse
rc3_InputReady = true;
}
}
void rc4()
{
// did the pin change to high or low?
if (digitalRead( ppm4 ) == HIGH)
{
// store the current micros() value
rc4_PulseStartTicks = micros();
}
else
{
// Pin transitioned low, calculate the duration of the pulse
rc4_val = micros() - rc4_PulseStartTicks; // may glitch during timer wrap-around
// Set flag for main loop to process the pulse
rc4_InputReady = true;
}
}
void loop() {
//////////////////////////////////signal1
if (rc1_InputReady)
{
// reset input flag
rc1_InputReady = false;
// constrain and map the pulse length
adj_val1 = map(constrain(rc1_val, 1000, 2000), 1000, 2000, 0, 511);
if (adj_val1 == 0){ // if value is 0, use last good value
adj_val1 = lastgood1;
}
else if (adj_val1 == 511){ // if value is 511, use last good value
adj_val1 = lastgood1;
}
else if (((adj_val1 - lastgood1) * 2) > delta_val){ // make sure the new value is within a reasonable range of the last known good value.
adj_val1 = lastgood1;
}
else {
lastgood1 = adj_val1; // if all conditions are met, use new value and set it as lastgood1 value.
}
}
//////////////////////////////////signal2
if (rc2_InputReady)
{
// reset input flag
rc2_InputReady = false;
// constrain and map the pulse length
adj_val2 = map(constrain(rc2_val, 1000, 2000), 1000, 2000, 0, 511);
if (adj_val2 == 0){ // if value is 0, use last good value
adj_val2 = lastgood2;
}
else if (adj_val2 == 511){ // if value is 511, use last good value
adj_val2 = lastgood2;
}
else if (((adj_val2 - lastgood2) * 2) > delta_val){ // make sure the new value is within a reasonable range of the last known good value.
adj_val2 = lastgood2;
}
else {
lastgood2 = adj_val2; // if all conditions are met, use new value and set it as lastgood1 value.
}
}
//////////////////////////////////signal3
//removed due to message size on forum
//////////////////////////////////signal4
//removed due to message size on forum
// Mesure du temps de cycle
time = micros();
timediff = ((time - timeold)) ; // calcul différence de temps et conversion en fréquence
timeold = time;
// Serial.print(" Temps cycle : ");
// Serial.println(timediff);
//print values
Serial.print("channel 1: ");
Serial.print(adj_val1);
Serial.print(" ");
Serial.print("rc1_val raw: ");
Serial.print(rc1_val);
Serial.print(" ");
Serial.print("channel 2: ");
Serial.print(adj_val2);
Serial.print(" ");
Serial.print("rc2_val raw: ");
Serial.print(rc2_val);
Serial.print(" ");
Serial.print("channel 3: ");
Serial.print(adj_val3);
Serial.print(" ");
Serial.print("rc3_val raw: ");
Serial.print(rc3_val);
Serial.print(" ");
Serial.print("channel 4: ");
Serial.print(adj_val4);
Serial.print(" ");
Serial.print("rc4_val raw: ");
Serial.print(rc4_val);
Serial.println(" ");
}