[résolu] Utilisation de <Servo.h> dans une librairie

Je viens d'essayer pendant 1/2 et je n'y comprend rien.
J'ai rapatrié le code de la lib dans le sketch, j'ai même changé le nom de la classe.
J'ai ajouté un objet Servo sur la pin 2
J'ai changé ta lib sur la pin 9

Tout seul, un objet Servo marche.
Et il suffit de créer une instance de ta classe pour que la lib Servo parte en vrac et que les signaux de commande fasse n'importe quoi
J'ai même regardé les signaux généré à l'analyseur logique (au risque de me faire foutre de moi par Skywodd;))

je donne ma langue au chat.

EDIT:
Je met ici le dernier code que j'ai essayé.

#include <Servo.h>

class TestYouplop {
  public:
    TestYouplop(int pin)
    {
       servo.attach(pin);
    }

    void commencer(int min, int max)
    {
      Serial.println("Test::commencer: Min");
      // avance jusqu'� la position minimale
      servo.write(min);
      delay(1000);
      
      // puis jusqu'� la position maximale
      Serial.println("Test::commencer: Max");
      servo.write(max);
      delay(1000);
    }
    
    private:
      Servo servo;
};

// positions du servo-moteur (en degr�s)
#define MIN_SERVO 20
#define MAX_SERVO 170

//TestYouplop servotest(2); // contructeur
Servo servo;

void setup() 
{
  digitalWrite( 13, LOW );
  pinMode( 13, OUTPUT );
  Serial.begin(9600);
  Serial.println( "setup()" );
  servo.attach( 8 );
}

void loop() {
  Serial.println( "loop()" );
 
  // la seule et unique fonction de ma lib, qui fait avancer le servo d'un point � un autre
  //servotest.commencer(MIN_SERVO, MAX_SERVO);

   // avance jusqu'� la position minimale
   servo.write(MIN_SERVO);
   delay(1000);

   // puis jusqu'� la position maximale
   servo.write(MAX_SERVO);
   delay(1000);  
}

Tant que la ligne

//TestYouplop servotest(2); // contructeur

est commentée, alors servo (sur la pin 8 ) se comporte bien.
Il suffit de décommenter cette ligne pour que servo fasse n'importe quoi (cf les captures à l'analyseur logique)

  • signal 0 : pin 2
  • signal 1 : pin 8

servo_KO.png

Bon, j'ai partiellement compris la situation.

Normalement, quand on crée un objet servo, la lib Servo va initialiser les timers hardware au moment où on appelle servo.attach() pour la 1ère fois. Une fois que le timer utilisé a été initialisé, on ne cherche plus à l'initialiser. Comme la lib Servo ne comporte pas de constructeur avec le numéro de pin, servo.attach( numPin ) est appelé dans le setup.

Or dans ta lib tu as décidé d'ajouter au constructeur le paramètre de pin et de faire servo.attach() dans le constructeur de l'objet Test.

On constate alors que si tu crée un objet Test comme variable globale par :

Test servotest(2);

ca ne marche pas. En effet si on regarde les signaux à l'analyseur logique, les signaux ne se comportent pas correctement, signe que le TIMER n'est pas configuré correctement pour la lib Servo.

Par contre si on fait cela :

Test *pservotest;
void setup()
{
  pservotest = new Test(2);
}

Alors tout marche bien.

Pourquoi ?

Parce que dans le premier, le constructeur de Test qui appelle servo.attach() est appelé durant les phases d'initialisations globales (avant l'appel à main() et à setup()) alors que dans l'autre cas, servo.attach() est appelé après le démarrage du sketch depuis setup().

Or les phases d'initialisations globales comportent d'autres initialisations que les tiennes, notamment des initialisations effectuées dans la bibliothèque Arduino Core, et certaines touchent au timer. Il se trouve que l'ordre d'exécution des initialisations globales font que servo.attach() est appelé en premier, que l'initialisation du timer par la lib Servo est effectué mais qu'ensuite une autre initialisation globale vient casser celle faites par Servo et replace le timer dans un autre mode qui est incompatible avec le fonctionnement de Servo.

Qu'elle est donc la solution :
Faire comme Servo. Ne pas passer de numero de pin au constructeur ou surtout ne pas effectuer servo.attach() dans le constructeur.
Mais ajouter une fonction attach ou begin à ta classe qui sera appelée depuis setup().
Cela assure que l'initialisation du timer nécessaire au bon fonctionnement de Servo sera effectuée après les autres initialisations globales et que le timer sera donc bien configurée correctement.

Voici par exemple un code qui marche. (attaché).

test_servo.ino (842 Bytes)

Ouah, super!

Merci pour tes explications.

Je viens de tester ton sketch, il marche très bien en effet.
J'essaierais de l'intégrer dans ma lib dans la soirée.

Merci encore!
Youp

Hé bien c'est bon je valide!
Tout marche super, un grand merci à toi barbutor, ainsi qu'aux autres contributeurs :slight_smile:

Note: Au début je comprenais pas trop, ça ne fonctionnait toujours pas sur ma lib.
Je me suis aperçu que j'avais branché mon servo sur la pin A5, qui n'est pas une sortie PWM, donc le servo déconnait évidement.
Tout va bien sur la pin 9.

C'est donc avec un immense plaisir et un grand soulagement que je clos la 1ere phase de mon projet (disons une version beta), qui n'est pas des moindres.

Je réserve donc ma "petite surprise" à Barbutor et à Skywodd, qui m'ont beaucoup aidé sur ce projet (cf début du topic).

Je vous pouvez jeter un œil sur le ss-forum des projets finis pour découvrir le mien!

Youp.