SE3Groupe2025-7

De projets-se.plil.fr
Aller à la navigation Aller à la recherche

Projet kicad :

Fichier:2025-PSE-7-PROG-RT.zip

Programmation des systèmes embarqués

Cette page est un exemple. N'oubliez pas de remplacer BB par votre numéro de binôme dans tous les noms de documents. Cliquez simplement sur le lien rouge pour téléverser un document.

Carte électronique

Carte réalisée en utilisant le logiciel KiCAD : Fichier:2025-PSE-BB-PROG.zip.

Schéma électronique de la carte :

schéma du groupe 7

Résultat du routage :

routage de la carte SE du groupe 7

Visualisation 3D de la carte via Kicad :

Visu 3D carte.png

Photo de la carte soudée :

Photo 1 de la carte.jpg
Photo 2 de la carte.jpg

Programmation

Bilan

J'indique où j'en suis arrivé à la fin des séances.

Eventuellement la vidéo brève du fonctionnement complet du programmateur : Média:2025-PSE-BB-PROG-final.mp4.

Premier système embarqué

Archive GIT

Notre dépot git : https://gitea.plil.fr/etardieu/2025_PSE_B7_etardieu_vvroman.git

Structure avec matériel (y compris production - gerber, bill of materials) / logiciel / documentation (e.g. documentation technique).

Description du système embarqué

L'objectif de notre groupe est de créer un mini clavier.

Il sera composé de deux touches entièrement configurables sur le pc (exemple : appuyer sur une touche ouvrira une page internet).

Ce clavier sera sans fil, et les signaux passeront par Radio-Fréquence.

Émetteur

Présentation

L’émetteur est la partie utilisée par l’utilisateur. C’est là qu’on retrouve les touches, qui permettent d’envoyer des commandes. Il est pensé pour être autonome, donc alimenté par batterie, ce qui le rend portable et utilisable sans fil. Son rôle est simplement de détecter les appuis sur les touches et d’envoyer les informations correspondantes au récepteur.

Carte réalisée en utilisant le logiciel KiCAD : Fichier:2025-PSE-BB-systeme.zip.

Schéma électronique :

La réalisation du schéma de l’émetteur s’est faite de manière progressive, en partant d’une base simple qui a ensuite été corrigée et complétée au fur et à mesure.


Dans un premier temps, on a commencé par définir les blocs principaux : le microcontrôleur (ATmega32U4), des boutons pour l’entrée utilisateur, ainsi qu’un module radio (NRF24L01) pour la communication. Cela nous a permis d’avoir une vue d’ensemble de la carte, même si tous les détails n’étaient pas encore fixés.

L’alimentation a probablement été la partie la plus difficile de la réalisation de la carte. Le choix d’une batterie Li-Po a impliqué l’ajout d’un circuit de charge (MAX1811) ainsi que d’un convertisseur buck-boost pour garantir une tension stable en 3,3 V. Cette partie a nécessité plusieurs modifications, afin de bien gérer les différentes sources (USB/batterie) et donne une alim adaptée à chaque composant. (notamment le module RF).

La gestion du microcontrôleur a également pris du temps : ajout du quartz externe avec ses condensateurs, mise en place du circuit de reset, ainsi que du connecteur de programmation ISP. L’interface USB a été intégrée, avec les lignes D+ et D− et les résistances associées, ce qui a demandé de la rigueur pour respecter les datasheet.

Nous avons ensuite ajouté le module NRF24L01. Il a fallu connecter correctement l’interface SPI (MISO, MOSI, SCK, CSN), ainsi que les signaux de contrôle (CE, IRQ), sans oublier les condensateurs de découplage. La partie antenne et adaptation RF a été reprise telle qu'indiquée dans le wiki "Radio".

Les boutons eux ont été plutôt simple, avec des entrées directes sur le microcontrôleur, accompagnées des résistances de tirage nécessaires.


Au cours de la conception, plusieurs modifications ont été faites. Nous avons modifié complètement certains blocs pour améliorer la lisibilité du schéma ou faciliter le routage PCB. Il a aussi fallu corriger quelques oublis (condensateurs de découplage, connexions d’alimentation, signaux mal nommés).

Enfin, une phase de vérification globale a permis de s’assurer que tous les blocs étaient correctement alimentés, que les connexions étaient cohérentes, et que le schéma était prêt à être utilisé pour le routage.

Au final, cette étape a surtout consisté à construire un schéma fonctionnel, en passant par plusieurs versions pour arriver à une version finale, fonctionnelle et exploitable pour la suite du projet.

Schéma élec emetteur.png


Résultats du routage :

