Une base motorisée

Nous allons commencer par une base à 3 roues, dont deux motorisées. C’est un classique qui permet de diriger le mobile en faisant varier la vitesse relative des deux roues latérales et motorisées. C’est aussi générateur de difficulté, puisque que pour rouler en ligne droite, il faut s’assurer que ces deux roues tournent bien à la même vitesse. La dernière roue sera une « roue-folle » qui tournera en fonction des forces exercées par les roues motorisées. Voilà ce que peut donner ce type de base :

Liste des composants

Au vu des dimensions du socle et de sa capacité d’évolution ultérieure, on va partir sur les éléments suivants (les liens sont donnés à titre indicatifs) :

On fera aussi porter par ce bloc fonctionnel, la capacité d’alimentation de l’ensemble du robot en 12V évidemment, et aussi en 5V / 2W, ainsi que quelques protections :

Pour interconnecter tout ça, il faudra aussi quelques résistances et diodes, fusibles, interrupteurs et surtout du fil (multibrins, AWG24 et AWG20 pour l’alimentation), soudure, etc.

Bloc alimentation

Ce bloc présente une prise pour la batterie Li-Ion 12,6V, un fusible 5A, un interrupteur marche/arrêt, une diode de protection de polarité, un convertisseur vers 5V (hacheur), 2 fusibles réarmables (polyfuses), un bornier de sortie et trois leds et leurs résistances associées qui indiqueront les présences tensions (batterie, 12V et 5V).

On pourra ajouter un bouton « coup de point » pour permettre l’arrêt d’urgence.

Bloc moteurs

Ce bloc va porter plusieurs fonctions :

  • Commande de puissance des moteurs ;
  • Gestion des détecteurs ultra-son pour assurer une protection volumétrique autour du robot (anti-collision) ;
  • Des commandes manuelles ;
  • Bus de communication (SPI) pour la communication avec le bloc de commande générale.
Les branchement du micro-contrôleur ne sont pas corrects

Dans le schéma précédent, on retrouve les composants nécessaires à la réalisation des fonctions. La commande des moteurs est basée sur un circuit L298 à double pont H qui permet :

  • Le contrôle des deux moteurs indépendamment,
  • La rotation dans les deux directions,
  • La vitesse variable de rotation.

Les moteurs sélectionnés étant équipés de codeurs angulaires, il faudra aussi prévoir leur connexion sur les entrées de l’Arduino.

Logiciel

Ce qui fait la force du microcontrôleur ATmega328 ce sont le nombre de fonctions câblées qu’il comporte, mais cela fait aussi sa faiblesse car il ne possède pas assez de broches pour les autoriser à fonctionner toutes ensemble. Il faut donc faire des compromis.

Pour assurer toutes les fonctions indiquées précédemment, il faudra donc utiliser :

  • le TIMER0 pour ses sorties en modulation de largeur d’impulsion (PWM) ainsi que 4 autres sorties pour la commande de sens des moteurs;
  • l’USART en mode série pour faire le débug par le port USB existant de l’Arduino Nano (2 broches : TX0, RX0) ;
  • le port de communication SPI en mode esclave pour recevoir les ordres de l’autre carte (4 broches : SS, SCK, MOSI, MISO) – à moins qu’une Raspberry PI face le boulot avec ses ports USB;
  • les entrées INT0 et INT1 pour recevoir les séquences des capteurs angulaires des moteurs, ainsi que deux entrées supplémentaires pour l’autre phase des capteurs ;
  • deux sorties et deux entrées pour assurer les déclenchements des capteurs Ultra-Son respectivement leurs réponses ;
  • deux entrée analogiques pour un joy-stick de commande en manuel.

Commande de hacheurs

Pour commander les hacheurs, on va moduler l’entrée EN de chacun d’eux avec le PWM de l’Arduino. On va devoir utiliser le TIMER0 (8 bits) parce que les broches associées sont les seules disponibles (OC0A & OC0B).

