Robot Raspberry Zumo

Au sommaire :

[Archive 2014] Un de mes tout premier projet robotique sur base d’une Raspberry PI version 1  … aujourd’hui , ce projet, est un peu ( ou complètement ) obsolète !

Présentation

Ce petit robot a été réalisé à l’aide d’une carte « Raspberry PI », d’un châssis à chenille de chez « Pololu », et d’une webcam.

a connexion Wifi lui permet de diffuser les flux vidéo sur le réseau et d’être commandé à distance de façon  très simple, depuis un ordinateur ou éventuellement un smartphone type Iphone ou Andoid.

Je vous propose de décrire, en quelques lignes, les différentes étapes de cette réalisation ;  les aspects mécaniques, électroniques et informatiques.

Liste des pièces mécaniques et électroniques

Voici la liste des pièces utilisées lors de la réalisation du robot :

  • Une carte SD de 8Go
  • Un module USB WIFI
  • Un Circuit pont en H 1A SN754410

… et aussi :

  • Un buzzer
  • Une LED tricolore
  • Un circuit imprimé type plaque pastille au pas 2,54mm
  • Quelques fils de connexion à connecteur femelle
  • Quelques entretoises, vis et écrous M3

Présentation rapide de carte Raspberry PI

La carte « Raspberry PI » est un nano-ordinateur de la taille d’une carte de crédit (ou presque : 86x54cm) équipé d’un processeur ARM à 700Mhz.

Elle dispose, dans ca dernière version, de 512Mo de Ram, d’une interface Ethernet 10/100, de 2 interfaces USB, d’une sortie audio 5.1 de type jack 3,5mm et  de deux sorties vidéo (HDMI et composite).

Son processeur graphique embarqué permet un encodage/décodage de flux vidéo au format h264/Mpeg4.

Son support de carte SD lui permet d’accueillir l’élément de stockage principal où est installé le système d’exploitation.

Un connecteur de 2×13 broches fournit :

  • 8 ports GPIO (entrée/sortie)
  • 1 UART Rs232
  • 2 bus SPI
  • 1 bus I2C
  • Une alimentation 5V
  • Une alimentation 3,3V

La carte Raspberry PI est alimentée en 5V via son connecteur micro USB

Configuration de la Raspberry

Installation de la distribution

Même si 4 Go peuvent suffire, j’utilise une carte SD de 8 Go pour héberger le système d’exploitation, ce qui permet d’avoir une souplesse de stockage à des fins expérimental. Il est de plus intéressant d’opter pour une carte performante en termes de débit (30Mb/s par exemple).

Diverses distributions Linux ont été compilées pour le processeur ARM de la image015Raspberry. J’utilise « Raspbian », recommandé par la fondation Raspberry PI, qui est tout simplement une adaptation de la distribution Debian « wheezy ».

 

Il existe plusieurs méthodes pour installer le système, « Win32DiskImage » sous Windows,  « dd » sous linux ou mac …

La toute dernière méthode proposée par la fondation Raspberry PI et fonctionnant sous Windows ou Mac est encore plus simple !!! :

Exemple d’installation de l’OS sous Windows :

  • Extraire le Zip et Copier l’intégralité des fichiers directement sur car SD
  • Installer la carte SD dans le slot de carte Raspberry PI
  • Démarrer la carte Raspberry en connectant écran, clavier, souris, interface réseau et alimentation
  • Le mode « Recovery »  de la raspberry  fait le reste … !!!

Configuration système

Lors du premier démarrage, sélectionner l’installation de la distribution « Raspbian ».

Après quelques minutes d’installation et un premier reboot, l’utilitaire « raspi-config » se lance automatiquement. Il permet de définir :

  • le mot de passe
  • les locales  (par exemple : fr_FR ISO-8859-1 et fr_FR.UTF-8 UTF-8)
  • le fuseau horaire
  • le type de clavier
  • le nom de host

Première connexion avec le nom d’utilisateur « pi », et mise à jour du système :

Puis :

Et pour le fun, un peu de couleur dans vi :

 

Installation des packages nécessaire

Dans cette distribution, les environnements de développement (Python, C, …) ainsi que  le module GPIO « python3-rpi.gpio » sont déjà installés, Il ne reste que peu de chose à installer.

La librairie « RPIO » sera nécessaire ; Elle permet de générer des signaux de type PWM.

