Pilotage d’un servomoteur de modélisme

Le but du projet sera de piloter un servomoteur ou « servo » de modèle réduit.

1.1.1        La théorie

Le servo de modèle réduit est un moteur qui est capable de se positionner à un angle compris entre 0 et 180° et d’y rester. Il sert à faire varier la position d’un élément dans un modèle réduit (gouvernail de bateau, direction de voiture ou aileron d’avion par exemple)

Pour fonctionner correctement, un servo devrait avoir un signal de fréquence 50Hz, c’est-à-dire qui se répète toutes les 20ms constitué d’une impulsion à l’état haut de 1 à 2ms, le reste étant à l’état bas.

Si l’impulsion fait 1ms, le servo se mettra à 0°, si l’impulsion fait 2ms, il se mettra à 180° et il prendra toutes les positions intermédiaires entre 1 et 2 ms

Ça, c’est pour la théorie, en pratique, les servos ne tourne pas tout à fait de 180° et les impulsions ne doivent pas être entre 1 et 2ms, ça peut varier en fonction des modèle de servos et même sur les mêmes modèles en fonction de la tolérance des composant électroniques de commande.

Attention : certains servos dit servo treuil, tel le DM-S0306D n’ont pas de buté et tourne comme un moteur. La commande fait varier simplement la vitesse du servo.

Les servos sont plutôt robuste, mais si on les commandes mal, on force le moteur et les engrenages, ce qui n’est jamais très bon pour la durée de vie. De plus, si la largeur de l’impulsion n’est pas bien calibrée, ils ont tendance à vibrer ce qui n’est pas très bon pour le maintien de la position.

La question est comment allons-nous faire le signal que le servo attend ?

En fait, on a déjà fait des signaux de ce type, c’est du PWM dans toute sa splendeur.

Dans les précédents montages utilisant le PWM, on avait juste fait varier le rapport cyclique, un peu « au pif » pour faire varier la luminosité de notre LED. Ici, il va falloir être beaucoup plus précis.

Dans un premier temps, on va donc faire un petit montage et un programme qui va permettre de calibrer les servos. Avant de les mettre dans un montage type robot ou grue par exemple, il faudra les calibrer pour éviter qu’ils ne vibrent et pour qu’ils soient les plus précis possible.

1.1.2        L’électronique

Un connecteur de servos comporte 3 broches, une alimentation, une masse et notre signal PWM.

Comment alimente-t-on un servo ?

Prenons par exemple un servo archi-standard, le Futaba S3003 dont voici la fiche technique.

Que voit-on ? Il y a principalement trois choses qui nous intéressent.

-          Required Pulse : on peut le commander entre 3 et 5V, le 3.3 V de notre PWM devrait suffire.

-          Operating Voltage : Il va falloir l’alimenter entre 4.8 et 6V

-          Current Drain : Le courant à vide est entre 7.2mA et 8mA, par contre, il peut monter très vite avec la charge qui peut monter à 4.1kg/cm pour 6V

Donc, qu’allons-nous faire pour l’alimenter ? Il y a bien le 5V de notre Raspberry qui doit pouvoir fournir les 7 à 8mA, mais si on le charge, que se passera-t-il ?

Sur internet, on trouve beaucoup de sites où ils alimentent le servo par le 5V du Raspberry. C’est à mon avis une très mauvaise idée pour les raisons suivante :

-          On ne sait pas combien de courant on va consommer sur le 5V. Si le courant est trop fort, on risque de faire chuter la tension pour le Raspberry et il va rebooter sans prévenir.

-          Au démarrage, les moteurs font un fort appel de courant qui risque là aussi de faire rebooter le Raspberry

-          L’alimentation du Raspberry n’est pas faite pour alimenter des moteurs et les appels de courant peuvent l’endommager.

-          Un moteur engendre beaucoup de parasites qui vont se retrouver sur l’alimentation du Raspberry et par conséquent sur les composants du Raspberry lui-même. Ces circuits ne sont pas conçus pour absorber ces parasites, ça risque de les perturber, voire de les endommager.

Donc, vous avez dû le comprendre, je préconise une alimentation externe pour le servo, soit une alimentation stabilisée, soit un bloc de piles ou de batterie.

Pour le montage, la seule chose dont nous ayons besoin est de 3 picots qui vont permettre de connecter la prise femelle du servo.

Afficher l'image d'origine


 

Suivant les marques des servos, le câblage est le suivant :

