Schéma de montage

 

 

Quelques explications :

  • J’ai volontairement inversé le sens d’alimentation du moteur 2, puisqu’il est inversé physiquement sur le châssis.
  • J’utilise le régulateur de tension du module pour alimenter la partie logique du L298N. Il est également possible d’utiliser la sortie +5V du Raspberry Pi. Plus d’info ici.
  • Sur le L298N, l’état bas est entre -0.3V et 1.5V, l’état haut entre 2.3V et 7V, ce qui colle bien avec les sorties 3V du Raspberry Pi.
  • J’utilise la numération BCM des broches du Raspberry Pi. Ce guide est très pratique pour s’y retrouver et en savoir plus sur les GPIO.

 

 Raspberry Pi L298N Description
18 ENA Activation du moteur A. Peut être raccordé à une sortie PWM pour contrôler la vitesse de rotation
23 IN1 Sens du moteur A : 3V → Avant / GND → Arrière
24 IN2 Sens du moteur A : GND → Avant / 3V → Arrière
17 ENB Activation du moteur B. Peut être raccordé à une sortie PWM pour contrôler la vitesse de rotation
27 IN3 Sens du moteur B : 3V → Avant / GND → Arrière
22 IN4 Sens du moteur B : GND → Avant / 3V → Arrière
GND GND Pour avoir une masse commune (Sur le Raspberry, peut importe laquelle)
MOTOR A Sortie de puissance sur le moteur A
MOTOR B Sortie de puissance sur le moteur B
VMS/GND À raccorder sur l’alimentation de puissance. Attention au sens, sinon ça chauffe 😉
04 Led ou buzzer

 

Un peu de code

L’idée est d’écouter 3 boutons du contrôleur :

  • Gâchette droite : En avant
  • Gâchette gauche : En arrière
  • Joystick gauche : Rotation sur soi-même

Ces boutons sont analogiques, on peut récupérer une valeur entre 0 et 100%. Si plusieurs boutons sont pressés en même temps, on prend la direction de celui qui a la plus forte intensité.

 

On reprend la même arborescence de fichiers que pour les tests de la manette de xbox :

.
├── lib
│   ├── __init__.py        Vide
│   ├── xbox_read.py       Script de Zephod pour traiter les évenements
└── controller.py          Script principal

 

#!/usr/bin/python
# -*- coding:Utf-8 -*-

import RPi.GPIO as GPIO
import atexit
from lib import xbox_read
import time

# Evenement a la fermeture
def exit_handler():
    print 'Tchao blaireau !'
    gauche_pwm.stop()
    droite_pwm.stop()
    GPIO.output(MOTEUR_GAUCHE_AVANT_PIN, 0)
    GPIO.output(MOTEUR_GAUCHE_ARRIERE_PIN, 0)
    GPIO.output(MOTEUR_DROIT_AVANT_PIN, 0)
    GPIO.output(MOTEUR_DROIT_ARRIERE_PIN, 0)

atexit.register(exit_handler)

#-------------[ CABLAGE ]--------------------

MOTEUR_GAUCHE_PWM_PIN = 18
MOTEUR_GAUCHE_AVANT_PIN = 23
MOTEUR_GAUCHE_ARRIERE_PIN = 24
MOTEUR_DROIT_PWM_PIN = 17
MOTEUR_DROIT_AVANT_PIN = 27
MOTEUR_DROIT_ARRIERE_PIN = 22
LED_PIN = 04

#-------------[ INITIALISATION DES GPIOS ]--------------

GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)

# Sens de sortie
GPIO.setup(MOTEUR_GAUCHE_PWM_PIN, GPIO.OUT)
GPIO.setup(MOTEUR_GAUCHE_AVANT_PIN, GPIO.OUT)
GPIO.setup(MOTEUR_GAUCHE_ARRIERE_PIN, GPIO.OUT)
GPIO.setup(MOTEUR_DROIT_PWM_PIN, GPIO.OUT)
GPIO.setup(MOTEUR_DROIT_AVANT_PIN, GPIO.OUT)
GPIO.setup(MOTEUR_DROIT_ARRIERE_PIN, GPIO.OUT)
GPIO.setup(LED_PIN, GPIO.OUT)

# Initialisation des PWM
gauche_pwm = GPIO.PWM(MOTEUR_GAUCHE_PWM_PIN, 100000) # Frequence 1 kHz
gauche_pwm.start(0)

droite_pwm = GPIO.PWM(MOTEUR_DROIT_PWM_PIN, 100000) # Frequence 1 kHz
droite_pwm.start(0)

# On commence en marche avant
GPIO.output(MOTEUR_GAUCHE_AVANT_PIN, 1) # ou GPIO.HIGH ou True
GPIO.output(MOTEUR_GAUCHE_ARRIERE_PIN, 0) # ou GPIO.LOW ou False
GPIO.output(MOTEUR_DROIT_AVANT_PIN, 1)
GPIO.output(MOTEUR_DROIT_ARRIERE_PIN, 0)

#-------------[ FONCTIONS ]---------------

