« SE3Groupe2024-3 » : différence entre les versions

De projets-se.plil.fr
Aller à la navigation Aller à la recherche
Aucun résumé des modifications
 
(36 versions intermédiaires par 2 utilisateurs non affichées)
Ligne 1 : Ligne 1 :
== Programmateur AVR ==
=== Description du projet ===
Pour notre module de Premier Système Embarqué (PSE), il nous a été demandé de concevoir un PCB et programmer un microcontrôleur permettant de programmer un autre microcontrôleur (qui sera testé sur une Arduino Uno).
'''<u>Etape 1 : Conception du circuit électronique</u>'''
La première étape fut de mettre en place le circuit électronique via KiCad, cette carte est composée de :
* 1 Atmega8U2-A qui est notre microcontrôleur
* 1 quartz 8 Mhz
* 1 LED de contrôle présence tension
* 2 LED de test
* 1 port USB-A pour la communication avec l'ordinateur
* 1 connecteur ISP 2x3 pour la connection avec l'AVR à programmer
* 1 bouton de BOOT
* 1 bouton de RESET
* 1 bouton de test
Nous avons conçu le schéma suivant pour notre carte selon les indications données. Il a fallu environ entre 2 et 3 séances de deux heures pour la concevoir.
[[Fichier:Schéma du programmateur.png|néant|vignette|<i>Schéma du programmateur AVR du binôme 3</i>]]
'''<u>Etape 2 : Routage de la carte</u>'''
Après avoir fait le schéma, nous avons fait une première version du routage de la carte qui fut modifié par souci d'optimisation (pour avoir notamment les composants sur une seule couche) par M.Boé, et nous avons obtenu ce routage suivant qui a été tiré en plusieurs fois.
[[Fichier:Schéma prototype.png|vignette|240x240px|<i>Routage du programmateur AVR du binôme 3, version 1</i>|gauche]]
[[Fichier:Routage v1.png|right|vignette|207x207px|<i>Routage du programmateur AVR du binôme 3, version modifié</i>]]
'''<u>Etape 3.0 : Fonctions pratiques</u>'''
Nous avons conçu 3 fonctions primaires, permettant de nous simplifier la gestion des Entrées/Sorties.
Nous avons la fonction ''setup_io'', qui permet, pour un pin et un port donné, de décider de l'assigner à une entrée ou une sortie, et d'activer ou non la résistance de PULL UP interne.
De plus, pour simplifier et éviter la répétition de code, le port utilisé est temporairement remplacé par un pointeur ayant l'adresse du port utilisé.
void setup_io(int pin, int is_output, int pull_up_active, char port){
volatile uint8_t* PORTx;
volatile uint8_t* PINx;
volatile uint8_t* DDRx;
if (port == 'b'){
PORTx = &PORTB;
PINx = &PINB;
DDRx = &DDRB;
}
if (port == 'c'){
PORTx = &PORTC;
PINx = &PINC;
DDRx = &DDRC;
}
if (port == 'd'){
PORTx = &PORTD;
PINx = &PIND;
DDRx = &DDRD;
}
if (is_output){
(*DDRx) |= 1<<pin;//met la led D1 en output
}else{
(*DDRx) |= 0<<pin;//met la led D1 en input
if (pull_up_active){
(*PORTx) |= 1<<pin;
}else{
(*PORTx) &= ~(1<<pin);
}
}
}
Nous avons la fonction ''active_o'', qui permet, pour un pin et un port donné, de le mettre à 1 ou à 0. La même méthode est utilisé pour la gestion de port via un pointeur.
Remarque : Cette fonction est destinée à agir sur des pins qui ont été paramétrés en sortie au préalable.
void active_o(int pin, int is_active, char port ){
volatile uint8_t* PORTx;
volatile uint8_t* PINx;
volatile uint8_t* DDRx;
if (port == 'b'){
PORTx = &PORTB;
PINx = &PINB;
DDRx = &DDRB;
}
if (port == 'c'){
PORTx = &PORTC;
PINx = &PINC;
DDRx = &DDRC;
}
if (port == 'd'){
PORTx = &PORTD;
PINx = &PIND;
DDRx = &DDRD;
}
if (is_active){
(*PORTx) &= ~(1<<pin); //allume la led
}else{
(*PORTx) |= 1<<pin;
}
}
Nous avons la fonction ''read_i'', qui permet, pour un pin et un port donné, de lire sa valeur.
Remarque : Cette fonction est destinée à lire sur des pins qui ont été paramétrés en entrée au préalable.
int read_i(int pin, char port){
    int val = 0;
    if (port == 'b'){
val = PINB;
    }else if (port == 'c'){
val = PINC;
    }else if (port == 'd'){
val = PIND;
    }
    int mask = 0;
    mask =  1 << pin;
    return (val & mask);
}
'''<u>Etape 3.1 : Premier programme, interaction bouton/LED</u>'''
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)
setup_io(LED_1, 1, 1, 'd'); // Led définie en OUTPUT sur le Port D
setup_io(LED_2, 1, 1, 'd'); //
setup_io(BUTTON, 0, 1, 'b'); // Bouton INPUT sur le Port B avec résistance de PULL UP interne
active_o(LED_2, 0, 'd'); // La LED 2 est éteinte
while(1) {
if( !read_i(BUTTON, 'b') ){
active_o(LED_1, 0, 'd'); //Si le bouton est activé, on allume la LED, sinon on l'éteint
}else{
active_o(LED_1, 1, 'd');
}
_delay_ms(100);
}
}
Ce programme permet basiquement d'allumer la LED lorsque que le bouton est appuyé. Il utilise les fonctions vues précédemment.
====== Vidéo démonstrative ci dessous : ======
[[Fichier:Video bouton.mov|néant|vignette]]
'''<u>Etape 4 : Deuxième programme, communication série PC/AVR</u>'''
Pour communiquer avec le PC en série, nous avons utilisé la librairie LUFA.
'''Voici les modifications que nous avons apportées :'''
A la fin du ''main'', nous avons paramétrés nos pins et rajouter une variable qui permettra de n'afficher sur la liaison série uniquement les changements d'états.
#define LED_1 0 // Port D
#define LED_2 1 // Port D
#define BUTTON 4 // Port B
int button_toggle = -1; //evite d'imprimer un texte tout le temps
//Initialisation
setup_io(LED_1, 1, 1, 'd'); // Led OUTPUT
setup_io(LED_2, 1, 1, 'd'); // Led
setup_io(BUTTON, 0, 1, 'b'); // Bouton INPUT
Nous avons ensuite modifié la fonction ''CDC_Task'' pour y implémenter la logique souhaitée :
Quand on appuie sur le bouton, le PC recevra "Button pressed\r\n", et quand on le relâche, le PC recevra "Button not pressed\r\n"
void CDC_Task(void)
{
...    //LUFA Code
        //Notre code
        int is_button_pressed = !read_i(BUTTON, 'b');
if( button_toggle != 0 &&  is_button_pressed ){
active_o(LED_1, 0, 'd'); //Si le bouton est activé, on allume la LED, sinon on l'éteint
ReportString = "Button pressed\r\n";
button_toggle = 0;
ActionSent = false;
}
if(button_toggle != 1 && !is_button_pressed ){
active_o(LED_1, 1, 'd');
button_toggle = 1;
ReportString = "Button not pressed\r\n";
ActionSent = false;
}
... //LUFA Code
}
'''Vidéo démonstrative ci dessous :'''
[[Fichier:Communication serie.mov|néant|vignette]]
[https://gitea.plil.fr/tduwez/se3_2024_binome3/src/branch/main/LUFA Lien Gitea : LUFA]
[https://gitea.plil.fr/tduwez/se3_2024_binome3/src/branch/main/carte_PSE Lien Gitea : Programmes]
== Description ==
== Description ==
'''<u>Sujet 1 : Manette sans fil</u>'''


=== Objectif ===
=== Objectif ===
Ligne 31 : Ligne 262 :


ReX : mieux expliciter les deux parties : la manette radio autonome et la base radio connectée en USB au terminal de jeu.
ReX : mieux expliciter les deux parties : la manette radio autonome et la base radio connectée en USB au terminal de jeu.
== Carte électronique ==
== Carte électronique ==



Version actuelle datée du 11 avril 2025 à 15:11

Programmateur AVR

Description du projet

Pour notre module de Premier Système Embarqué (PSE), il nous a été demandé de concevoir un PCB et programmer un microcontrôleur permettant de programmer un autre microcontrôleur (qui sera testé sur une Arduino Uno).

Etape 1 : Conception du circuit électronique

La première étape fut de mettre en place le circuit électronique via KiCad, cette carte est composée de :

  • 1 Atmega8U2-A qui est notre microcontrôleur
  • 1 quartz 8 Mhz
  • 1 LED de contrôle présence tension
  • 2 LED de test
  • 1 port USB-A pour la communication avec l'ordinateur
  • 1 connecteur ISP 2x3 pour la connection avec l'AVR à programmer
  • 1 bouton de BOOT
  • 1 bouton de RESET
  • 1 bouton de test

Nous avons conçu le schéma suivant pour notre carte selon les indications données. Il a fallu environ entre 2 et 3 séances de deux heures pour la concevoir.

Schéma du programmateur AVR du binôme 3


Etape 2 : Routage de la carte

Après avoir fait le schéma, nous avons fait une première version du routage de la carte qui fut modifié par souci d'optimisation (pour avoir notamment les composants sur une seule couche) par M.Boé, et nous avons obtenu ce routage suivant qui a été tiré en plusieurs fois.

Routage du programmateur AVR du binôme 3, version 1
Routage du programmateur AVR du binôme 3, version modifié












Etape 3.0 : Fonctions pratiques

Nous avons conçu 3 fonctions primaires, permettant de nous simplifier la gestion des Entrées/Sorties.

Nous avons la fonction setup_io, qui permet, pour un pin et un port donné, de décider de l'assigner à une entrée ou une sortie, et d'activer ou non la résistance de PULL UP interne.

De plus, pour simplifier et éviter la répétition de code, le port utilisé est temporairement remplacé par un pointeur ayant l'adresse du port utilisé.

void setup_io(int pin, int is_output, int pull_up_active, char port){
	volatile uint8_t* PORTx;
	volatile uint8_t* PINx;
	volatile uint8_t* DDRx;


	if (port == 'b'){
		PORTx = &PORTB;
		PINx = &PINB;
		DDRx = &DDRB;
	}
	if (port == 'c'){
		PORTx = &PORTC;
		PINx = &PINC;
		DDRx = &DDRC;
	}
	if (port == 'd'){
		PORTx = &PORTD;
		PINx = &PIND;
		DDRx = &DDRD;
	}


	if (is_output){
		(*DDRx) |= 1<<pin;//met la led D1 en output
	}else{
		(*DDRx) |= 0<<pin;//met la led D1 en input
		if (pull_up_active){
			(*PORTx) |= 1<<pin;
		}else{
				(*PORTx) &= ~(1<<pin);
		}
	}
}


Nous avons la fonction active_o, qui permet, pour un pin et un port donné, de le mettre à 1 ou à 0. La même méthode est utilisé pour la gestion de port via un pointeur.

Remarque : Cette fonction est destinée à agir sur des pins qui ont été paramétrés en sortie au préalable.

void active_o(int pin, int is_active, char port ){

	volatile uint8_t* PORTx;
	volatile uint8_t* PINx;
	volatile uint8_t* DDRx;


	if (port == 'b'){
		PORTx = &PORTB;
		PINx = &PINB;
		DDRx = &DDRB;
	}
	if (port == 'c'){
		PORTx = &PORTC;
		PINx = &PINC;
		DDRx = &DDRC;
	}
	if (port == 'd'){
		PORTx = &PORTD;
		PINx = &PIND;
		DDRx = &DDRD;
	}

	if (is_active){
		(*PORTx) &= ~(1<<pin); //allume la led
	}else{
		(*PORTx) |= 1<<pin;
	}
}

Nous avons la fonction read_i, qui permet, pour un pin et un port donné, de lire sa valeur.

Remarque : Cette fonction est destinée à lire sur des pins qui ont été paramétrés en entrée au préalable.

int read_i(int pin, char port){
    int val = 0;
    if (port == 'b'){
	val = PINB;
    }else if (port == 'c'){
	val = PINC;
    }else if (port == 'd'){
	val = PIND;
    }
    int mask = 0;
    mask =  1 << pin;
    return (val & mask);
}



Etape 3.1 : Premier programme, interaction bouton/LED

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)
	setup_io(LED_1, 1, 1, 'd'); // Led définie en OUTPUT sur le Port D
	setup_io(LED_2, 1, 1, 'd'); // 
	setup_io(BUTTON, 0, 1, 'b'); // Bouton INPUT sur le Port B avec résistance de PULL UP interne

	active_o(LED_2, 0, 'd'); // La LED 2 est éteinte
	while(1) {
		if( !read_i(BUTTON, 'b') ){ 
			active_o(LED_1, 0, 'd'); //Si le bouton est activé, on allume la LED, sinon on l'éteint
		}else{	
			active_o(LED_1, 1, 'd');
		}
	_delay_ms(100);
	}
}