Il faudra mettre nos piles ou notre alimentation sur le + et le – et mettre notre GPIO18 (PWM) sur le fil de signal et surtout, ne pas oublier de relier les masses du Raspberry et de l’alimentation.

Voici le schéma.


 

1.1.3        Un logiciel de calibration des servos

Maintenant qu’on a notre schéma, on va passer à la programmation :

Quelques questions se posent :

-          Comment programmer la fréquence de notre PWM ? On a vu qu’il nous faut 20ms entre les impulsions, soit 1/0.02 = 50Hz

-          Comment programmer finement la largeur de notre impulsion ?

Pour la fréquence de notre PWM, en cherchant sur notre ami Google, on finit par trouver que l’horloge de base du PWM est de 19.2 MHz, j’ai cherché dans pas mal de documentation sur le Raspberry et je n’ai pas trouvé cette info.

On doit ensuite programmer le diviseur d’horloge de notre PWM et le nombre de pas que l’on veut avoir.

Par défaut, le pas est au maximum à 1024. Le pas permet de donner la finesse de l’impulsion, il va diviser le signal de 20ms en 1024 pas et en mettre un certain nombre à 1 pour générer l’impulsion.

Pour notre diviseur on va devoir mettre 19200000 / 1024 / 50 = 375.

Les instructions WiringPi pour programmer ça sont pwmSetClock(375) et pwmSetRange(1024);

Voici le programme pour tester le rapport cyclique des servomoteurs.

#include <iostream>        // Include pour affichage et clavier

#include <wiringPi.h> // Include WiringPi library!

 

using namespace std;

 

// Pin number declarations. We're using the Broadcom chip pin numbers.

const int pwmPin = 18; // PWM LED - Broadcom pin 18, P1 pin 12

 

int pwmValue = 0; // Use this to set an LED brightness

 

int main(void)

{

    // Setup stuff:

    wiringPiSetupGpio(); // Initialize wiringPi -- using Broadcom pin numbers

 

    pinMode(pwmPin, PWM_OUTPUT); // Set PWM LED as PWM output

       pwmSetMode(PWM_MODE_MS);

       pwmSetClock(375);

       pwmSetRange(1024);

    cout << "PWM is running! Press CTRL+C to quit" << endl;

 

    // Loop (while(1)):

    while(1)

    {

             cout << "Rapport cyclique actuel: " << pwmValue << endl;

             cout << "Rapport cyclique désiré: ";

             cin >> pwmValue;

             pwmWrite(pwmPin, pwmValue); // Entre 0 et 1024

    }

 

    return 0;

}


 

On donne le rapport cyclique désiré et notre servo va tourner pour se mettre dans la position demandé.

Par exemple, j’ai testé avec plusieurs servos différents et j’obtiens les valeurs suivantes :

Modèle

Rapport cyclique min (plus proche du 0°)

Largeur d’impulsion min (ms)

Rapport cyclique max (plus proche du 180°)

Largeur d’impulsion max (ms)

Remarque

T2M TS-301

24

0.468

121

2.363

Servo standard

Futaba S3003

19

0.371

119

2.324

Servo standard

Futaba S3305

21

0.41

126

2.46

Servo à couple important

Robbe FS40 Pico

27

0.527

127

2.48

Micro servo

T2M TS-301 monté dans un véhicule 4x4

47

0.918

106

2.07

Rapport min et max imposés par le montage mécanique des roues

 

Cela impose pas mal de remarque :

-          Les temps d’impulsion réels pour un servo sont plutôt de 0.4ms à 2.4ms.

-          Les temps d’impulsion théoriques de 1 à 2ms semblent plutôt imposés par la mécanique des modèles réduits. D’ailleurs en regardant de plus près, le débattement des roues, d’un gouvernail ou d’un aileron est plus proche de 90° que de 180°

-          Dès qu’on sort des valeurs utilisables, le servo à tendance à vibrer et à forcer sur sa mécanique.

-          Certains servos comme le S3305 à fort couple ne peuvent pas passer de leur valeur min à leur valeur max d’un coup, il faut leur donner des valeurs intermédiaires.

Pour vérifier tout ça on va réutiliser notre petit oscilloscope sur tableur afin d’avoir la courbe réelle généré par le PWM.

Pour que cela fonctionne, branchez la GPIO18 sur la voie 7 du convertisseur

Pour ça, on va faire un petit programme qui mixe les programmes de gestion du servo et de l’oscilloscope sur tableur.

#include <iostream>        // Include pour affichage et clavier

