« SE4Binome2023-11 » : différence entre les versions
mAucun résumé des modifications |
|||
Ligne 61 : | Ligne 61 : | ||
== Conception de la carte == | == Conception de la carte == | ||
Pour une première étape on a essayé d'avoir une idée sur le microcontrôleur utilisé (AT90USB647), pour cela on a commencé par lire la [https://ww1.microchip.com/downloads/en/DeviceDoc/doc7593.pdf fiche technique] du microcontrôleur en annexes (Rendus). on a | Pour une première étape on a essayé d'avoir une idée sur le microcontrôleur utilisé (AT90USB647), pour cela on a commencé par lire la [https://ww1.microchip.com/downloads/en/DeviceDoc/doc7593.pdf fiche technique] du microcontrôleur en annexes (Rendus). on a décidé de travailler avec deux ports USB, <code>USB A</code> femelle pour la connexion du clavier et <code>USB-Mini</code> mâle pour la programmation de la carte. | ||
Version du 17 janvier 2024 à 09:46
Ordonnanceur (OS)
SOUDURE SHIELD.
Dans la première séance on a commencé à souder le Shield qui servira comme une carte-mère de prototypage pour les cartes filles qu'on va réaliser au cours de ce module. Premièrement on a fait le soudage du lecteur de la carte SD et les résistances 3.3 k Ohm, 680 Ohm et les LEDs pour tester le bon fonctionnement du Shield après.
Ensuite, on a passé à la 2ème partie de soudage : Le bouclier avec la carte Arduino. L'objectif sera de pouvoir tester régulièrement notre carte fille (Clavier "USB") en se servant de le carte mère prototype (Shield + Arduino).
Pour la séance prochaine on continue sur le soudage du Shield et on va tester son fonctionnement et la lecture de la carte de masse SD.
Test avec des LEDs
Dans la deuxième séance on a finalisé la soudure du SHIELD avec les différents composantes (LEDs, résistances , Lecteur carte SD, les PINs et les connecteurs HE-10).
On a testé le fonctionnement des LEDs avec un ampèremètre .
Après, on a implémenté le code suivant dans une carte Arduino pour revérifier le clignotement des LEDs (1s on / 1s off) :
#include <avr/io.h>
#include <util/delay.h>
void setup() {
// Configuration des PINs 1,4,7 connectés au LEDs comme des OUTPUT.
DDRB |= (1 << DDB1);
DDRD |= (1 << DDD4);
DDRD |= (1 << DDD7);
// Configuration des PINs analogique A0, A3.
DDRC |= (1 << DDC0);
DDRC |= (1 << DDC3);
}
void loop() {
// Mettre les PINs à l'état HIGH.
PORTB |= (1 << PORTB1);
PORTD |= (1 << PORTD4);
PORTD |= (1 << PORTD7);
PORTC |= (1 << PORTC0);
PORTC |= (1 << PORTC3);
_delay_ms(1000); // Delay de 1000 milliseconds
// Basculement d'état des LEDs
PORTB &= ~(1 << PORTB1);
PORTD &= ~(1 << PORTD4);
PORTD &= ~(1 << PORTD7);
PORTC &= ~(1 << PORTC0);
PORTC &= ~(1 << PORTC3);
_delay_ms(1000);
}
int main(void){
setup();
while(1){
loop();
}
return 0;
}
Test Ordonnanceur
//
Carte fille clavier "USB"
Conception de la carte
Pour une première étape on a essayé d'avoir une idée sur le microcontrôleur utilisé (AT90USB647), pour cela on a commencé par lire la fiche technique du microcontrôleur en annexes (Rendus). on a décidé de travailler avec deux ports USB, USB A
femelle pour la connexion du clavier et USB-Mini
mâle pour la programmation de la carte.
On a créé le schéma de la carte fille dans kiCAD :
Après avoir bien vérifier le schéma, on a commencé à importer les footprints de chaque composant (en utilisant la bibliothéque SparkFun pour USB A-S femelle) pour se lancer à la réalisation de schéma PCB de la carte.
Programmation de la carte et gestion du clavier
On a utilisé la bibliothèque LUFA
comme hôte USB avec l'utilitaire dfu-programmer
pour pouvoir programmer AT90USB647.
Pour la partie gestion du clavier USB, on s'est appuyé sur la démonstration KeyboardHost
présente dans la bibliothèque LUFA.
Dans un premier temps, on a commencé par débuguer les appuis des touches sur le clavier de telle façon à basculer l'état de la LED D4 (jaune) quand une lettre est appuyée ([a-z]), et basculer l'état de la LED D3 (bleue) si un chiffre est appuyé ([0-9]) (vous trouvez le code source et la démonstration de cette partie ci-dessous).
A bien noter que la convention adoptée (code ASCII), est pour un clavier de type QWERTY. On développera par la suite une primitive qui gére la conversion QWERTY -> AZERTY.
/* Verifier si une touche a été appuyée */
if (KeyCode)
{
char PressedKey = 0;
if ((KeyCode >= HID_KEYBOARD_SC_A) && (KeyCode <= HID_KEYBOARD_SC_Z))
{
PressedKey = (KeyCode - HID_KEYBOARD_SC_A) + 'A';
}
else if ((KeyCode >= HID_KEYBOARD_SC_1_AND_EXCLAMATION) &
(KeyCode < HID_KEYBOARD_SC_0_AND_CLOSING_PARENTHESIS))
{
PressedKey = (KeyCode - HID_KEYBOARD_SC_1_AND_EXCLAMATION) + '1';
}
else if (KeyCode == HID_KEYBOARD_SC_0_AND_CLOSING_PARENTHESIS)
{
PressedKey = '0';
}
else if (KeyCode == HID_KEYBOARD_SC_SPACE)
{
PressedKey = ' ';
}
else if (KeyCode == HID_KEYBOARD_SC_ENTER)
{
PressedKey = '\n';
}
else if (KeyCode == HID_KEYBOARD_SC_TAB)
{
PressedKey = '\t';
}
else if (KeyCode == HID_KEYBOARD_SC_DELETE)
{
PressedKey = 0x7f;
}
else if (KeyCode == HID_KEYBOARD_SC_SEMICOLON_AND_COLON)
{
PressedKey = 'M'; // ';' en qwerty -> 'M' en azerty
}
else if (Modifier & (1 << 1))
{
PressedKey = 0xff;
}
/* Stockage de la touche appuyée dans le buffer */
addKeyToBuffer(keyBuffer, PressedKey);
}
Avant d'envoyer les données à la carte mère, il faut d'abord les stocker dans un buffer et savoir combien de touches sont présentes dedans, tout en activant la ligne d'interruption pour chaque touche appuyée. On a donc décidé de travailler avec une structure qui permet cela :
struct KeyboardBuffer {
char keys[30]; // Tableau pour stocker les touches
uint8_t count; // Nombre de touches dans le tampon
uint8_t interruptFlag; // Drapeau d interruption
};
/* Fonction pour ajouter une touche au tampon et activer le drapeau d interruption */
void addKeyToBuffer(struct KeyboardBuffer *buffer, char key) {
if (buffer->count < sizeof(buffer->keys)) {
buffer->keys[buffer->count++] = key;
buffer->interruptFlag = 1; // Activer le drapeau d interruption (<=>PCINT4)
}
}
Programmation en SPI - Envoi et réception des données
Principe de fonctionnement
Le protocole SPI (Serial Peripheral Interface) est une méthode de communication série synchrone utilisée pour transférer des données entre un dispositif maître (carte mère) et un ou plusieurs dispositif(s) esclave(s) (carte fille).
Le maître ATMega328p contrôle le processus en initiant la communication, générant l'horloge de 16MHz, et activant/désactivant la ligne SS/CS selon le périphérique esclave visé (carte clavier ou carte d'affichage). Les données seront transférées en paquets de 8 bits (un octet).
Tests et Réalisations
Dans un premier temps, la carte mère doit identifier le clavier, elle envoie donc des commandes SPI 0x00.
La carte fille répond alors avec 0x01 lorsqu'elle détecte 0x00 pour dire à la carte mère "Hey, C'est moi le clavier !".
Lorsque cette identification est réalisée, on commence le traitement d'envoi des données (nombre de touches + les touches), sauf que l'envoi ne sera effectué que si une requête SPI de code commande 0x01 est reçue [...]
Pour un premier essai, on a testé et de-bugué l'envoi SPI dans un seul sens Envoi depuis Master ATMega328p
-> Réception Slave AT90USB647
, voir la démonstration dans la vidéo ci-dessous :
On a créé une primitive spi_receive_buffer
(à implanter dans la carte mère) qui gére le réception et le stockage des touches :
void spi_receive_buffer(uint8_t lineSelect, struct KeyboardBuffer *saveBuffer) {
/* Transmission du 0x01 = "(Carte mère): Je suis prêt à recevoir les données" */
SPDR = lineSelect;
/* Attente de la réponse */
while(!(SPSR & (1<<SPIF)));
/* Recevoir la réponse de la carte fille et vérifier si c'est 0x02 = "(Carte fille): Je suis prêt à envoyer les données" */
uint8_t receivedByte = SPDR;
if (receivedByte == 0x02) {
while (!(SPSR & (1 << SPIF))); // Attendre la réception de la taille
saveBuffer->count = SPDR; // Stockage de la taille dans le tampon
/* Reception des touches une par une */
for (uint8_t i = 0; i < saveBuffer->count; i++) {
// Attendre la réception de la touche
while (!(SPSR & (1 << SPIF)));
// Stockage touche par touche dans le buffer
saveBuffer->keys[i] = SPDR;
}
}
}
Liens utiles
Git repository pour nos codes sources : git