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

De projets-se.plil.fr
Aller à la navigation Aller à la recherche
Aucun résumé des modifications
Ligne 33 : Ligne 33 :
Par contre pour la gestion de la LED le passage par <code>libusb-1.0</code> est nécessaire.
Par contre pour la gestion de la LED le passage par <code>libusb-1.0</code> est nécessaire.


=== Contrôle de la manette USB ===
=== Contrôle de la LED 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 <code>libusb-1.0</code> pour écrire un programme C permettant de
contrôler la manette USB. Vous avez le manuel complet de la bibliothèque à l'URL
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é
[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/}.
de la bibliothèque à l'URL [https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/].
Pour cette utilisation assez basique nous utiliserons les fonctions de communication bloquantes.
Pour cette utilisation assez basique nous utiliserons les fonctions de communication bloquantes.


\subsection{Enumération des périphériques USB}
==== Enumération des périphériques USB ====
Ecrivez une fonction pour examiner tous les périphériques USB disponibles sur les bus 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é,
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  
sauvez la "poignée" vers ce périphérique dans une variable globale de type  
{\tt libusb\_device\_handle *}.
<code>libusb_device_handle *</code>.
~\\
 
~\\
Vous pouvez utiliser la commande <code>lsusb</code> pour trouver les identifiants USB de votre type de
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
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.
se trouve le périphérique ainsi que son adresse sur ce bus.


\subsection{Configuration du périphérique USB}
==== Récupération de la configuration du périphérique USB ====
Une fois le périphérique détecté, il faut le configurer. Ecrivez une fonction de configuration.
Une fois le périphérique détecté, il faut connaître sa configuration. Vous pouvez faire cela avec
Commencez par récupérer la première configuration du périphérique, c'est à dire la configuration
la fonction <code>libusb_get_active_config_descriptor</code>. Cette fonction nécessite un pointeur
d'indice 0. La fonction {\tt libusb\_get\_config\_descriptor} qui permet cela nécessite un pointeur
sur périphérique de type <code>libusb\_device *</code>. Vous pouvez retrouver ce pointeur en fonction de
sur périphérique de type {\tt libusb\_device *}. Vous pouvez retrouver ce pointeur en fonction de
la "poignée" par la fonction <code>libusb_get_device</code>. Faites afficher la valeur de cette configuration.
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 l'interface que vous avez ajouté sur votre manette pour gérer la LED.
~\\
Attention, la fonction <code>libusb_claim_interface</code> nécessite le numéro de l'interface et non son indice.
~\\
Vous allez donc parcourir la structure arborescente de description de configuration du périphérique de la façon suivante :
Il vous reste ensuite, à réclamer {\em toutes} ses interfaces pour votre usage. Attention, la fonction
* itérer sur le nombre d’interfaces ;
{\tt libusb\_claim\_interface} nécessite le numéro de l'interface et pas son indice. Vous allez donc
* explorer chaque sous-structure d’interface de classe <code>LIBUSB_CLASS_VENDOR_SPEC</code> ;
parcourir la structure arborescente de description de configuration du périphérique de la façon suivante :
* pour chaque interface, prendre la première alternative d’interface ;
\begin{itemize}
* trouver le numéro d’interface pour utilisation avec <code>libusb_claim_interface</code> ;
  \item itérer sur le nombre d'interfaces ;
* récupérer le point d’accès présent, sauver l'adresse du point d’accès dans un tableau global.  
  \item explorer chaque sous-structure d'interface ;
 
  \item pour chaque interface, prendre la première alternative d'interface ;
Affichez l’indice et le numéro de chaque interface détectée et réclamée. Affichez aussi l'adresse du point d’accès trouvé.
  \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}