#include <wiringPi.h> // Include WiringPi library!

#include <wiringPiSPI.h>

#include <linux/spi/spidev.h>

#include <stdint.h>

 

#include "mcp3208.h"

 

using namespace std;

 

// Pin number declarations. We're using the Broadcom chip pin numbers.

const int pwmPin = 18; // PWM LED - Broadcom pin 18, P1 pin 12

 

int pwmValue = 20; // Valeur cyclique à tester

 

int main(void)

{

    // Setup stuff:

    wiringPiSetupGpio(); // Initialize wiringPi -- using Broadcom pin numbers

 

    pinMode(pwmPin, PWM_OUTPUT); // Set PWM as PWM output

       pwmSetMode(PWM_MODE_MS);

       pwmSetClock(375);

       pwmSetRange(1024);

       pwmWrite(pwmPin, pwmValue); // Entre 0 et 1024

    wiringPiSPISetup (channel1, SPI_SPEED_33);

      

       cout << "temps;valeur" << endl;

       // Mesure le plus vite possible

       while(1){

             cout << clock() << ";" << conversion_mcp3208(channel1, voie_7) << endl;

       }

 

    return 0;

}

 

Ce programme fixe la valeur du rapport cyclique et lance tout une série de mesure qu’il faut envoyer dans un fichier.

Comme d’habitude, on compile « g++ -o servo_oscillo servo_oscillo.cpp -l wiringPi » et on lance en redirigeant dans un fichier csv « sudo ./servo_oscillo >servo20.csv »

On le laisse tourner quelques secondes puis un arrêt avec un CTRL-C.

Comme pour l’oscilloscope, on va générer la courbe dans le tableur.

J’ai pris la courbe avec 2000 valeurs en plein milieu du fichier (Ne pas prendre au début car le PWM met quelques impulsions à bien se mettre en place)


 


Courbe avec un rapport cyclique à 20

 


Courbe avec un rapport cyclique à 120

 


Voici quelques informations sur les courbes :

-          Sur la courbe du rapport cyclique à 20

J’ai pris un point quelconque représentant un début d’impulsion et une fin d’impulsion

La largeur d’impulsion est donc d’environ =0.000396s soit 0.396ms

En prenant également le début d’impulsion suivant, nous allons avoir la fréquence de répétition.

Soit un temps entre deux impulsion de (889163-869159)/1000000= 0,020004 soit un tout petit peu plus de 20ms, ce qui donne une fréquence de 1/T=49.99Hz, ce qui est excellent pour les 50Hz visé.

-          Sur la courbe du rapport cyclique à 120

J’ai pris un point quelconque représentant un début d’impulsion


 

Et une fin d’impulsion

La largeur d’impulsion est donc d’environ =0.002363s soit 2.363ms

En prenant également le début d’impulsion suivant, nous allons avoir la fréquence de répétition.

Soit un temps entre deux impulsion de (897592-)/1000000= 0,020056 soit là encore un tout petit peu plus de 20ms, ce qui donne une fréquence de 1/T=49.86Hz.

Malgré quelques petites erreurs dues à la fréquence d’échantillonnage, nos mesures sont plutôt justes et donnent une très bonne idée de la réalité qui est assez loin de la théorie que l’on trouve partout.

 


 

1.1.4        Le logiciel

Comme c’est notre but, on va faire un petit programme qui fera tourner le servomoteur.

On va surtout en profiter pour faire une jolie classe qui gèrera le PWM et une autre pour le servo.

/*

 * GestionPwm.h

 *

 *  Created on: 14 août 2016

 *      Author: totof

 */

 

#ifndef GESTIONPWM_H_

#define GESTIONPWM_H_

 

// Classe de gestion du PWM

class GestionPWM

{

public:

    GestionPWM();

    void init();

    int mode(int mode);

    int diviseur(int diviseur);

    int precision(int nbValeur);

    int write(int valeur);

    virtual ~GestionPWM();

 

private:

    int range = 1024;

};

 

#endif /* GESTIONPWM_H_ */


 

/*

 * GestionPWM.cpp

 *

 *  Created on: 1 août 2016

 *      Author: totof

 */

 

#include <wiringPi.h>

#include "GestionPWM.h"

 

#define diviseurMax 4096

#define precisionMax 1024

#define pwmPin 18 // PWM LED - Broadcom pin 18, P1 pin 12

 

// ***************************

// Constructeur

// Initialise le PWM en sortie

// ***************************

