IMA4 2018/2019 EC4

De Wiki d'activités IMA

Présentation du projet

Contexte

L'élève continue son semestre S8 à l'école.

Objectif

L'objectif est de terminer la conception d'une mini-manette de jeu à base d'ATMega16u2 pour des travaux pratiques d'IMA4. Il est aussi demandé de programmer le micro-contrôleur.

Description du projet

Concernant la partie matérielle, il vous est demandé de :

  • partir du circuit Media:Circuit_16u2_v7.zip (remplacez l'extension par .fzz) ;
  • remplacer le quartz par un quartz plus compact de type FA238 ;
  • d'ajouter un joystick sur la partie gauche et un circuit d'acquisition analogique pour l'exploiter.

Le circuit d'acquisition peut être un MCP3008 qui présente la bonne propriété de pouvoir être connecté à l'ATMega16u2 par le bus SPI.

Pour pouvoir faire tenir le MCP3008 et le joystick sur le circuit vous pouvez sacrifier une LED et agrandir modérément le PCB.

Concernant la partie logicielle, programmez le micro-contrôleur en utilisant la bibliothèque LUFA pour que la manette apparaisse comme une manette USB classique, c'est à dire comme un périphérique USB de la classe HID. La manette doit pouvoir être utilisée directement par un jeu contrôlable par manette. Comme base vous utiliserez la démonstration Joystick de la LUFA (code bas niveau).

Matériel nécessaire

Description Fabricant Référence Fabricant Fournisseur Quantité Lien fournisseur

Planning prévisionnel

  • Semaine 1 : étude du sujet, prise en main du logiciel Fritzing, commencer de concevoir le schématic;
  • Semaine 2 : conception et routage du PCB, test;
  • Semaine 3 : Soudage de la carte, test;
  • Semaine 4 : Programmation de Joystick;

Travail effectué

La première partie de mon travail est de concevoir le PCB de la manette. En suivi l'énoncé, j'ai changé le quartz pae un quartz plus compact de type FA238 et ajouté un Joystick sur la partie gauche. J'avais dû mettre un circuit d'acquisition analogique (MCP3008). Par contre, monsieur Boé m'a proposé d'utiliser un ATmega16u4 (ATmega32u4) à la place d'un ATmega16u2 pour simplifier la lecture d'une valeur analogique. Donc, avec un ATmega32u4, je n'ai plus besoin un MCP3008.

Le schématic de mon PCB :

Schéma technique.png

Une fois le schématic est fait, le travail suivant est le routage du PCB.


Routage TAN.png


Après avoir vérifié tout le routage de mon PCB , la carte est envoyé à fabriquer. ET voici, la carte reçue :

Carte reçu.jpg


Soudage de la carte

Cependant, il y a un problème grave avec ma carte. J'ai pris un ATmega32u4 en boitier QFN, qui a un métal en bas. C'est à dire si je mets des vias sous l'ATmega32u4, il va avoir des court-circuits et la carte ne va pas bien fonctionner comme elle faut. Donc, je suis obligé de gratter les deux vias qui sont connectés à UCAP et à PB6(ADC13).

L'étape suivante est de souder la première parts de composants.

Carte soudée2.jpg

Ensuite, monsieur REDON essayait de brancher la carte sur un PC et tester avec l'instruction 'lsusb'. La carte ne peut pas d'être détectée. Après avoir testé avec un multimètre, on a trouvé que j'ai oublié de connecté AVCC et C6 à 5V. Pour corriger cette erreur, j'ai mis deux fils à externe.

Carte soudée3.jpg

Malheureusement, le périphérique ne peut toujours pas être détecté. Donc, la seule possibilité qui reste est la connection UCAP, qui a était gratté pour éviter le court-circuit. J'ajoutais un fil pour la connection de UCAP et la carte est enfin détectée. On a testé le fonctionnement des composants soudés avec un Arduino Leonardo, en conséquence, il n'y a qu'une seule LED s'allume parmi les trois mais les autres composants fonctionnent correctement. Je soudais du coup la deuxième parts de composants, c'est à dire le Joystick et les boutons.

Carte soudée4.jpg


Programmation

Enfin, je passe à la deuxième partie de mon épreuve complémentaire, la programmation pour la manette. J'ai réalisé cette partie par 3 étape :

1) Allumer la LED en appuyant sur un bouton

2) Allumer la LED en jouant sur le Joystick

3) Assembler ces deux derniers et tester le fonctionnement de la manette

Allumer la LED en appuyant sur un bouton

