arduino  RC Navy (2012)

Exemple asynchrone avec les librairies <SoftRcPulseIn> et <SoftRcPulseOut>:

Le sketch: l'arduino lit une impulsion RC d'un récepteur à l'aide d'un objet de type SoftRcPulseIn, inverse l'impulsion, recopie la commande directe vers un premier servo et la commande inversée vers un second servo, le tout en faisant clignotter une LED. Il montre également comment utiliser subtilement un tableau de 2 objets de type SoftRcPulseOut pour piloter les servos.
En cas de disparition des impulsions entrantes, les servos sont rafraichis toutes les 30 ms à la dernière position connue, ainsi, ils ne deviennent pas "mous".
L'utilisateur pourra vérifier que les servos tournent en sens inverse l'un de l'autre en effectuant la même course. Il pourra également tester la macro de moyennage avec les différentes valeurs proposées.

#include <SoftRcPulseIn.h>
#include <SoftRcPulseOut.h>
#include <TinyPinChange.h>

#define BROCHE_VOIE 2

#define BROCHE_SERVO1 3
#define BROCHE_SERVO2 4

#define BROCHE_LED 13

#define DEMI_PERIODE_LED_MS 250

#define IMPULSION_DELAI_MAX_MS 30 /* Pour rafraichir le servo si disparition des impulsions */

#define MAINTENANT 1

#define NEUTRE_US 1500

enum {NORMAL=0, INVERSE, NBR_SERVOS}; /* Astuce: une enumeration pour declarer les N° de servo ET par la meme occasion le nombre de servos */


SoftRcPulseIn ImpulsionVoie; /* ImpulsionVoie est un objet de type SoftRcPulseIn */
SoftRcPulseOut ServoMoteur[NBR_SERVOS]; /* Creation d'un tableau de 2 objets de type SoftRcPulseOut */

/* Declaration des valeurs possibles pour faire une moyenne glissante afin de lisser la mesure de largeur d'impulsion recue */
#define MOY_SUR_1_VALEUR 0
#define MOY_SUR_2_VALEURS 1
#define MOY_SUR_4_VALEURS 2
#define MOY_SUR_8_VALEURS 3
#define MOY_SUR_16_VALEURS 4

#define TAUX_DE_MOYENNAGE MOY_SUR_4_VALEURS /* Choisir ici le taux de moyennage parmi les valeurs precedentes possibles listees ci-dessus */
/* Plus le taux est élevé, plus le système est stable (diminution de la gigue), mais moins il est réactif */

/* Macro de lissage */
#define MOYENNE(Valeur_A_Moyenner,DerniereValeurRecue,TauxDeMoyEnPuissanceDeDeux) Valeur_A_Moyenner=(((Valeur_A_Moyenner)*((1<<(TauxDeMoyEnPuissanceDeDeux))-1)+(DerniereValeurRecue))/(1<<(TauxDeMoyEnPuissanceDeDeux)))

/* Variables */
uint32_t DebutChronoLedMs=millis();
uint32_t DebutChronoServoMs=millis();
boolean EtatLed=HIGH;


void setup()
{
#if !defined(__AVR_ATtiny24__) && !defined(__AVR_ATtiny44__) && !defined(__AVR_ATtiny84__) && !defined(__AVR_ATtiny25__) && !defined(__AVR_ATtiny45__) && !defined(__AVR_ATtiny85__)
Serial.begin(9600);
Serial.print("SoftRcPulseIn library V");Serial.print(SoftRcPulseIn::LibTextVersionRevision());Serial.print(" demo");
#endif
ImpulsionVoie.attach(BROCHE_VOIE);
ServoMoteur[NORMAL].attach(BROCHE_SERVO1); /* L'enumeration nous sert d'index pour le tableau */
ServoMoteur[INVERSE].attach(BROCHE_SERVO2);
/* L'enumeration nous sert d'index pour le tableau */
pinMode(BROCHE_LED, OUTPUT);
}

void loop()
{
static uint16_t Largeur_us=NEUTRE_US;

/* Gestion acquisition de l'impulsion du recepteur et commande des 2 servos, dont un en mouvement inverse */
if(ImpulsionVoie.available())
{
MOYENNE(Largeur_us,ImpulsionVoie.width_us(),TAUX_DE_MOYENNAGE);
ServoMoteur[NORMAL].write_us(Largeur_us); /* Signal direct */
ServoMoteur[INVERSE].write_us((NEUTRE_US*2)-Largeur_us);
/* Signal inverse */
SoftRcPulseOut::refresh(MAINTENANT); /* Permet de synchroniser les impulsions sortantes avec les impulsions entrantes */
DebutChronoServoMs=millis(); /* Relance Chrono */
#if !defined(__AVR_ATtiny24__) && !defined(__AVR_ATtiny44__) && !defined(__AVR_ATtiny84__) && !defined(__AVR_ATtiny25__) && !defined(__AVR_ATtiny45__) && !defined(__AVR_ATtiny85__)
Serial.print("Pulse=");Serial.println(Largeur_us);
#endif
}
else
{
/* Test de disparition des impulsions */
if(millis()-DebutChronoServoMs>=IMPULSION_DELAI_MAX_MS)
{
/* Raffraichit le servo avec la derniere position connue pour eviter qu'il ne soit "mou" */
SoftRcPulseOut::refresh(MAINTENANT); /* Permet la mise a jour immediate des impulsions sortantes */
DebutChronoServoMs=millis(); /* Relance Chrono Seervo */
}
}

/* Gestion du clignottement de la LED */
if(millis()-DebutChronoLedMs>=DEMI_PERIODE_LED_MS)
{
digitalWrite(BROCHE_LED, EtatLed);
EtatLed=!EtatLed; /* A la prochaine boucle, si la demi-periode est ecoulee, l'etat LED sera inverse */
DebutChronoLedMs=millis(); /* Rearme le Chrono LED */
}

}

Retour