« I2L 2022 Groupe4 » : différence entre les versions

De wiki-se.plil.fr
Aller à la navigation Aller à la recherche
Aucun résumé des modifications
Aucun résumé des modifications
Ligne 344 : Ligne 344 :
- Télécharger [https://www.macports.org/install.php MacPorts] avant d'installer la libus
- Télécharger [https://www.macports.org/install.php MacPorts] avant d'installer la libus


- Voici la [https://ports.macports.org/port/libusb-devel/ libusb] à utiliser sur Mac
- Voici la [https://ports.macports.org/port/libusb-devel/ libusb] qui est libusb-devel à utiliser sur Mac


== '''Prog PC (lib USB) :''' ==
== '''Prog PC (lib USB) :''' ==

Version du 15 juin 2023 à 13:25

Sujet du projet

Clavier de raccourcis programmables - par Axel Lebas & Wassim Djamaa & Maxime Vitse

Proposition de système

Une carte avec 4 boutons programmables via un fichier de configuration qui est fourni par l'utilisateur. Accompagnée d'une LED.

Contre-proposition

Bonne idée. Votre périphérique USB sera programmé avec une interface comportant un point d'accès OUT pour envoyer les chaînes de caractères à envoyer sur pression des boutons. Il serait intéressant d'écrire ces chaînes dans l'EEPROM de l'ATMega16u2 pour qu'elles persistent une fois le périphérique débranché. Les LED du périphérique doivent permettre d'indiquer quelles touches sont programmées. Le programme de configuration sera écrit avec la bibliothèque libusb-1.0.

Carte

Schéma
Carte

Carte soudée :

I2L-2022-G4-carte-soudée.jpg












Fichiers

Le circuit imprimé à utiliser est le même que celui du groupe 3 avec le clavier de la carte du groupe 2.

Après quelques problèmes avec le connecteur USB C, une variante de la carte du groupe 3 est proposée avec un connecteur USB A.

Projet KiCAD : Fichier:I2L-2022-CLIPET-MATHON-BOUKELLAL version USBA.zip

Trois parties à faire

  • Prog SE:

- LED

  • Prog USB:

- LUFA

  • Prog PC:

- Lib usb

Prog SE :

Makefile pour automatiser le processus suivant

Par défaut le micro processeur a un bootloader qui permet de faire de la programmation (sans passer par le SPI) , l'utilitaire que nous utilisons est DFU/USB.

"5.2  ATMega328p: Chaîne de compilation (2/2)" de https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme.html
$ apt install gcc-avr avr-libc dfu-programmer // DFU/USB dfu 6 programmer

$ avr-gcc -mmcu=atmega328p -DF_CPU=8000000UL -c -Wall -I. -Os timer.c -o timer.o // compilation source en un . objet

$ avr-gcc -mmcu=atmega328p -g -lm -Wl,--gc-sections -o timer.elf timer.o // édition des liens (afin d'obtenir un exécutable)

$ avr-objcopy -j .text -j .data -O ihex timer.elf timer.hex // nécessaire pour les utilitaires

$ dfu-programmer atmega16u2 erase

$ dfu-programmer atmega16u2 flash timer.hex

$ dfu-programmer atmega16u2 reset
Exemple de makefile
CC = avr-gcc
OBJCOPY = avr-objcopy
DFU_PROGRAMMER = dfu-programmer

CFLAGS = -mmcu=atmega328p -DF_CPU=8000000UL -c -Wall -I. -Os
LDFLAGS = -mmcu=atmega328p -g -lm -Wl,--gc-sections

all: timer.hex

timer.o: timer.c
	$(CC) $(CFLAGS) $< -o $@

timer.elf: timer.o
	$(CC) $(LDFLAGS) $< -o $@

timer.hex: timer.elf
	$(OBJCOPY) -j .text -j .data -O ihex $< $@

erase:
	$(DFU_PROGRAMMER) atmega16u2 erase

flash: timer.hex
	$(DFU_PROGRAMMER) atmega16u2 flash $<

reset:
	$(DFU_PROGRAMMER) atmega16u2 reset

clean:
	rm -f timer.o timer.elf timer.hex

Gestion des entrées-sorties numériques avec avr-gcc

Code : https://github.com/Weamix/shortcut/blob/master/timer.c

1ère version :
#include <avr/io.h>
#include <util/delay.h>

int main(void){
    CLKSEL0 = 0b00010101;   // sélection de l'horloge externe
    CLKSEL1 = 0b00001111;   // minimum de 8Mhz
    CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)
    CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)

    DDRB |= 0x01;  // direction sortie pour PB0
    PORTB &= ~0x01;

    PORTD &= ~0x78; // entrees
    PORTD |= ~0x78;


    while(1){

        if ((PIND & 0x40))
            PORTB &= ~0x80; // LED éteinte
        else
            PORTB |= 0x80; // LED allumée

        if ((PIND & 0x20))
            // open led on pb6
            PORTB &= ~0x40; // LED éteinte
        else
            PORTB |= 0x40; // LED allumée

        if ((PIND & 0x10))
            // open led on pb5
            PORTB &= ~0x20; // LED éteinte
        else
            PORTB |= 0x20; // LED allumée

        if ((PIND & 0x08))
            // open led on pb4
            PORTB &= ~0x10; // LED éteinte
        else
            PORTB |= 0x10; // LED allumée
    }
}


2nde version :

int main(void){
    CLKSEL0 = 0b00010101;   // sélection de l'horloge externe
    CLKSEL1 = 0b00001111;   // minimum de 8Mhz
    CLKPR = 0b10000000;     // modification du diviseur d'horloge (CLKPCE=1)
    CLKPR = 0;              // 0 pour pas de diviseur (diviseur de 1)

#if 0
    DDRB |= 0x01;  // direction sortie pour PB0
    PORTB &= ~0x01;

    PORTD &= ~0x78; // entrees
    PORTD |= ~0x78;
#endif

    DDRB |= 0xf0;
    PORTB &= ~0xf0;

    DDRD &= ~0x78;
    PORTD |= 0x78;
    // lire pin d sur les bits 40 20 10 et 08

    //DDRB &= ~0b00000011; // Entrée pour le bouton
    //PORTB |= 0x02; // Configuration de la résistance de tirage

    while(1){
        if(!(PIND & 0x40)) PORTB |= 0x80; else PORTB &= ~0x80;
    }
    while(1){

        if ((PIND & 0x40))
            PORTB &= ~0x80; // LED éteinte
        else
            PORTB |= 0x80; // LED allumée

        if ((PIND & 0x20))
            // open led on pb6
            PORTB &= ~0x40; // LED éteinte
        else
            PORTB |= 0x40; // LED allumée

        if ((PIND & 0x10))
            // open led on pb5
            PORTB &= ~0x20; // LED éteinte
        else
            PORTB |= 0x20; // LED allumée

        if ((PIND & 0x08))
            // open led on pb4
            PORTB &= ~0x10; // LED éteinte
        else
            PORTB |= 0x10; // LED allumée
    }
}
Ports

B: 8 sorties

C: > 8 sorties

D: 8 sorties

En général 8 fois 3 entrées, ici une vingtaine de sorties

Registre DDR (data direction register) : sens de la LED

Pour chaque bit du port si le bit correspond à une entrée ou une sortie


Voir PB0 / PB1 sur le schéma KICAD

- Par défaut, BIT à 0 en entrée

- 1 pour sortie


Il faut toucher au bit avec le poids le plus faible.

Rappels sur les opérandes en C

& | sont des opérandes bit à bit pas comme les opérandes logiques dans les if && ou ||

tilde is NOT

Le OU exclusif s'écrit PORTB ^ = 0X01


le & avec le tilde permet un bit à 0

le | sans le tilde permet un bit à 1


2 types de registres

Port B -> sortie

PINB -> entrée

Prog Lufa :

Bibliothèque LUFA

  • boucler sur la gestion des événements USB USB_USBTask ;
  • éventuellement appeler aussi la gestion d’une classe (e.g. HID_Task) ;
  • écrire les fonctions de rappel (callback) pour implanter les fonctionnalités souhaitées.
  • Modifier le Makefile de LUFA en mettant MCU en atmega16u2 4 premières lignes à modifier seulement (une à none).
  • Modifier dans descriptor.c et descriptor.h

Base pour le projet

Comme base pour le programme LUFA vous pouvez prendre le projet LUFA "écho" disponible sur la page Wiki du groupe 2.

Code

https://github.com/Weamix/shortcut/blob/master/lufa/Demos/Device/LowLevel/Keyboard/Keyboard.c
void SetupHardware(void)
{
    ...

    // LEDS : PB7 à PB4

	/* Hardware Initialization */
	USB_Init();

    DDRB |= 0x01;  // direction sortie pour PB0
    PORTB &= ~0x01;

    PORTD &= ~0x78; // entrees
    PORTD |= ~0x78;
}


void CreateKeyboardReport(USB_KeyboardReport_Data_t* const ReportData)
{
    uint8_t UsedKeyCodes      = 0;

    /* Clear the report contents */
	memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));

    // Add shortcuts for copy, paste, and delete

    // PB3 à PB0  - PD3 à PD6: touches

    if (!(PIND & 0x40))
    {
        // Copy shortcut: Ctrl + C
        ReportData->Modifier = HID_KEYBOARD_MODIFIER_LEFTGUI;
        ReportData->KeyCode[UsedKeyCodes++] = HID_KEYBOARD_SC_C;
    }

    if (!(PIND & 0x20))
    {
        // Paste shortcut: Ctrl + V
        ReportData->Modifier = HID_KEYBOARD_MODIFIER_LEFTGUI;
        ReportData->KeyCode[UsedKeyCodes++] = HID_KEYBOARD_SC_V;
    }

    if (!(PIND & 0x10))
    {
        // letters
        ReportData->KeyCode[UsedKeyCodes++] = HID_KEYBOARD_SC_F;
        ReportData->KeyCode[UsedKeyCodes++] = HID_KEYBOARD_SC_P;
        ReportData->KeyCode[UsedKeyCodes++] = HID_KEYBOARD_SC_D;
    }
}
Schémas pinb pind.png

