Un robot à tous faire / conflit PWM

Bonjour,

Ca fait quelques temps que je fabrique des petits machins avec mon arduino UNO.
Je suis développeur informatique et l’électronique c est juste un hobby.
Mais là je cale. Si quelqu’un, Une âme charitable, pouvait m’expliquer pourquoi cela ne fonctionne pas.
Je vais détailler donc ça risque d’être un bon pavé de lecture, désolé.

Le projet : Un robot/engin chenillé pour mon fils (bon et pour moi aussi :grin: )
Fontionnalités :

  • 2 moteurs DC (piloter par un L293D, pas un shield mais juste le composant) pour faire se mouvoir cet engin.
  • 1 interception IR pour le piloter avec la télécommande de la TV (AVANCE,RECULE,STOP, GAUCHE, DROITE, ACCELERE, RALENTIR, MODEAUTONOME )
  • 1 servo Moteur + HC_SR04 pour le mode autonome et donc éviter les obstacles
  • 1 HP pour fair bipbip comme R2D2
  • Alimentation par une batterie 7.2V 1100mAH . Ce n’est pas arduino qui fournit les 5V pour le circuit je met un L7805 pour la partie 5V et les moteurs seront alimenter par la batterie.
  • Faire ma propre carte avec tout ca dessus (un Standalone) lorsque cela fonctionnera sur la breadboard.

Et me voilà partie pour fabriquer ce truc sur une UNO. Je compte le Broches

  • 6 pour le L293D dont 2 PWM :
    • Moteur 1 :
      • E1 = 9 /
      • M1_1 = 8 /
      • M1_2 = 7
      • respectivement sur 1, 2 et 7 du L293D
    • Moteur 2 :
      • E2 = 6 /
      • M2_1= 5 /
      • M21_1= 4
      • respectivement sur 9, 10 et 15 du L293D
  • 1 pour le IR_RECEIVER
    • IR_RECEIVE_PIN= 12
  • 1 pour le HP
    • TONE_PIN = 11
    • EYE_PIN = 13 ( bon ca c’est juste pour faire clignoter la led de l’arduino… je garde les basic pour les contrôles )
  • 3 pour la détection via Ultra SON
    • 1 pour le servo moteur SERVO_PIN = 3
    • 2 pour le HC-SR04 … ECHO _PIN = 10 et TRIGGER_PIN = 2

Total 11 + le RX / TX . ok ca rentre… c est juste mais ca doit rentrer… J’utilise meme pas les analogique. les PWM y en a assez

ETAPE 0 : faire un schéma.
Ouverture de KICAD nouveau projet ( je vous passe le résultat du schéma en image )

ETAPE 1 : Faire tourner les DC pour le déplacement.
Je code juste cette fonction avec les petites méthodes qui sont pour le moment appeler par port Serie
C est partie pour les tests : impec mes petits moteurs tournent en passant mes commandes via Serial.

ETAPE 2: l’IR
Je code d’abord juste pour intercept les codes de la télécommande. Impec
Je rajoute ca à mon code de pilotage du L293D impec…

Voilà mes petits moteurs pilotés par la télécommande de la Télé.

ETAPE 3: The voice.
Après quelques petite recherche je trouve de quoi faire avec la fonction tone des petit buit à la R2D2.
Je le rajoute à mon projet
Et la ca commence… faut que le temps que j’utilise la fonction tone je coupe et arrete l’interception IR… ??? :question: :thinking:
Ok un problème de timer PWM. je comprends pas trop. Mais ok, je contourne sans trop comprendre.

QUESTION 1 : Je veux bien une explication sur ce sujet de conflit entre IR et la fonction tone de timer etc…

Bon il bouge je le pilote, il parle… le mode autonome…

ETAPE 4: Faire bouger le servo moteur
Alors c 'est partie. un petit bout de code pour bien me remettre dans le bain des servoMoteurs. et hop je rajoute le “cou” à mon projet…

et hop PAF ! ca marche plus. j’ai un moteur qui tourne pas du L293D.
Les instructions de sens partent bien vers le L293D mais impossible d’avoir le MOTEUR 2 qui tourne. pas d’énergie. rien sur ma patte PWM.
Si j’enleve l’utilisation du servo moteur (le servo.attach) dans mon code ca repart.