vitesse_gauche_courante = 0
vitesse_droite_courante = 0

# Controle la pwm des moteurs en fonction de gauche et droit (de -100% a 100%)
def piloter_moteurs(gauche, droit):
    global vitesse_gauche_courante
    global vitesse_droite_courante
    
	# Contrôle des GPIOS => Sens des moteurs
    GPIO.output(MOTEUR_GAUCHE_AVANT_PIN, gauche >= 0)
    GPIO.output(MOTEUR_GAUCHE_ARRIERE_PIN, gauche < 0)
    GPIO.output(MOTEUR_DROIT_AVANT_PIN, droit >= 0)
    GPIO.output(MOTEUR_DROIT_ARRIERE_PIN, droit < 0)
    
	# Contrôle de la PWM => Vitesse des moteurs
    vitesse_gauche = float(abs(gauche))
    vitesse_droite = float(abs(droit))
    
    if (vitesse_gauche != vitesse_gauche_courante):
        gauche_pwm.ChangeDutyCycle(vitesse_gauche)
        vitesse_gauche_courante = vitesse_gauche
    
    if (vitesse_droite != vitesse_droite_courante):
        droite_pwm.ChangeDutyCycle(vitesse_droite)
        vitesse_droite_courante = vitesse_droite
        
    
#-------------[ ECOUTE DU CONTROLEUR ]--------------

rt_intensite = 0 # Gachette droite -> Marche avant
lt_intensite = 0 # Gachette gauche -> Marche arriere
x1_intensite = 0 # Joystick gauche -> Rotation

print 'En avant Guingamp !'

# En attente d'evenement du controleur
for event in xbox_read.event_stream(deadzone=12000):
    boutons = ['RT', 'LT', 'X1', 'A']
    
    if event.key in boutons:
        # MAJ des valeurs des boutons
        if event.key == 'RT': # De 0 a 255
            rt_intensite = event.value * 100 / 255 # en %
        
        if event.key == 'LT': # De 0 a 255
            lt_intensite = event.value * 100 / 255 # en %
            
        if event.key == 'X1': # De -32767 a 32767 
            x1_intensite = min(100, max(-100, event.value * 100 / 32767)) # Pour rester entre -100 et 100
                
        if event.key == 'A':
            GPIO.output(LED_PIN, event.value)
            
        # On choisit la direction avec la plus grande valeur
        directions = {
            'avant': rt_intensite,
            'droite': x1_intensite if x1_intensite >= 0 else 0,
            'arriere': lt_intensite,
            'gauche': -x1_intensite if x1_intensite < 0 else 0
        }
        direction = max(directions, key=directions.get)
        
        # On pilote les moteurs
        if direction == 'avant' :
            piloter_moteurs(rt_intensite, rt_intensite)
        if direction == 'droite' :
            piloter_moteurs(x1_intensite, -x1_intensite)
        if direction == 'arriere' :
            piloter_moteurs(-lt_intensite, -lt_intensite)
        if direction == 'gauche' :
            piloter_moteurs(x1_intensite, -x1_intensite)

Châssis et moteurs

Comme squelette de ce robot, j’ai choisi un châssis MakeBlock (sans électronique) qui est facilement modulable pour les futures évolutions.

makeblock

Caractéristiques des moteurs :

  • Alimentation: 6 V
  • Vitesse: 185 rpm (à vide)
  • Rapport de réduction: 1:46
  • Consommation à vide: <= 250 mA
  • Consommation en charge: <= 850 mA
  • Couple: +/- 0,5 kg.cm

 

Alimentation

Nous avons besoin d’un source 5V pour alimenter le Raspberry, ainsi qu’une source de 6V pour alimenter les moteurs. Pour le Raspberry, j’ai opté pour cette batterie Anker disponible à 10€.

Pour les moteurs, j’utilise un simple coupleur de 4 piles AA (LR6). Attention, dans le cas d’accumulateurs rechargeables, la tension est de 1,2V par pile au lieu de 1,5V. On se retrouve avec une tension de 4,8V, donc les moteurs ne seront pas à vitesse maximale.

 

Contrôle des moteurs

Pour diriger les deux moteurs en vitesse et direction, on utilise un double pont en H, ici le L298N. Il est disponible en breakout, comprenant déjà les diodes de protection anti retour et un dissipateur. Avec l’utilisation de ce module, il est nécessaire de désactiver certaines résistances pour protéger le Raspberry Pi.

J’utilise ce pont puisque c’est une récupération d’un ancien projet. Pour des moteurs de faible puissance (600mA, 36 volts max), il est possible d’utiliser le L293D.

Pour chaque moteur, 2 entrées permettent de basculer le sens du moteur et une 3ème entrée permet de choisir la vitesse. Pour cela, on utilise un signal carré (PWM) qui nous permet d’adapter la tension de sortie en fonction du rapport cyclique du signal. Pour plus d’information, voir la documention du module.

 

L298N

Source : http://mchobby.be/wiki/index.php?title=Pont-H_L298N