==== Fermeture du périphérique USB ====
Ecrivez une fonction qui libère le périphérique détecté. Pour cela, relachez toutes ses interfaces
Ecrivez une fonction qui libère le périphérique détecté. Pour cela, relachez son interface
réclamées puis fermez la "poignée". Vous allez devoir, à nouveau, explorer la structure arborescente
réclamée puis fermez la "poignée". Vous allez devoir, à nouveau, explorer la structure arborescente de description de
de description de configuration du périphérique. Pour récupérer la structure utilisez cette fois
configuration du périphérique ou sauver les numéros des interfaces dans un tableau global. Affichez l’indice et le numéro
la fonction {\tt libusb\_get\_active\_config\_descriptor}.
de chaque interface libérée.
Affichez l'indice et le numéro de chaque interface libérée.


\subsection{Gestion de la manette}
==== Test de la LED 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
Dans un premier temps testez la connexion USB entre le PC et la manette en faisant clignoter la LED.
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
La gestion de la manette doit être effectuée via le point d'accès OUT de l'interface de gestion de la LED.
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
Pour communiquer avec la manette vous utiliserez la fonction <code>libusb_interrupt_transfer</code>.
utiliserez la fonction {\tt libusb\_interrupt\_transfer}.


\section{Programme ATMega328p}
=== Programme ATMega328p ===
Le programme à faire tourner sur l'ATMega328p est très simple. Il s'agit :
Le programme à faire tourner sur l'ATMega328p est très simple. Il s'agit :
\begin{itemize}
* de scanner l'état des 5 boutons principaux 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 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 ;
* de scanner l'état du joystick du bouclier jeu, dès que la position change sur un axe, 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.
* 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 sur PB5.
\end{itemize}
 
Il est conseillé, pour le déverminage, d'utiliser des codes ASCII pour la communication série :
Il est conseillé, pour le déverminage, d'utiliser des codes ASCII pour la communication série :
\begin{itemize}
* synthétisez l'état du joystick et des boutons sur trois octets, par exemple en utilisant, pour chaque octet, les 5 bits de poids faibles, fixez le sixième
  \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
bit à 1 et les deux autres à 0 ;
autres à 0 ;
* prenez 48 comme code pour éteindre la LED et 49 pour l'allumer.
  \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
La programmation du micro-contrôleur ATMega328p se fait classiquement en C. Récupérez les fichiers Makefile sur le cours.
\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}
Pour trouver sur quels ports se trouvent les lignes, référez-vous aux schémas de l'Arduino Uno R3 et du bouclier "joystick shield V1.A de funduino".
 
Testez votre programme en utilisant le terminal série <code>minicom</code>. Si votre liaison série est configurée à 9600 bauds, vous pouvez lancer
<code>minicom</code> de la façon suivante :
minicom -8 -o -b 9600 -D /dev/ttyACM0
Il peut être nécessaire de désactiver le contrôle de flux. Pour ce faire, sous <code>minicom</code>, tapez <code>CTRL-A</code> puis <code>o</code> puis choisissez
la configuration du port série et tapez <code>F</code>.
 
=== Programme ATMega16u2 ===
Il s'agit du point le plus délicat du tutorat, la programmation du comportement USB de la manette.
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}
Sur le principe vous devez implanter un périphérique USB de classe HID et de protocole joystick mais avec une fonctionnalité supplémentaire.
Si vous avez terminé le travail demandé, vous pouvez paufiner votre projet. Voici quelques idées.
La fonctionnalité manette va donner lieu à une interface USB de classe HID et vous allez ajouter une seconde interface de classe "vendeur" pour
\begin{itemize}
la gestion de la LED. Cette second interface va contenir un point d'accès de type interruption en écriture (endpoint OUT).
  \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}.
Sur le cours téléchargez la bibliothèque USB <code>LUFA</code>. Créez un répertoire <code>PolytechLille</code> au même niveau que les répertoires
D'un point de vue fonctionnel, utilisez quatre boutons pour déplacer le canon, tirer les missiles et sortir du jeu.
<code>Demos</code> et <code>Projects</code>. Dans ce répertoire copiez la démonstration bas niveau <code>Joystick</code> sous le nom, par exemple,
  \item Plutôt que d'utiliser les boutons du bouclier jeu, utilisez le joystick en réalisant des acquisitions analogiques. Vous pouvez utiliser
