« TPI SE3 2025/2026 » : différence entre les versions

De projets-se.plil.fr
Aller à la navigation Aller à la recherche
(Page créée avec « \documentclass{article} \usepackage[french]{babel} \usepackage[T1]{fontenc} \usepackage[latin1]{inputenc} \usepackage{hevea} \usepackage[dvips]{graphicx,epsfig} \usepackage{graphics} \usepackage{verbatim} \usepackage{url} \usepackage{ifthen} \title{Tutorat système IMA4 (USB et Arduino)} \date{2017 - 2018} \author{Thomas Vantroys, Julien Forget et Xavier Redon} \begin{document} \maketitle \section{Objectif} Notre ambition en introduisant ce tutorat en 2010/2... »)
 
Aucun résumé des modifications
Ligne 1 : Ligne 1 :
\documentclass{article}
== Objectif ==


\usepackage[french]{babel}
Le but est de réaliser un périphérique USB à l'aide d'un Arduino Uno pour contrôler votre jeu.
\usepackage[T1]{fontenc}
\usepackage[latin1]{inputenc}


\usepackage{hevea}
Si vous visualisez le schéma d'un Arduino Uno Rev3, vous constatez la présence de deux micro-contrôleurs. Vous trouvez, bien entendu, l'ATMega328p
\usepackage[dvips]{graphicx,epsfig}
qui est le microcontrôleur sur lequel sont exécutés les programmes téléchargés sur la platine. Vous trouvez aussi un ATMega16u2, ce microcontrôleur
\usepackage{graphics}
\usepackage{verbatim}
\usepackage{url}
\usepackage{ifthen}
 
\title{Tutorat système IMA4 (USB et Arduino)}
\date{2017 - 2018}
\author{Thomas Vantroys, Julien Forget et Xavier Redon}
 
\begin{document}
\maketitle
 
\section{Objectif}
Notre ambition en introduisant ce tutorat en 2010/2011 était de vous permettre de comprendre le fonctionnement du bus USB par la pratique.
Jusque là, le tutorat se limitait à la commande d'un périphérique USB de type gadget (lance-missiles, bras robotique) par un programme C
utilisant une bibliothèque Linux. L'utilisation d'un Arduino pour la commande du gadget permettait juste de pratiquer la programmation C
sur Arduino sans avoir de rapport direct avec USB.
 
Vous avez la chance de pouvoir expérimenter une modification profonde du sujet de ce tutorat. Si la partie contrôle d'un périphérique USB
avec la bibliothèque {\tt libusb-1.0} reste d'actualité, cette fois vous allez vous même réaliser un périphérique USB à l'aide d'un Arduino Uno.
Si vous visualisez le schéma d'un Arduino Uno récent, vous constatez la présence de deux micro-contrôleurs. Vous trouvez, bien entendu, l'ATMega328p
qui est le micro-contrôleur sur lequel sont exécutés les programmes téléchargés sur la platine. Vous trouvez aussi un ATMega16u2, ce micro-contrôleur
est chargé de la gestion du port USB de l'Arduino. Des lignes de l'ATMega16u2 sont d'ailleurs directement connectées sur les contacts de la prise
est chargé de la gestion du port USB de l'Arduino. Des lignes de l'ATMega16u2 sont d'ailleurs directement connectées sur les contacts de la prise
USB de la platine. L'ATMega16u2 est flashé avec un programme fixe qui implante un périphérique USB/série. La communication entre l'ATMega16u2 et
USB de la platine. L'ATMega16u2 est flashé avec un programme fixe qui implante un périphérique USB/série. La communication entre l'ATMega16u2 et
l'ATMega328p se fait via une communication série en utilisant leurs UART respectifs.
l'ATMega328p se fait via une communication série asynchrone en utilisant leurs UART respectifs.


