IMA4 2016/2017 P30 : Voiture radiocommandée controlée par gant

De Wiki de Projets IMA


Vidéo HD


Cahier des charges

Présentation générale du projet

Contexte

Les véhicules commandés par une commande radio existent depuis déjà bien longtemps. Cependant, peu de nouveautés au niveau du contrôle ont été apportés. Proposer une télécommande différente et intuitive à utiliser (avec le corps) peut donc s'avérer intéressant et toucher un large public. De plus, le fait d'embarquer un serveur web (sur lequel l'utilisateur trouverait une vidéo filmée en direct par la caméra sur le véhicule) fait intervenir la notion d'objet connecté, qui sont en pleine expansion depuis ces dernières années.

Objectif du projet

Le projet "Voiture radiocommandée contrôlée par gant" consiste à réaliser une télécommande pour piloter une voiture radiocommandée à distance. La commande à créer doit permettre de contrôler les mouvements de la voiture avec le corps. Dans notre cas, la commande sera un gant afin que l'utilisateur puisse faire bouger la voiture avec sa main.

Description du projet

Ce projet propose donc de réaliser entièrement le gant qui contrôlera la voiture, mais également de remplacer la commande déjà existante et par conséquent de contrôler directement les moteurs. Il se découpe donc en trois grandes parties :

  • Création du gant et acquisition des données des capteurs.
  • Contrôles des servomoteurs.
  • Réalisation de la communication entre le contrôleur (gant) et les moteurs.

Choix techniques : matériel et logiciel

Afin de mener à bien le projet, nous aurons besoin du matériel ci-dessous :

  • Un gant sur lequel nous collerons un accéléromètre. L'accéléromètre sera utilisé pour faire tourner la voiture à droite ou à gauche, mais également pour avancer et reculer. Lorsque l'utilisateur penchera la main vers l'avant ou vers l'arrière, la voiture avancera ou reculera. Il en sera de même pour faire tourner la voiture. Afin de récupérer et traiter les données issues des capteurs, nous aurons besoin d'une plateforme Arduino Nano accrochée au gant.
  • Une voiture radiocommandée sur laquelle seront embarquées une Raspberry Pi. La Raspberry Pi aura pour fonction de recevoir les données envoyées par le premier et de commander les servomoteurs. Elle sera également utilisée pour héberger un serveur Web (qui sera ré-utilisée dans la cadre des TP IMA5). Nous pouvons aussi nous servir de la caméra de RPi pour que l'utilisateur ait une vue depuis sa voiture si il pour bouger d'une pièce à une autre dans son logement par exemple.
  • Deux modules Xbee Shield seront montés sur l'Arduino et la Raspberry Pi afin de gérer la liaison sans fil entre la télécommande et la voiture. Le protocole Zigbee permet une transmission de données sur une portée de 30m en intérieur et jusqu'à 100m en extérieur, ce qui semble convenable pour le projet.

Pour réaliser, nous aurons également besoin d'un PC pour configurer les modules (tel que la RPi), mais aussi pour programmer. Pour cela, Arduino IDE devra être installé sur le PC. Enfin, nous pourrons recourir à des librairies supplémentaires en cours de projet si nous en trouvons l'utilité.

Calendrier prévisionnel

Liste des tâches à effectuer

  • Partie télécommande (le gant)
    • Récupération et traitement des valeurs issues des capteurs avec l'Arduino.
    • Création du gant : fixer dessus les flex sensor, l'accéléromètre et l'Arduino.
  • Partie embarqué (la voiture)
    • Configuration de la Raspberry Pi et installation du serveur web (probablement Apache).
    • Installation physique des modules embarqués sur la voiture.
    • Contrôle des servomoteurs en fonction des données reçues.
  • Communication sans fil
    • Installation des modules Xbee sur les Arduinos.
    • Prise en main du protocole.
    • Tests de portée et d'envoi/réception de données.
    • Mise en place de la liaison finale.

Calendrier

  • Partie télécommande : 90h
  • Partie embarqué : 90h
  • Partie communication : 30h
  • Coordination entre tout les éléments, tests et validation du prototype : 20h
  • Finitions, remplissage du wiki : 10h

Feuille d'heures

Tâche Prélude Heures S1 Heures S2 Heures S3 Heures S4 Heures S5 Heures S6 Heures S7 Heures S8 Heures S9 Heures S10 Total
Cahier des charges et justifications des choix 4 4
Rédaction du wiki 1 1 1 1 1 1 1 1 1 1 1 10
Tests et choix de l'Arduino Nano, programmation Arduino 6 6
Prise en main de Xbee, réception de données 5 5
Installation de la RPi en point d'accès Wi-Fi 3 4 7
Programmation, tests et recherches sur la RPi (création de PWM, tests avec des LEDs) 3 7 7 2 2 21
Mise en lien de l'Arduino et de la RPi (réception de données en fonction du capteur) 4 4
Réalisation d'un Shield RPi (Fritzing et soudure) 3 7 5 15
Tests sur la voiture 5 5 10
Conception de shield pour tenir l'arduino, accéléromètre et module XBee. 3 3
Travail supplémentaire (calibrage, modifications de dernière minute) 8 8

Avancement du Projet

Semaine 1

Durant la première séance de la semaine, nous avons revu avec nos enseignants le cahiers des charges initial afin d'affiner et de modifier certains choix. Après avoir vu sur internet que la Raspberry Pi pouvait réaliser une PWM et était compatible avec le module Xbee (choisi pour la transmission de données), nous avons décidé de supprimer l'Arduino prévue sur la voiture pour ne conserver qu'une Raspberry Pi. Cette dernière peut également prendre de la vidéo, comme cela est optionnellement prévu. Pour le gant, l'Arduino Uno étant trop grande, notre choix s'est tourné vers les modèles plus petits : Micro ou Mini.

Pour la deuxième séance, nous avons commencé à utiliser l'Arduino Mini. Cette carte est petite mais n'embarque pas de liaison pour la relier à un PC et y mettre du code. La première chose à faire à été essayer de brancher la carte via un programmateur FTDI suivant le montage suivant :

Montage qui permet d'upload un code sur l'Arduino Mini

Après différent essais, nous ne parvenons pas à envoyer un code sur la carte avec Arduino IDE lorsque l'on sélectionne "Arduino Mini /w Atmega328". Lorsque l'on sélectionne "Arduino Micro" cependant, le programme est envoyé dans la carte mais ne fonctionne pas (les pins sont différentes entre les Arduino).

Après quelque recherches, on a vu qu'il était possible d'utiliser une Arduino Nano comme programmateur FTDI :

Montage qui permet d'upload un code sur l'Arduino Mini via Arduino Uno

Les problèmes restent les mêmes qu'avec le FTDI utilisé précédemment. Finalement, la carte sera remplacée par une Arduino Nano, légèrement plus grande mais disposant d'une liaison USB déja intégrée. Si nous avons encore du temps à la fin, nous pourrons ré-essayer d'utiliser une carte plus petite.

Durant la dernière séance de la semaine, nous avons récupéré les composants tels que les modules Xbee, l'Arduino Nano et commencé à tester ces derniers. Nous avons également fait la liste du matériel.

Semaine 2

Pendant la deuxième semaine, avons échangé l'Arduino Micro par une Arduino Nano. La semaine à consisté en des tests sur les modules Xbee avec le logiciel X-CTU. Ce dernier propose une interface graphique et permet de paramétrer les modules, ainsi que de visualiser ce que ces derniers reçoivent. On peut également les faire envoyer des données. Le logiciel se présente sous la forme suivant :

Logiciel X-CTU

Ici, deux modules sont connectés et via le bouton "console", on peut visualiser/envoyer des données émises/reçues. Une fois le logiciel pris en main, on a décidé de connecter un module Xbee à une Arduino Uno, et enfin à notre Arduino Nano. Le montage et le code associé à la partie "émission des données du capteurs via Arduino" est la suivante :

Émission des valeurs des axes X et Y par Arduino et réception sur PC


void setup() {                
    Serial.begin(9600);    
}

void loop() {
  //lecture des valeurs de l'axe X
  int val = analogRead(A0);
  Serial.print(10*val);
  Serial.print("\n");
  delay(10);
  
  //lecture des valeurs de l'axe Y
  int val2 = analogRead(A1);
  Serial.print(10*val2);
  Serial.print("\n");
  delay(10);   
}




Dans le montage, le Xbee est alimenté en 3,3V, sa pin Rx est reliée à la pin Tx du l'Arduino, et sa pin Tx est reliée à la pin Rx de l'Arduino. De cette manière, lorsque l'on utilise la liaison série série de l'Arduino, les valeurs envoyées sont transmises au Xbee associé. Comme nous avons mit les deux Xbee sur le même canal, le second Xbee reçoit bien les données du capteur (multipliées par 10 afin d'observer une plus grande différence) :

Visualisation des valeurs du capteurs reçu par le Xbee sur X-CTU

Semaine 3

Raspberry Pi

Pour ce qui concerne la configuration de la Raspberry Pi nous avons effectué les étapes suivantes:

  • Nous avons commencé par monter les partitions de la carte SD pour retrouver le fichier config.txt. Une fois trouvé, nous avons ajouté la ligne de code "enable_uart=1" à la fin du fichier.
  • À l'aide de la liaison série et l'outil minicom configuré comme suivant: à 115200 bauds 8N1(8 data bits, pas de bit de parité et 1 bit de stop), sur /dev/ttyUSBn avec n un numéro entier qui désigne le port su lequel la Raspberry est connecté et sans flux de contrôle. Nous avons ensuite pu modifier le fichier /etc/network/interfaces pour définir une addresse IP statique de l'appareil.
  auto eth0
  iface eth0 inet static
  address 172.26.78.112
  netmask 255.255.240.0
  gateway 172.26.79.254
  • Tuer tout les processus en lien avec DHCP, grâce à la commande "killall -9 dhcpcd".
  • Ajout de l'adresse IP du serveur DNS de l'école pour pouvoir se connecter à internet. À la fin du fichier /etc/resolv.conf nous avons ajouter "nameserver 193.48.57.34".
  • Exécuter la commande export "http_proxy=http://proxy.polytech-lille.fr:3128" pour pouvoir utiliser le proxy de l'école.
  • Il suffit ensuite d’exécuter la commande "ifup eth0" et se connecter en SSH sur la Raspberry Pi depuis un autre terminal ou un autre ordinateur(cela nous permet de libérer le port série pour autres usages).

Remarque : Les outils DHCP modifie lors de chaque démarrage de eth0 le fichier "/etc/resolv.conf". Pour avoir accès à internet nous sommes obligé donc de démarrer eth0 ("ifup eth0"), modifier le fichier mentionné, faire nos démarches sans faire "ifdown eth0" lors de la session. De plus, il faut refaire l'export à chaque démarrage si on veut télécharger des paquets.

Le mise en route de la Raspberry ayant pris plus de temps que prévu, nous avons juste eu le temps de brancher le module XBee en USB afin de visualiser sur minicom les données reçu par le Xbee. Nous recevons bien les données envoyées par le capteur. Enfin, il a fallu définir une protocole afin de bien comprendre les valeurs reçues : une valeur sur deux correspondra à l'axe X et l'autre à l'axe Y ; les valeurs seront reçues en décimale et chaque valeur aura pour taille 4 chiffres.

Remarque : Les valeurs de l'axe Y seront doublées par rapport à celle de l'axe X afin de bien faire la différence entre les deux.

La prochaine semaine, nous devrons réaliser un programme qui récupère les données arrivant sur le Xbee.

Semaine 4

Pendant tout cette semaine, nous avons travaillé sur la Raspberry Pi. Nous avons paramétré cette dernière en point d'accès, puis nous avons réalisé le programme pour récupérer les valeurs de la liaison série.

La méthode ci-dessus pour que le fichier "/etc/resolv.conf" ne se vide pas à chaque démarrage n'étant pas optimale (tuer dhcpcd...), notre tuteur nous a supprimé SystemD et a installé à la place SysV qui permet plus de "libertés".

Raspberry Pi en point d'accès

  • Définir une adresse IP statique pour la carte

Dans le fichier /etc/network/interfaces, il faut ajouter :

  allow-hotplug wlan0
  iface wlan0 inet static
  address 192.168.100.1
  netmask 255.255.255.0

L'adresse de notre Rpi sur son réseau sera donc 192.168.100.1

  • Installation du serveur DHCP

Le serveur DHCP utilisé est isc-dhcp-server. On se rend ensuite dans le fichier de configuration du DHCP, à savoir /etc/dhcp/dhcpd.conf, afin d'ajouter une plage d'adresse qui pourra être distribuée :

  subnet 192.168.100.0 netmask 255.255.255.0 {
    range 192.168.100.10 192.168.100.50;
    option broadcast-address 192.168.100.255;
    option routers 192.168.100.1;
  }

Enfin, dans le fichier /etc/default/isc-dhcp-server on ajoute wlan0 comme interface par défaut pour répondre aux requêtes DHCP.

  • Création du point d'accès

Après avoir lu des articles et tutoriel sur le sujet, nous avons décidé d'installer "Hostapd", qui est un programme tournant en arrière plan afin de créer le point d'accès Wi-Fi. Une fois installé, il faut créer son fichier de configuration : /etc/hostapd/hostapd.conf dans lequel on met : (voir https://wiki.gentoo.org/wiki/Hostapd)

  interface=wlan0             #interface utilisée
  ssid=gosse_hagui            #nom du point d'accès
  hw_mode=g                   
  channel=6                   #canal à utiliser
  wpa=2
  wpa_passphrase=raspberry    #mot de passe du point d'accès
  wpa_key_mgmt=WPA-PSK  
  rsn_pairwise=CCMP

Il ne reste qu'a dire à Hostapd d'utiliser ce fichier en tant que fichier de configuration en ajout dans /etc/default/hostapd :

  DAEMON_CONF="/etc/hostapd/hostapd.conf"

A partir de ce moment, la Raspberry est détectable en tant que point d'accès Wi-Fi par les machines dans le périmètre ; nous arrivons a nous connecter dessus et ouvrir dans un navigateur la page html de base d'Apache.

Récupération des données

Le code suivant en C, sur la Rpi, permet d'afficher sur l'écran les valeurs du capteur envoyées par l'Arduino :

#include <stdio.h>
#include <stdlib.h>
int main(void) {
        FILE* fichier = NULL;
        int val=0;
        fichier=fopen("/dev/ttyUSB0","r");
        if(fichier == NULL) {
                perror("ouverture fichier:");
                exit(1);
        }
        while(1) {
                fscanf(fichier,"%d",&val);
                printf("%d\n",val);
        }
        return 0;
}   

Sur la Rpi, on reçoit bien :

Réception des données sur la Rpi

3xxx correspondent aux valeur de l'axe X et 7xxx à l'axe Y. La prochaine étape de projet va être de contrôler les pins de sortie de la Raspberry en modifiant le programme ci-dessus.

Semaine 5

L'envoi de données entre les deux entités sur projet étant réussi, nous avons décidé de réaliser les PWM sur la Rpi qui seront nécessaire au contrôle des moteurs. Dans un premier temps, nous avons vu des exemples en Python et cela fonctionnait. Cependant, après quelque recherche, nous avons trouvé une librairie qui s'appelle Wiring-Pi et qui permet de contrôler les GPIO (de la Rpi) grâce au langage C. Le code simple suivant permet donc de réaliser une PWM sur la pin 1 (GPIO 18) :

#include <stdio.h>
#include <wiringPi.h>
#include <softPwm.h>

int main(void)
{
	int pin =1;
	int i=0;
	if(wiringPiSetup()==-1) return 0;
	pinMode(pin,PWM_OUTPUT);
	while(1)
	{
 		for(i=0;i<1024;i++) 
		{
			pwmWrite(1,i);
			delay(1);
		}
		for(i=1023;i>=0;i--)
		{
			pwmWrite(1,i);
			delay(1);
		}
	}
	return 0;
}

Nous avons câblé une LED afin de vérifier le bon fonctionnement de la PWM. Dans la deuxième partie de la semaine, nous avons décidé d'inclure la PWM au code qui reçoit les valeurs du capteur et commander l'allumage de notre LED en fonction de ce dernier :

while(1)
	{
		fscanf(fichier,"%d",&val);
		printf("%d\n",val);
                pwmWrite(1,val);
                delay(1);
	}

Un des problème que nous avons rencontré est que la librairie actuelle n'autorise qu'une seule PWM sur la pin 1. La prochaine étape du projet est de trouver comment réaliser une seconde PWM, et également d'améliorer le code pour que les PWM soient plus "lisses".

Semaine 6

Durant cette semaine nous avons continué de travailler sur la création de deux PWM par la RaspBerry Pi. Nous avons trouvé une librairie associé à WiringPi appelée softPwm qui inclus des fonctions nous permettant de faire ceci. Nous allons notamment utiliser les deux fonctions :

  int softPwmCreate (int pin, int initialValue, int pwmRange);

Pour autoriser une pin à faire une PWM avec une valeur initiale donnée par le deuxième paramètre, et le troisième paramètre définit la plage de valeurs à envoyer. Cette fonction nous renvoi un 0 si tout s'est bien passé, tout autre valeur signifie une erreur. Ainsi que

  void softPwmWrite (int pin, int value);

Qui va nous permettre de modifier la valeur sur la pin spécifié. La valeur doit respecter la plage précisée précédemment par la fonction softPwmCreate, sinon elle sera ignoré.

Nous avons intégré ces deux fonction dans notre code pour avoir une version qui ressemble à ceci.

#include <stdio.h>
#include <stdlib.h>
#include <wiringPi.h>
#include <softPwm.h>
#include <unistd.h>

int main(void) {
	FILE* fichier = NULL;
	int val=0;
        if(wiringPiSetupGpio()==-1) return 0;
	fichier=fopen("/dev/ttyUSB0","r");
	if(fichier == NULL){
		perror("ouverture fichier:");
		exit(1);
	}

	if(softPwmCreate(21,0,100)!=0){
                perror("softPwmCreate");
                exit(1);
        }

        if(softPwmCreate(20,0,100)!=0){
                perror("softPwmCreate");
                exit(1);
        }


	while(1){
		fscanf(fichier,"%d",&val);
		printf("%d\n",val);
		//Notre programme reçoit 0(repos) ou 100(non-repos) pour l'axe X et 10(repos) ou 90(non-repos) pour l'axe Y.
		if(val==0 || val ==100){
	                softPwmWrite(20,val);
		}
		else{
			//Si on reçoit 10 ou 90 pour l'axe Y on envoi 0 et 100 respectivement sur le pin. 
			if(val==10){
				softPwmWrite(21,0);
			}
			else{
				softPwmWrite(21,100);
			}
		}
	}
	return 0;
}

Notre programme contrôle ainsi deux LEDs. Une LED Rouge qui s'allume quand l’accéléromètre n'est pas en position de repos par rapport à l'axe Y et une LED Jaune qui s'allume par rapport à l'axe X.

Nous avons également créé un Makefile pour faciliter la compilation de notre code lors de sa modification.

CC = gcc
CFLAGS = -Wall -lpthread -lwiringPi

all : prog_controle_v2

prog_controle_v2 : controle_v2.c
	$(CC) controle_v2.c -o prog_controle_v2 $(CFLAGS)

clean :
	rm prog_*
Projet entier avec les LEDs et la Rpi

Semaine 7

Cette semaine, nous nous sommes fixé l'objectif de réaliser une carte électronique sur Fritzing qui sera utilisée pour faciliter le branchement des composants de la voiture (batterie externe, Raspberry Pi, les moteurs de la voiture). La batterie externe sera utilisée pour alimenter la Raspberry Pi avec 5V/1.0A. Une batterie déja disponible sur la voiture sera utilisée pour l'alimentation des moteurs. Le module Xbee sera connecté à la Raspberry Pi avec un simple cable USB-MicroUSB. Veillez trouver ci-dessous une capture d'écran de la carte réalisé sur Fritzing :

PCB réalisé sur Fritzing.

Semaine 8

Après avoir récupéré notre carte électronique et vérifié son fonctionnement, nous avons commencé à souder les composants, ce qui nous a pris une bonne partie de la séance de 4h. Nous avons ensuite testé si le courant circulait bien comme nous l'avions prévu et relevé les sorties de l'alimentation. Celle ci délivre bien 8V, nous avons donc pu brancher notre "Shield" sur la Rpi, et connecter la batterie et les moteurs de dessus, comme sur l'image suivante :

Voiture avec la Raspberry et notre "Shield"

Le programme que nous avions déja fait avec une PWM n'est pas encore approprié pour la voiture, le moteur de la direction se met actuellement tout le temps dans la même direction. Dans la prochaine séance, nous allons essayer de faire tourner le moteur de direction de droite à gauche en fonction de l’accéléromètre. Il faut aussi réussir à connecter le moteur qui déplace la voiture.

Semaine 9

Nous avons consacré cette semaine à l'écriture d'un code adapté au bon fonctionnement de la voiture. Nous avons écrit un code Arduino qui nous envoi un chiffre différent pour les cas suivants :

	Direction Neutre: 10
	Vitesse Nulle: 11
	Avancer: 
	Reculer:
	Droite:
	Gauche:

Nous avons également écrit un code en C sur la Raspberry Pi pour recevoir et interpréter chaque valeur reçu de l'accéléromètre. Chaque valeur correspond à une commande softPwmWrite différente pour envoyer un certain signal PWM aux moteurs. Enfin, nous avons finalisé le calibrage du contrôleur de moteur de trouvé une range adapté pour que le voiture roule à une vitesse modérée. Le calibrage à été effectué selon la notice constructeur que pouvez consulter à l'adresse : http://www.zonacrawling.com/ManualTamiyaTEU-101BK.pdf . Nous avons simulé la manette qui sert habituellement à commander un véhicule par l'envoie de signaux PWM correspondant aux actions que nous voulions.

Semaine 10

Durant cette semaine nous nous sommes penché sur la réalisation d'une carte PCB pour regrouper tout les composants du gant (Accéléromètre, Arduino et module Xbee). Veuillez trouver ci-dessous la carte réalisée sur Fritzing.

Deuxième carte sur Fritzing
Carte après la soudure des barrettes

Une fois la carte imprimée nous avons soudé des barrettes pour pouvoir brancher les composants.

Nous avons ensuite testé le bon fonctionnement de la carte et l'avons cousu sur un gant pour finaliser notre projet. Vous trouverez ci-dessous des photos du gant et la voiture finalisée.

Gant et carte pas dessus
Voiture et Raspberry Pi par dessus

Le reste de la séance a été dédié a faire des modifications pour le bon déroulement de la séance de tournage de vidéo.

Conclusion

A l'issue du projet, la voiture effectue tout les déplacements souhaités, excepté la marche arrière qui ne fonctionne plus depuis que nous avons modifié les valeurs de PWM dans le but de lisser la direction. Nous avons cependant réussi à mettre en place le système que nous voulions et cela nous a apporté beaucoup de connaissances, aussi bien pratiques qu'humaines. En effet, nous avons re-travaillé du langage C, de l'Arduino, utilisé les modules XBee, utilisé la Raspberry Pi pour des applications que nous n'avions jamais fait. Ce projet fut donc une bonne expérience.

Fichiers Rendus

Fichier:Rapport hagui gosse.pdf