PCB Emetteur.png

Photo des cartes soudées :

Groupe7Emetteur1.jpg
Groupe7Emetteur2.jpg

Vidéo très courte et en basse résolution de la carte en fonctionnement :

Média:2025-PSE-BB-systeme-video.mp4

Récepteur

Présentation

Le récepteur, lui, est connecté à l’ordinateur via USB. Il reçoit les données envoyées par l’émetteur, puis les transmet au PC sous une forme compréhensible (par exemple comme un périphérique d’entrée). C’est donc lui qui fait le lien entre le système et l’ordinateur.

Carte réalisée en utilisant le logiciel KiCAD : Fichier:2025-PSE-BB-systeme.zip.

Schémas électroniques :

Le recepteur

Résultats du routage :

Mon routage

Photo de la carte soudée :

Mon routage Mon routage

Vidéo très courte et en basse résolution de la carte en fonctionnement :

Média:2025-PSE-BB-systeme-video.mp4

Travail effectué

Séance du 17 février

Ces deux séances nous ont permis de nous mettre d'accord sur le projet que nous allions réaliser, initialiser notre git et notre wiki ainsi que rechercher les composants électroniques nécessaires à leur réalisation.

Aux premiers abords nous hésitions entre réaliser une manette de jeu ou un mini-clavier. Nous avons finalement opté pour le mini-clavier car nous pensions que la manette était déjà plus susceptible d'être un projet réalisé par de nombreux autres de nos camarades. Une fois fixé sur notre mini-clavier, nous avons discuté avec M.Redon qui nous a finalement demandé de réaliser le mini-clavier fonctionnant par radiofréquence plutôt qu'en filaire car sinon c'était un peu trop simple.

Notre projet fut alors lancé. Nous sommes repartis les taches pour la conception, Eliott s'est principalement occupé de la partie émetteur tandis que Valentin s'est majoritairement occupé de la partie récepteur. Nous nous sommes donc mis à la recherche des éléments électroniques nécessaires pour réaliser la carte.
Initialement, nous avions cette liste : listeComposant1

Séance du 3 Mars

  • Présentation du sujet : réalisation d'un mini-clavier sans fil à deux touches programmables.
  • Définition de l'architecture générale du système.
  • Choix des principaux composants :
    • ATmega32U4 comme microcontrôleur principal.
    • nRF24L01 comme module de communication radio.
    • Batterie LiPo pour l'alimentation autonome.
  • Mise en place de l'organisation du dépôt Git (matériel, logiciel, documentation).

Séance du 10 Mars

  • Étude du microcontrôleur ATmega32U4.
  • Analyse des différentes possibilités de programmation du microcontrôleur.
  • Mise en place du connecteur ISP pour la programmation.
  • Début de la réalisation du schéma électrique sous KiCad.
  • Ajout du quartz externe 16 MHz et des composants associés.

Séance du 17 Mars

  • Étude approfondie de l'interface radio nRF24L01.
  • Analyse de la documentation constructeur.
  • Détermination des liaisons SPI entre l'ATmega32U4 et le nRF24L01 :
    • MOSI
    • MISO
    • SCK
    • CSN
    • CE
  • Répartition des broches du microcontrôleur utilisées pour la communication radio.
  • Réflexion sur l'utilisation de la broche IRQ du nRF24L01.

Séance du 24 Mars

  • Intégration du nRF24L01 dans le schéma KiCad.
  • Étude détaillée du schéma d'application fourni dans la datasheet.
  • Ajout :
    • du quartz 16 MHz du nRF24L01,
    • des condensateurs associés,
    • de la résistance IREF,
    • des condensateurs de découplage.
  • Analyse du réseau RF entre ANT1, ANT2 et l'antenne.
  • Mise en place du schéma complet de la partie radio.

Séance du 1er Avril

  • Conception de la gestion de l'alimentation du système.
  • Étude de la compatibilité des tensions entre :
    • ATmega32U4,
    • nRF24L01,
    • alimentation batterie.
  • Analyse des contraintes liées aux niveaux logiques.
  • Décision d'utiliser une alimentation commune en 3,3 V afin de simplifier les échanges entre le microcontrôleur et le module radio.
  • Début de l'intégration de la batterie LiPo dans le schéma.
  • Intégration des boutons du mini-clavier.
  • Choix des entrées du microcontrôleur utilisées pour les deux touches.
  • Sélection des empreintes compatibles avec les interrupteurs mécaniques Kailh Box Black.
  • Ajout des boutons dans le schéma.
  • Vérification de la cohérence globale du schéma ATmega32U4 + nRF24L01 + boutons.

