IMA4 2018/2019 EC4

De Wiki d'activités IMA
Révision datée du 6 avril 2019 à 21:54 par Ytan (discussion | contributions) (Documents)

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

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 à la place d'un ATmega16u2 pour simplifier la lecture d'une valeur analogique. Donc, avec un ATmega16u4, 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

Cependant, il y a un problème grave avec ma carte. J'ai pris un ATmega16u4 en boitier QFN, qui a un métal en bas. C'est à dire si je mets des vias sous l'ATmega16u4, 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


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.


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.

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);}

Documents

Fichier:Joystick.zip