Vous allez modifier le programme de l'ATMega16u2 pour faire apparaitre l'Arduino comme un périphérique USB spécifique. Le prétexte du tutorat est
Vous allez modifier le programme de l'ATMega16u2 pour faire apparaitre l'Arduino comme un périphérique USB spécifique. Le prétexte du tutorat est
de réaliser une manette USB à partir d'un bouclier jeu pour Arduino. Vous ferez en sorte que l'ATMega328p puisse acquérir l'état des 5 boutons du
de réaliser une manette USB à partir d'un bouclier jeu pour Arduino. Vous ferez en sorte que l'ATMega328p puisse acquérir l'état du joystick et
bouclier et gérer la LED connectée sur la ligne 13 de l'Arduino Uno. Via l'ATMega16u2, le PC doit pouvoir lire l'état des boutons et commander la LED.
des 5 principaux boutons du bouclier et gérer la LED connectée sur la ligne 13 de l'Arduino Uno. L'ATMega16u2 doit assurer l'interface USB et
L'idée est de commander un "space invaders" avec votre manette USB.
s'annoncer comme une manette USB.


\section{Matériel}
=== Matériel ===
Pour le tutorat vous disposerez d'un Arduino Uno, de son câble USB et d'un bouclier jeu. Si vous manipulez correctement, vous n'aurez besoin d'aucun
Pour le tutorat vous disposerez d'un Arduino Uno, de son câble USB et d'un bouclier jeu. Si vous manipulez correctement, vous n'aurez besoin d'aucun
autre matériel. En cas de briquage de l'Arduino, il est toujours possible de flasher l'ATMega16u2 et l'ATMega328p au travers de leurs connecteurs ICSP.
autre matériel. En cas de briquage de l'Arduino, il est toujours possible de flasher l'ATMega16u2 et l'ATMega328p au travers de leurs connecteurs ICSP.
Ligne 44 : Ligne 20 :
arrivez là, il vous faudra un second Arduino utilisé comme programmateur et quelques câbles pour connecter les deux Arduinos.
arrivez là, il vous faudra un second Arduino utilisé comme programmateur et quelques câbles pour connecter les deux Arduinos.


\section{Programmation}
=== Programmation ===
Comme vous l'avez compris, vous allez devoir écrire trois programmes.
Comme vous l'avez compris, vous allez devoir écrire trois programmes.
\begin{itemize}
* Vous devez programmer l'ATMega328p pour acquérir l'état des 5 boutons du bouclier jeu et la LED de la ligne 13. Vous utiliserez <code>avr-gcc</code>
  \item Vous devez programmer l'ATMega328p pour acquérir l'état des 5 boutons du bouclier jeu et la LED de la ligne 13. Vous utiliserez {\tt avr-gcc}
pour la compilation de votre programme C et <code>avrdude</code> pour télécharger le programme dans le microcontrôleur. Il est impératif de programmer
pour la compilation de votre programme C et {\tt avrdude} pour télécharger le programme dans le micro-contrôleur. Il est impératif de programmer
l'ATMega328p avant l'ATMega16u2, <code>avrdude</code> utilisant l'interface USB/série. Cela dit, comme mentionné ci-avant, l'ATMega328p est aussi programmable
l'ATMega328p avant l'ATMega16u2, {\tt avrdude} utilisant l'interface USB/série. Cela dit, comme mentionné ci-avant, l'ATMega328p est aussi programmable
par son connecteur ICSP.
par son connecteur ICSP.
  \item Vous devez programmer l'ATMega16u2 pour gérer le bus USB et implanter un périphérique USB. Là encore, vous utiliserez {\tt avr-gcc} comme
* Vous devez programmer l'ATMega16u2 pour gérer le bus USB et implanter un périphérique USB. Là encore, vous utiliserez <code>avr-gcc</code> comme
compilateur C. La programmation du micro-contrôleur se fera cette fois en utilisant l'utilitaire {\tt dfu-programmer} capable de programmer l'ATMega16u2
compilateur C. La programmation du micro-contrôleur se fera cette fois en utilisant l'utilitaire <code>dfu-programmer</code> capable de programmer l'ATMega16u2
via le bus USB. Vous n'aurez pas à programmer directement les registres de l'ATMega16u2 pour gérer l'USB, vous utiliserez une bibliothèque nommée {\tt LUFA}.
via le bus USB. Vous n'aurez pas à programmer directement les registres de l'ATMega16u2 pour gérer l'USB, vous utiliserez une bibliothèque nommée <code>LUFA</code>.
  \item Enfin vous écrirez un programme C conventionnel sur le PC pour utiliser votre manette. Ce programme est compilé par {\tt gcc} et utilise la