QUESTION 2 : Pourquoi ?

Avez vous besoin du code ? et Oui j ai déjà cherché sur internet avant de me taper un pavé pareil sur un forum.

Merci à ceux qui auront pris le temps de me lire.
Un grand MERCI PAR AVANCE à ceux qui me répondront.

Pour la question 1, c’est un problème bien documenté de conflit entre la bibliothèque IRremote et la fonction tone qui utilisent en même temps le même timer. Pour contourner le problème, tu peux utiliser la bibliothèque Newtone ou timer free tone qui n’utilise pas de timer.

Pour la question 2, je ne suis pas spécialiste des moteurs, donc je n’ai pas de réponse précise. Je vois sur la doc de la bibliothèque servo qu’elle a des effets de bord :

On boards other than the Mega, use of the library disables analogWrite() (PWM) functionality on pins 9 and 10, whether or not there is a Servo on those pins.

Comme tu utilises la pin 9 pour tes moteurs, tu perds le PWM et ils peuvent ne plus fonctionner. Donc évite d’utiliser la D9…

Pour tone, soit on utilise un timer et le son est généré hard, et on a un code non bloquant, soit on n’utilise pas le timer et on fait des boucles. Le code devient alors bloquant et le détecteur IR ne fonctionnera pas.
Le PWM ressemble à tone, et utilise aussi un timer
La bibliothèque servo utilise aussi un timer (pire il monopolise tous les TIMER?_COMPA_vect des timers 16 bits, mais pour un uno, c’est pas important, il 'y en a qu’un!)

Pour faire le tout, il faut raisonner en fonctions des timers et pas des entrées. Au passage:

Les broches A0…A5 sont aussi des E/S numériques. Je dirais même que ce sont surtout des broches numériques qui peuvent en plus être utilisées en entrées analogiques. Donc total 11 sur 17 ça passe largement.

Bref, pour les timers:
IRremote utilise le timer2 (8 bits)
tone utilise le timer 2
le PWM utilise un timer, mais on peut utiliser le timer 0
servo utilise le timer 1

Comme il n’y a que 3 timers sur une Uno, cela coince un peu. Surtout pour le timer 2. Si je devais faire ce projet, comme tone est assez facile à faire (signal simple, pas trop besoin de précision), je la ferai sans utiliser la bibliothèque, ce qui permet de faire un code non bloquant en utilisant par exemple le timer 0. Même si beaucoup pensent que ce n’est pas possible, j’utilise personnellement le timer 0 pour avoir une interruption toutes les 1,024ms (pour delay, millis, micros), une interruption toutes les 1 ms pour une base de temps personnelle et j’appelle une fonction toutes les 100ms. Générer par interruption n’importe quelle fréquence avec le timer 0 n’est pas une évidence, mais ce n’est pas trop compliqué quand on en connait l’astuce.
Cette méthode permet de libérer tone du timer 2

Sûr que c’est le moteur 2 et pas le moteur 1? Car le PWM du 2 est sur la broche 6 liée au timer 0 et cela n’interfère pas avec servo. Par contre le PWM du moteur 1 est sur la broche 9 qui est lié au timer 1, incompatible avec servo

Pour s’en sortir, il faut que les PWM n’utilisent que le timer 0, car le 1 est utilisée par servo, et le 2 est utilisé par IRremote. Les deux PWM doivent donc être sur les broches 5 et 6 uniquement.

Pour tone, je peux t’aider, mais il faut que tu précises toutes les fréquences utilisées.

1 Like

Je pense aussi à autre chose:
Pour alimenter un moteur CC avec un L293D, on a au moins deux possibilités:
a) Mettre le PWM sur la broche EN et mettre une entrée du pont à 1 pendant qu’on met l’autre à 0
b) Mettre EN à 1, mettre une des broche d’entrée du pont à 0 et le PWM sur l’autre.

On conseille sur le net d’utiliser la solution a) avec les MCC.

La solution b) est simple à analyser. Si la broche PWM est à 1, le moteur reçoit VCC, si le PWM est à 0, le moteur reçoit du 0V. La tension moyenne aux bornes du moteur est proportionnelle au PWM. En gros la vitesse du moteur est proportionnelle au PWM.
Si le moteur tourne au maximum de sa vitesse et que l’on veut arrêter le moteur, on impose alors un 0V aux bornes du moteur et le moteur est freiné.