Travail en Autonomie

  • Finalisation du schéma électronique sous KiCad.
  • Vérification des connexions et correction des éventuelles erreurs de conception.
  • Attribution des empreintes aux composants et préparation du PCB.
  • Documentation des choix techniques réalisés pour le projet.

Séance du 7 Avril

  • Réalisation du placement des composants sur le circuit imprimé.
  • Organisation des différents blocs fonctionnels afin d'optimiser le futur routage.
  • Définition du contour de la carte et vérification des contraintes d'encombrement.
  • Préparation des règles de conception en vue du routage PCB.

Travail en Autonomie

  • Optimisation du placement des composants.
  • Réalisation progressive du routage des pistes.
  • Vérification des règles de conception (ERC/DRC).
  • Préparation des fichiers de fabrication et des rendus du circuit imprimé.
  • Rédaction et mise à jour du compte-rendu de projet.

Séance du 5 au 26 Mai

Soudure des cartes.

Séance du 2 Juin et plus

Nous sommes passés à la partie pragrammation. Nous avons décidé de commencer par la carte émetteur. Nous avons réussi à flasher du code via un Arduino as ISP pour faire clignoter la LED. Cependant le bootloader n'est pas détecté par lsusb. Nous nous sommes rendus compte qu'il y avait un problème avec la partie USB de la carte. Après plusieurs tests nous en avons conclu que c'était sûrement la carte qui était mal dimensionnée (On avait 3.3 Volts au lieu de 5 qui rentrait dans le VCC coup à un sortie on a trouvé 3.22V au lieu de 3.3 par exemple).

Le problème étant long à régler nous sommes passés à la programmation de l'émetteur et avons laissé de côté le récepteur.

Le bootloader de l'émetteur lui, était bel et bien détecté par le lsusb, il a donc été plus simple de le programmer. Par manque de temps nous avons simplement flashé le code de la lufa (ci dessous) qui lui permet de se comporter comme un clavier, nous avons même trouvé sur github un document avec toutes les touches du clavier.

Le code Keyboard.c de la lufa adapté à l'émetteur :

#include <avr/io.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <LUFA/Drivers/USB/USB.h>
#include "Descriptors.h"
#include "usb_hid_keys.h"

/* ------------------------------------------------------------------ */
/*  Rapport HID clavier (boot-compatible, 8 octets)                    */
/*  Modifier | Reserved | KeyCode[6]                                   */
/* ------------------------------------------------------------------ */
typedef struct {
    uint8_t Modifier;
    uint8_t Reserved;
    uint8_t KeyCode[6];
} USB_KeyboardReport_t;

/* ------------------------------------------------------------------ */
/*  Matériel                                                           */
/* ------------------------------------------------------------------ */
#define LED_DDR   DDRC
#define LED_PORT  PORTC
#define LED_PIN   PC7

/* Boutons en PD4 et PD5, pull-up interne, actif à 0 */
#define BTN_DDR   DDRD
#define BTN_PIN   PIND
#define BTN_PORT  PORTD
#define BTN_A     PD4   /* → keycode 'A' (0x04) */
#define BTN_B     PD5   /* → keycode 'B' (0x05) */

/* Keycodes HID USB (Usage Table, page Keyboard/Keypad) */
//#define HID_KEY_A  0x04
//#define HID_KEY_B  0x05

/* ------------------------------------------------------------------ */
/*  Debounce simple : état précédent                                   */
/* ------------------------------------------------------------------ */
static uint8_t prev_state = 0xFF;  /* 1 = relâché (pull-up) */

/* ------------------------------------------------------------------ */
/*  Initialisation PLL manuelle pour cristal externe 16 MHz           */
/*  ATmega32U4 datasheet §6.8 : PLLCSR                                */
/* ------------------------------------------------------------------ */
static void PLL_Init(void)
{
    /* Source PLL = cristal externe (PINDIV=1 pour 16 MHz) */
    PLLCSR = (1 << PINDIV);        /* diviseur /2 → PLL reçoit 8 MHz  */
                                   /* (entrée PLL max = 8 MHz)         */
    PLLCSR |= (1 << PLLE);         /* active la PLL                    */

    /* Attente lock PLL (bit PLOCK) */
    while (!(PLLCSR & (1 << PLOCK)));
}

