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