Lettura canali R/C da ricevitore Futaba

Salve a tutti,

ho la necessità di controllare un servo usando Arduino Mini e un ricevitore radio Futaba. Devo leggere un canale dal ricevitore e regolare la velocità di rotazione del servo in modo proporzionale alla posizione dello stick del mio radiotrasmettitore (sto realizzando un supporto camera motorizzato per videoriprese).

Il problema è che quando leggo il canale dal ricevitore (sul pin 3) tramite la funzione pulseIn() rilevo dei valori molto oscillanti. Se ad esempio lascio lo stick della radio nella posizione centrale il valore che leggo è 1500us ma oscilla con valori di +/- 100/150 abbastanza casuali per cui diventa molto difficile poter comandare il servo con precisione.

Questo è il codice che ho scritto:

/* 
 * 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
 * 
 */  


// 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);

    // 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;
	}
    }
	
}

Vi è mai successo di avere questo tipo di problema con la pulseIn()? Qualche suggerimento?

Grazie

Nessun suggerimento?

Forse devi usare o l’interrupt oppure la pulse in ma non saprei proprio aiutarti… cè un articolo su gioblu… dagli un occhio…