Schémas PINB/PIND :

Bibliothèque LUFA-210230

- Télécharger la bibliothèque (ici)

- Ajouter l'archive dans le projet et compiler (make et make dfu) afin de tester son bon fonctionnement

Installation de la libusb et son kit de développement sur Mac

- Télécharger MacPorts avant d'installer la libus

- Voici la libusb qui est libusb-devel à utiliser sur Mac

Prog PC (lib USB) :

Comme base pour le programme PC vous pouvez prendre le programme libusb disponible sur la page Wiki du groupe 2.

Difficultés rencontrées

Problème de compatibilité avec l'OS Mac, souvent nous avons eu des problèmes de liaison entre la carte programmable et nos ordinateurs. Pour contrer certaines problématiques et après beaucoup de recherche. Nous avons réussi à faire évoluer notre système afin d'atteindre notre objectif final (l'installation de LUFA-210230 et lsusb)

Démo finale

Démo des touches (PB1/PB0) qui sont rattachés au ctrl/c et ctrl/v et exemple de programmation d'une toûche.

Conclusion

Le code finale fonctionne avec 2 parties :

1) lib usb (la programmation pc) où le code intéressant se trouve dans : https://github.com/Weamix/shortcut/blob/master/USBprogI2L/proj_echo.c

2) la partie lufa keyboard dans : https://github.com/Weamix/shortcut/blob/master/lufa-copy-paste/Demos/Device/LowLevel/Keyboard/Keyboard.c