* Enfin vous écrirez un programme C conventionnel sur le PC pour utiliser votre manette. Ce programme est compilé par <code>gcc</code> et utilise la
bibliothèque USB {\tt libusb-1.0}. Il ne vous est pas demandé d'écrire une version de space invaders. Si vous souhaitez utiliser votre manette pour contrôler
bibliothèque USB <code>libusb-1.0</code>. Pour la partie manette à proprement parler il vous suffit d'utiliser la gestion des manettes intégrée à SDL2.
un jeu vous pouvez récuperer les sources de {\tt ninvaders}, une version texte de ce classique et modifier la fonction de gestion du clavier.
Par contre pour la gestion de la LED le passage par <code>libusb-1.0</code> est nécessaire.
\end{itemize}


\section{Contrôle de la manette USB}
=== Contrôle de la manette USB ===


Utilisez la bibliothèque USB {\tt libusb-1.0} pour écrire un programme C permettant de
Utilisez la bibliothèque USB {\tt libusb-1.0} pour écrire un programme C permettant de

Version du 9 avril 2026 à 13:14

Objectif

Le but est de réaliser un périphérique USB à l'aide d'un Arduino Uno pour contrôler votre jeu.

Si vous visualisez le schéma d'un Arduino Uno Rev3, vous constatez la présence de deux micro-contrôleurs. Vous trouvez, bien entendu, l'ATMega328p qui est le microcontrôleur sur lequel sont exécutés les programmes téléchargés sur la platine. Vous trouvez aussi un ATMega16u2, ce microcontrôleur est chargé de la gestion du port USB de l'Arduino. Des lignes de l'ATMega16u2 sont d'ailleurs directement connectées sur les contacts de la prise USB de la platine. L'ATMega16u2 est flashé avec un programme fixe qui implante un périphérique USB/série. La communication entre l'ATMega16u2 et l'ATMega328p se fait via une communication série asynchrone en utilisant leurs UART respectifs.

Vous allez modifier le programme de l'ATMega16u2 pour faire apparaitre l'Arduino comme un périphérique USB spécifique. Le prétexte du tutorat est de réaliser une manette USB à partir d'un bouclier jeu pour Arduino. Vous ferez en sorte que l'ATMega328p puisse acquérir l'état du joystick et des 5 principaux boutons du bouclier et gérer la LED connectée sur la ligne 13 de l'Arduino Uno. L'ATMega16u2 doit assurer l'interface USB et s'annoncer comme une manette USB.

Matériel

Pour le tutorat vous disposerez d'un Arduino Uno, de son câble USB et d'un bouclier jeu. Si vous manipulez correctement, vous n'aurez besoin d'aucun autre matériel. En cas de briquage de l'Arduino, il est toujours possible de flasher l'ATMega16u2 et l'ATMega328p au travers de leurs connecteurs ICSP. Un connecteur ISCP dispose de toutes les lignes permettant de flasher un ATMega, à savoir l'alimentation, le reset et les lignes du bus SPI. Si vous en arrivez là, il vous faudra un second Arduino utilisé comme programmateur et quelques câbles pour connecter les deux Arduinos.

Programmation

Comme vous l'avez compris, vous allez devoir écrire trois programmes.

  • Vous devez programmer l'ATMega328p pour acquérir l'état des 5 boutons du bouclier jeu et la LED de la ligne 13. Vous utiliserez avr-gcc

pour la compilation de votre programme C et avrdude pour télécharger le programme dans le microcontrôleur. Il est impératif de programmer l'ATMega328p avant l'ATMega16u2, avrdude utilisant l'interface USB/série. Cela dit, comme mentionné ci-avant, l'ATMega328p est aussi programmable par son connecteur ICSP.

  • Vous devez programmer l'ATMega16u2 pour gérer le bus USB et implanter un périphérique USB. Là encore, vous utiliserez avr-gcc comme

