Bogue avec la bibliothèque Servo, comment corriger ce problème ???

Bonjour,

Je suis à me construire un petit véhicule autonome à deux roues, mais je suis embêté avec un bogue dans la bibliothèque « Servo » qui me désactive la fonctionnalité de mes ports PWM pour le contrôle de deux moteurs CC avec engrenage démultiplicateur.

Comme bien des petits robots mobiles, j'utilise un capteur à ultrason sur un petit servomoteur TowerPro SG90 9G et un contrôleur moteur L298N (H-Bridge) pour les moteurs CC.

J'utilise les trois broche par moteur du contrôleur (ENA, ENB, IN1, IN2, IN3, IN4), pour contrôler la vitesse des moteurs CC, mais après une commande du genre « UnServo.attach (46,0,180); », je perds l'usage des moteurs CC en mode vitesses variables sur le contrôleur, sauf si la valeur de ENA, ENB est au maximum soit 255, ils passent donc du mode vitesse variable au mode binaire On/Off.

C'est comme si le mode PWM des Arduino (tester avec deux Mega, pour les autres je ne sais pas) était déréglé par l'utilisation de la librairie « Servo ».

Je suis actuellement en recherche d'autres cas similaires dans la francophonie (je suis unilingue francophone).

Pour info, je rencontre ce problème avec toutes les versions de l'IDE d'Arduino (1.0.3, 1.0.5, 1.5.2 et 1.5.3) et je suis sous Linux Kubuntu 12.04, 64 bits.

En fichier joint, mon code source avec le détail des pièces utilisées et des branchements (brouillon didactique pour un véhicule autonome à deux roues).

Dans la description de la bibliothèque, il y a bien une limitation et une désactivation du mode PWM de la broche 11 et 12 avec une carte Arduino Mega, mais seulement si plus de 12 servomoteurs sont utilisés, je n'en ai qu’un :