GestionPWM::GestionPWM()

{

}

 

// *********************

// Initialisation du pwm

// *********************

void GestionPWM::init()

{

    pinMode(pwmPin, PWM_OUTPUT);

}

// ***************************************

// Applique le mode du PWM

// @param pMode le mode

// @return 0 si OK -1 si KO (mode inconnu)

// ***************************************

int GestionPWM::mode(int pMode)

{

    int valRetour;

    switch(pMode)

    {

    case PWM_MODE_BAL:

    case PWM_MODE_MS:

        pwmSetMode(pMode);

        valRetour = 0;

        break;

    default:

        valRetour = -1;

    }

    return(valRetour);

}

 

// ***********************************************

// Le diviseur de fréquence de l'horloge

// @param pDiviseur la valeur du diviseur

// @return 0 si OK -1 si diviseur hors possibilite

// ***********************************************

int GestionPWM::diviseur(int pDiviseur)

{

    if(pDiviseur < diviseurMax)

    {

        pwmSetClock(pDiviseur);

        return(0);

    }

    else

    {

        return(-1);

    }

}

 

// **************************************************

// Précision du PWM

// @param pNbValeur le nombre de pas pour une periode

// @return 0 si OK -1 si nombre hors possibilite

// **************************************************

int GestionPWM::precision(int pNbValeur)

{

    if(pNbValeur <= precisionMax)

    {

        range = pNbValeur;

        pwmSetRange(pNbValeur);

        return(0);

    }

    else

    {

        return(-1);

    }

}

 

// ***************************************************

// Nombre de pas à l'état haut du PWM pour une période

// @param nombre de pas

// @return 0 si OK -1 si valeur hors possibilite

// ***************************************************

int GestionPWM::write(int pValeur)

{

    if(pValeur <= range)

    {

        pwmWrite(pwmPin, pValeur);

        return(0);

    }

    else

    {

        return(-1);

    }

}

 

// ****************

// Désactive le pwm

// ****************

GestionPWM::~GestionPWM()

{

    pinMode(pwmPin, INPUT);

}


 

/*

 * GestionServo.h

 *

 *  Created on: 14 août 2016

 *      Author: totof

 */

 

#ifndef GESTIONSERVO_H_

#define GESTIONSERVO_H_

 

#include "GestionPWM.h"

 

// Classe de gestion d'un servomoteur

class GestionServo

{

public:

    GestionServo(int pCycleMin, int pCycleMax);

    GestionServo(int pCycleMin, int pCycleMax, int pAngleDebattement);

    void init();

    int getCycleMin();

    int getCycleMax();

    int getAngleDebattement();

    int move(int pValeur);

    int move(float pAngle);

    int getValeur();

    float getAngle();

    int isInitError();

    virtual ~GestionServo();

 

private:

    void initCycles(int pCycleMin, int pCycleMax);

    int cycleMin;

    int cycleMax;

    int angleDebattement;

    int valeur = -1;

    float angle = -1.0;

    GestionPWM pwm;

    bool initError = false;

};

 

#endif /* GESTIONSERVO_H_ */


 

/*

 * GestionServo.cpp

 *

 *  Created on: 1 août 2016

 *      Author: totof

 */

 

#include <wiringPi.h>

#include "GestionPWM.h"

#include "GestionServo.h"

 

#define DIVISEUR 375

#define RANGE 1024

#define ERROR -1

#define DEBATTEMENT_DEFAUT 180

 

// ******************************************

// Constructeur

// Initialise les valeurs min et max du servo

// @param pCycleMin le cycle Min

// @param pCycleMax le cycle Max

// ******************************************

GestionServo::GestionServo(int pCycleMin, int pCycleMax)

{

    initCycles(pCycleMin, pCycleMax);

    angleDebattement = DEBATTEMENT_DEFAUT;

}

 

// ******************************************

// Constructeur

// Initialise les valeurs min et max du servo

// @param pCycleMin le cycle Min

// @param pCycleMax le cycle Max

// ******************************************

GestionServo::GestionServo(int pCycleMin, int pCycleMax, int pAngleDebattement)

{

    initCycles(pCycleMin, pCycleMax);

    angleDebattement = pAngleDebattement;

}

 

// *************************

// Initialisation des cycles

// *************************

void GestionServo::initCycles(int pCycleMin, int pCycleMax)

{

    if(pCycleMin < 0)

    {

        initError = true;

    }

    if(pCycleMax > RANGE)

    {

        initError = true;

    }

    if(!initError)

    {

        cycleMin = pCycleMin;

        cycleMax = pCycleMax;

     }

}

 