D’autres packages seront également utile,  pour le wifi, la webcam …   ils sont traités plus bas

Configuration du wifi

Dans sa configuration actuelle, le robot se connecte directement à la borne Wifi de mon domicile. Ce qui lui permet un accès complet aux diverses ressources du réseau local, et un accès à Internet.

Une autre solution (une évolution possible) pourrait être de configurer la carte Raspberry en Acces-Point Wifi (en « hotspot »), ce qui la rendrait entièrement autonome.

L’ajout de l’adaptateur Usb Wifi crée une interface réseau nommée « wlan0 »,  il suffit d’éditer le fichier  /etc/network/interfaces pour configurer une adresse IP, le SSID et mot de passe wifi.

				
					auto wlan0
iface wlan0 inet static
        address 192.168.21.61
        netmask 255.255.255.0
        network 192.168.21.0
        broadcast 192.168.21.255
        gateway 192.168.21.1
        wpa-ssid "mon_wifi"
        wpa-psk "mon_mot_de_passe"
				
			

Gestion de la webcam et du flux video

L’objectif est de diffuser le simplement possible, le flux vidéo de la webcam sur le réseau local.

Après plusieurs tentatives avec diverses solutions tel que Motion, ffmpeg, vlc  ou autres,  j’ai fini par adopter « MJPG-Streamer » qui pour avantages d’être peu consommateur en ressources, d’embarquer son propre serveur web pour la diffusion, et le tout avec une faible latence !

MJPG-Streamer n’est pas packagé pour Raspbian, il faut donc le compiler pour le processeur ARM de la Raspberry.

Les sources sont disponibles sur sourceforge : http://sourceforge.net/projects/mjpg-streamer/

Installation de MJPG-Streamer

				
					#  cd /home/pi
 
#  wget  http://sourceforge.net/projects/mjpg-streamer/files/mjpg-streamer/Sourcecode/mjpg-streamer-r63.tar.gz
#  tar -zxvf mjpg-streamer-r63.tar.gz
#  ln -s mjpg-streamer-r63 mjpg-streamer
#  cd mjpg-streamer
 
#  ln -s /usr/include/linux/videodev2.h /usr/include/linux/videodev.h
#  apt-get install libjpeg8-dev libmath++-dev
 
#  make clean all
				
			

Lancement du processus MJPG-Streamer

				
					# /home/pi/mjpg-streamer/start.sh
 
MJPG Streamer Version.: 2.0
 i: Using V4L2 device.: /dev/video0
 i: Desired Resolution: 640 x 480
 i: Frames Per Second.: 5
 i: Format............: MJPEG
 o: www-folder-path...: ./www/
 o: HTTP TCP port.....: 8080
 o: username:password.: disabled
 o: commands..........: enabled
				
			

Reste à vérifier :         http://Mon_Adresse_IP:8080

Schémas électroniques

Connecteur GPIO

Voici le détail du connecteur de 2×13 broches de Raspberry.

Les broches sont numérotées de 1 à 26 sont également identifiées par une référence GPIO qui est plus simple à utiliser lors de la programmation. Elles peuvent être configurées en entrée ou en sortie.

Le Robot « Raspberry Zumo » utilise (dans sa version actuelle) 8 sorties GPIO :

  • GPIO 25       –>    Moteur Droite, marche avant
  • GPIO 24       –>    Moteur Droite, marche arrière
  • GPIO 23       –>    Moteur Gauche, marche avant
  • GPIO 18       –>    Moteur Gauche, marche arrière
  • GPIO 22       –>    LED tricolore, rouge
  • GPIO 27       –>    LED tricolore, vert
  • GPIO 17       –>    LED tricolore, bleu
  • GPIO 04       –>   Buzzer

Précision sur l’alimentation

Le robot utilise deux sources d’énergie.

  • La batterie ANKER de 3000mAh fournit 5volt à la Rasberry et ces interfaces USB, comprenant le module Wifi et la Webcam. Elle alimente également la LED externe et le circuit SN754410
  • Quatre piles rechargeables placées dans le châssis à chenille fournissent environ 6Volt aux deux moteurs

Schéma du robot « Raspberry Zumo »

Les sorties GPIO fournissent 3.3Volt pour un courant maximum de 100mA. Il est donc très simple d’alimenter une LED ou un Buzzer.