La documentation du L298 indique qu’il doit être modulé idéalement à 25 kHz et au maximum à 40 kHz. Évidemment plus la fréquence est au-dessus des 20 kHz, moins on entendra les moteurs « siffler ». Une valeur théorique de 30 kHz semble une base idéale.

Les timers n’ont pas une grande latitude de fréquence de modulation PWM, puisqu’ils utilisent la fréquence de l’horloge interne que l’on peut diviser par quelques puissances de deux.

Si l’on utilise le TIMER0 dans sa configuration la plus simple (Mode Fast PWM), il ne pourra fonctionner qu’aux fréquences données par la formule :

$$f_{osc} = {f_{io} \over {N * (TOP + 1)}}$$

AN : fio = 16 MHz ; TOP = 255; N = 1, 8, 64, 256 et 1024

$$f_{osc} = {{16 \text{MHz}} \over {N * 256}}$$

$$N = 1 => f_{osc} = {{16000 \text{kHz}} \over 1*256} = 62.5 \text{kHz}$$

$$N = 8 => f_{osc} = {{16000 \text{kHz}} \over 8*256} = {{16000 \text{kHz}} \over 2048} = 7.8125 \text{kHz}$$

Si la première valeur pour N = 1 est trop haute, la suivante pour N = 8 est elle trop basse. Par contre si l’on pouvait diviser par deux la première on tomberait sur une valeur acceptable.

On peut obtenir cet effet avec les modes « PWM sans déphasage », la fréquence de modulation est données par une formule qui réduit de deux la valeur pour les mêmes paramètres :

$$f_{osc} = {f_{io} \over {N * 2 * TOP}}$$

AN : fio = 16 MHz ; TOP = 255; N = 1

$$f_{osc} = {{16000 \text{ kHz}} \over {1 * 2 * 255}} = {{16000 \text{ kHz}} \over {510}} = 31.37 \text{ kHz}$$

Et ça, ça tombe dans intervalle acceptable du driver des moteurs !

On pourra donc moduler les deux entrées EN du L298 entre 0 et 255, soient 28 (8 bits).

Le TIMER0 a ses 2 sorties modulées OC0A & OC0B sur les ports D5 et D6 de l’Arduino Nano ; ces deux broches iront donc directement sur les EN1 & EN2 de la carte L298.

La configuration du TIMER0 sera donc la suivante :

  • Mode PWM sans déphasage #1 : WGM02,01,00 = 001 ;
  • signal d’horloge à 16 MHz (pas de prédivision) : CS02,01,00 = 001 ;
  • Sorties OC0A & OC0B en mode non inversé : COM0A1,COM0A0= 10 ; COM0B1,COM0B0= 10.

TCCR0A – Timer/Counter0 Control Register A
COM0A1 = COM0B1 = 1 ; COM0A0 = COM0B0 = 0 ; WGM01 = 0 ; WGM00 = 1
Valeur : 10100001

TCCR0B – Timer/Counter0 Control Register B
WGM02 = 0 ; CS02,01,00 = 001
Valeur : 00000001

TCNT0 – Timer/Compter 0
Peut être remis à zéro, avant de lancer le timer, mais sans grand intérêt

OCR0A – Output Compare Register 0A
Valeur comparée au compteur en continu pour former le signal présent sur la sortie OC0A

OCR0B – Output Compare Register 0B
Valeur comparée au compteur en continu pour former le signal présent sur la sortie OC0B

void setup() {
  DDRD |= _BV(DDD5) | _BV(DDD6);  // PD5 (D5) & PD6 (D6) : OUTPUT
  TCCR0A = 0b10100001;
  TCCR0B = 0b00000001;
  OCR0A = 0;  // PWM A = 0 [0,255]
  OCR0B = 0;  // PWM B = 0 [0,255]
}

A noter que le timer en mode PWM continue à produire un pic quand la valeur du registre OC0x est à zéro. Si l’on veut éviter toute sortie à l’état haut, il faut repasser les sorties du timer en mode déconnecté et s’assurer que le port correspondant est bien en sortie à l’état bas.

Références