« SE4Binome2025-1 » : différence entre les versions
(corrections + quelques ajout) |
Aucun résumé des modifications |
||
| Ligne 1 : | Ligne 1 : | ||
= Shield Arduino = | = Shield Arduino = | ||
== Hardware == | == Hardware == | ||
Afin de tester notre futur carte réseau, nous avons fait un | Afin de tester notre futur carte réseau, nous avons fait un shield d'arduino qui prendra le rôle de la carte mère durant. | ||
=== Schématique === | === Schématique === | ||
Nous nous sommes évidemment aider de la datasheet de l'atmega328p ainsi que celle de l'arduino uno afin de | Nous nous sommes évidemment aider de la datasheet de l'atmega328p ainsi que celle de l'arduino uno afin de sélectionner les bon pins. | ||
[[Fichier:Atmel-7810-Automotive-Microcontrollers-ATmega328P Datasheet.pdf|centré|vignette|Datasheet ATmega328p]] | [[Fichier:Atmel-7810-Automotive-Microcontrollers-ATmega328P Datasheet.pdf|centré|vignette|Datasheet ATmega328p]] | ||
[[Fichier:A000066-datasheet.pdf|centré|vignette|Datasheet Arduino Uno R3]] | [[Fichier:A000066-datasheet.pdf|centré|vignette|Datasheet Arduino Uno R3]] | ||
Plus précisément nous nous | Plus précisément nous nous inspirons très fortement du schéma page 10 de la datasheet de l'arduino : | ||
[[Fichier:Screenshot 2025-11-07 11-08-46.png|centré|vignette|Schéma pinouts]] | [[Fichier:Screenshot 2025-11-07 11-08-46.png|centré|vignette|Schéma pinouts]] | ||
Nous sommes donc parti de l'exemple fourni par Mr Redon. Mais nous avons utilisé une template disponible dans kicad permettant de créer des | Nous sommes donc parti de l'exemple fourni par Mr Redon. Mais nous avons utilisé une template disponible dans kicad permettant de créer des shields d'arduino Uno R3.[[Fichier:Tyetyuy.png|vignette|Schématique shield arduino|centré|438x438px]] | ||
=== Routage === | === Routage === | ||
Au niveau du routage, nous avons tenté de faire simple (sans trop abuser sur les vias. Nous avons positionner le lecteur de carte sd au bord de la carte afin de ne pas avoir de problèmes avec d'autres composants lorsque nous voudrons mettre ou enlever la carte sd. | Au niveau du routage, nous avons tenté de faire simple (sans trop abuser sur les vias. Nous avons positionner le lecteur de carte sd au bord de la carte afin de ne pas avoir de problèmes avec d'autres composants lorsque nous voudrons mettre ou enlever la carte sd. | ||
| Ligne 14 : | Ligne 14 : | ||
===Soudage=== | ===Soudage=== | ||
La schématique et le routage terminés, nous avons soudé les différents pins permettant de souder la carte shield à l'arduino, le reste n'étant pas forcément utile pour le moment (il est important de noter que notre shield est arrivé avec des composants | La schématique et le routage terminés, nous avons soudé les différents pins permettant de souder la carte shield à l'arduino, le reste n'étant pas forcément utile pour le moment (il est important de noter que notre shield est arrivé avec des composants pré-soudés). | ||
[[Fichier:Shield soudage de base .jpg|centré|vignette]] | [[Fichier:Shield soudage de base .jpg|centré|vignette]] | ||
| Ligne 119 : | Ligne 119 : | ||
</syntaxhighlight> | </syntaxhighlight> | ||
=====test===== | =====test===== | ||
Les processus de clignotement de leds ont tous un délai d'attente différent, l'interruption se produit toutes les | Les processus de clignotement de leds ont tous un délai d'attente différent, l'interruption se produit toutes les millisecondes. On obtient ceci :[[Fichier:Ordonnanceur basique.mp4|centré|vignette]]Il est intéressant de remarqué que la vitesse à laquelle les leds changent d'état ne correspond pas au délai qui leur à été donné. Cela parait logique puisque l'interruption met la fonction _delay_ms en pause, ainsi la vitesse se voit divisé par le nombre de processus actif. | ||
====Ajout d'un système d'endormissement des processus==== | ====Ajout d'un système d'endormissement des processus==== | ||
| Ligne 235 : | Ligne 235 : | ||
Pour tester notre processus de communication, on utilise minicom.[[Fichier:Test lecture et écriture port série.mp4|centré|vignette]]On notera que si la période entre les interruptions est trop élevé, certains caractères ne seront pas lus. | Pour tester notre processus de communication, on utilise minicom.[[Fichier:Test lecture et écriture port série.mp4|centré|vignette]]On notera que si la période entre les interruptions est trop élevé, certains caractères ne seront pas lus. | ||
====afficheur 7 | ====afficheur 7 segments==== | ||
=====test===== | =====test===== | ||
=Carte Réseau= | =Carte Réseau= | ||
Version du 9 novembre 2025 à 16:35
Shield Arduino
Hardware
Afin de tester notre futur carte réseau, nous avons fait un shield d'arduino qui prendra le rôle de la carte mère durant.
Schématique
Nous nous sommes évidemment aider de la datasheet de l'atmega328p ainsi que celle de l'arduino uno afin de sélectionner les bon pins.
Plus précisément nous nous inspirons très fortement du schéma page 10 de la datasheet de l'arduino :
Nous sommes donc parti de l'exemple fourni par Mr Redon. Mais nous avons utilisé une template disponible dans kicad permettant de créer des shields d'arduino Uno R3.
Routage
Au niveau du routage, nous avons tenté de faire simple (sans trop abuser sur les vias. Nous avons positionner le lecteur de carte sd au bord de la carte afin de ne pas avoir de problèmes avec d'autres composants lorsque nous voudrons mettre ou enlever la carte sd.
Soudage
La schématique et le routage terminés, nous avons soudé les différents pins permettant de souder la carte shield à l'arduino, le reste n'étant pas forcément utile pour le moment (il est important de noter que notre shield est arrivé avec des composants pré-soudés).
Tests
Il faudra ensuite faire des test d'allumage des leds, afin de vérifier le bon fonctionnement du shield
Les leds fonctionnant à merveille, Il est temps de passer de passer à l'ordonnanceur.
Software
Ordonnanceur
[à completer et commenter , seulement des codes pour le moment !!!!]
Ordonnanceur basique
La première étape consiste à définir la structure d'un process, il sera composé :
-d'un pointeur de pile
-de l'adresse de la fonction
-d'un temps de sommeil
-d'un état : 0 pour en cours et 1 pour terminé ou vide
Ces deux derniers points nous servirons plus tard.
typedef struct {
uint16_t stackPointer;
void (*functionAddress)(void);
int sleep_time;
int state;
} process;
On initialise donc notre tableau de processus de la façon suivante :
process Tasks_list[NBTASKS] = {
{0, led1_blink, 0,0},
...
};
Concernant les fonction liés leds, on utilise une simple boucle while contenant un changement d'état
void led_init() {
...
}
void led1_blink() {
while(1) {
PORTC ^= (1<<PLED1);
_delay_ms(100);
}
}
void led2_blink() {
...
initialisation pointeur de pile et pile
void init_stackPointer_tasks(int Cprocess) { //initialise le pointer de pile
if(Tasks_list[Cprocess].state == 0) {
Tasks_list[Cprocess].stackPointer = FIRST_STACK_POSITION - (Cprocess * STACK_LENGTH);
}
}
void init_piles(int Cprocess){ //initilalise la pile
if(Tasks_list[Cprocess].state == 0) {
int save = SP;
SP = Tasks_list[Cprocess].stackPointer;
uint16_t address = (uint16_t)Tasks_list[Cprocess].functionAddress;
asm volatile("push %0" : : "r" (address & 0x00ff) );
asm volatile("push %0" : : "r" ((address & 0xff00)>>8) );
SAVE_REGISTERS();
Tasks_list[Cprocess].stackPointer = SP;
SP = save;
}
}
le scheduler permet de passer à la tâche suivante
void scheduler() {
Current_task++;
if (Current_task >= NBTASKS) {
Current_task = 0;
}
l'atmega328p ne dispose pas de de fonction en assembleur permettant de push ou de pop tout les registres. on doit donc le faire un par un. On défini alors les macros suivantes :
#define SAVE_REGISTERS() \
asm volatile ( \
"push r0 \n\t" \
...\
)
#define RESTORE_REGISTERS() \
asm volatile ( \
"pop r31 \n\t" \
...\
)
ISR
ISR(TIMER1_COMPA_vect, ISR_NAKED) {
SAVE_REGISTERS();
Tasks_list[Current_task].stackPointer = SP;
scheduler();
SP = Tasks_list[Current_task].stackPointer;
RESTORE_REGISTERS();
asm volatile("reti");
}
test
Les processus de clignotement de leds ont tous un délai d'attente différent, l'interruption se produit toutes les millisecondes. On obtient ceci :
Il est intéressant de remarqué que la vitesse à laquelle les leds changent d'état ne correspond pas au délai qui leur à été donné. Cela parait logique puisque l'interruption met la fonction _delay_ms en pause, ainsi la vitesse se voit divisé par le nombre de processus actif.
Ajout d'un système d'endormissement des processus
La fonction wait va permettre d'endormir un processus, elle va donné un temps de sommeil au processus puis lancer une interruption (car on veut changer de processus directement après que le précédent ait été endormi).
void wait(int time) { // met un process en veille pour une durée donné
// valeur max de time 32000 car int sur atmega328p code sur 16 bits donc 32000 max
cli();
Tasks_list[Current_task].sleep_time = time;
TCNT1=0;
sei();
TIMER1_COMPA_vect();
Pour verifier si un processus a besoin d'être lancé, on ajoute une boucle while dans le scheduler afin de vérifier si il y a un temps de sommeil. Le scheduler va aussi servir à diminuer le temps de sommeil de tout les processus (avec un minimum de 0).
void scheduler() {
for (int i=0 ; i<NBTASKS ; i++) {
if (Tasks_list[i].sleep_time - SLEEP_DEC < 0) {
Tasks_list[i].sleep_time = 0;
} else {
Tasks_list[i].sleep_time -= SLEEP_DEC;
}
}
do {
Current_task++;
if (Current_task >= NBTASKS) {
Current_task = 0;
}
} while (Tasks_list[Current_task].sleep_time > 0);
}
Tableau dynamique des tâches
En premier lieu on va initialiser les état de tout les cases du tableau de processus. On choisit 1 la case est vide, 0 sinon.
void init_state() { //initialise state
for (int i= 0; i<NBTASKS; i++) {
if (Tasks_list[i].functionAddress == NULL) {
Tasks_list[i].state = 1;
}
else {
Tasks_list[i].state = 0;
}
}
}
Nous avons programmer deux fonction d'arrêt et une fonction d'ajout de processus :
-finish stop le processus en cours et le supprime de tableau, puis lance une interruption
-kill stop un processus donné et le supprime du tableau
-add ajoute un processus sur la première case vide du tableau, initialise son pointeur de position et sa pile.
Pour finish et kill, on met le temps de sommeil à 0 au cas où on arrête un processus endormi. C'est une mesure de sécurité pour finish, mais une obligation pour kill.
void finish() { //supprime un process lorsque celui-ci est terminé
cli();
Tasks_list[Current_task].state =1;
Tasks_list[Current_task].sleep_time = 0;
Tasks_list[Current_task].functionAddress = NULL;
TCNT1=0;
sei();
TIMER1_COMPA_vect();
}
void kill(void (*function)(void)) { //tue le process passé en paramètre
cli();
for(int i = 0; i<NBTASKS; i++) {
if(Tasks_list[i].functionAddress == function) {
Tasks_list[i].state =1;
Tasks_list[i].sleep_time = 0;
Tasks_list[i].functionAddress = NULL;
}
}
sei();
}
void add(void (*newFunction)(void)) { //ajoute un process
cli();
int i =0;
while(Tasks_list[i].state != 1) {
i++;
}
Tasks_list[i].functionAddress = newFunction;
Tasks_list[i].state = 0;
init_stackPointer_tasks(i);
init_piles(i);
sei();
}
test
Pour tester les fonction add et finish, on fait le test suivant :
-on créer un process qui ajoute le process led2_blink (avec add) au bout d'un certain temps
-le process led2_blink s'arrête (avec finish) au bout de 20 changement d'état (c'est à dire 10 clignotement).
on obtient le résultat suivant :
lecture et écriture sur le port série
Afin de lire et écrire sur le port série, on utilise les fonctions USART_Init, USART_Transmit et USART_Receive vu en cours de microP l'année précédente. Le but sera donc d'écrire le message qui vient d'être reçu, on utilise donc le processus suivant :
void Serial_Message(){
unsigned char data;
while(1){
data = USART_Receive();
USART_Transmit(data);
}
}
test
Pour tester notre processus de communication, on utilise minicom.
On notera que si la période entre les interruptions est trop élevé, certains caractères ne seront pas lus.
afficheur 7 segments
test
Carte Réseau
Lors de la répartition des tâches, nous avons opté pour la carte réseau.
Description
Le sujet nous permettait de choisir parmi plusieurs microcontrôleurs. Nous avons retenu l’ATmega32U4, qui nous semble représenter un juste milieu entre l’ATmega16U2 et l’AT90USB.
Hardware
Notre carte intègre des LED permettant d’afficher différents états de communication (que nous définirons ultérieurement).
À la demande de M. Redon, nous avons ajouté un MAX232 ainsi que des connecteurs DB9 et DB25. Nous espérons que ces éléments pourront être utiles.