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)

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/

Pour pouvoir être mobile, le raspberry doit pouvoir communiquer par Wifi. J’ai choisi la nano clé wifi TP-Link TL-WN725N V2 qui peut se trouver à moins de 10€.

 

Installation du pilote

Cette clé Wifi ne fonctionne pas directement après l’avoir branché, il faut installer manuellement le pilote. Un internaute écrit ce script shell qui télécharge et installe le pilote correspondant à la version du noyau linux de la machine. Après exécution du script et reboot du Raspberry, l’interface wlan0 devrait apparaître sur la liste des interfaces réseau (ifconfig)

 

Si le script ne trouve pas la version du pilote associé au noyau, il est peut-être nécessaire de mettre à jour avec la commande rpi-update.
La commande uname -a permet de connaître la version du noyau installé.

root@raspberrypi:~# uname -a
Linux raspberrypi 4.1.18+ #845 Thu Feb 18 19:37:13 GMT 2016 armv6l GNU/Linux

 

Si le script ne trouve toujours pas le pilote,  ça veut sûrement dire que le nouveau noyau est trop récent. La liste des versions supportées est disponible sur ce forum. Si la version du noyau n’y est pas, il faut downgrader jusqu’au dernier supporté, en suivant cette procédure.

 

Source : http://www.latelierdugeek.fr/2014/05/20/installer-la-clef-wifi-tp-link-tl-wn725n-v2-sur-un-raspberrypi-avec-raspbian/
https://www.raspberrypi.org/forums/viewtopic.php?p=462982#p462982

 

Configuration de la connexion

Le fichier /etc/network/interfaces qui contient la configuration des interfaces réseau doit être sous la forme :

auto lo
iface lo inet loopback

auto eth0
allow-hotplug eth0
iface eth0 inet manual

auto wlan0
allow-hotplug wlan0
iface wlan0 inet manual
wpa-conf /etc/wpa_supplicant/wpa_supplicant.conf

 

Le fichier /etc/wpa_supplicant/wpa_supplicant.conf correspond à la configuration du réseau Wifi où le Raspberry doit se connecter.

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
	ssid="Le_SSID_De_Ma_Box"
	psk="LeMotDePasseDeMaBox"
}

 

Pour tester, il faut redémarrer l’interface et afficher la configuration du wifi :

ifdown wlan0
ifup wlan0
iwconfig

 

Source : http://www.fars-robotics.net/

Premier démarrage

Le premier démarrage nécessite que le Raspberry soit branché sur un écran par un câble HDMI et un clavier. Après l’avoir démarré, si l’écran reste noir, il est peut-être nécessaire de modifier le fichier config.txt qui se trouve à la racine de la carte SD, sur la partition accessible depuis Windows.

Décommentez la ligne contenant hdmi_force_hotplug=1 pour forcer le signal vers la sortie HDMI.
Si malgré ça l’écran reste noir, essayez de mettre config_hdmi_boost=4 ou supérieur (jusqu’à 9). Si l’affichage est un écran d’ordinateur, utilisez hdmi_group=1 ou si c’est une télévision plus ancienne, hdmi_group=2. Ne pas mettre hdmi_safe=1 ou cela écraserait les précédentes options.

Source : https://www.raspberrypi.org/forums/viewtopic.php?f=91&t=34061

 

Configuration

On arrive sur l’interface de configuration. Elle est accessible avec la commande sudo raspi-config

raspi-config

On y retrouve les options :

  • Expand Filesystem : Pour que la totalité de la carte SD soit prise en compte (par défaut il ne s’occupe que de 4 Go)
  • Change User Password : Changer le mot de passe de l’utilisateur par défaut (pi)
  • Enable Boot to Desktop/Scratch : Si vous mettez non à cette option l’interface graphique ne sera pas démarré. Vous pouvez la démarrer plus tard à l’aide de la commande startx.
  • Internationalisation Options : Permet de configurer la langue par défaut, le clavier et le fuseau horaire.
  • Enable Camera : Pour pouvoir utiliser la caméra
  • Add to Rastrack : Pour participer au projet Rastrack
  • Overclock : Pour overclocker le Raspberry Pi
  • Advanced Options : Plusieurs options comme la mise à jour du système ou la gestion du SSH.

Au minimum, il faut activer le protocole SSH si on veut pouvoir accéder au Raspberry sans écran.

Une fois la configuration terminée, on va connecter le Raspberry sur le même réseau local que l’ordinateur qui va y accéder par SSH. Avec un câble Ethernet, on le relie directement à l’ordinateur, ou sur la box de la maison.

On va prendre soin de noter l’IP locale avec la commande ifconfig si on veut pouvoir s’y connecter. Si le Raspberry est branché sur la box, on peut aussi trouver l’IP avec le logiciel SoftPerfect WifiGuard qui va envoyer un ping sur toutes les IP du réseau local. (On pourrait également le faire en cas d’une connexion directe, mais comme le broadcast est 255.255.0.0, cela va mettre beaucoup plus de temps).

Source : http://hawkcreation.com/raspberry-pi-installation-premiers-pas/

 

Connexion par SSH

Sur Windows, il faut utiliser putty pour se connecter, ou le logiciel WinSCP qui intègre putty et permet le FTP/SFTP.
On se connecte sur l’IP notée précédemment avec les identifiants : pi:raspberry

On en profite pour mettre à jour le mot de passe root :

 sudo su
 passwd

Télécharger l’image de Raspbian

Pour ce projet, j’ai décidé de choisir l’OS Raspbian dans sa version Wheezy, puisque c’était la plus récente au commencement du projet. On la trouve sur le site officiel Raspberry, ou le cas échéant, sur des sites comme Raspbian-France.

 

Copie de l’image sur une carte SD

À l’aide du logiciel Win32 Disk Imager, on va écrire l’image sur la carte SD, qui doit pouvoir contenir au minimum 8Go.

Après l’avoir installé et executé, selectionner l’image de Raspbian puis la lettre du lecteur correspondant à  SD. Cliquer sur Write pour commencer la copie.

Source : http://www.libellules.ch/phpBB2/debuter-avec-le-raspberry-pi-t40775.html#p290244