A partir d'Arduino 0017, la librairie Servo supporte jusqu'à 12 servomoteurs sur la plupart des cartes Arduino (la Duemilanove par exemple) et 48 sur l'Arduino Mega. Sur les cartes autres que la Mega, l'utilisation de la librairie Servo désactive l'instruction analogWrite() sur les broches 9 et 10, qu'il y ait ou non un servomoteur sur ces broches. Sur la Mega, jusqu'à 12 servomoteurs peuvent être utilisés sans interférer avec la fonction PWM (càd avec l'instruction analogWrite); utiliser de 12 à 23 servomoteurs désactivera les impulsions PWM sur les broches 11 et 12. (Note : PWM pour Pulse Width Modulation ou Modulation de Largeur d'Impulsion).

Référence : http://arduino.cc/fr/Main/LibrairieServo

Est-ce que je suis le seul à expérimenter ce problème ?

Existe-t-il une parade à ce problème ?

Est-ce qu'il n'y aurait pas une âme charitable qui pourrait nous corriger ce problème récurrent dans les versions de cette bibliothèque. Je lui serais éternellement reconnaissant ! :wink:

L'ami René
(M-à-j code source : 2013-09-09)

Arduinobot.zip (30.7 KB)

Bonjour,

Quoi qu'il arrive les broches 9 et 10 ne peuvent plus faire de PWM dés que la librairie Servo est utilisée.
Pour les broches 11 et 12 c'est vraiment QUE si tu utilises plus de 12 servomoteurs, pour le coup même la doc anglaise est d'accord là dessus.
Tu est sûr et certain que la PWM ne marche plus du tout ?

Bonjour skywodd,

Voici les connexions que j'ai pour le montage des deux moteurs CC :

// Broche d'Arduino pour le controleur moteur 1 (double Pont en H avec un L298N).
const byte CONTROLE_MOTEUR_1_ENA = 44;
const byte CONTROLE_MOTEUR_1_ENB = 45;
const byte CONTROLE_MOTEUR_1_IN1 = 34;
const byte CONTROLE_MOTEUR_1_IN2 = 32;
const byte CONTROLE_MOTEUR_1_IN3 = 30;
const byte CONTROLE_MOTEUR_1_IN4 = 28;

J'utilise un module d'extension "Shield" d'un écran LCD 16 colonnes 2 lignes à 6 boutons et je dois donc configurer la broche 10 pour la luminosité du fond de l'écran et effectivement la mode PWM de cette broche 10 est désactivée. La preuve en est qu'il y a un rétroéclairage que si je mais la valeur 255 à la fonction « analogWrite (LCD_1_A, LCD_1FondEcranValeur); ».

Voici toutes les connexions pour le montage (qui confirme que je suis dans les limites exigées pour les modes PWM des broches 28, 30, 32, 34, 44 et 45) :

//*****************************************************************************
// Déclaration des constantes des connecteurs Arduino.
//*****************************************************************************
// En prévision d'un ARDUINO_RESET par télécommande.
const byte ARDUINO_RESET = A7;

// Broche d'Arduino pour le controleur moteur 1 (double Pont en H).
const byte CONTROLE_MOTEUR_1_ENA = 44;
const byte CONTROLE_MOTEUR_1_ENB = 45;
const byte CONTROLE_MOTEUR_1_IN1 = 34;
const byte CONTROLE_MOTEUR_1_IN2 = 32;
const byte CONTROLE_MOTEUR_1_IN3 = 30;
const byte CONTROLE_MOTEUR_1_IN4 = 28;

// Pour gérer l'action d'humains le bouton de la planche d'expérimentation.
const byte BOUTON_1_SORTIE = 15;

// Broche d'Arduino pour recevoir le signale du capteur infrarouge.
const byte CAPTEUR_IR_1_1SORTIE = 14;

// Câblage pour la DEL verte sur la planche d'expérimentation et l'Arduino
const byte DEL_1_PLUS = 13;

// Broche d'Arduino pour le capteur a ultrason 1, le sonar.
const byte Sonar_1_TRIG = 22;
const byte Sonar_1_ECHO = 23;

// Broche d'Arduino pour le capteur a ultrason 2, le sonar.
const byte Sonar_2_TRIG = 24;
const byte Sonar_2_ECHO = 25;

// Broche d'Arduino pour le capteur a ultrason 3, le sonar.
const byte Sonar_3_TRIG = 26;
const byte Sonar_3_ECHO = 27;

// Constantes des broches sur l'Arduino pour une carte LCD1602.
const byte LCD_1_RS      = 8;// Écran LCD.
const byte LCD_1_E       = 9;// Écran LCD.
const byte LCD_1_D4      = 4;// Écran LCD.
const byte LCD_1_D5      = 5;// Écran LCD.
const byte LCD_1_D6      = 6;// Écran LCD.
const byte LCD_1_D7      = 7;// Écran LCD.
const byte LCD_1_A       = 10;// Écran LCD controle la liminosité arrière.
const byte LCD_1_SELECT  = A0;// Carte écran LCD 1 boutons
const byte LCD_1_UP      = A0;// Carte écran LCD 2 boutons
const byte LCD_1_RIGHT   = A0;// Carte écran LCD 3 boutons
const byte LCD_1_DOWN    = A0;// Carte écran LCD 4 boutons
const byte LCD_1_LEFT    = A0;// Carte écran LCD 5 boutons
const byte LCD_1_BOUTONS = A0;// Pour la gestion des boutons

// Câblage pour le Buzzer sur la planche d'expérimentation et l'Arduino :
const byte BOZZER_1_PLUS = 52;

// Attribution du port Arduino controlent le servo moteur.
const byte SERVO_MOTEUR_SONAR_1 = 46;// DigitalPWM
//*****************************************************************************

Je suis très loin des 12 servomoteurs, je n'en utilise que 1.

Et c'est avec la fonction « Servo.attach » que tout se dérègle.

Auriez-vous une suggestion de solution ?

L'ami René

Et pour le mode PWM des moteurs CC, pour qu'ils fonctionnent, je dois mettre la valeur 255 à la fonction « analogWrite (CONTROLE_MOTEUR_1_ENA, MOTEUR_1_VITESSE_MAXIMUM); », à 254 les roues ne bougent pas. C'est exactement comme pour la broche 10 et le rétroéclairage.

L'ami René

Une bride de code comme ça c'est sans intérêt :wink:
-> code complet.

si ça ce trouve c'est pas Servo qui bug mais une autre librairie qui utilise le même timer que Servo.

Bonjour skywodd,

Le code complet est déjà dans le premier message de cette discussion, mais voici en pièce jointe la toute dernière version.

Merci pour ton aide, comme je suis débutant avec Arduino, j'apprécie grandement !

L'ami René

Arduinobot2013-09-10.zip (16.4 KB)

Tout devient plus clair.
C'est surement la librairie IRremote qui utilise un timer dont tu as besoin :wink:

Regarde dans IRremoteInt.h au début tu doit avoir un truc du style :

// Arduino Mega
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  //#define IR_USE_TIMER1   // tx = pin 11
  #define IR_USE_TIMER2     // tx = pin 9
  //#define IR_USE_TIMER3   // tx = pin 5
  //#define IR_USE_TIMER4   // tx = pin 6
  //#define IR_USE_TIMER5   // tx = pin 46

Essaye avec un autre timer voir ce qui ce passe.

D'après http://arduino.cc/en/Hacking/PinMapping2560 :
Pins 11, 12 -> timer 1 // Lib IRremote actuellement (?)
Pins 9, 10 -> timer 2 // Lib Servo
Pins 2, 3, 5 -> timer 3
Pins 6, 7, 8 -> timer 4
Pins 44, 45, 46 -> timer 5

Pin 13 -> timer 0 et timer 1
Pin 4 -> timer 0

Bonjour skywodd,

Je suis très, très, très impressionné !

Il est clair pour moi qu'à ce niveau, cela dépasse largement mes connaissances et sans votre aide je ne pourrais trouver une solution de ce niveau, mais je cherche a comprendre du mieux que je peux.

Pour ce qui est du fichier « IRremoteInt.h », j'ai effectivement (voici un copier/coller de mon fichier) :

// Arduino Mega
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  //#define IR_USE_TIMER1   // tx = pin 11
  #define IR_USE_TIMER2     // tx = pin 9
  //#define IR_USE_TIMER3   // tx = pin 5
  //#define IR_USE_TIMER4   // tx = pin 6
  //#define IR_USE_TIMER5   // tx = pin 46

Et si j'utilise un autre que "IR_USE_TIMER2", j'ai des erreurs de compilation du genre :

Avec « #define IR_USE_TIMER5 // tx = pin 46) » :

Servo/Servo.cpp.o: In function `__vector_17':
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/Servo/Servo.cpp:103: multiple definition of `__vector_47'
IRremote/IRremote.cpp.o:/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp:70: first defined here
/home/rene/sda6/Électroniques/Arduino_Linux/hardware/tools/avr/bin/../lib/gcc/avr/4.3.2/../../../avr/bin/ld: Disabling relaxation: it will not work with multiple definitions

Et c'est la même chose avec :

« #define IR_USE_TIMER4 // tx = pin 6 »
« #define IR_USE_TIMER3 // tx = pin 5 »
« #define IR_USE_TIMER1 // tx = pin 11 »

Et avec « #define IR_USE_TIMER0 » :

Dans le fichier inclus à partir de /home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp:20:
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremoteInt.h:441:2: erreur: #error "Internal code configuration error, no known IR_USE_TIMER# defined\n"
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp: In member function ‘void IRsend::mark(int)’:
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp:227: error: ‘TIMER_ENABLE_PWM’ was not declared in this scope
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp: In member function ‘void IRsend::space(int)’:
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp:235: error: ‘TIMER_DISABLE_PWM’ was not declared in this scope
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp: In member function ‘void IRsend::enableIROut(int)’:
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp:253: error: ‘TIMER_DISABLE_INTR’ was not declared in this scope
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp:255: error: ‘TIMER_PWM_PIN’ was not declared in this scope
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp:263: error: ‘TIMER_CONFIG_KHZ’ was not declared in this scope
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp: In member function ‘void IRrecv::enableIRIn()’:
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp:279: error: ‘TIMER_CONFIG_NORMAL’ was not declared in this scope
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp:282: error: ‘TIMER_ENABLE_INTR’ was not declared in this scope
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp:284: error: ‘TIMER_RESET’ was not declared in this scope
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp: In function ‘void TIMER_INTR_NAME()’:
/home/rene/sda6/Électroniques/Arduino_Linux/libraries/IRremote/IRremote.cpp:313: error: ‘TIMER_RESET’ was not declared in this scope

Je ne sais pas quoi faire d'autres.

J'ai regardé le contenu du fichier « IRremote.cpp » et j'ai trouvé ce code qui pourrait-être la confirmation de mon problème de PWM :

/* Leave pin off for time (given in microseconds) */
void IRsend::space(int time) {
  // Sends an IR space for the specified number of microseconds.
  // A space is no output, so the PWM output is disabled.
  TIMER_DISABLE_PWM; // Disable pin 3 PWM output
  delayMicroseconds(time);
}

Mais pour l'instant, je suis dans la mélasse, j'espère que vous pourrez m'aider à me sortir de ce bourbier !

Au-delà d'être impressionné par l'étendue de vos connaissances et vos compétences, j'apprécie grandement votre aide !

L'ami René

Rebonjour,

J'ai fait une version de mon Arduinobot sans télécommande et donc sans la bibliothèque « IRremote » et malheureusement, le problème persiste.

J'en déduis qu'il y aurait une ou plusieurs autres bibliothèques qui interfèrent avec les "TIMERx" ou les "INTx" et le mode PWM !

Il me reste comme coupable potentiel la bibliothèque "LiquidCrystal.h" ou "Servo.h".

Monsieur le Juge, quel est votre verdict ?

L'ami René

Rebonjour,

J'ai fait une version de mon Arduinobot sans télécommande et donc sans la bibliothèque « IRremote » et sans la bibliothèque "LiquidCrystal.h", malheureusement, le problème persiste.

J'en déduis qu'il y a interfèrent avec les "TIMERx" ou les "INTx" et le mode PWM causé par la bibliothèque "Servo.h".

Monsieur le Juge, vous avez le même verdict assurément, mais quelle serait la solution au problème ?

L'ami René

Bonjour,

Cherchant à remplacer la bibliothèque « Servo », j'ai produit le code qui suit, mais le servomoteur reste inerte. Où est l'erreur dans mon code (je suis avec une carte Mega, voire tout le code en pièce jointe).

Le nouveau bout de code :

// Pour attribution du port Arduino contrôlent le servo moteur.
const byte SERVO_MOTEUR_SONAR_1 = 19;// DigitalPWM

//*****************************************************************************
void setup ()
//*****************************************************************************
{
  // Initialiser le port Arduino pour un servomoteur et centrage de l'angle du moteur.
  pinMode (SERVO_MOTEUR_SONAR_1, OUTPUT);
}

//*****************************************************************************
void loop()
//*****************************************************************************
{
  for (int i = 0; i < 180; i = i +1)
  {
    ServoMoteur (SERVO_MOTEUR_SONAR_1, i);
  }
}
//*****************************************************************************

//*****************************************************************************
// FONCTION ServoMoteur
//*****************************************************************************
void ServoMoteur (byte UnServoMoteur, int Angle)
{
  Angle = map (Angle, 0, 180, 0, 255);
  analogWrite (UnServoMoteur, Angle);
}

Merci d'avance pour votre aide inestimable !

L'ami René

Désolé pour le retard je suis overbooké :grin:

Bon donc :

  1. La lib IRremote était bien en conflit avec Servo (toutes les deux sur le Timer2)
  2. L'erreur de redéfinition multiple vient de la lib Servo qui déclare des handler d'interruptions inutiles pour ton utilisation.

Solution :

  1. utilise un autre timer que le n°2 (disont #define IR_USE_TIMER5)
  2. utilise une lib plus simple du genre "ServoTimer2" (elle porte bien son nom au moins celle là ;))
    Arduino/libraries/ServoTimer2 at master · DerekK19/Arduino · GitHub

Bonjour skywodd,

Un très grand merci pour votre aide, c'est très apprécié !

J'ai procédé comme vous l'indiquez, mais cela ne change pas le problème et en plus le servomoteur ne fonctionne pas avec la nouvelle bibliothèque.

Voici en détail ce que j'ai fait (voir en pièces jointes tous les fichiers utilisés).

  1. Utiliser un autre timer que le n°2, le « #define IR_USE_TIMER5 » :

Donc, changer dans le fichier « IRremoteInt.h » le code :

// Arduino Mega
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  //#define IR_USE_TIMER1   // tx = pin 11
  #define IR_USE_TIMER2     // tx = pin 9
  //#define IR_USE_TIMER3   // tx = pin 5
  //#define IR_USE_TIMER4   // tx = pin 6
  //#define IR_USE_TIMER5   // tx = pin 46

Pour le code :

// Arduino Mega
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  //#define IR_USE_TIMER1   // tx = pin 11
  //#define IR_USE_TIMER2     // tx = pin 9
  //#define IR_USE_TIMER3   // tx = pin 5
  //#define IR_USE_TIMER4   // tx = pin 6
  #define IR_USE_TIMER5   // tx = pin 46
  1. Utiliser la bibliothèque plus simple "ServoTimer2" :

Donc, télécharger et installer dans le dossier « ~/Arduino_Linux/libraries ».

  1. Dans mon code source, modifier la ligne # 423, pour la nouvelle bibliothèque :
#include "Servo.h"

Par la ligne :

#include "ServoTimer2.h"
  1. Toujours dans mon code source, modifier la ligne # 702 de la création de l'objet Servomoteur :
Servo ServoMoteurSonar_1;

Par la ligne :

ServoTimer2 ServoMoteurSonar_1;
  1. Fermer l'IDE d'Arduino pour m'assurer que tous les changements de bibliothèque soient pris en compte.

  2. Au relancement de l'IDE d'Arduino et à la compilation, il y a l'erreur suivante :

Arduinobot_Travail.cpp.o: In function `setup':
/home/rene/sda6/Électroniques/Arduino_Linux/Arduinobot_Travail.ino:830: undefined reference to `ServoTimer2::attach(int, int, int)'
  1. Toujours dans mon code source, modifier la ligne # 806 de la création de l'objet Servomoteur :
ServoMoteurSonar_1.attach (SERVO_MOTEUR_SONAR_1, ServoMoteurSonar_1PositionMinimum, ServoMoteurSonar_1PositionMaximum);
  1. Donc, il semble que le type de variable pourrait être en cause, car « `ServoTimer2::attach(int, int, int)' » :
const byte SERVO_MOTEUR_SONAR_1 = 19;// DigitalPWM

Que je remplace par (ligne # 620) :

const int SERVO_MOTEUR_SONAR_1 = 19;// DigitalPWM
  1. Pour les deux autres variables, c'est correct (ligne # 667) :
int ServoMoteurSonar_1PositionMinimum = 500;

Et (ligne # 669) :

int ServoMoteurSonar_1PositionMaximum = 2400;
  1. À la recompilation, même erreur :
Arduinobot_Travail.cpp.o: In function `setup':
/home/rene/sda6/Électroniques/Arduino_Linux/Arduinobot_Travail.ino:830: undefined reference to `ServoTimer2::attach(int, int, int)'

Après étude du code de la nouvelle bibliothèque, je décide d'essayer sans les deux derniers paramètres de « attach ».

  1. Alors, je modifie la ligne # 828 :
ServoMoteurSonar_1.attach (SERVO_MOTEUR_SONAR_1, 
                             ServoMoteurSonar_1PositionMinimum, 
                             ServoMoteurSonar_1PositionMaximum);

Sans les deux derniers paramètres :

ServoMoteurSonar_1.attach (SERVO_MOTEUR_SONAR_1);
  1. À la compilation, pas d'erreurs, alors je charge la compilation sur le Mega.

Et c'est là que je constate que :

A) Le problème de base reste entier, c'est-à-dire que le fonctionnement du mode PWM est désactivé et que je ne peux utiliser une vitesse variable pour mes deux moteurs CC. Normalement, c'est deux moteurs à courant continu devraient se mettent en mouvement avec un PWM au alentour de 110, mais même à 254, il ne bougent pas. Je dois passer à 255 pour qu'ils se mettent en action.

B) Le servomoteur du capteur sonar HR-SC04 ne fonctionne plus, pas un bruit, pas un mouvement.

C) En reprenant l'ancienne version du code source, le servomoteur du capteur sonar HR-SC04 fonctionne de nouveau.

Je sens bien que l'on est sur la bonne piste, mais pour le moment ça ne fonctionne pas.

Qu'en pensez-vous, une piste de solution ?

L'ami René
P.-S. : Votre aide est grandement appréciée...

Arduinobot_11_AvecServoTimer2.zip (16.4 KB)

IRremote.zip (33.5 KB)

ServoTimer2.zip (3.62 KB)

Bizarre bizarre, ServoTimer2 a pourtant une version de attach() à trois arguments (pin, min, max).

Bonjour skywodd,

Oui, bizarre et je respecte pourtant les indications et types de variable, mais ... bogue !!!

Il ne faut pas oublier que j'ai fait une version de mon Arduinobot sans la bibliothèque « IRremote » et sans la bibliothèque "LiquidCrystal.h", malheureusement, le problème persiste.

J'en déduis qu'il y a interfèrent avec les "TIMERx" ou les "INTx" et le mode PWM causé par la bibliothèque "Servo.h".

Mais quelle serait la solution au problème ?

En attendant une autre piste de solution, je recherche une autre bibliothèque type « Servo ».

Merci pour votre aide !

L'ami René

J'ai la solution... malheureusement réservée à un public averti. Je crois comprendre que tu utilises une méga. de là, rien de plus simple. on a à notre disposition 4 timer 16bits totalement indépendants avec chacun trois sorties PWM. dans mes projets utilisant des servos, je configure moi-même un timer 16bits qui me permet de gérer 3 servos avec une fiabilité hors du commun.

volatile word E_ICR1 = 35000;     // 17,5ms par défaut, période de signal servo. ICR = T / 500ns.

#define servo1 OCR1A           // raccourci d'accès au registre servo 1
#define servo2 OCR1B           // raccourci d'accès au registre servo 2
#define servo3 OCR1C           // raccourci d'accès au registre servo 3

void servos_cfg(){
  DDRB |= 0xE0;   // B5 (OCR1A, pin 11), B6 (OCR1B, pin 12), B7 (OCR1C, pin 13) output
  TCCR1B = 0x18;  // désactiver timer1
  TCCR1A = 0xAA;  // configurer les 3 sorties PWM
  ICR1  = E_ICR1;        //  TOP : T(pwm)
  servo1 = 2000;            //  Init servo 1
  servo2 = 2000;           //  Init servo 2  
  servo3 = 2000;          //  Init servo 3  
  TCCR1C = 0x00;
  TCCR1B |= 0x02;  // Activer timer1, prescaler = F_CPU/8  
}

il te suffit de lancer servos_cfg() dans le setup, puis pour changer la valeur d'un servo, simplement servo1 = valeur; avec valeur compris généralement entre 2000 et 4000, à ajuster selon le type de servo (durée impulsion (en seconde) = valeur / 2 000 000, ou encore valeur = durée x 2 000 000).

si l'utilisation du timer1 t'embête, tu peux utiliser un autre timer (3, 4 ou 5), ils fonctionnent tous pareil. Mais il te faut changer le nom des registres (OCR1A et TCCR1B deviennent OCR4A et TCCR4B pour le timer4 par exemple, attention à la première ligne "DDRB = ...", elle doit changer aussi!).

C'est très certainement dur à comprendre, mais cette solution va te permettre de gagner un maximum en vitesse d'exécution et précision. De cette manière, le CPU n'a plus rien à gérer hormis l'affectation d'une valeur à servo1, 2 ou 3. de plus, elle n'utilise qu'un seul timer pour 3 servos, laissant les autres libres.

je crois qu'il est temps que je crée une vraie biblio pour servos, mais j'aurais besoin d'un coup de main, j'ai encore du mal à transformer mon code en biblio...

Bonjour Super_Cinci,

Un très grand merci pour ton aide !

Je vais essayer d'utiliser ton code.

Pour produire une bibliothèque, je suis partant comme partenaire, même si je n'en ai jamais écrit en C ou en C++, de 1989 à 2000, j'étais un professionnel (programmeur analyste) et le langage Pascal sur PC et sur Mac n'avait pas de secret pour moi. Le C, C++ ressemble à du Pascal fusionné avec de l'Assembleur, alors il faut simple se jeter à l'eau pour apprendre à nager.

Si toi aussi tu es partant pour produire une bibliothèque, nous devrions passer en message privé, courriel, etc.

Pour ce qui est de ton code, sans les documents de références des adresses et/ou nom des registres, etc., oui, c'est laborieux à comprendre, mais j'en comprends le principe.

Si on se lance dans une bibliothèque, je te suggère que l'on s'inspire de la bibliothèque que tu trouves la plus didactique et la plus aboutie que tu connaisses. Pour ce qui est de structurer et systématisé les choses de la logique des algorithmes je pourrais sûrement être d'une aide appréciable. Je suis simplement nouveau avec l'Arduino et en langage C/C++, mais de moins en moins nouveau...

Je reviendrai ici avec ton code intégré au mien et avec le problème résolu ou avec les points ou cela bloque.

En souhaitant que tu puisses l’orienter, si besoin était.

Merci encore pour ton aide !

L'ami René

pas de quoi.

J'ai commencé à voir comment pondre une lib servo. Pour l'instant, celà ne pose aucun problème pour une mega et uno, il n'y a pas de ressources communes et ça va passer nikel. mais si on veut jouer avec toutes les arduinos, ce sera peut-être un peu plus dur.

chiche pour une version 1.0 pour 2560 et UNO?

en gros, on aura juste une fonction :

void servoInit(byte N, word T, boolean inv);  // N = Num servo; T = période signal en nS; inv = mode inverse.

et l'accès au(x) servo(s) par word servoN = valeur; . N = numéro de pin, UNO : 9 et 10; MEGA2560 : 2, 3, 5, 6, 7, 8, 11, 12, 13, 44, 45 et 46.

Ho ho,

Les choses ne tardent pas avec vous !

Je n'ai eu le temps que de taper que cela dans mon code :

/*
Cette librairie permet à une carte Arduino de contrôler les servomoteurs de 
modélisme. Les servomoteurs intègrent un mécanisme et un axe qui peut-être 
contrôlé précisément. Les servomoteurs standards permettent de positionner 
l'axe à différents angles, habituellement entre 0 et 180 degrés (ces 
servomoteurs permettent de maintenir l'axe à une position précise). Les 
servomoteurs à rotation continue permettent des rotations de l'axe à 
différentes vitesses.
*/
/*
Il suffit de lancer servos_cfg () dans la section « setup (); », puis pour 
changer la valeur d'un servo, simplement « Servomoteur_1 = UneValeur; » avec 
une valeur comprise généralement entre 2000 et 4000, à ajuster selon le type 
de servo Ex. :

DureeImpulsionEnSeconde = UneValeur / 2000000;

Ou encore :

UneValeur = Duree * 2000000;

Si l'utilisation du timer1 vous embête, vous pouvez utiliser un autre "timer" 
(3, 4 ou 5), ils fonctionnent tous de la même manière. Mais il faut changer le 
nom des registres (OCR1A et TCCR1B deviennent OCR4A et TCCR4B pour le timer4 
par exemple, attention à la première ligne "DDRB = ...", elle doit changer 
aussi!).

C'est très certainement dur à comprendre, mais cette solution va permettre de 
gagner un maximum en vitesse d'exécution et précision. De cette manière, le 
CPU n'a plus rien à gérer hormis l'affectation d'une valeur à servo1, 2 ou 3. 
de plus, elle n'utilise qu'un seul "timer" pour 3 servomoteurs, laissant les autres 
libres.
*/
// 17,5ms par défaut, période de signal servo. ICR = T / 500ns.
volatile word E_ICR1 = 35000; 

#define Servomoteur_1 OCR1A // raccourci d'accès au registre servo 1.
#define Servomoteur_2 OCR1B // raccourci d'accès au registre servo 2.
#define Servomoteur_3 OCR1C // raccourci d'accès au registre servo 3.

void servos_cfg ()
{
  // B5 (OCR1A, pin 11), B6 (OCR1B, pin 12), B7 (OCR1C, pin 13) output.
  DDRB          |= 0xE0;
  // désactiver timer1.
  TCCR1B         = 0x18;  
  // configurer les 3 sorties PWM.
  TCCR1A         = 0xAA;
  //  TOP : T(pwm).
  ICR1           = E_ICR1;
  //  Init servo 1.
  Servomoteur_1  = 2000;
  //  Init servo 2.
  Servomoteur_2  = 2000;
  //  Init servo 3.
  Servomoteur_3  = 2000;
  TCCR1C         = 0x00;
  // Activer timer1, prescaler = F_CPU/8  
  TCCR1B        |= 0x02;
}

Je profite de l'occasion, si vous avez le temps... Comme j'utilise un module LCD1602 avec 6 boutons, donc toutes les broches standards "Uno" de mon Mega sont occupées physiquement par ce "Shield", alors quel serait les adresses pour utiliser la broche ARDUINO_19_PWM_RX1, et avec quel « TimerX » ?

L'ami René

Rebonjour Super_Cinci,

Comme j'utilise une mini télécommande et un capteur infrarouge VS1838B (TSOP1838) avec la bibliothèque "IRremote.h" qui utilise déjà le "Timer2". Est-ce que je suis dans le trouble ?

Référence :

http://www.dipmicro.com/store/VS1838B

Est-ce que ce code est correct ? :

#define Servomoteur_1 OCR1A // raccourci d'accès au registre servo 1, BROCHE 11.
#define Servomoteur_2 OCR1B // raccourci d'accès au registre servo 2, BROCHE 12.
#define Servomoteur_3 OCR1C // raccourci d'accès au registre servo 3, BROCHE 13.
#define Servomoteur_4 OCR1D // raccourci d'accès au registre servo 4, BROCHE 14.
#define Servomoteur_5 OCR1E // raccourci d'accès au registre servo 5, BROCHE 15.
#define Servomoteur_6 OCR1F // raccourci d'accès au registre servo 6, BROCHE 16.
#define Servomoteur_7 OCR1G // raccourci d'accès au registre servo 7, BROCHE 17.
#define Servomoteur_8 OCR1H // raccourci d'accès au registre servo 8, BROCHE 18.
#define Servomoteur_9 OCR1I // raccourci d'accès au registre servo 9, BROCHE 19.
#define Servomoteur_10 OCR1J // raccourci d'accès au registre servo 10, BROCHE 20.
#define Servomoteur_11 OCR1K // raccourci d'accès au registre servo 11, BROCHE 21.

L'ami René