<code>Manette</code>. Renommez les fichiers dans le répertoire et modifiez le <code>makefile</code>. Au niveau du <code>makefile</code> indiquez
les fonctions ci-dessous pour implanter ces acquisitions sur l'ATMega328p :
<code>atmega16u2</code> comme microcontrôleur, <code>UNO</code> comme platine et passez à 16Mhz.
\begin{verbatim}
 
void ad_init(unsigned char channel)
Vous pouvez ensuite modifier le projet pour obtenir un périphérique USB avec une seconde interface possédant un point d'accès de type interruption.
{
La déclaration des interfaces et des points d'accès se fait dans les fichiers {\tt Descriptors.h} et {\tt Descriptors.h}. La gestion de points
ADCSRA|=(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
d'interruption est montrée dans le cours.
ADMUX|=(1<<REFS0)|(1<<ADLAR);
 
ADMUX=(ADMUX&0xf0)|channel;
Pour la communication série avec l'ATMega328p, vous pouvez utiliser les fonctions série de la bibliothèque <code>LUFA</code> : <code>Serial_Init</code>,
ADCSRA|=(1<<ADEN);
<code>Serial_SendByte</code>, <code>Serial_IsCharReceived</code> et <code>Serial_ReceiveByte</code>.
}


unsigned int ad_sample(void){
Pour téléverser votre programme sur l'ATMega16u2, le paquetage Debian <code>dfu-programmer</code> est nécessaire. Installez le au besoin.
ADCSRA|=(1<<ADSC);
La procédure à suivre pour charger votre programme sur l'ATMega16u2 est la suivante :
while(bit_is_set(ADCSRA, ADSC));
* court-circuitez les lignes reset et masse de l'ATMega16u2 présentes sur l'ICSP de ce microcontrôleur ;
return ADCH;
* l'Arduino ne doit plus être listé comme port série dans un <code>lsusb</code>, vous pouvez alors lancer la commande <code>make dfu</code>
}
dans le répertoire <code>Manette</code>.
\end{verbatim}
* débranchez et rebranchez votre Arduino, votre programme doit être actif sur l'ATMega16u2.
  \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}