En revanche pour commander les 2 moteurs 6volt à courant continu, et qui plus est, pour gérer leur sens de rotation, il est nécessaire d’utiliser un « circuit pont en H ». J’utilise un SN754410 (équivalant au L293D) qui permet de piloter deux moteurs CC de 4,5V à 36V provenant d’une source d’alimentation dédiée, pour un prix très économique.

Programmation

Descriptif des fonctions

L’objectif est de développer un petit programme permettant de piloter les deux moteurs, d’allumer la LED tricolor en mode « tout-ou-rien » pour chaque couleurs et d’envoyer un signal de type PWM au buzzer.

Pour faciliter l’envoie de commandes via le réseau et permettre de futurs évolutions, j’ai souhaité mettre en place une solution client/serveur. Le robot héberge un serveur IP qui crée un socket TCP sur le port 12345. Cela a comme principal avantage d’être complètement indépendant de la plate-forme cliente (Linux, MacOs, Windows, Smartphone..) et du langage utilisé (Java, C… ou autre). Telnet, peut par exemple, et dans un premier temps, être très bon client !

Les différentes librairies et exemples sont disponibles pour la Raspberry en langage Python. De plus l’environnement de développement est déjà préinstallé dans la distribution Raspbian Wheezy. Le serveur est donc développé en Python. Les principales commandes (marche avant, marche arrière, tourner à droite ou à gauche ….etc) ont été implémenté ainsi qu’un petit menu à la connexion.

Le code

Le fichier « robot-srv.py » est créé dans le répertoire /home/pi,  l’attribut d’exécution doit être positionné sur ce fichier (chmod +x)

				
					#!/usr/bin/python
# -*- coding:Utf-8 -*-
 
from RPIO import PWM
import RPIO
import socket
import RPi.GPIO as GPIO
import time
import sys
 
HOST = "0.0.0.0"
PORT = 12345
 
#-------------[ CABLAGE ]--------------------
My_LED = 22
 
Moteur_1_Forward = 25
Moteur_1_Reverse = 24
Moteur_2_Forward = 23
Moteur_2_Reverse = 18
 
LED_R = 22
LED_V = 27
LED_B = 17
BUZZER_PIN = 04
 
#-------------[ Initialisation ]--------------
 
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BCM)
GPIO.setup(Moteur_1_Forward, GPIO.OUT)
GPIO.setup(Moteur_1_Reverse, GPIO.OUT)
GPIO.setup(Moteur_2_Forward, GPIO.OUT)
GPIO.setup(Moteur_2_Reverse, GPIO.OUT)
 
GPIO.setup(LED_R, GPIO.OUT)
GPIO.setup(LED_V, GPIO.OUT)
GPIO.setup(LED_B, GPIO.OUT)
 
BUZZER = RPIO.PWM.Servo()
 
 
#--------------------------------------------
def BIP() :
   BUZZER.set_servo(BUZZER_PIN,15000)
   time.sleep(.1)
   BUZZER.stop_servo(BUZZER_PIN)
   time.sleep(.01)
   BUZZER.set_servo(BUZZER_PIN,15000)
   time.sleep(.1)
   BUZZER.stop_servo(BUZZER_PIN)
 
def AVANT() :
    print "Marche Avant"
    GPIO.output(Moteur_1_Forward, GPIO.HIGH)
    GPIO.output(Moteur_2_Forward, GPIO.HIGH)
 
def ARRIERE() :
    print "Marche Arriere"
    GPIO.output(Moteur_1_Reverse, GPIO.HIGH)
    GPIO.output(Moteur_2_Reverse, GPIO.HIGH)
    time.sleep(0.5)
    STOP()
 
def DROITE() :
    print "tourne a droite"
    GPIO.output(Moteur_1_Forward, GPIO.HIGH)
    GPIO.output(Moteur_2_Reverse, GPIO.HIGH)
    time.sleep(0.5)
    STOP()
 
def DROITE_Toute() :
    print "tourne a droite"
    GPIO.output(Moteur_1_Forward, GPIO.HIGH)
    GPIO.output(Moteur_2_Reverse, GPIO.HIGH)
 
def GAUCHE() :
    print "tourne a gauche"
    GPIO.output(Moteur_1_Reverse, GPIO.HIGH)
    GPIO.output(Moteur_2_Forward, GPIO.HIGH)
    time.sleep(0.5)
    STOP()
 
def GAUCHE_Toute() :
    print "tourne a gauche"
    GPIO.output(Moteur_1_Reverse, GPIO.HIGH)
    GPIO.output(Moteur_2_Forward, GPIO.HIGH)
 
 