Pour la solution a), un signal PWM étant sur la broche EN, le L293 alimente le moteur avec VCC ou passe en haute impédance. Quand le moteur est en haute impédance, la tension s’inverse tant que le courant est non nul puis quand le courant est nul, la tension est égale à la fcem du moteur (entre 0V et VCC). Du coup, la tension moyenne n’est pas proportionnelle au PWM. Pour de fortes valeurs du PWM, le moteur va tourner vite, la fcem sera voisine de VCC; lorsque l’on passe en haute impédance, le courant va décroitre très vite (la fcem aide à la décroissance), puis quand il n’y a plus de courant la tension sera égal à la fcem. On aura une tension moyenne supérieure à ce que l’on voudrait.
Si le moteur tourne au maximum de sa vitesse et que l’on veut arrêter le moteur, on met le moteur en haute impédance, et dès que le courant est nul, il n’y a plus de courant dans le moteur, celui-ci n’est plus freiné, il mettra plus de temps à s’arrêter.

Dans le cas a) on est linéaire et on peut freiner le moteur, dans le cas b) on n’est pas linéaire et le moteur est mal freiné.

Le cas b) nécessite 2 broches par moteur (plus une pour tous les moteurs si on veut pouvoir les déconnecter). On économise ainsi une ou deux broches avec une commande meilleure.

Mais il faut 2 PWM par moteur au lieu d’une. Il existe donc une troisième solution (celle que je préfère) Mettre EN à 1 (ou sur une broche si on veut déconnecter le moteur un jour). Mettre une entrée PWM sur une broche d’entrée du pont et une broche non PWM pour l’autre. La première permet de faire varier la tension, la deuxième permet de choisir le sens. Si la deuxième est à 0V, la tension est proportionnelle au PWM. Si la deuxième broche est à 1, la tension (inverse) est proportionnelle à (100%-PWM). Il y a une petite adaptation logicielle, mais on n’a plus besoin que d’une seule PWM par moteur.

Merci de m’avoir lut et aussi merci pour vos réponses.

Oui c est possible dans tous mes tests, j ai probablement inversé… :cry: désolé pour la coquille.

Si j ai bien compris c’est un problème lié au timer. C’est ce que j’avais plus ou moins compris avec mes recherches. Mais j’avais un espoir de contournement.
Donc en conclusion :

  • Est ce que vous pouvez me conseiller quelques documents/livres que je peux consulter pour savoir ce que c’est ces timers et mieux comprendre comment utiliser cela. Accès sur le uno par exemple. je commence par cet article mais y a peut être mieux.
  • je vais voir pour modifier mon projet en fonction de vos conseils dans un premier temps.

Encore merci pour votre aide.

Il y a aussi le site de Nick Gammon

Perso, je ai comme lecture principale sur le sujet la datasheet du processeur. C’est un peu plus ardu, mais j’ai tous les renseignements possibles. Commencer par locoduino ou Nick permet de dégrossir.

Le terme utilisé dans la datasheet est “Timer Counter”.
AMHA leur fonction principale est plutôt d’être des compteurs dotés de possibilité d’interuptions.

Précision : dans les microcontrôleurs il y a la partie programation mais aussi des zones d’électronique numérique pure. C’est parce que l’électronique “câblée” est plus rapide que la programmation, c’est tès utile dans le cas de fonctionalités répétitives (Timer, liaison série, I2C, SPI, PWM, etc…). Cela “soulage” le microcontrôleur qui n’a plus a se préocuper de taches subalternes.

Le programme “actionne” ces blocs d’électronique en écrivant dans des zones mémoire particulière que l’on appelle des registres.

Les “Timers” sont hautement configurables. L’environnement Arduino les configure “a sa sauce” en utilisant une fonction “init()” qui est insérée automatiquement dans le code qui est envoyé au compilateur ce qui fait que tu ne voit rien.

Il est parfaitement possible de les régler autrement mais attention cela peut avoir des conséquence avec les fonctions delay , millis et micro ou avec des bibliothèques qui utilisent la configuration arduino.