En appliquant le fichier IO.c et IO.h, je suis permet de paramètrer les INPUTs (les boutons) et les OUTPUTs (les LEDs). J'utilise PB7 comme INPUT, c'est à dire le bouton "Haut". J'initialise avec le code :

   inputs_init(0b10000000, 0x00,0x00,0x00,0x00,0x00);

J'utilise PF5 comme OUTPUT, c'est la LED qui fonctionne. J'initialise avec le code :

   outputs_init(0x00,0x00,0b11100000);

Donc, dans une boucle infinie, après avoir récupéré l'état du bouton, j'ai mis un if(). Si le bouton est appuyé, le LED s'allume, sinon la LED s'étteint. Voici le code :

   for (;;){
       inputs_get(&portb, &portc, &portd);
       if((portb&0b10000000) != 0x00){outputs_set(0x00,0x00,0xe0);}
       else{outputs_set(0x00,0x00,0x00);}
       }

Et la LED fonctionne comme elle faut.

Bouton demo.jpg

Allumer la LED en jouant sur le Joystick

Pour pouvoir utiliser un Joystick, il faut appliquer le module ADC, parce que les variables envoyées par le joystick sont en analogique.

    void initializeADC(unsigned char channel){
         ADCSRA  = (1 << ADEN) | (0b111 << ADPS0);
         ADCSRB =  (1 << MUX5);
         ADMUX   = (0b11 << REFS0) | channel;} 
    int readAnalogADCValue(void){
         ADCSRA |= (1<<ADSC);
         while (ADCSRA & (1 << ADSC));
         return ADC;} 


Avec la fonction 'initializeADC()', je pourrais choisir la variable que je veux récupérer (il y a deux variables : V et H). 'V' est connecté à la PIN ADC8 et 'H' est connecté à ADC11.

ADMUX1.png

ADMUX2.png

Premièrement, je récupère la valeur de 'V' et la mettre dans un variable 'analog1' : `

   initializeADC(0b000000);
   analog1=readAnalogADCValue();

Je fait la même chose pour 'H' :

   initializeADC(0b000011);
   analog2=readAnalogADCValue();


Avec l'ATmega32u4, la valeur analogique est sauvegarder en 10 bits, de 0 à 1024. Et je veux l'exprimer de -100 à 100. Donc, avec le code suivant, je peux réaliser la transformation de valeur :

   calc1=(analog1*200)>>10;
   calc2=(analog2*200)>>10;
   ReportData->Y = calc1-100;
   ReportData->X = calc2-100;

Dans une boucle infinie, si ReportData->Y est égale à -100 ou 100, j'allume la LED. Pour l'axe X, je fait la même chose.

Démo1.jpg

Assembler ces deux derniers et tester le fonctionnement de la manette

Maintenant, il faut rassembler les deux dernières parties ensemble.

Dans une fonction 'GetNextReport()', on compare l'état des boutons et du Joystick, si l'état est changé, la LED clignote.

   analog=analog1<<16|analog2;
   buttons=ReportData->Button;
   
   InputChanged = (uint8_t)(PrevJoyStatus ^ analog) | (uint8_t)(PrevButtonStatus ^ buttons);
   if(InputChanged) {outputs_set(0x00,0x00,0xe0);} else{outputs_set(0x00,0x00,0x00);}

Ensuite, on a téléchargé une application de demo pour le Joystick :

SIMULATION.png


Les 2 premiers barres bougent en suivant le Joystick, mais les valeurs affichées ne sont pas correctes. Et le bouton fonctionne aussi.

Problème rencontrés

  • Sur la concerption de PCB, je ne savais pas qu'il faut bien finir le schématic avant de faire le routage. J'avais fait le routage sans toucher le schématic, et cela est une faute grave.
  • Avec une boitier QFN, il ne faut pas avoir des vias en bas du micro-controleur. A cause de cette faute, j'ai gaspillé le temps sur le soudage d'un fil complémentaire.
  • J'ai soudé 3 LEDs, mais il y a qu'une seule qui fonctionne. Après avoir testé, je trouve que le sens des 2 LEDs sont correcte et les 2 résistances sont bien soudées aussi. Je ne comprends pas c'est à cause de quoi.
  • Je ne suis pas arriver d'afficher la bonne valeur (de -100 à 100) d'axe X et Y sur l'application de demo de Joystick, les valeurs affichées va toujours de -32766 à 32766. Au début, je croyais que la valeur est en 8 bits, mais après avoir corrigé, la valeur n'affichait pas correctement.

Documents

Fichier:Joystick.zip