/* ------------------------------------------------------------------ */
/*  Initialisation matérielle                                          */
/* ------------------------------------------------------------------ */
void SetupHardware(void)
{
    /* 1. Désactivation prescaler — écriture directe CLKPR */
    CLKPR = (1 << CLKPCE);
    CLKPR = 0x00;                  /* CPU à 16 MHz                     */

    /* 2. Délai stabilisation cristal */
    _delay_ms(10);

    /* 3. PLL manuelle (nécessaire avec USB_OPT_MANUAL_PLL) */
    //PLL_Init();

    /* 4. LED PC7 en sortie, éteinte */
    LED_DDR  |=  (1 << LED_PIN);
    LED_PORT &= ~(1 << LED_PIN);

    /* 5. PD4, PD5 en entrée avec pull-up interne */
    BTN_DDR  &= ~((1 << BTN_A) | (1 << BTN_B));
    BTN_PORT |=  ((1 << BTN_A) | (1 << BTN_B));

    /* 6. Init USB (PLL déjà stable) */
    USB_Init();
}

/* ------------------------------------------------------------------ */
/*  Lecture des boutons → construction du rapport HID                 */
/* ------------------------------------------------------------------ */
static void BuildKeyboardReport(USB_KeyboardReport_t *report)
{
    report->Modifier   = 0;
    report->Reserved   = 0;
    report->KeyCode[0] = 0;
    report->KeyCode[1] = 0;
    report->KeyCode[2] = 0;
    report->KeyCode[3] = 0;
    report->KeyCode[4] = 0;
    report->KeyCode[5] = 0;

    uint8_t pins = BTN_PIN;
    uint8_t idx  = 0;

    if (!(pins & (1 << BTN_A)) && idx < 6)
        report->KeyCode[idx++] = KEY_BACKSPACE;

    if (!(pins & (1 << BTN_B)) && idx < 6)
        report->KeyCode[idx++] = KEY_B;
}

/* ------------------------------------------------------------------ */
/*  Envoi du rapport sur l'endpoint IN                                 */
/* ------------------------------------------------------------------ */
static void SendKeyboardReport(void)
{
    if (USB_DeviceState != DEVICE_STATE_Configured)
        return;

    Endpoint_SelectEndpoint(KEYBOARD_EPADDR);

    if (!Endpoint_IsINReady())
        return;

    USB_KeyboardReport_t report;
    BuildKeyboardReport(&report);

    /* N'envoyer que si l'état a changé */
    uint8_t cur_state = BTN_PIN & ((1 << BTN_A) | (1 << BTN_B));
    if (cur_state == prev_state)
    {
        Endpoint_ClearIN();
        return;
    }
    prev_state = cur_state;

    Endpoint_Write_Stream_LE(&report, sizeof(report), NULL);
    Endpoint_ClearIN();

    if (report.KeyCode[0] != 0 || report.KeyCode[1] != 0)
        LED_PORT |=  (1 << LED_PIN);
    else
        LED_PORT &= ~(1 << LED_PIN);
}

/* ------------------------------------------------------------------ */
/*  Callbacks LUFA                                                     */
/* ------------------------------------------------------------------ */
void EVENT_USB_Device_Connect(void)
{
    LED_PORT |= (1 << LED_PIN);
}

void EVENT_USB_Device_Disconnect(void)
{
    LED_PORT &= ~(1 << LED_PIN);
}

void EVENT_USB_Device_ConfigurationChanged(void)
{
    bool ok = Endpoint_ConfigureEndpoint(KEYBOARD_EPADDR,
                                         EP_TYPE_INTERRUPT,
                                         KEYBOARD_EPSIZE,
                                         1);
    if (!ok) {
        for (uint8_t i = 0; i < 3; i++) {
            LED_PORT |=  (1 << LED_PIN); _delay_ms(150);
            LED_PORT &= ~(1 << LED_PIN); _delay_ms(150);
        }
    }
}