Ce programme permet basiquement d'allumer la LED lorsque que le bouton est appuyé. Il utilise les fonctions vues précédemment.

Vidéo démonstrative ci dessous :


Etape 4 : Deuxième programme, communication série PC/AVR

Pour communiquer avec le PC en série, nous avons utilisé la librairie LUFA.

Voici les modifications que nous avons apportées :

A la fin du main, nous avons paramétrés nos pins et rajouter une variable qui permettra de n'afficher sur la liaison série uniquement les changements d'états.

	#define LED_1 0 // Port D
	#define LED_2 1 // Port D
	#define BUTTON 4 // Port B

	int button_toggle = -1; //evite d'imprimer un texte tout le temps
	//Initialisation
	setup_io(LED_1, 1, 1, 'd'); // Led OUTPUT
	setup_io(LED_2, 1, 1, 'd'); // Led
	setup_io(BUTTON, 0, 1, 'b'); // Bouton INPUT

Nous avons ensuite modifié la fonction CDC_Task pour y implémenter la logique souhaitée :

Quand on appuie sur le bouton, le PC recevra "Button pressed\r\n", et quand on le relâche, le PC recevra "Button not pressed\r\n"

void CDC_Task(void)
{
...    //LUFA Code

       //Notre code
       int is_button_pressed = !read_i(BUTTON, 'b');
	if( button_toggle != 0 &&  is_button_pressed ){
		active_o(LED_1, 0, 'd'); //Si le bouton est activé, on allume la LED, sinon on l'éteint
		ReportString = "Button pressed\r\n";
		button_toggle = 0;
		ActionSent = false;
	}
	if(button_toggle != 1 && !is_button_pressed ){
		active_o(LED_1, 1, 'd');
		button_toggle = 1;
		ReportString = "Button not pressed\r\n";
		ActionSent = false;
	}

... //LUFA Code
}