// *********************

// Initialisation du PWM

// *********************

void GestionServo::init()

{

    if(!initError)

    {

        pwm.init();

        if(pwm.mode(PWM_MODE_MS) == ERROR)

        {

            initError = true;

        }

        if(pwm.diviseur(DIVISEUR) == ERROR)

        {

            initError = true;

        }

        if(pwm.precision(RANGE) == ERROR)

        {

            initError = true;

        }

    }

}

 

// ***********************************

// Getter de l'erreur d'initialisation

// @return true si erreur d'init

// ***********************************

int GestionServo::isInitError()

{

    return(initError);

}

 

// ********************

// Getter du cycle min

// @return le cycle min

// ********************

int GestionServo::getCycleMin()

{

    if(!initError)

    {

        return(cycleMin);

    }

    else

    {

        return(ERROR);

    }

}

 

// ********************

// Getter du cycle max

// @return le cycle max

// ********************

int GestionServo::getCycleMax()

{

    if(!initError)

    {

        return(cycleMax);

    }

    else

    {

        return(ERROR);

    }

}

 

// ********************************

// Getter de l'angle de debattement

// @return l'angle de debattement

// ********************************

int GestionServo::getAngleDebattement()

{

    if(!initError)

    {

        return(angleDebattement);

    }

    else

    {

        return(ERROR);

    }

}

 

// *********************************************

// Fait bouger le servo vers une valeur

// @param pValeur la valeur à atteindre

// @return 0 si OK -1 si valeur hors possibilite

// *********************************************

int GestionServo::move(int pValeur)

{

    if(!initError)

    {

        if(pValeur > cycleMax || pValeur < cycleMin)

        {

            // Valeur depassant les cycles

            return(ERROR);

        }

        else

        {

            if(pwm.write(pValeur) == ERROR)

            {

                // erreur d'écriture

                return(ERROR);

            }

            valeur = pValeur;

            angle = valeur * (float)angleDebattement / (float)(cycleMax - cycleMin) - (float)(cycleMin * angleDebattement / (float)(cycleMax - cycleMin));

            return(0);

        }

    }

    else

    {

        // Erreur à l'initialisation

        return(ERROR);

    }

}

 

// ********************************************

// Fait bouger le servo vers un angle

// @param pAngle l'angle à atteindre

// @return 0 si OK -1 si angle hors possibilite

// ********************************************

int GestionServo::move(float pAngle)

{

    if(pAngle > angleDebattement || pAngle < 0)

    {

        return(ERROR);

    }

    int valeur = (float)(cycleMax - cycleMin) / (float)angleDebattement * pAngle + cycleMin;

    return(move(valeur));

}

 

// *******************

// Getter de la valeur

// @return la valeur

// *******************

int GestionServo::getValeur()

{

    if(!initError)

    {

        return(valeur);

    }

    else

    {

        return(ERROR);

    }

}

 

// *****************

// Getter de l'angle

// @return l'angle

// *****************

float GestionServo::getAngle()

{

    if(!initError)

    {

        return(angle);

    }

    else

    {

        return(ERROR);

    }

}

 

// ****************

// Désactive le pwm

// ****************

GestionServo::~GestionServo()

{

    pwm.~GestionPWM();

}

//============================================================================

// Name        : moveServo.cpp

// Author      : totof

// Version     :

// Copyright   : Free

// Description : Fait bouger un servo en utilisant les classes du servo et pwm

//============================================================================

 

#include <iostream>   // impression cout

#include <signal.h>   // signal de fin de programme

#include <stdlib.h>   // La librairie standard

#include <errno.h>    // Gestion des numéros d'erreur

#include <string.h>   // Gestion des String d'erreur

#include <wiringPi.h> // La wiringPi

#include "GestionServo.h"

 

#define ERROR -1

 

// Cycle Min

#define CYCLE_MIN 27

// Cycle Min

#define CYCLE_MAX 127

// Cycle Min

#define DEBATTEMENT 170

// Temporisation pour le servo

#define TEMPORISATION 20

 

using namespace std;

 

// Objets utilisés

GestionServo servo(CYCLE_MIN, CYCLE_MAX, DEBATTEMENT);

 

// *************************************

// Fonction de fin déclenchée par CTRL-C

// *************************************

void fin(int sig)

