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

Installation du pilote

J’utilise une manette sans-fil de Xbox 360 prévue pour PC. Pour installer les pilotes :

sudo apt-get install xboxdrv

On vérifie que la manette est prête à être utilisée :

sudo xboxdrv

 

Comme indiqué, s’il y a une erreur Error couldn't claim the USB interface: LIBUSB_ERROR_BUSY, il faut exécuter la commande sudo rmmod xpad puis relancer xboxdrv, ou lancer xboxdrv avec l’option --detach-kernel-driver.

On peut démarrer la manette si ce n’était pas déjà, et cette commande affiche les événements qu’elle reçoit. Si aucun événement ne s’affiche, il faut peut-être resynchroniser en appuyant 3 secondes sur le bouton du récepteur, puis sur celui de la manette.

 

Source : http://mattdyson.org/blog/2013/01/using-an-xbox-360-wireless-controller-with-raspberry-pi/

 

Utilisation avec Python

Pour l’utiliser avec Python, j’utilise ce script écrit par Zephod : https://github.com/zephod/lego-pi/blob/master/lib/xbox_read.py
Pour l’utiliser en tant que librairie, on le met dans un dossier lib avec un fichier __init__.py qui peut être vide. Ce fichier sert à indiquer que le dossier est un package importable.

 

L’arborescence des fichiers est :

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

 

Le fichier test.py contient :

#!/usr/bin/python

from lib import xbox_read

for event in xbox_read.event_stream(deadzone=12000):
	print event

 

On lui donne les droits en exécution et on le lance :

chmod +x test.py
sudo python test.py

 

Source : https://github.com/zephod/lego-pi
http://tomre.es/post/lego-xbox-raspberry-pi/
http://mattdyson.org/blog/2013/01/using-an-xbox-360-wireless-controller-with-raspberry-pi/

 

Contrôle de GPIO

En guise de Hello World, on va allumer une LED à l’appui du bouton A de la manette. Voici le schéma de montage associé :

 

Schéma de montage

Schéma de montage

 

On garde la même arborescence de fichier que précédemment :

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

 

Pour interagir avec les entrées/sorties GPIO, on utilise le module RPi.GPIO. Je n’ai pas eu besoin de l’installer sur le Raspberry mais si jamais, voici les instructions d’installation.

#!/usr/bin/python

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

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

LED_PIN = 04

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

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

GPIO.setup(LED_PIN, GPIO.OUT)

#-------------[ ECOUTE DU CONTROLEUR ]--------------

print 'En avant Guingamp !'

# En attente d'evenement de la manette
for event in xbox_read.event_stream(deadzone=12000):
    if event.key == 'A':
		GPIO.output(LED_PIN, event.value)
		if event.value == 1:
			print 'Bip'

 

Documentation de RPi.GPIO : https://sourceforge.net/p/raspberry-gpio-python/wiki/Examples/