Si jamais vous souhaitez revenir à l'état d'origine c'est à dire avec un ATMega16u2 configuré en FTDI, utilisez le binaire de ce lien :
[https://raw.githubusercontent.com/arduino/Arduino/master/hardware/arduino/avr/firmwares/atmegaxxu2/arduino-usbserial/Arduino-usbserial-uno.hex].

Version du 9 avril 2026 à 14:41

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 LED de la manette USB

Utilisez la bibliothèque USB 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 [1]. Vous trouverez un résumé de la bibliothèque à l'URL [2]. Pour cette utilisation assez basique nous utiliserons les fonctions de communication bloquantes.

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 libusb_device_handle *.

Vous pouvez utiliser la commande 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.

Récupération de la configuration du périphérique USB

Une fois le périphérique détecté, il faut connaître sa configuration. Vous pouvez faire cela avec la fonction libusb_get_active_config_descriptor. Cette fonction nécessite un pointeur sur périphérique de type libusb\_device *. Vous pouvez retrouver ce pointeur en fonction de la "poignée" par la fonction libusb_get_device. Faites afficher la valeur de cette configuration.

Il vous reste ensuite, à réclamer l'interface que vous avez ajouté sur votre manette pour gérer la LED. Attention, la fonction libusb_claim_interface nécessite le numéro de l'interface et non son indice. Vous allez donc parcourir la structure arborescente de description de configuration du périphérique de la façon suivante :

  • itérer sur le nombre d’interfaces ;
  • explorer chaque sous-structure d’interface de classe LIBUSB_CLASS_VENDOR_SPEC ;
  • pour chaque interface, prendre la première alternative d’interface ;
  • trouver le numéro d’interface pour utilisation avec libusb_claim_interface ;
  • récupérer le point d’accès présent, sauver l'adresse du point d’accès dans un tableau global.

Affichez l’indice et le numéro de chaque interface détectée et réclamée. Affichez aussi l'adresse du point d’accès trouvé.

Fermeture du périphérique USB

Ecrivez une fonction qui libère le périphérique détecté. Pour cela, relachez son interface réclamée puis fermez la "poignée". Vous allez devoir, à nouveau, explorer la structure arborescente de description de configuration du périphérique ou sauver les numéros des interfaces dans un tableau global. Affichez l’indice et le numéro de chaque interface libérée.

Test de la LED de la manette

Dans un premier temps testez la connexion USB entre le PC et la manette en faisant clignoter la LED. La gestion de la manette doit être effectuée via le point d'accès OUT de l'interface de gestion de la LED. Pour communiquer avec la manette vous utiliserez la fonction libusb_interrupt_transfer.

Programme ATMega328p

Le programme à faire tourner sur l'ATMega328p est très simple. Il s'agit :

  • de scanner l'état des 5 boutons principaux du bouclier jeu, dès que l'état d'un bouton change, il faut envoyer l'état global sur la liaison série ;
  • de scanner l'état du joystick du bouclier jeu, dès que la position change sur un axe, il faut envoyer l'état global sur la liaison série ;
  • 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 sur PB5.

Il est conseillé, pour le déverminage, d'utiliser des codes ASCII pour la communication série :

  • synthétisez l'état du joystick et des boutons sur trois octets, par exemple en utilisant, pour chaque octet, les 5 bits de poids faibles, fixez le sixième

bit à 1 et les deux autres à 0 ;

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

La programmation du micro-contrôleur ATMega328p se fait classiquement en C. Récupérez les fichiers Makefile sur le cours.

Pour trouver sur quels ports se trouvent les lignes, référez-vous aux schémas de l'Arduino Uno R3 et du bouclier "joystick shield V1.A de funduino".

Testez votre programme en utilisant le terminal série minicom. Si votre liaison série est configurée à 9600 bauds, vous pouvez lancer minicom de la façon suivante :

minicom -8 -o -b 9600 -D /dev/ttyACM0 

Il peut être nécessaire de désactiver le contrôle de flux. Pour ce faire, sous minicom, tapez CTRL-A puis o puis choisissez la configuration du port série et tapez F.

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 un périphérique USB de classe HID et de protocole joystick mais avec une fonctionnalité supplémentaire. La fonctionnalité manette va donner lieu à une interface USB de classe HID et vous allez ajouter une seconde interface de classe "vendeur" pour la gestion de la LED. Cette second interface va contenir un point d'accès de type interruption en écriture (endpoint OUT).

Sur le cours téléchargez la bibliothèque USB LUFA. Créez un répertoire PolytechLille au même niveau que les répertoires Demos et Projects. Dans ce répertoire copiez la démonstration bas niveau Joystick sous le nom, par exemple, Manette. Renommez les fichiers dans le répertoire et modifiez le makefile. Au niveau du makefile indiquez atmega16u2 comme microcontrôleur, UNO comme platine et passez à 16Mhz.

Vous pouvez ensuite modifier le projet pour obtenir un périphérique USB avec une seconde interface possédant un point d'accès de type interruption. La déclaration des interfaces et des points d'accès se fait dans les fichiers {\tt Descriptors.h} et {\tt Descriptors.h}. La gestion de points d'interruption est montrée dans le cours.

Pour la communication série avec l'ATMega328p, vous pouvez utiliser les fonctions série de la bibliothèque LUFA : Serial_Init, Serial_SendByte, Serial_IsCharReceived et Serial_ReceiveByte.

Pour téléverser votre programme sur l'ATMega16u2, le paquetage Debian dfu-programmer est nécessaire. Installez le au besoin. La procédure à suivre pour charger votre programme sur l'ATMega16u2 est la suivante :

  • court-circuitez les lignes reset et masse de l'ATMega16u2 présentes sur l'ICSP de ce microcontrôleur ;
  • l'Arduino ne doit plus être listé comme port série dans un lsusb, vous pouvez alors lancer la commande make dfu

dans le répertoire Manette.

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

Si jamais vous souhaitez revenir à l'état d'origine c'est à dire avec un ATMega16u2 configuré en FTDI, utilisez le binaire de ce lien : [3].