compilateur C. La programmation du micro-contrôleur se fera cette fois en utilisant l'utilitaire dfu-programmer capable de programmer l'ATMega16u2 via le bus USB. Vous n'aurez pas à programmer directement les registres de l'ATMega16u2 pour gérer l'USB, vous utiliserez une bibliothèque nommée LUFA.

  • Enfin vous écrirez un programme C conventionnel sur le PC pour utiliser votre manette. Ce programme est compilé par gcc et utilise la

bibliothèque USB libusb-1.0. Pour la partie manette à proprement parler il vous suffit d'utiliser la gestion des manettes intégrée à SDL2. Par contre pour la gestion de la LED le passage par libusb-1.0 est nécessaire.

Contrôle de la manette USB

Utilisez la bibliothèque USB {\tt libusb-1.0} pour écrire un programme C permettant de contrôler la manette USB. Vous avez le manuel complet de la bibliothèque à l'URL \url{http://libusb.sourceforge.net/api-1.0/modules.html}. Vous trouverez un résumé de la bibliothèque à l'URL \url{http://rex.plil.fr/Enseignement/Systeme/Systeme.IMA4/}. Pour cette utilisation assez basique nous utiliserons les fonctions de communication bloquantes.

\subsection{Enumération des périphériques USB} Ecrivez une fonction pour examiner tous les périphériques USB disponibles sur les bus USB de votre machine de TP. Dès qu'un périphérique s'avère être le périphérique USB du type cherché, sauvez la "poignée" vers ce périphérique dans une variable globale de type {\tt libusb\_device\_handle *}. ~\\ ~\\ Vous pouvez utiliser la commande {\tt lsusb} pour trouver les identifiants USB de votre type de périphérique. Pour chaque périphérique sélectionné, faites afficher le numéro du bus sur lequel se trouve le périphérique ainsi que son adresse sur ce bus.

\subsection{Configuration du périphérique USB} Une fois le périphérique détecté, il faut le configurer. Ecrivez une fonction de configuration. Commencez par récupérer la première configuration du périphérique, c'est à dire la configuration d'indice 0. La fonction {\tt libusb\_get\_config\_descriptor} qui permet cela nécessite un pointeur sur périphérique de type {\tt libusb\_device *}. Vous pouvez retrouver ce pointeur en fonction de la "poignée" par la fonction {\tt libusb\_get\_device}. Faites afficher la valeur de cette configuration. Vous pouvez alors installer cette configuration comme configuration courante. ~\\ ~\\ Il vous reste ensuite, à réclamer {\em toutes} ses interfaces pour votre usage. Attention, la fonction {\tt libusb\_claim\_interface} nécessite le numéro de l'interface et pas son indice. Vous allez donc parcourir la structure arborescente de description de configuration du périphérique de la façon suivante : \begin{itemize}

 \item itérer sur le nombre d'interfaces ;
 \item explorer chaque sous-structure d'interface ;
 \item pour chaque interface, prendre la première alternative d'interface ;
 \item trouver le numéro d'interface pour utilisation avec {\tt libusb\_claim\_interface} ;
 \item pour chaque interface, récupérer les points d'accès présents, sauver en mémoire le premier point d'accès de type interruption.

\end{itemize} Affichez l'indice et le numéro de chaque interface détectée et réclamée. Affichez aussi les points d'accès trouvés en précisant ceux sauvés.

\subsection{Fermeture du périphérique USB} Ecrivez une fonction qui libère le périphérique détecté. Pour cela, relachez toutes ses interfaces réclamées puis fermez la "poignée". Vous allez devoir, à nouveau, explorer la structure arborescente de description de configuration du périphérique. Pour récupérer la structure utilisez cette fois la fonction {\tt libusb\_get\_active\_config\_descriptor}. Affichez l'indice et le numéro de chaque interface libérée.

\subsection{Gestion de la manette} Dans un premier temps testez la manette en allumant la LED et en affichant les boutons pressés ou relachés jusqu'à pression sur le bouton d'arrêt. Eteignez alors la LED et fermez le périphérique USB. La gestion de la manette doit être effectuée via le point d'accès OUT de la première interface pour la LED et via le point d'accès IN de la seconde interface pour les boutons. Pour communiquer avec la manette vous utiliserez la fonction {\tt libusb\_interrupt\_transfer}.

\section{Programme ATMega328p} Le programme à faire tourner sur l'ATMega328p est très simple. Il s'agit : \begin{itemize}

 \item de scanner l'état des 5 boutons du bouclier jeu, dès que l'état d'un bouton change, il faut envoyer l'état global sur la liaison série ;
 \item de vérifier si un octet arrive par le port série, si c'est le cas, utiliser la valeur pour allumer ou éteindre la LED de la ligne 13.

\end{itemize} Il est conseillé, pour le déverminage, d'utiliser des codes ASCII pour la communication série : \begin{itemize}

 \item synthétisez l'état des boutons sur un octet, par exemple en utilisant les 5 bits de poids faibles, fixez le sixième bit à 1 et les deux

autres à 0 ;

 \item prenez 48 comme code pour éteindre la LED et 49 pour l'allumer.

\end{itemize}

La programmation du micro-contrôleur ATMega328p se fait en C pur sans utiliser l'IDE Arduino. Vous pouvez vous inspirer du squelette de projet à l'URL \url{http://rex.plil.fr/Enseignement/Systeme/Tutorat.Systeme.IMA4/Arduino.tar}. ~\\ ~\\ Pour trouver sur quels ports se trouvent les lignes, référez-vous au diagramme disponible à l'URL \url{http://arduino.cc/en/uploads/Main/Arduino_Uno_Rev3-schematic.pdf}. ~\\ ~\\ Testez votre programme en utilisant le terminal série {\tt minicom}. Si votre liaison série est configurée à 9600 baud, vous pouvez lancer {\tt minicom} de la façon suivante : \begin{verbatim} minicom -8 -o -b 9600 -D /dev/ttyACM0 \end{verbatim} Il peut être nécessaire de désactiver le contrôle de flux. Pour ce faire, sous {\tt minicom}, tapez {\tt CTRL-A} puis {\tt o} puis choisissez la configuration du port série et tapez {\tt F}.

\section{Programme ATMega16u2} Il s'agit du point le plus délicat du tutorat, la programmation du comportement USB de la manette. ~\\ ~\\ Sur le principe vous devez implanter une périphérique USB n'appartenant à aucune classe particulière, ne comportant qu'une configuration mais qui elle comporte deux interfaces. La première interface est dédiée à la gestion de la LED et va contenir un point d'accès de type interruption en écriture (endpoint OUT). La seconde interface est dediée à la gestion des boutons et va contenir un point d'accès de type interruption en lecture (endpoint IN). ~\\ ~\\ Sur le site \url{http://www.fourwalledcubicle.com/LUFA.php} téléchargez la dernière version de la bibliothèque USB {\tt LUFA}. Créez un répertoire {\tt PolytechLille} au même niveau que les répertoires {\tt Demos} et {\tt Projects}. Dans ce répertoire copiez le projet {\tt RelayBoard} sous le nom, par exemple, {\tt PAD}. Renommez les fichiers dans le répertoire et modifiez le {\tt makefile}. Au niveau du {\tt makefile} indiquez {\tt atmega16u2} comme micro-contrôleur, {\tt UNO} comme platine et passez à 16Mhz. Dans le fichier de configuration du répertoire {\tt Config}, commentez l'option {\tt CONTROL\_ONLY\_DEVICE}. ~\\ ~\\ Vous pouvez ensuite modifier le projet pour obtenir un périphérique USB avec deux interfaces et un point d'accès de type interruption par interface. Un point d'accès dans le sens hôte vers périphérique et un autre en sens inverse. Vous pouvez vous aider de la démonstration {\tt Keyboard} dans le répertoire {\tt Device/LowLevel}. La déclaration des interfaces et des point d'accès est clairement montrée dans les fichiers {\tt Descriptors.c} et {\tt Descriptors.h} de cette démonstration. La gestion de points d'interruption est montrée dans l'autre source C de la démonstration, cherchez les fonctions {\tt Endpoint\_ConfigureEndpoint}, {\tt Endpoint\_SelectEndpoint}, etc. N'hésitez pas à consulter la documentation de la bibliothèque sur Internet. ~\\ ~\\ Pour la communication série avec l'ATMega328p, vous pouvez utiliser les fonctions série de la bibliothèque {\tt LUFA} : {\tt Serial\_Init}, {\tt Serial\_SendByte}, {\tt Serial\_IsCharReceived} et {\tt Serial\_ReceiveByte}. ~\\ ~\\ Pour téléverser votre programme sur l'ATMega16u2, le paquetage Debian {\tt dfu-programmer} est nécessaire. Installez le au besoin. La procédure à suivre pour charger votre programme sur l'ATMega16u2 est la suivante : \begin{itemize}

 \item court-circuitez les lignes reset et masse de l'ATMega16u2 présentes sur l'ICSP de ce micro-contrôleur ;
 \item l'Arduino ne doit plus être listé comme port série dans un {\tt lsusb}, vous pouvez alors exécuter les commandes suivantes :

\begin{verbatim} dfu-programmer atmega16u2 erase dfu-programmer atmega16u2 flash PAD.hex dfu-programmer atmega16u2 reset \end{verbatim}

 \item débranchez et rebranchez votre Arduino, votre programme doit être actif sur l'ATMega16u2.

\end{itemize} Si jamais vous souhaitez revenir à l'état d'origine c'est à dire avec un ATMega16u2 configuré en FTDI, utilisez le binaire de ce lien : \url{https://raw.githubusercontent.com/arduino/Arduino/master/hardware/arduino/avr/firmwares/atmegaxxu2/arduino-usbserial/Arduino-usbserial-uno.hex}

\section{Pour continuer} Si vous avez terminé le travail demandé, vous pouvez paufiner votre projet. Voici quelques idées. \begin{itemize}

 \item Récupérez les sources du jeu space invaders en mode texte par la commande {\tt apt-get source ninvaders}. Intégrez vos sources dans 

les sources du jeu, modifiez la fonction {\tt readInput} puis reconstruisez le paquetage par la commande {\tt dpkg-buildpackage}. D'un point de vue fonctionnel, utilisez quatre boutons pour déplacer le canon, tirer les missiles et sortir du jeu.

 \item Plutôt que d'utiliser les boutons du bouclier jeu, utilisez le joystick en réalisant des acquisitions analogiques. Vous pouvez utiliser

les fonctions ci-dessous pour implanter ces acquisitions sur l'ATMega328p : \begin{verbatim} void ad_init(unsigned char channel) { ADCSRA|=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0); ADMUX|=(1<<REFS0)|(1<<ADLAR); ADMUX=(ADMUX&0xf0)|channel; ADCSRA|=(1<<ADEN); }

unsigned int ad_sample(void){ ADCSRA|=(1<<ADSC); while(bit_is_set(ADCSRA, ADSC)); return ADCH; } \end{verbatim}

 \item Si vous le souhaitez vous pouvez concevoir une carte électronique comportant juste un ATMega16u2, son éco-système (quartz, condensateurs,

résistances, etc), quelques boutons et quelques LEDs. Les boutons et les LEDs peuvent facilement être gérées directement par l'ATMega16u2. L'alimentation peut se faire directement par le bus USB.

 \item Vous pouvez aussi changer de périphérique et partir sur une catapulte USB. Une catapulte est réalisable avec 3 servo-moteurs, concevez

la partie mécanique pour réalisation avec la découpeuse laser du Fabricarium.

 \item Si vous êtes très ambitieux, réalisez la catapulte avec une carte électronique à base d'ATMega16u2 de votre propre conception.

\end{itemize}

\end{document}