{

    // Désactive le servo

    servo.~GestionServo();

    cout << "FIN signal: " << sig << endl;

    exit(0);

}

 

// ******************

// Fonction pricipale

// ******************

int main()

{

    cout << "Mouvement d'un servomoteur" << endl;

 

    // Ecoute du CTRL-C avec fonction à lancer

    signal(SIGINT, fin);

 

    // Initialisation de la librairie wiringPi

    if (wiringPiSetupGpio() < 0)

    {

        cerr << "Erreur d'initialisation de wiringPi: " <<  strerror (errno) << endl;

        exit(ERROR);

    }

 

    servo.init();

 

    if(servo.isInitError())

    {

        cerr << "Erreur d'initialisation du servomoteur: " << endl;

        exit(ERROR);

    }

 

    cout << "Cycle minimum = " << servo.getCycleMin() << endl;

    cout << "Cycle maximum = " << servo.getCycleMax() << endl;

    cout << "Debattement   = " << servo.getAngleDebattement() << endl;

 

    // 4 boucles par valeur

    for(int boucle = 0; boucle < 2; boucle ++)

    {

        for(int compteur = CYCLE_MIN; compteur <= CYCLE_MAX; compteur++)

        {

            if(servo.move(compteur) == ERROR)

            {

                cerr << "Erreur move boucle 1" << endl;

                exit(ERROR);

            }

            cout << "Valeur = " << servo.getValeur() << endl;

            cout << "Angle  = " << servo.getAngle() << endl;

            delay(TEMPORISATION);

        }

        for(int compteur = CYCLE_MAX; compteur >= CYCLE_MIN; compteur--)

        {

            if(servo.move(compteur) == ERROR)

            {

                cerr << "Erreur move boucle 2" << endl;

                exit(ERROR);

            }

            cout << "Valeur = " << servo.getValeur() << endl;

            cout << "Angle  = " << servo.getAngle() << endl;

            delay(TEMPORISATION);

        }

    }

 

    // 4 boucles par angle

    for(int boucle = 0; boucle < 2; boucle ++)

    {

        for(int compteur = 0; compteur <= DEBATTEMENT; compteur++)

        {

            if(servo.move((float)compteur) == ERROR)

            {

                cerr << "Erreur move boucle 1" << endl;

                exit(ERROR);

            }

            cout << "Valeur = " << servo.getValeur() << endl;

            cout << "Angle  = " << servo.getAngle() << endl;

            delay(TEMPORISATION);

        }

        for(int compteur = DEBATTEMENT; compteur >= 0; compteur--)

        {

            if(servo.move((float)compteur) == ERROR)

            {

                cerr << "Erreur move boucle 2" << endl;

                exit(ERROR);

            }

            cout << "Valeur = " << servo.getValeur() << endl;

            cout << "Angle  = " << servo.getAngle() << endl;

            delay(TEMPORISATION);

        }

    }

}

 

Une petite explication sur la classe de gestion du servo. La fonction principale est la fonction move qui permet de faire bouger le servo. Cette fonction peut prendre en paramètre une valeur entière, auquel cas ce sera un nombre de pas à l’état haut. Elle peut également prendre en paramètre un nombre flottant (avec virgule) et dans ce cas, c’est un angle.

On met les cinq fichiers (GestionPWM.h, GestionPWM.cpp, GestionServo.h, GestionServo.cpp et moveServo.cpp) dans un répertoire.

Attention : dans le fichier moveServo.cpp, modifiez les valeurs de CYCLE_MIN et CYCLE_MAX en fonction du servo que vous utilisez.

On compile et on exécute après avoir branché le servo. Il doit faire quelques allés et retours et afficher les valeurs et les angles.

On a maintenant une classe qui gère le PWM et une autre qui gère les servos, notre bibliothèque de composants s’enrichit.


 

1.1.5        Liste des programmes

https://github.com/montotof123/raspberry/blob/master/170_Servo/GestionPWM.cpp

https://github.com/montotof123/raspberry/blob/master/170_Servo/GestionPWM.h

https://github.com/montotof123/raspberry/blob/master/170_Servo/GestionServo.cpp

https://github.com/montotof123/raspberry/blob/master/170_Servo/GestionServo.h

https://github.com/montotof123/raspberry/blob/master/170_Servo/moveServo.cpp

https://github.com/montotof123/raspberry/blob/master/170_Servo/servo.cpp

https://github.com/montotof123/raspberry/blob/master/170_Servo/servo_oscillo.cpp

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Lien vers la base du site.