void EVENT_USB_Device_ControlRequest(void)
{
    switch (USB_ControlRequest.bRequest)
    {
        case HID_REQ_GetReport:
            if (USB_ControlRequest.bmRequestType ==
                (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
            {
                USB_KeyboardReport_t report;
                BuildKeyboardReport(&report);
                Endpoint_ClearSETUP();
                Endpoint_Write_Control_Stream_LE(&report, sizeof(report));
                Endpoint_ClearOUT();
            }
            break;

        case HID_REQ_SetReport:
            break;
    }
}

/* ------------------------------------------------------------------ */
/*  Point d'entrée                                                     */
/* ------------------------------------------------------------------ */
int main(void)
{
    SetupHardware();
    GlobalInterruptEnable();

    while (1)
    {
        SendKeyboardReport();
        USB_USBTask();
    }
}

Le fichier usb_hid_keys.h trouvé sur github avec toutes les touches d'un clavier.

/**
 * USB HID Keyboard scan codes as per USB spec 1.11
 * plus some additional codes
 *
 * Created by MightyPork, 2016
 * Public domain
 *
 * Adapted from:
 * https://source.android.com/devices/input/keyboard-devices.html
 */

#ifndef USB_HID_KEYS
#define USB_HID_KEYS

/**
 * Modifier masks - used for the first byte in the HID report.
 * NOTE: The second byte in the report is reserved, 0x00
 */
#define KEY_MOD_LCTRL  0x01
#define KEY_MOD_LSHIFT 0x02
#define KEY_MOD_LALT   0x04
#define KEY_MOD_LMETA  0x08
#define KEY_MOD_RCTRL  0x10
#define KEY_MOD_RSHIFT 0x20
#define KEY_MOD_RALT   0x40
#define KEY_MOD_RMETA  0x80

/**
 * Scan codes - last N slots in the HID report (usually 6).
 * 0x00 if no key pressed.
 *
 * If more than N keys are pressed, the HID reports
 * KEY_ERR_OVF in all slots to indicate this condition.
 */

#define KEY_NONE 0x00 // No key pressed
#define KEY_ERR_OVF 0x01 //  Keyboard Error Roll Over - used for all slots if too many keys are pressed ("Phantom key")
// 0x02 //  Keyboard POST Fail
// 0x03 //  Keyboard Error Undefined
#define KEY_A 0x04 // Keyboard a and A
#define KEY_B 0x05 // Keyboard b and B
#define KEY_C 0x06 // Keyboard c and C
#define KEY_D 0x07 // Keyboard d and D
#define KEY_E 0x08 // Keyboard e and E
#define KEY_F 0x09 // Keyboard f and F
#define KEY_G 0x0a // Keyboard g and G
#define KEY_H 0x0b // Keyboard h and H
#define KEY_I 0x0c // Keyboard i and I
#define KEY_J 0x0d // Keyboard j and J
#define KEY_K 0x0e // Keyboard k and K
#define KEY_L 0x0f // Keyboard l and L
#define KEY_M 0x10 // Keyboard m and M
#define KEY_N 0x11 // Keyboard n and N
#define KEY_O 0x12 // Keyboard o and O
#define KEY_P 0x13 // Keyboard p and P
#define KEY_Q 0x14 // Keyboard q and Q
#define KEY_R 0x15 // Keyboard r and R
#define KEY_S 0x16 // Keyboard s and S
#define KEY_T 0x17 // Keyboard t and T
#define KEY_U 0x18 // Keyboard u and U
#define KEY_V 0x19 // Keyboard v and V
#define KEY_W 0x1a // Keyboard w and W
#define KEY_X 0x1b // Keyboard x and X
#define KEY_Y 0x1c // Keyboard y and Y
#define KEY_Z 0x1d // Keyboard z and Z

#define KEY_1 0x1e // Keyboard 1 and !
#define KEY_2 0x1f // Keyboard 2 and @
#define KEY_3 0x20 // Keyboard 3 and #
#define KEY_4 0x21 // Keyboard 4 and $
#define KEY_5 0x22 // Keyboard 5 and %
#define KEY_6 0x23 // Keyboard 6 and ^
#define KEY_7 0x24 // Keyboard 7 and &
#define KEY_8 0x25 // Keyboard 8 and *
#define KEY_9 0x26 // Keyboard 9 and (
#define KEY_0 0x27 // Keyboard 0 and )

#define KEY_ENTER 0x28 // Keyboard Return (ENTER)
#define KEY_ESC 0x29 // Keyboard ESCAPE
#define KEY_BACKSPACE 0x2a // Keyboard DELETE (Backspace)
#define KEY_TAB 0x2b // Keyboard Tab
#define KEY_SPACE 0x2c // Keyboard Spacebar
#define KEY_MINUS 0x2d // Keyboard - and _
#define KEY_EQUAL 0x2e // Keyboard = and +
#define KEY_LEFTBRACE 0x2f // Keyboard [ and {
#define KEY_RIGHTBRACE 0x30 // Keyboard ] and }
#define KEY_BACKSLASH 0x31 // Keyboard \ and |
#define KEY_HASHTILDE 0x32 // Keyboard Non-US # and ~
#define KEY_SEMICOLON 0x33 // Keyboard ; and :
#define KEY_APOSTROPHE 0x34 // Keyboard ' and "
#define KEY_GRAVE 0x35 // Keyboard ` and ~
#define KEY_COMMA 0x36 // Keyboard , and <
#define KEY_DOT 0x37 // Keyboard . and >
#define KEY_SLASH 0x38 // Keyboard / and ?
#define KEY_CAPSLOCK 0x39 // Keyboard Caps Lock

#define KEY_F1 0x3a // Keyboard F1
#define KEY_F2 0x3b // Keyboard F2
#define KEY_F3 0x3c // Keyboard F3
#define KEY_F4 0x3d // Keyboard F4
#define KEY_F5 0x3e // Keyboard F5
#define KEY_F6 0x3f // Keyboard F6
#define KEY_F7 0x40 // Keyboard F7
#define KEY_F8 0x41 // Keyboard F8
#define KEY_F9 0x42 // Keyboard F9
#define KEY_F10 0x43 // Keyboard F10
#define KEY_F11 0x44 // Keyboard F11
#define KEY_F12 0x45 // Keyboard F12

#define KEY_SYSRQ 0x46 // Keyboard Print Screen
#define KEY_SCROLLLOCK 0x47 // Keyboard Scroll Lock
#define KEY_PAUSE 0x48 // Keyboard Pause
#define KEY_INSERT 0x49 // Keyboard Insert
#define KEY_HOME 0x4a // Keyboard Home
#define KEY_PAGEUP 0x4b // Keyboard Page Up
#define KEY_DELETE 0x4c // Keyboard Delete Forward
#define KEY_END 0x4d // Keyboard End
#define KEY_PAGEDOWN 0x4e // Keyboard Page Down
#define KEY_RIGHT 0x4f // Keyboard Right Arrow
#define KEY_LEFT 0x50 // Keyboard Left Arrow
#define KEY_DOWN 0x51 // Keyboard Down Arrow
#define KEY_UP 0x52 // Keyboard Up Arrow

#define KEY_NUMLOCK 0x53 // Keyboard Num Lock and Clear
#define KEY_KPSLASH 0x54 // Keypad /
#define KEY_KPASTERISK 0x55 // Keypad *
#define KEY_KPMINUS 0x56 // Keypad -
#define KEY_KPPLUS 0x57 // Keypad +
#define KEY_KPENTER 0x58 // Keypad ENTER
#define KEY_KP1 0x59 // Keypad 1 and End
#define KEY_KP2 0x5a // Keypad 2 and Down Arrow
#define KEY_KP3 0x5b // Keypad 3 and PageDn
#define KEY_KP4 0x5c // Keypad 4 and Left Arrow
#define KEY_KP5 0x5d // Keypad 5
#define KEY_KP6 0x5e // Keypad 6 and Right Arrow
#define KEY_KP7 0x5f // Keypad 7 and Home
#define KEY_KP8 0x60 // Keypad 8 and Up Arrow
#define KEY_KP9 0x61 // Keypad 9 and Page Up
#define KEY_KP0 0x62 // Keypad 0 and Insert
#define KEY_KPDOT 0x63 // Keypad . and Delete

#define KEY_102ND 0x64 // Keyboard Non-US \ and |
#define KEY_COMPOSE 0x65 // Keyboard Application
#define KEY_POWER 0x66 // Keyboard Power
#define KEY_KPEQUAL 0x67 // Keypad =

#define KEY_F13 0x68 // Keyboard F13
#define KEY_F14 0x69 // Keyboard F14
#define KEY_F15 0x6a // Keyboard F15
#define KEY_F16 0x6b // Keyboard F16
#define KEY_F17 0x6c // Keyboard F17
#define KEY_F18 0x6d // Keyboard F18
#define KEY_F19 0x6e // Keyboard F19
#define KEY_F20 0x6f // Keyboard F20
#define KEY_F21 0x70 // Keyboard F21
#define KEY_F22 0x71 // Keyboard F22
#define KEY_F23 0x72 // Keyboard F23
#define KEY_F24 0x73 // Keyboard F24

#define KEY_OPEN 0x74 // Keyboard Execute
#define KEY_HELP 0x75 // Keyboard Help
#define KEY_PROPS 0x76 // Keyboard Menu
#define KEY_FRONT 0x77 // Keyboard Select
#define KEY_STOP 0x78 // Keyboard Stop
#define KEY_AGAIN 0x79 // Keyboard Again
#define KEY_UNDO 0x7a // Keyboard Undo
#define KEY_CUT 0x7b // Keyboard Cut
#define KEY_COPY 0x7c // Keyboard Copy
#define KEY_PASTE 0x7d // Keyboard Paste
#define KEY_FIND 0x7e // Keyboard Find
#define KEY_MUTE 0x7f // Keyboard Mute
#define KEY_VOLUMEUP 0x80 // Keyboard Volume Up
#define KEY_VOLUMEDOWN 0x81 // Keyboard Volume Down
// 0x82  Keyboard Locking Caps Lock
// 0x83  Keyboard Locking Num Lock
// 0x84  Keyboard Locking Scroll Lock
#define KEY_KPCOMMA 0x85 // Keypad Comma
// 0x86  Keypad Equal Sign
#define KEY_RO 0x87 // Keyboard International1
#define KEY_KATAKANAHIRAGANA 0x88 // Keyboard International2
#define KEY_YEN 0x89 // Keyboard International3
#define KEY_HENKAN 0x8a // Keyboard International4
#define KEY_MUHENKAN 0x8b // Keyboard International5
#define KEY_KPJPCOMMA 0x8c // Keyboard International6
// 0x8d  Keyboard International7
// 0x8e  Keyboard International8
// 0x8f  Keyboard International9
#define KEY_HANGEUL 0x90 // Keyboard LANG1
#define KEY_HANJA 0x91 // Keyboard LANG2
#define KEY_KATAKANA 0x92 // Keyboard LANG3
#define KEY_HIRAGANA 0x93 // Keyboard LANG4
#define KEY_ZENKAKUHANKAKU 0x94 // Keyboard LANG5
// 0x95  Keyboard LANG6
// 0x96  Keyboard LANG7
// 0x97  Keyboard LANG8
// 0x98  Keyboard LANG9
// 0x99  Keyboard Alternate Erase
// 0x9a  Keyboard SysReq/Attention
// 0x9b  Keyboard Cancel
// 0x9c  Keyboard Clear
// 0x9d  Keyboard Prior
// 0x9e  Keyboard Return
// 0x9f  Keyboard Separator
// 0xa0  Keyboard Out
// 0xa1  Keyboard Oper
// 0xa2  Keyboard Clear/Again
// 0xa3  Keyboard CrSel/Props
// 0xa4  Keyboard ExSel

// 0xb0  Keypad 00
// 0xb1  Keypad 000
// 0xb2  Thousands Separator
// 0xb3  Decimal Separator
// 0xb4  Currency Unit
// 0xb5  Currency Sub-unit
#define KEY_KPLEFTPAREN 0xb6 // Keypad (
#define KEY_KPRIGHTPAREN 0xb7 // Keypad )
// 0xb8  Keypad {
// 0xb9  Keypad }
// 0xba  Keypad Tab
// 0xbb  Keypad Backspace
// 0xbc  Keypad A
// 0xbd  Keypad B
// 0xbe  Keypad C
// 0xbf  Keypad D
// 0xc0  Keypad E
// 0xc1  Keypad F
// 0xc2  Keypad XOR
// 0xc3  Keypad ^
// 0xc4  Keypad %
// 0xc5  Keypad <
// 0xc6  Keypad >
// 0xc7  Keypad &
// 0xc8  Keypad &&
// 0xc9  Keypad |
// 0xca  Keypad ||
// 0xcb  Keypad :
// 0xcc  Keypad #
// 0xcd  Keypad Space
// 0xce  Keypad @
// 0xcf  Keypad !
// 0xd0  Keypad Memory Store
// 0xd1  Keypad Memory Recall
// 0xd2  Keypad Memory Clear
// 0xd3  Keypad Memory Add
// 0xd4  Keypad Memory Subtract
// 0xd5  Keypad Memory Multiply
// 0xd6  Keypad Memory Divide
// 0xd7  Keypad +/-
// 0xd8  Keypad Clear
// 0xd9  Keypad Clear Entry
// 0xda  Keypad Binary
// 0xdb  Keypad Octal
// 0xdc  Keypad Decimal
// 0xdd  Keypad Hexadecimal

#define KEY_LEFTCTRL 0xe0 // Keyboard Left Control
#define KEY_LEFTSHIFT 0xe1 // Keyboard Left Shift
#define KEY_LEFTALT 0xe2 // Keyboard Left Alt
#define KEY_LEFTMETA 0xe3 // Keyboard Left GUI
#define KEY_RIGHTCTRL 0xe4 // Keyboard Right Control
#define KEY_RIGHTSHIFT 0xe5 // Keyboard Right Shift
#define KEY_RIGHTALT 0xe6 // Keyboard Right Alt
#define KEY_RIGHTMETA 0xe7 // Keyboard Right GUI

#define KEY_MEDIA_PLAYPAUSE 0xe8
#define KEY_MEDIA_STOPCD 0xe9
#define KEY_MEDIA_PREVIOUSSONG 0xea
#define KEY_MEDIA_NEXTSONG 0xeb
#define KEY_MEDIA_EJECTCD 0xec
#define KEY_MEDIA_VOLUMEUP 0xed
#define KEY_MEDIA_VOLUMEDOWN 0xee
#define KEY_MEDIA_MUTE 0xef
#define KEY_MEDIA_WWW 0xf0
#define KEY_MEDIA_BACK 0xf1
#define KEY_MEDIA_FORWARD 0xf2
#define KEY_MEDIA_STOP 0xf3
#define KEY_MEDIA_FIND 0xf4
#define KEY_MEDIA_SCROLLUP 0xf5
#define KEY_MEDIA_SCROLLDOWN 0xf6
#define KEY_MEDIA_EDIT 0xf7
#define KEY_MEDIA_SLEEP 0xf8
#define KEY_MEDIA_COFFEE 0xf9
#define KEY_MEDIA_REFRESH 0xfa
#define KEY_MEDIA_CALC 0xfb

#endif // USB_HID_KEYS

Le clavier fonctionne donc en USB, et les deux touches sont paramétrables. (Exemple ci dessous avec une vidéo ou le miniclavier a une touche qui écrit une lettre tandis que l'autre est un Backspace)

Problèmes rencontrés :

Routage de l’antenne RF

L’un des principaux défis rencontrés lors de la conception du PCB a été le routage de l’antenne RF du module NRF24L01. Contrairement aux autres signaux présents sur la carte, les signaux radiofréquences sont particulièrement sensibles à la géométrie des pistes et à leur environnement. Il a donc été nécessaire de suivre attentivement les recommandations de la documentation constructeur, notamment concernant le réseau d’adaptation RF, le placement des composants associés et le routage des pistes entre le module et l’antenne. Une attention particulière a également été portée à la présence du plan de masse et à l’absence de cuivre sous certaines zones critiques afin de garantir le bon fonctionnement de la liaison radio.

Gestion de l’alimentation USB et batterie

Un autre point important a concerné la gestion des différentes sources d’alimentation de l’émetteur. Celui-ci devait pouvoir fonctionner aussi bien lorsqu’il est connecté en USB que lorsqu’il est alimenté par sa batterie Li-Po. La solution retenue repose sur un circuit de charge MAX1811 permettant de recharger la batterie depuis l’USB, tandis qu’un convertisseur buck-boost LTC3531 assure la génération d’une tension stable de 3,3 V à partir de la batterie. Une diode a également été ajoutée sur le chemin d’alimentation afin d’éviter les retours de courant indésirables entre les différentes sources. Cette architecture permet de recharger la batterie tout en assurant l’alimentation correcte du système.

Soudure des composants CMS

L’assemblage de la carte a également présenté quelques difficultés. Certains composants possèdent des connexions peu accessibles ou situées sous le boîtier, rendant leur soudure délicate avec un simple fer à souder. Afin d’obtenir des soudures fiables et d’éviter les défauts de contact, il a été nécessaire d’utiliser une station à air chaud pour plusieurs composants CMS. Cette méthode a permis d’assurer un meilleur positionnement et une meilleure qualité d’assemblage.

Temps limité pour l’assemblage

Enfin, le temps disponible pendant les séances de travaux pratiques n’était pas suffisant pour réaliser l’intégralité de l’assemblage de la carte. Une partie importante du travail de soudure a donc été effectuée en dehors des heures de cours, à l’aide de matériel personnel. Cette organisation a permis d’avancer plus efficacement sur le projet et de respecter le calendrier prévu pour les phases de test et de validation.

Bilan

Ce projet nous a permis de mener de bout en bout la conception d'un système embarqué sans fil, depuis le schéma électronique jusqu'à la programmation finale. La partie émetteur est pleinement fonctionnelle : la carte est reconnue en USB, le bootloader DFU est détecté, et le firmware LUFA permet au mini-clavier d'être utilisé comme un vrai périphérique HID avec deux touches configurables. La partie récepteur n'a malheureusement pas pu être finalisée dans les temps. Un problème de tension (3,3 V au lieu de 5 V sur le VCC) a empêché l'énumération USB correcte, et le manque de temps n'a pas permis de corriger le dimensionnement de la carte. Malgré cela, le projet nous a apporté beaucoup : maîtrise de KiCad pour la conception PCB, soudure de composants CMS, utilisation de LUFA, gestion de l'alimentation avec batterie Li-Po, et compréhension concrète des contraintes liées aux systèmes embarqués réels. C'est un projet que nous aurions aimé avoir plus de temps pour finaliser complètement. À l'avenir, grâce aux problèmes que nous avons rencontrés, nous procéderons différemment car nous avons compris les erreurs faites lors du dimensionnement de nos cartes (notamment le récepteur).