Servo control and R/C from Futaba

Hello,

I need to control the speed of a standard servo (not continuous) using Arduino and a R/C radio. I found a lot of example on the web but in most of cases are not suitable for my case.

My need is to control the speed of the servo proportionally to the stick movement, and the idea is to increase PWM width proportionally to the stick angle in order to move the servo until it arrives to the min/max position or the stick turns to center position.

The problem is reading the R/C PWM using pulseIn() function, it returns a value that have a lot of fluctuation. For example, if the stick of the radio is in the center position I read 1500 (correct value) but casually it changes to +/- 100-150 then can back to 1500.

How can I read R/C stable value?

This is my code:

/* 
 * ServoGimbal
 * ----------- 
 * Controllo della velocità del servo tramite R/C 
 * 
 * Gestione del tilt della camera usando la variazione di velocit? del 
 * servo, con incrementi dell'ampiezza del segnale PWM in funzione
 * della psizione dello stick della radio
 * 
 * Read pulse from pin 3
 * Output pulse on pin 9
 * be sure to tie grounds together
 * Delay 20 to make serial output easier to read
 * serial output is just to monitor the control signal
 *
 * Created 8 luglio 2011
 * Omar Morando
 * 
 */  


// Include della libreria di gestione del servo  
#include <Servo.h>


// Parametri globali per il setup delle funzioni
int radioPin       = 3;    	// pin a cui è collegato il ricevitore della radio Futaba
int servoPin       = 9;   	// pin a cui è collegato il servo  
int minPulse       = 1050;  // minimum servo position
int maxPulse      = 1950; 	// maximum servo position  
int turnRate       = 10;  	// velocità di movimento del servo (larger value, faster rate)  
int refreshTime  = 20;   	// intervallo (ms) tra gli impulsi (50Hz)  
int lastPosition    = 1500;	// ultima posizione del servo
int centerPosition = 1500;	// posizione di riposo del servo
int deltaPosition  = 0;		// differenza tra
int writePosition  = 1500;	// posizione da scrivere nel servo
unsigned long radioValue = 0;   // variabile usata per la scalatura del valore numerico letto dallo stick

Servo servoGimbal;		// Oggetto servo a velocità variabile per il controllo del tilt

#define DELTA_VALUE	10	// tolleranza del valore letto dalla radio
#define STEP_VALUE	10	// valore per il calcolo della proporzione con la posizione dello stick


// *************************************************************************
// Funzione di setup
// *************************************************************************
void setup() 
{

	// Definisco l'ingresso per la lettura del PWM della radio
	pinMode(radioPin,INPUT);
	
	// Definisco l'uscita per il comando del servo
	servoGimbal.attach(servoPin); 

	// Inizializzo le variabili
	centerPosition = 1500;
	writePosition = centerPosition;
	
	// Muovo il servo nella posizione di default
	servoGimbal.writeMicroseconds(centerPosition);

}


// *************************************************************************
// Main loop Arduino
// *************************************************************************
void loop () 
{

    // Leggo il valore dello stick della radio
    radioValue = pulseIn(radioPin, HIGH);     // <== value has fluctuation

    // Calcolo la differenza tra la posizione dello stick e quella centrale
    deltaPosition = int(radioValue) - centerPosition;

    // Se la differenza è maggiore del valore di tolleranza entro nella routine di comando del servo
    if (abs(deltaPosition) > DELTA_VALUE)
    {
	// Calcolo il valore di turnRate in modo proporzionale alla posizione dello stick
	turnRate = int(deltaPosition / STEP_VALUE);
		
	// Se il valore è positivo muovo il servo in avanti altrimenti decremento l'angolo del servo
        if (deltaPosition > 0)
            writePosition += turnRate;
        else
            writePosition -= turnRate;
		
	// Se il valore del movimento ? compreso nel range di minimo e massimo scrivo nel servo
	if (writePosition > minPulse && writePosition < maxPulse)
	{
	    // Muovo il servo
	    servoGimbal.writeMicroseconds(writePosition);
			
	    // Aggiorno la posizione attuale del servo
	    lastPosition = writePosition;
	}
	else
	{
	    // Scrivo la posizione attuale del servo nella variabile di scrittura per annullare l'effetto
	    // dell'incremento del turnRate nel caso abbia raggiunto i limiti min e max del servo
	    writePosition = lastPosition;
	}
    }
	
}

One thing to try is increasing DELTA_VALUE to 150, then it won't move during the fluctuations. another is to calculate a moving average so the change in reading is reduced:

radioValue = (radioValue *9 + pulseIn(radioPin, HIGH))/10;

wildbill: One thing to try is increasing DELTA_VALUE to 150, then it won't move during the fluctuations. another is to calculate a moving average so the change in reading is reduced:

radioValue = (radioValue *9 + pulseIn(radioPin, HIGH))/10;

Thanks for your good suggestion, I will try it tomorrow. Only to understand, is it normal to have a lot of fluctuations reading R/C with pulseIn?