def STOP () :
    print "stop"
    GPIO.output(Moteur_1_Forward, GPIO.LOW)
    GPIO.output(Moteur_2_Forward, GPIO.LOW)
    GPIO.output(Moteur_1_Reverse, GPIO.LOW)
    GPIO.output(Moteur_2_Reverse, GPIO.LOW)
 
 
def LED_R_UP() :
    print "LED Rouge Marche"
    GPIO.output(LED_R, GPIO.HIGH)
def LED_V_UP() :
    print "LED Vert Marche"
    GPIO.output(LED_V, GPIO.HIGH)
def LED_B_UP() :
    print "LED Bleu Marche"
    GPIO.output(LED_B, GPIO.HIGH)
def LED_DOWN() :
    print "LED Stop"
    GPIO.output(LED_R, GPIO.LOW)
    GPIO.output(LED_V, GPIO.LOW)
    GPIO.output(LED_B, GPIO.LOW)
 
def MENU() :
    connexion.send( "\n\r" )
    connexion.send( "  A  --> en Avant\n" )
    connexion.send( "  R  --> en Arriere\n" )
    connexion.send( "  D  --> a Droite\n" )
    connexion.send( "  DD --> a Droite (sans stop)\n" )
    connexion.send( "  G  --> a Gauche\n" )
    connexion.send( "  GG --> a Gauche (sans stop)\n" )
    connexion.send( "  S  --> STOP\n" )
    connexion.send( "  1  --> LED Rouge ON\n" )
    connexion.send( "  2  --> LED Vert ON\n" )
    connexion.send( "  3  --> LED Bleu ON\n" )
    connexion.send( "  0  --> LED OFF\n" )
    connexion.send( "  B  --> BIP\n" )
    connexion.send( "  M  --> MENU\n" )
    connexion.send( "\n" )
 
print "GO"
print "Start\n"
 
# Creation du socket
mySocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
 
# Liaison du socket avec l'interface
try:
   mySocket.bind((HOST, PORT))
except socket.error:
   print "La liaison du socket à l'adresse choisie a échoué."
   sys.exit()
 
BIP()
# --------------------------------------
while 1:
 
   print "Serveur en attente ..."
   mySocket.listen(5)
 
   # Etablissement de la connexion :
   connexion, adresse = mySocket.accept()
   print "Client connecté, adresse IP %s, port %s" % (adresse[0], adresse[1])
 
   # Envoi d'un message qu client :
   connexion.send("\nWelcome to Fred's Robot Server\n\n")
   MENU()
 
   # Reception des message client
   while 1:
      msgClient = connexion.recv(10).rstrip()
      print "C>"+msgClient+"<"
      if msgClient.lower() == "fin" or msgClient =="" or msgClient.lower() == "stop":
         print "Break !!!"
         break
 
      elif msgClient.upper() == "M" :
         MENU()
 
      # Commandes Robot
      elif msgClient.upper() == "A" :
         AVANT()
      elif msgClient.upper() == "R" :
         ARRIERE()
      elif msgClient.upper() == "D" :
         DROITE()
      elif msgClient.upper() == "DD" :
         DROITE_Toute()
      elif msgClient.upper() == "G" :
         GAUCHE()
      elif msgClient.upper() == "GG" :
         GAUCHE_Toute()
      elif msgClient.upper() == "S" :
         STOP()
      elif msgClient.upper() == "1" :
         LED_R_UP()
      elif msgClient.upper() == "2" :
         LED_V_UP()
      elif msgClient.upper() == "3" :
         LED_B_UP()
      elif msgClient.upper() == "0" :
         LED_DOWN()
      elif msgClient.upper() == "B" :
         BIP()
 
 
   # Fin de la session
   connexion.send("By By !")
   print "Connexion interrompue."
   connexion.close()
 
   # fin du programme
   if msgClient.lower() == "stop":
      break
				
			

Tests

Et voilà !!!  Il ne reste plus qu’à tester !

Donc sur la raspberry PI,  heu … NON !!! à SUR LE ROBOT « Raspberry ZUMO », on lance la Webcam & le serveur :

				
					# /home/pi/mjpg-streamer/start.sh
 
# /home/pi/robot-srv.py
				
			

Et on test, depuis un poste Windows par exemple :

Galerie photos