Vidéo démonstrative ci dessous :


Lien Gitea : LUFA

Lien Gitea : Programmes

Description

Sujet 1 : Manette sans fil

Objectif

Concevoir et réaliser une manette de jeu sans fil basée sur un microcontrôleur avec communication radio. La manette permettra d’envoyer des commandes à  un récepteur connecté à  un système de jeu (par exemple, un PC ou une console), tout en respectant les contraintes d'autonomie et de modularité.

Cahier des charges

  • Commandes analogiques via deux joysticks : un pour les déplacements, un pour la caméra.
  • Retour visuel via des LED indiquant l’état de la manette (connexion, batterie faible, etc.).
  • Commandes numériques : plusieurs boutons pour des actions spécifiques (tir, saut, pause, etc.).
  • Communication radio entre la manette et le PC
  • Gestion de l’alimentation hybride (filaire/batterie)

Spécification techniques

  • Transmission des commandes au récepteur via le module radio NRF24L01
  • Double alimentation hybride [Filaire/autonome]
    • Batterie Lithium
      • Recharge via USB
    • Port USB pour programmer et utiliser en mode filaire
  • Utilisation du processeur ATmega32u4 pour que la manette soit reconnue comme telle par un ordinateur.
  • LED multicolores pour indiquer :
    • le niveau de batterie ;
    • la connexion avec le récepteur ;
    • les différents modes de jeu.

ReX : mieux expliciter les deux parties : la manette radio autonome et la base radio connectée en USB au terminal de jeu.

Carte électronique

Schématique

Routage

Réalisation

Programmation

Tests

Rendus

Archive GIT

Autres rendus

SE3 2024 G3 prog schema.pdf
SE3 2024 G3 prog PCB.png

Projet KiCAd programmateur AVR : Fichier:2024-PSE-G3-Prog.zip