<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="fr">
	<id>https://projets-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ncazin</id>
	<title>projets-se.plil.fr - Contributions [fr]</title>
	<link rel="self" type="application/atom+xml" href="https://projets-se.plil.fr/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Ncazin"/>
	<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php/Sp%C3%A9cial:Contributions/Ncazin"/>
	<updated>2026-05-14T03:34:02Z</updated>
	<subtitle>Contributions</subtitle>
	<generator>MediaWiki 1.39.1</generator>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2771</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2771"/>
		<updated>2024-01-16T12:28:47Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Matériel : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Matériel : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câbles reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus, nous avons dû souder 2 connecteurs permettant la jonction avec les cartes. Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
=== Clignotement de 2 LEDs ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs, à l'aide de deux tâches statiques, avec des périodes différentes. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et de restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
=== Ecriture de caractères sur le port série ===&lt;br /&gt;
Tout d'abord, avant de commencer la tâche, nous savions que nous devions utiliser l'UART du microcontrôleur. De plus, la tâche suivante devait utiliser aussi l'UART. Puisque 2 tâches utilisent la même ressource, il faut implémenter un système pour savoir quelle tâche utilise la ressource. Nous avons alors utilisé un sémaphore pour chaque tâche, permettant ainsi de limiter l'accès temporairement à la ressource aux autres tâches : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void semaphore_write(int action){&lt;br /&gt;
    if(action == TAKE_RESOURCE){&lt;br /&gt;
        while(1){&lt;br /&gt;
            cli();&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource Disponible */&lt;br /&gt;
            if(sem_writing &amp;gt; 0){&lt;br /&gt;
                sem_writing = 0;&lt;br /&gt;
                sei();&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource occupée */&lt;br /&gt;
            else{&lt;br /&gt;
                tasks[actuel].reason = WORKING;&lt;br /&gt;
                tasks[actuel].state = SLEEPING;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
                TIMER1_COMPA_vect();&lt;br /&gt;
            }&lt;br /&gt;
        sei();&lt;br /&gt;
        while(sem_writing == 0);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(action == DROP_RESOURCE){&lt;br /&gt;
        cli();&lt;br /&gt;
        sem_writing = 1;&lt;br /&gt;
        sei();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir implémenté ce sémaphore, il fallait que nous comprenions comment utiliser l'UART du microcontrôleur. Pour cela, il faut initialiser correctement l'UART pour pouvoir écrire et lire en série. La fonction suivante permet d'initialiser correctement l'UART : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void init_usart(long int speed){&lt;br /&gt;
    UBRR0 = FREQUENCE/((unsigned long int)speed &amp;lt;&amp;lt; 4) -1;&lt;br /&gt;
    UCSR0B = (1 &amp;lt;&amp;lt; TXEN0 | 1 &amp;lt;&amp;lt; RXEN0);&lt;br /&gt;
    UCSR0C = (1 &amp;lt;&amp;lt; UCSZ01 | 1 &amp;lt;&amp;lt; UCSZ00);&lt;br /&gt;
    UCSR0A &amp;amp;= ~(1 &amp;lt;&amp;lt; U2X0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, une fois l'initialisation réalisée, nous pouvons réaliser la tâche utilisant les fonctions permettant d'écrire plusieurs caractères (ici &amp;quot;abc&amp;quot;) sur le port série, que l'on peut observer grâce à la commande shell ''&amp;quot;minicom -D /dev/ttyUSB0 -b 9600&amp;quot;.'' On utilise alors les fonctions suivantes pour écrire sur le port série :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void serial_send(unsigned char c){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, UDRE0);&lt;br /&gt;
    UDR0 = c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_send_str(char chaine[]){&lt;br /&gt;
    semaphore_write(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        serial_send(chaine[i]);&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_write(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut observer que la tâche fonctionne comme sur la vidéo suivante :[[Fichier:Tâche d'écriture sur le port série.mp4|vignette|Tâche d'écriture sur le port série|centré]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture sur le port série ===&lt;br /&gt;
De la même façon que la tâche précédente, pour cette tâche nous devons lire les pressions de touches du clavier et les afficher sur le minicom. L'initialisation est déjà effectuée et le sémaphore et la même que dans la partie précédente, nous ne la traiterons donc pas. On utilise alors les fonctions suivantes pour lire les pressions des touches sur le clavier, et la tâche les fait afficher ensuite : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
unsigned char serial_read(void){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, RXC0);&lt;br /&gt;
    return UDR0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_read_str(char chaine[]){&lt;br /&gt;
    semaphore_read(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        chaine[i] = serial_read();&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_read(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut alors observer les résultats grâce à la vidéo suivante : &lt;br /&gt;
[[Fichier:Tâche de lecture sur le port série.mp4|centré|vignette|Tâche de lecture sur le port série]]&lt;br /&gt;
&lt;br /&gt;
=== Matrice de LEDs ===&lt;br /&gt;
Dans cette partie, nous souhaitons gérer l'affichage d'une matrice de LEDs 8x8 grâce au SPI. Il faut alors réussir à initialiser le SPI correctement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, nous avons rédigé un programme utilisé par notre tâche afin d'afficher différents caractères sur la matrice en allumant les LEDs voulues bit par bit :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void loop_matrix(char letter[8]){&lt;br /&gt;
    int temp;&lt;br /&gt;
    PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    for(short int i = 0; i &amp;lt; 8; i++){&lt;br /&gt;
            &lt;br /&gt;
        for(short int j = 0; j &amp;lt; 8; j++)&lt;br /&gt;
        {&lt;br /&gt;
            temp = letter[i] &amp;amp; (1 &amp;lt;&amp;lt; j); &lt;br /&gt;
            diplayLED(temp); //Envoir de chaque bit sur le SPI&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après vérification du bon fonctionnement de notre programme, nous avons ajouté la fonction principale dans notre fichier de gestion des tâches. Nous pouvons alors voir le changement des LEDs allumées lorsque l'on appuie sur un autre caractère grâce à la vidéo suivante :&lt;br /&gt;
[[Fichier:Matrice2.mov|centré|vignette|Affichage des caractères sur la matrice]]&lt;br /&gt;
&lt;br /&gt;
=== Afficheur 7 segments ===&lt;br /&gt;
Pour le 7 segments, l'initialisation est différente. En effet, le 7 segments ne fonctionne qu'à une fréquence maximale de 250kHz, il faut alors modifier l'initialisation du SPI de la tâche pour le faire fonctionner en changeant le paramètre SPCR :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit_segments(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0) | (1 &amp;lt;&amp;lt; SPR1);    //SPR1 &amp;amp; SPR0 à 1 pour une fréquence en dessous de 250kHz (fréquence de l'afficheur 7 segments)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;En envoyant alors la lettre appuyée sur le clavier, le 7 segments convertit (si c'est possible) la lettre en segments à allumer comme nous pouvons le voir sur la vidéo suivante :[[Fichier:7segments.mp4|centré|vignette|Affichage des caractères sur le 7 segments]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
=== Contrôleur de bus série SPI ===&lt;br /&gt;
Pour ce programme VHDL, nous avons voulu faire une communication SPI Maitre/Esclave. Pour cela, nous nous sommes documentés sur comment fonctionnait cette communication. Il faut alors réaliser les 4 signaux MOSI, MISO, SS et SCK afin de pouvoir communiquer. On vérifie alors chacun de bits envoyé afin de gérer les signaux de contrôle et de l'entrée MISO. Ensuite, on génère les données de sortie pour la réponse. Enfin, on peut assigner les sorties avec les informations que l'on a. Voici alors les processus utilisés : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
-- Processus 1 : Gestion des signaux de contrôle et de l'entrée MISO&lt;br /&gt;
    process (reset, start_transfer, MISO)&lt;br /&gt;
    begin&lt;br /&gt;
        if reset = '1' then&lt;br /&gt;
            -- En cas de réinitialisation, retour à l'état IDLE&lt;br /&gt;
            state &amp;lt;= IDLE;&lt;br /&gt;
            bit_counter &amp;lt;= 0;&lt;br /&gt;
            SS &amp;lt;= '1';&lt;br /&gt;
        elsif start_transfer = '1' then&lt;br /&gt;
            -- Au début d'une nouvelle transmission, passage à l'état TRANSFER&lt;br /&gt;
            state &amp;lt;= TRANSFER;&lt;br /&gt;
            bit_counter &amp;lt;= 0;&lt;br /&gt;
            SS &amp;lt;= '0'; -- Sélection du périphérique esclave au début de la transmission&lt;br /&gt;
        elsif state = TRANSFER then&lt;br /&gt;
            -- Déplacement du bit reçu dans le tampon&lt;br /&gt;
            received_data &amp;lt;= MISO &amp;amp; received_data(7 downto 1);&lt;br /&gt;
            bit_counter &amp;lt;= bit_counter + 1;&lt;br /&gt;
            if bit_counter = 7 then&lt;br /&gt;
                -- Si tous les bits ont été déplacés, passage à l'état DONE&lt;br /&gt;
                state &amp;lt;= DONE;&lt;br /&gt;
            end if;&lt;br /&gt;
        elsif state = DONE then&lt;br /&gt;
            -- Fin de la transmission, désélection du périphérique esclave&lt;br /&gt;
            SS &amp;lt;= '1';&lt;br /&gt;
            state &amp;lt;= IDLE;&lt;br /&gt;
        end if;&lt;br /&gt;
    end process;&lt;br /&gt;
&lt;br /&gt;
-- Processus 2 : Génération des données de sortie (data_out)&lt;br /&gt;
    process (reset, start_transfer, bit_counter)&lt;br /&gt;
    begin&lt;br /&gt;
        if reset = '1' then&lt;br /&gt;
            -- En cas de réinitialisation, les données de sortie sont mises à zéro&lt;br /&gt;
            data_out &amp;lt;= (others =&amp;gt; '0');&lt;br /&gt;
        elsif start_transfer = '1' then&lt;br /&gt;
            -- Au début d'une nouvelle transmission, envoi du premier bit&lt;br /&gt;
            data_out &amp;lt;= data_out(6 downto 0) &amp;amp; '0';&lt;br /&gt;
        elsif state = TRANSFER then&lt;br /&gt;
            -- Déplacement du bit à envoyer dans le registre de sortie&lt;br /&gt;
            data_out &amp;lt;= '0' &amp;amp; data_out(7 downto 1);&lt;br /&gt;
        end if;&lt;br /&gt;
    end process;&lt;br /&gt;
&lt;br /&gt;
-- Assignements des sorties&lt;br /&gt;
    transfer_done &amp;lt;= '1' when state = DONE else '0';&lt;br /&gt;
    clk &amp;lt;= not clk after 5 ns; -- Simulation de l'horloge (pour la démo)&lt;br /&gt;
    MOSI &amp;lt;= data_out(7);&lt;br /&gt;
    data_in &amp;lt;= received_data;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Contrôleur VGA ===&lt;br /&gt;
Pour ce contrôleur, il faut utiliser le port VGA présent sur la carte Basys-3. Sur ce connecteur VGA, il y a plusieurs sorties à gérer. En effet, il y a les signaux de synchronisation HS et VS qui fonctionnent s'ils ont une certaine forme d'ondes. Ces signaux doivent être à 0 pendant un certain temps. De plus, nous avons les ports permettant de gérer les couleur, vert, bleu et rouge, chacun sur 4 bits. L'horloge du FPGA fonctionnant à 100MHz, nous devons la moduler à 60Hz, car l'écran fonctionne à cette fréquence. Pour cela, nous avons utilisé les IP catalogs. Ce sont des composants existants dans des librairies qui peuvent être utilisés. Dans notre cas, nous avons utilisé un composant qui permet de modifier la fréquence d’un signal.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite reconstitué le signal de HS et VS. En effet, ces signaux ont besoin d’une période très spécifique permettant de bien configurer la taille de notre écran. Nous avons donc configuré un compteur incrémenté à chaque front montant de l’horloge, ce qui permet de mettre à l’état bas nos signaux.&lt;br /&gt;
&lt;br /&gt;
Le signal HS possède un front descendant à chaque changement de pixel, et lorsque que l’on a fait toute la ligne, un front descendant est envoyé sur VS pour descendre d’une ligne. Voici les programmes fait pour créer ces signaux : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
Balayage : process(clk_pixel)&lt;br /&gt;
begin&lt;br /&gt;
    if clk_pixel'event and clk_pixel = '1' then&lt;br /&gt;
    -- Compteur horizontal&lt;br /&gt;
        if compteur_horizontal &amp;lt; 1343 then&lt;br /&gt;
            compteur_horizontal &amp;lt;= compteur_horizontal + 1;&lt;br /&gt;
        else&lt;br /&gt;
            compteur_horizontal &amp;lt;= 0;&lt;br /&gt;
            &lt;br /&gt;
        -- Compteur vertical&lt;br /&gt;
            if compteur_vertical &amp;lt; 805 then&lt;br /&gt;
                compteur_vertical &amp;lt;= compteur_vertical + 1;&lt;br /&gt;
             else&lt;br /&gt;
                compteur_vertical &amp;lt;= 0;&lt;br /&gt;
            end if;&lt;br /&gt;
        end if;&lt;br /&gt;
    end if;&lt;br /&gt;
    &lt;br /&gt;
    -- Création signal HS&lt;br /&gt;
    if compteur_horizontal &amp;gt; 1047 and compteur_horizontal &amp;lt; 1184 then&lt;br /&gt;
        HS_out &amp;lt;= '0';&lt;br /&gt;
        HS_sig &amp;lt;= '0';&lt;br /&gt;
    else&lt;br /&gt;
        HS_out &amp;lt;= '1';&lt;br /&gt;
        HS_sig &amp;lt;= '1';&lt;br /&gt;
    end if;&lt;br /&gt;
    &lt;br /&gt;
    -- Création signal VS&lt;br /&gt;
    if compteur_vertical &amp;gt; 770 and compteur_vertical &amp;lt; 777 then&lt;br /&gt;
        VS_out &amp;lt;= '0';&lt;br /&gt;
        VS_sig &amp;lt;= '0';&lt;br /&gt;
    else&lt;br /&gt;
        VS_out &amp;lt;= '1';&lt;br /&gt;
        VS_sig &amp;lt;= '1';&lt;br /&gt;
    end if;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir fait ces programmes, nous avons fait la simulation pour voir si les signaux étaient bien réalisés. Voici les simulations de ces signaux : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:VGA signal VS.png|alt=VGA signal VS|centré|vignette|VGA signal VS]]&lt;br /&gt;
[[Fichier:VGA signal HS.png|alt=VGA signal HS|centré|vignette|VGA signal HS]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir fait cela, il fallait s’occuper des sorties des couleurs. Pour cela, nous devons mettre les valeurs des canaux de couleurs au maximum lorsque les boutons correspondants sont appuyés et quand les signaux HS et VS sont eux aussi à 1. Une condition supplémentaire permet de contrôler la taille du carré à afficher. Les programmes de gestion des couleurs étant quasiment les mêmes aux exceptions des boutons à appuyer, nous ne montrerons que celui de la couleur rouge sur l’image ci-dessous : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
-- Gestion couleur rouge --&lt;br /&gt;
    if B1_in = '1' and clk_pixel'event and clk_pixel = '1' then&lt;br /&gt;
        if VS_sig = '1' and HS_sig = '1' then&lt;br /&gt;
            if compteur_horizontal &amp;gt; 400 and compteur_horizontal &amp;lt; 600 then&lt;br /&gt;
                if compteur_vertical &amp;gt; 200 and compteur_vertical &amp;lt; 400 then&lt;br /&gt;
                    red_out &amp;lt;= &amp;quot;1111&amp;quot;;&lt;br /&gt;
                else&lt;br /&gt;
                    red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
                end if;&lt;br /&gt;
            else&lt;br /&gt;
                red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
            end if;&lt;br /&gt;
        else&lt;br /&gt;
            red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
        end if;&lt;br /&gt;
    end if;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Au final, après la génération du fichier .bit, de la modification du fichier de contrainte et de l'envoi du programme sur la carte FPGA Basys-3, nous avons bien un carré pouvant changer de couleur lorsque l'on appuie sur un bouton : &lt;br /&gt;
[[Fichier:Carré qui change de couleur grâce au contrôleur VGA.mp4|centré|vignette|Carré qui change de couleur grâce au contrôleur VGA]]&lt;br /&gt;
Il nous manque alors la gestion de la couleur en mémoire, mais nous n'avons pas eu le temps de réaliser cette fonction. Cependant la gestion du contrôleur VGA et de la création des signaux HS et VS nous ont beaucoup appris sur le fonctionnement du VGA.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS, car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte était pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur à utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utilisé un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecté des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenté un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur ne se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir réalisé le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur, car nous savons comment elles doivent être disposées. Le plus difficile dans ce routage a été de mettre les capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de vias possibles pour ne pas endommager les signaux que l'on souhaite envoyer. Nous avons fait le plan de masse de la carte et au final, nous avons réussi à compacter la carte pour qu'elle fasse une taille de 43mm par 33mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|245x245px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une représentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors routé notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :''&lt;br /&gt;
[[Fichier:Carte reconnue après un &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue après un &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue après un &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous avons entamé la programmation pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== Programmation de la carte électronique RNDIS ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utilisé une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassé. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite, nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créé, mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. &lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par la suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping de l'adresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut maintenant recevoir les paquets envoyés et vérifiés leur bonne réception sur le terminal. Nous avons alors utilisé l'outil &amp;quot;ether&amp;quot; afin d'observer les paquets reçus sur l'interface &amp;quot;usb0&amp;quot; créée. Pour rendre compte des paquets envoyés/reçus, nous allumons une LED à chaque ping :  &lt;br /&gt;
[[Fichier:Reception .mp4|centré|vignette|Réception de paquets IP ]]À ce moment précis, la carte allume bien les LEDs lors de la récéption des mêmes paquets que ceux implémentés dans la pile TCP/IP. Puisque l'on veut utiliser nos propres paquets avec notre protocole, nous devons ajouter dans cette pile le traitement de notre protocole. &lt;br /&gt;
&lt;br /&gt;
Tout d'abord, dans le fichier &amp;quot;EthernerProtocols.h&amp;quot;, nous avons créé notre propre protocole et sera le suivant : &amp;quot;0x0903&amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define ETHERTYPE_PICO                   0x0903&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, il faut créer une structure représentant notre trame dans un fichier permettant son traitement. Ici, le fichier s'appelle &amp;quot;PICO.h&amp;quot;. Nous avons alors choisi d'utiliser cette structure de trame : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/** Type define for a PICO header. */&lt;br /&gt;
    typedef struct&lt;br /&gt;
    {&lt;br /&gt;
        MAC_Address_t   Destination_MAC; /**&amp;lt; MAC address of the packet recipient */&lt;br /&gt;
        MAC_Address_t   Source_MAC; /**&amp;lt; MAC address of the packet source */&lt;br /&gt;
        IP_Address_t    Destination_IP; /**&amp;lt; IP address of the packet recipient */&lt;br /&gt;
        IP_Address_t    Source_IP; /**&amp;lt; IP address of the packet source */&lt;br /&gt;
        uint16_t        PICOType; /**&amp;lt; PICO packet sub-protocol type*/&lt;br /&gt;
    }PICO_Header_t;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans le fichier c, il faut alors réaliser le traitement de cette trame pour créer la réponse : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int16_t PICO_ProcessPICOPacket(void* InDataStart,&lt;br /&gt;
                           void* OutDataStart)&lt;br /&gt;
{&lt;br /&gt;
    PICO_Header_t* PICOHeaderIN  = (PICO_Header_t*)InDataStart;&lt;br /&gt;
	PICO_Header_t* PICOHeaderOUT = (PICO_Header_t*)OutDataStart;&lt;br /&gt;
    &lt;br /&gt;
    /* Ensure that the PICO request is a PICO request packet */&lt;br /&gt;
	if (SwapEndian_16(PICOHeaderIN-&amp;gt;PICOType) == ETHERTYPE_PICO)&lt;br /&gt;
	{&lt;br /&gt;
        if (IP_COMPARE(&amp;amp;PICOHeaderIN-&amp;gt;Destination_IP, &amp;amp;ServerIPAddress)||&lt;br /&gt;
            MAC_COMPARE(&amp;amp;PICOHeaderIN-&amp;gt;Destination_MAC, &amp;amp;ServerMACAddress))&lt;br /&gt;
		{&lt;br /&gt;
            /* Fill out the PICO response header */&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Destination_MAC = PICOHeaderIN-&amp;gt;Source_MAC;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Source_MAC = ServerMACAddress;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Destination_IP = PICOHeaderIN-&amp;gt;Source_IP;&lt;br /&gt;
			PICOHeaderOUT-&amp;gt;Source_IP = ServerIPAddress;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;PICOType = PICOHeaderIN-&amp;gt;PICOType;&lt;br /&gt;
            &lt;br /&gt;
            /* Blink the LED */&lt;br /&gt;
            PORTC ^= 0x30;&lt;br /&gt;
            &lt;br /&gt;
            /* Return the size of the response so far */&lt;br /&gt;
			return sizeof(PICO_Header_t);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
            &lt;br /&gt;
    return NO_RESPONSE;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;De cette façon, lorsqu'une trame respectant notre forme et utilisant notre protocole est envoyée sur l'interface, la LED de la carte devrait clignoter.&lt;br /&gt;
&lt;br /&gt;
Enfin, il faut aussi adapter le fichier &amp;quot;ProtocolsDecoders&amp;quot; afin que la LUFA arrive à décoder notre trame : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void DecodePICOFrameHeader(void* InDataStart)&lt;br /&gt;
{&lt;br /&gt;
	PICO_Header_t* PICOHeader = (PICO_Header_t*)InDataStart;&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;   \\\r\n    PICO\r\n&amp;quot;));&lt;br /&gt;
	&lt;br /&gt;
	if (!(IP_COMPARE(&amp;amp;PICOHeader-&amp;gt;Destination_IP, &amp;amp;ServerIPAddress)) &amp;amp;&amp;amp;&lt;br /&gt;
	    !(IP_COMPARE(&amp;amp;PICOHeader-&amp;gt;Destination_IP, &amp;amp;BroadcastIPAddress)))&lt;br /&gt;
	{&lt;br /&gt;
		printf_P(PSTR(&amp;quot;  + NOT ADDRESSED TO DEVICE\r\n&amp;quot;));&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + MAC Dest: %u:%u:%u:%u:%u:%u\r\n&amp;quot;),    PICOHeader-&amp;gt;Destination_MAC.Octets[0],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[1],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[2],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[3],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[4],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[5]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + MAC Source : %u:%u:%u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Source_MAC.Octets[0],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[1],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[2],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[3],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[4],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[5]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + IP Dest : %u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Destination_IP.Octets[0],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[1],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[2],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[3]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + IP Source : %u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Source_IP.Octets[0],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[1],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[2],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[3]);&lt;br /&gt;
&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + Protocol : %x\r\n&amp;quot;), SwapEndian_16(PICOHeader-&amp;gt;PICOType));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après cela, nous pouvons envoyer une trame sur l'interface &amp;quot;usb0&amp;quot; utilisant notre protocole. Pour cela, nous avons modifié l'outil &amp;quot;ether&amp;quot; pour observer directement l'interface &amp;quot;usb0&amp;quot; et aussi pour que le filtre accepte notre protocole. En envoyant alors la trame, la LED s'allume bien correctement : &lt;br /&gt;
[[Fichier:WhatsApp Video 2023-12-21 at 11.58.12.mp4|centré|vignette|Carte RNDIS réagissant à notre propre trame]]&lt;br /&gt;
&lt;br /&gt;
Cependant, on remarque que la LED s'allume, c'est-à-dire que la réponse est bien créée, mais elle n'est pas envoyée. En remontant chaque fonction pouvant être la cause du non-envoi de la réponse, nous avons &amp;quot;RNDIS_Task&amp;quot; que nous n'arrivons pas à comprendre. Cependant, nous n'avons pas modifié cette fonction, cela doit provenir de la trame envoyée, mais pourtant, le programme rentre bien complétement dans la fonction. À ce stade, nous n'arrivons toujours pas à trouver la cause du problème.&lt;br /&gt;
&lt;br /&gt;
== Conclusion : ==&lt;br /&gt;
Durant ce projet, nous avons essayé de travailler sur toutes les parties. En effet, nous avons consacré beaucoup de temps sur la partie Ordonnanceur pendant que la carte électronique était expédiée, c'est d'ailleurs comme ça que nous avons réussi à terminer toutes les tâches. Nous avons rencontré beaucoup de difficultés pendant la programmation de l'ordonnanceur, certaines tâches étaient plus compliquées pour nous que d'autres, mais nous avons réussi à nous organiser et à réaliser ces tâches. Ensuite, nous nous sommes séparés en deux, un qui travaillait sur le VHDL et l'autre sur la carte RNDIS. Du côté de la partie VHDL, la gestion du SPI était compliquée à réalisée et nous n'avons pas eu le temps de tester notre programme sur une carte FPGA. Cependant, nous avons pu tester et beaucoup mieux avancer sur le VGA. Enfin, la carte RNDIS a été compliquée à comprendre et nous avons perdu beaucoup de temps sur la réduction de la pile TCP/IP. Nous avons quand même réussi à avancer jusqu'à ce blocage sur la réponse que l'on devait recevoir.&lt;br /&gt;
&lt;br /&gt;
Globalement, nous sommes contents du résultat de notre travail. Nous avons travaillé sur chaque partie comme nous le voulions afin de renforcer ou d'acquérir de nouvelles compétences. L'organisation entre nous nous a permis de gagner du temps sur notre travail. De plus, nous avons travaillé chez nous, ce qui nous permit aussi de mieux nous organiser et de mieux prévoir les séances de travail qui venaient. &lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2644</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2644"/>
		<updated>2023-12-29T10:35:56Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Matériel : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Matériel : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câbles reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus, nous avons dû souder 2 connecteurs permettant la jonction avec les cartes. Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
=== Clignotement de 2 LEDs ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs, à l'aide de deux tâches statiques, avec des périodes différentes. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et de restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
=== Ecriture de caractères sur le port série ===&lt;br /&gt;
Tout d'abord, avant de commencer la tâche, nous savions que nous devions utiliser l'UART du microcontrôleur. De plus, la tâche suivante devait utiliser aussi l'UART. Puisque 2 tâches utilisent la même ressource, il faut implémenter un système pour savoir quelle tâche utilise la ressource. Nous avons alors utilisé un sémaphore pour chaque tâche, permettant ainsi de limiter l'accès temporairement à la ressource aux autres tâches : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void semaphore_write(int action){&lt;br /&gt;
    if(action == TAKE_RESOURCE){&lt;br /&gt;
        while(1){&lt;br /&gt;
            cli();&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource Disponible */&lt;br /&gt;
            if(sem_writing &amp;gt; 0){&lt;br /&gt;
                sem_writing = 0;&lt;br /&gt;
                sei();&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource occupée */&lt;br /&gt;
            else{&lt;br /&gt;
                tasks[actuel].reason = WORKING;&lt;br /&gt;
                tasks[actuel].state = SLEEPING;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
                TIMER1_COMPA_vect();&lt;br /&gt;
            }&lt;br /&gt;
        sei();&lt;br /&gt;
        while(sem_writing == 0);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(action == DROP_RESOURCE){&lt;br /&gt;
        cli();&lt;br /&gt;
        sem_writing = 1;&lt;br /&gt;
        sei();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir implémenté ce sémaphore, il fallait que nous comprenions comment utiliser l'UART du microcontrôleur. Pour cela, il faut initialiser correctement l'UART pour pouvoir écrire et lire en série. La fonction suivante permet d'initialiser correctement l'UART : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void init_usart(long int speed){&lt;br /&gt;
    UBRR0 = FREQUENCE/((unsigned long int)speed &amp;lt;&amp;lt; 4) -1;&lt;br /&gt;
    UCSR0B = (1 &amp;lt;&amp;lt; TXEN0 | 1 &amp;lt;&amp;lt; RXEN0);&lt;br /&gt;
    UCSR0C = (1 &amp;lt;&amp;lt; UCSZ01 | 1 &amp;lt;&amp;lt; UCSZ00);&lt;br /&gt;
    UCSR0A &amp;amp;= ~(1 &amp;lt;&amp;lt; U2X0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, une fois l'initialisation réalisée, nous pouvons réaliser la tâche utilisant les fonctions permettant d'écrire plusieurs caractères (ici &amp;quot;abc&amp;quot;) sur le port série, que l'on peut observer grâce à la commande shell ''&amp;quot;minicom -D /dev/ttyUSB0 -b 9600&amp;quot;.'' On utilise alors les fonctions suivantes pour écrire sur le port série :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void serial_send(unsigned char c){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, UDRE0);&lt;br /&gt;
    UDR0 = c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_send_str(char chaine[]){&lt;br /&gt;
    semaphore_write(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        serial_send(chaine[i]);&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_write(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut observer que la tâche fonctionne comme sur la vidéo suivante :[[Fichier:Tâche d'écriture sur le port série.mp4|vignette|Tâche d'écriture sur le port série|centré]]&lt;br /&gt;
&lt;br /&gt;
=== Lecture sur le port série ===&lt;br /&gt;
De la même façon que la tâche précédente, pour cette tâche nous devons lire les pressions de touches du clavier et les afficher sur le minicom. L'initialisation est déjà effectuée et le sémaphore et la même que dans la partie précédente, nous ne la traiterons donc pas. On utilise alors les fonctions suivantes pour lire les pressions des touches sur le clavier, et la tâche les fait afficher ensuite : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
unsigned char serial_read(void){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, RXC0);&lt;br /&gt;
    return UDR0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_read_str(char chaine[]){&lt;br /&gt;
    semaphore_read(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        chaine[i] = serial_read();&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_read(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut alors observer les résultats grâce à la vidéo suivante : &lt;br /&gt;
[[Fichier:Tâche de lecture sur le port série.mp4|centré|vignette|Tâche de lecture sur le port série]]&lt;br /&gt;
&lt;br /&gt;
=== Matrice de LEDs ===&lt;br /&gt;
Dans cette partie, nous souhaitons gérer l'affichage d'une matrice de LEDs 8x8 grâce au SPI. Il faut alors réussir à initialiser le SPI correctement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, nous avons rédigé un programme utilisé par notre tâche afin d'afficher différents caractères sur la matrice en allumant les LEDs voulues bit par bit :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void loop_matrix(char letter[8]){&lt;br /&gt;
    int temp;&lt;br /&gt;
    PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    for(short int i = 0; i &amp;lt; 8; i++){&lt;br /&gt;
            &lt;br /&gt;
        for(short int j = 0; j &amp;lt; 8; j++)&lt;br /&gt;
        {&lt;br /&gt;
            temp = letter[i] &amp;amp; (1 &amp;lt;&amp;lt; j); &lt;br /&gt;
            diplayLED(temp); //Envoir de chaque bit sur le SPI&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après vérification du bon fonctionnement de notre programme, nous avons ajouté la fonction principale dans notre fichier de gestion des tâches. Nous pouvons alors voir le changement des LEDs allumées lorsque l'on appuie sur un autre caractère grâce à la vidéo suivante :&lt;br /&gt;
[[Fichier:Matrice2.mov|centré|vignette|Affichage des caractères sur la matrice]]&lt;br /&gt;
&lt;br /&gt;
=== Afficheur 7 segments ===&lt;br /&gt;
Pour le 7 segments, l'initialisation est différente. En effet, le 7 segments ne fonctionne qu'à une fréquence maximale de 250kHz, il faut alors modifier l'initialisation du SPI de la tâche pour le faire fonctionner en changeant le paramètre SPCR :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit_segments(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0) | (1 &amp;lt;&amp;lt; SPR1);    //SPR1 &amp;amp; SPR0 à 1 pour une fréquence en dessous de 250kHz (fréquence de l'afficheur 7 segments)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;En envoyant alors la lettre appuyée sur le clavier, le 7 segments convertit (si c'est possible) la lettre en segments à allumer comme nous pouvons le voir sur la vidéo suivante :[[Fichier:7segments.mp4|centré|vignette|Affichage des caractères sur le 7 segments]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
=== Contrôleur de bus série SPI ===&lt;br /&gt;
Pour ce programme VHDL, nous avons voulu faire une communication SPI Maitre/Esclave. Pour cela, nous nous sommes documentés sur comment fonctionnait cette communication. Il faut alors réaliser les 4 signaux MOSI, MISO, SS et SCK afin de pouvoir communiquer. On vérifie alors chacun de bits envoyé afin de gérer les signaux de contrôle et de l'entrée MISO. Ensuite, on génère les données de sortie pour la réponse. Enfin, on peut assigner les sorties avec les informations que l'on a. Voici alors les processus utilisés : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
-- Processus 1 : Gestion des signaux de contrôle et de l'entrée MISO&lt;br /&gt;
    process (reset, start_transfer, MISO)&lt;br /&gt;
    begin&lt;br /&gt;
        if reset = '1' then&lt;br /&gt;
            -- En cas de réinitialisation, retour à l'état IDLE&lt;br /&gt;
            state &amp;lt;= IDLE;&lt;br /&gt;
            bit_counter &amp;lt;= 0;&lt;br /&gt;
            SS &amp;lt;= '1';&lt;br /&gt;
        elsif start_transfer = '1' then&lt;br /&gt;
            -- Au début d'une nouvelle transmission, passage à l'état TRANSFER&lt;br /&gt;
            state &amp;lt;= TRANSFER;&lt;br /&gt;
            bit_counter &amp;lt;= 0;&lt;br /&gt;
            SS &amp;lt;= '0'; -- Sélection du périphérique esclave au début de la transmission&lt;br /&gt;
        elsif state = TRANSFER then&lt;br /&gt;
            -- Déplacement du bit reçu dans le tampon&lt;br /&gt;
            received_data &amp;lt;= MISO &amp;amp; received_data(7 downto 1);&lt;br /&gt;
            bit_counter &amp;lt;= bit_counter + 1;&lt;br /&gt;
            if bit_counter = 7 then&lt;br /&gt;
                -- Si tous les bits ont été déplacés, passage à l'état DONE&lt;br /&gt;
                state &amp;lt;= DONE;&lt;br /&gt;
            end if;&lt;br /&gt;
        elsif state = DONE then&lt;br /&gt;
            -- Fin de la transmission, désélection du périphérique esclave&lt;br /&gt;
            SS &amp;lt;= '1';&lt;br /&gt;
            state &amp;lt;= IDLE;&lt;br /&gt;
        end if;&lt;br /&gt;
    end process;&lt;br /&gt;
&lt;br /&gt;
-- Processus 2 : Génération des données de sortie (data_out)&lt;br /&gt;
    process (reset, start_transfer, bit_counter)&lt;br /&gt;
    begin&lt;br /&gt;
        if reset = '1' then&lt;br /&gt;
            -- En cas de réinitialisation, les données de sortie sont mises à zéro&lt;br /&gt;
            data_out &amp;lt;= (others =&amp;gt; '0');&lt;br /&gt;
        elsif start_transfer = '1' then&lt;br /&gt;
            -- Au début d'une nouvelle transmission, envoi du premier bit&lt;br /&gt;
            data_out &amp;lt;= data_out(6 downto 0) &amp;amp; '0';&lt;br /&gt;
        elsif state = TRANSFER then&lt;br /&gt;
            -- Déplacement du bit à envoyer dans le registre de sortie&lt;br /&gt;
            data_out &amp;lt;= '0' &amp;amp; data_out(7 downto 1);&lt;br /&gt;
        end if;&lt;br /&gt;
    end process;&lt;br /&gt;
&lt;br /&gt;
-- Assignements des sorties&lt;br /&gt;
    transfer_done &amp;lt;= '1' when state = DONE else '0';&lt;br /&gt;
    clk &amp;lt;= not clk after 5 ns; -- Simulation de l'horloge (pour la démo)&lt;br /&gt;
    MOSI &amp;lt;= data_out(7);&lt;br /&gt;
    data_in &amp;lt;= received_data;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Contrôleur VGA ===&lt;br /&gt;
Pour ce contrôleur, il faut utiliser le port VGA présent sur la carte Basys-3. Sur ce connecteur VGA, il y a plusieurs sorties à gérer. En effet, il y a les signaux de synchronisation HS et VS qui fonctionnent s'ils ont une certaine forme d'ondes. Ces signaux doivent être à 0 pendant un certain temps. De plus, nous avons les ports permettant de gérer les couleur, vert, bleu et rouge, chacun sur 4 bits. L'horloge du FPGA fonctionnant à 100MHz, nous devons la moduler à 60Hz, car l'écran fonctionne à cette fréquence. Pour cela, nous avons utilisé les IP catalogs. Ce sont des composants existants dans des librairies qui peuvent être utilisés. Dans notre cas, nous avons utilisé un composant qui permet de modifier la fréquence d’un signal.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite reconstitué le signal de HS et VS. En effet, ces signaux ont besoin d’une période très spécifique permettant de bien configurer la taille de notre écran. Nous avons donc configuré un compteur incrémenté à chaque front montant de l’horloge, ce qui permet de mettre à l’état bas nos signaux.&lt;br /&gt;
&lt;br /&gt;
Le signal HS possède un front descendant à chaque changement de pixel, et lorsque que l’on a fait toute la ligne, un front descendant est envoyé sur VS pour descendre d’une ligne. Voici les programmes fait pour créer ces signaux : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
Balayage : process(clk_pixel)&lt;br /&gt;
begin&lt;br /&gt;
    if clk_pixel'event and clk_pixel = '1' then&lt;br /&gt;
    -- Compteur horizontal&lt;br /&gt;
        if compteur_horizontal &amp;lt; 1343 then&lt;br /&gt;
            compteur_horizontal &amp;lt;= compteur_horizontal + 1;&lt;br /&gt;
        else&lt;br /&gt;
            compteur_horizontal &amp;lt;= 0;&lt;br /&gt;
            &lt;br /&gt;
        -- Compteur vertical&lt;br /&gt;
            if compteur_vertical &amp;lt; 805 then&lt;br /&gt;
                compteur_vertical &amp;lt;= compteur_vertical + 1;&lt;br /&gt;
             else&lt;br /&gt;
                compteur_vertical &amp;lt;= 0;&lt;br /&gt;
            end if;&lt;br /&gt;
        end if;&lt;br /&gt;
    end if;&lt;br /&gt;
    &lt;br /&gt;
    -- Création signal HS&lt;br /&gt;
    if compteur_horizontal &amp;gt; 1047 and compteur_horizontal &amp;lt; 1184 then&lt;br /&gt;
        HS_out &amp;lt;= '0';&lt;br /&gt;
        HS_sig &amp;lt;= '0';&lt;br /&gt;
    else&lt;br /&gt;
        HS_out &amp;lt;= '1';&lt;br /&gt;
        HS_sig &amp;lt;= '1';&lt;br /&gt;
    end if;&lt;br /&gt;
    &lt;br /&gt;
    -- Création signal VS&lt;br /&gt;
    if compteur_vertical &amp;gt; 770 and compteur_vertical &amp;lt; 777 then&lt;br /&gt;
        VS_out &amp;lt;= '0';&lt;br /&gt;
        VS_sig &amp;lt;= '0';&lt;br /&gt;
    else&lt;br /&gt;
        VS_out &amp;lt;= '1';&lt;br /&gt;
        VS_sig &amp;lt;= '1';&lt;br /&gt;
    end if;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir fait ces programmes, nous avons fait la simulation pour voir si les signaux étaient bien réalisés. Voici les simulations de ces signaux : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:VGA signal VS.png|alt=VGA signal VS|centré|vignette|VGA signal VS]]&lt;br /&gt;
[[Fichier:VGA signal HS.png|alt=VGA signal HS|centré|vignette|VGA signal HS]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir fait cela, il fallait s’occuper des sorties des couleurs. Pour cela, nous devons mettre les valeurs des canaux de couleurs au maximum lorsque les boutons correspondants sont appuyés et quand les signaux HS et VS sont eux aussi à 1. Une condition supplémentaire permet de contrôler la taille du carré à afficher. Les programmes de gestion des couleurs étant quasiment les mêmes aux exceptions des boutons à appuyer, nous ne montrerons que celui de la couleur rouge sur l’image ci-dessous : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
-- Gestion couleur rouge --&lt;br /&gt;
    if B1_in = '1' and clk_pixel'event and clk_pixel = '1' then&lt;br /&gt;
        if VS_sig = '1' and HS_sig = '1' then&lt;br /&gt;
            if compteur_horizontal &amp;gt; 400 and compteur_horizontal &amp;lt; 600 then&lt;br /&gt;
                if compteur_vertical &amp;gt; 200 and compteur_vertical &amp;lt; 400 then&lt;br /&gt;
                    red_out &amp;lt;= &amp;quot;1111&amp;quot;;&lt;br /&gt;
                else&lt;br /&gt;
                    red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
                end if;&lt;br /&gt;
            else&lt;br /&gt;
                red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
            end if;&lt;br /&gt;
        else&lt;br /&gt;
            red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
        end if;&lt;br /&gt;
    end if;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Au final, après la génération du fichier .bit, de la modification du fichier de contrainte et de l'envoi du programme sur la carte FPGA Basys-3, nous avons bien un carré pouvant changer de couleur lorsque l'on appuie sur un bouton : &lt;br /&gt;
[[Fichier:Carré qui change de couleur grâce au contrôleur VGA.mp4|centré|vignette|Carré qui change de couleur grâce au contrôleur VGA]]&lt;br /&gt;
Il nous manque alors la gestion de la couleur en mémoire, mais nous n'avons pas eu le temps de réaliser cette fonction. Cependant la gestion du contrôleur VGA et de la création des signaux HS et VS nous ont beaucoup appris sur le fonctionnement du VGA.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS, car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte était pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur à utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utilisé un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecté des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenté un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur ne se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir réalisé le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur, car nous savons comment elles doivent être disposées. Le plus difficile dans ce routage a été de mettre les capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de vias possibles pour ne pas endommager les signaux que l'on souhaite envoyer. Nous avons fait le plan de masse de la carte et au final, nous avons réussi à compacter la carte pour qu'elle fasse une taille de 43mm par 33mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|245x245px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une représentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors routé notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :''&lt;br /&gt;
[[Fichier:Carte reconnue après un &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue après un &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue après un &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous avons entamé la programmation pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== Programmation de la carte électronique RNDIS ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utilisé une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassé. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite, nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créé, mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. &lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par la suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping de l'adresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut maintenant recevoir les paquets envoyés et vérifiés leur bonne réception sur le terminal. Nous avons alors utilisé l'outil &amp;quot;ether&amp;quot; afin d'observer les paquets reçus sur l'interface &amp;quot;usb0&amp;quot; créée. Pour rendre compte des paquets envoyés/reçus, nous allumons une LED à chaque ping :  &lt;br /&gt;
[[Fichier:Reception .mp4|centré|vignette|Réception de paquets IP ]]À ce moment précis, la carte allume bien les LEDs lors de la récéption des mêmes paquets que ceux implémentés dans la pile TCP/IP. Puisque l'on veut utiliser nos propres paquets avec notre protocole, nous devons ajouter dans cette pile le traitement de notre protocole. &lt;br /&gt;
&lt;br /&gt;
Tout d'abord, dans le fichier &amp;quot;EthernerProtocols.h&amp;quot;, nous avons créé notre propre protocole et sera le suivant : &amp;quot;0x0903&amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define ETHERTYPE_PICO                   0x0903&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, il faut créer une structure représentant notre trame dans un fichier permettant son traitement. Ici, le fichier s'appelle &amp;quot;PICO.h&amp;quot;. Nous avons alors choisi d'utiliser cette structure de trame : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/** Type define for a PICO header. */&lt;br /&gt;
    typedef struct&lt;br /&gt;
    {&lt;br /&gt;
        MAC_Address_t   Destination_MAC; /**&amp;lt; MAC address of the packet recipient */&lt;br /&gt;
        MAC_Address_t   Source_MAC; /**&amp;lt; MAC address of the packet source */&lt;br /&gt;
        IP_Address_t    Destination_IP; /**&amp;lt; IP address of the packet recipient */&lt;br /&gt;
        IP_Address_t    Source_IP; /**&amp;lt; IP address of the packet source */&lt;br /&gt;
        uint16_t        PICOType; /**&amp;lt; PICO packet sub-protocol type*/&lt;br /&gt;
    }PICO_Header_t;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans le fichier c, il faut alors réaliser le traitement de cette trame pour créer la réponse : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int16_t PICO_ProcessPICOPacket(void* InDataStart,&lt;br /&gt;
                           void* OutDataStart)&lt;br /&gt;
{&lt;br /&gt;
    PICO_Header_t* PICOHeaderIN  = (PICO_Header_t*)InDataStart;&lt;br /&gt;
	PICO_Header_t* PICOHeaderOUT = (PICO_Header_t*)OutDataStart;&lt;br /&gt;
    &lt;br /&gt;
    /* Ensure that the PICO request is a PICO request packet */&lt;br /&gt;
	if (SwapEndian_16(PICOHeaderIN-&amp;gt;PICOType) == ETHERTYPE_PICO)&lt;br /&gt;
	{&lt;br /&gt;
        if (IP_COMPARE(&amp;amp;PICOHeaderIN-&amp;gt;Destination_IP, &amp;amp;ServerIPAddress)||&lt;br /&gt;
            MAC_COMPARE(&amp;amp;PICOHeaderIN-&amp;gt;Destination_MAC, &amp;amp;ServerMACAddress))&lt;br /&gt;
		{&lt;br /&gt;
            /* Fill out the PICO response header */&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Destination_MAC = PICOHeaderIN-&amp;gt;Source_MAC;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Source_MAC = ServerMACAddress;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Destination_IP = PICOHeaderIN-&amp;gt;Source_IP;&lt;br /&gt;
			PICOHeaderOUT-&amp;gt;Source_IP = ServerIPAddress;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;PICOType = PICOHeaderIN-&amp;gt;PICOType;&lt;br /&gt;
            &lt;br /&gt;
            /* Blink the LED */&lt;br /&gt;
            PORTC ^= 0x30;&lt;br /&gt;
            &lt;br /&gt;
            /* Return the size of the response so far */&lt;br /&gt;
			return sizeof(PICO_Header_t);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
            &lt;br /&gt;
    return NO_RESPONSE;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;De cette façon, lorsqu'une trame respectant notre forme et utilisant notre protocole est envoyée sur l'interface, la LED de la carte devrait clignoter.&lt;br /&gt;
&lt;br /&gt;
Enfin, il faut aussi adapter le fichier &amp;quot;ProtocolsDecoders&amp;quot; afin que la LUFA arrive à décoder notre trame : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void DecodePICOFrameHeader(void* InDataStart)&lt;br /&gt;
{&lt;br /&gt;
	PICO_Header_t* PICOHeader = (PICO_Header_t*)InDataStart;&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;   \\\r\n    PICO\r\n&amp;quot;));&lt;br /&gt;
	&lt;br /&gt;
	if (!(IP_COMPARE(&amp;amp;PICOHeader-&amp;gt;Destination_IP, &amp;amp;ServerIPAddress)) &amp;amp;&amp;amp;&lt;br /&gt;
	    !(IP_COMPARE(&amp;amp;PICOHeader-&amp;gt;Destination_IP, &amp;amp;BroadcastIPAddress)))&lt;br /&gt;
	{&lt;br /&gt;
		printf_P(PSTR(&amp;quot;  + NOT ADDRESSED TO DEVICE\r\n&amp;quot;));&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + MAC Dest: %u:%u:%u:%u:%u:%u\r\n&amp;quot;),    PICOHeader-&amp;gt;Destination_MAC.Octets[0],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[1],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[2],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[3],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[4],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[5]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + MAC Source : %u:%u:%u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Source_MAC.Octets[0],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[1],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[2],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[3],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[4],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[5]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + IP Dest : %u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Destination_IP.Octets[0],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[1],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[2],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[3]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + IP Source : %u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Source_IP.Octets[0],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[1],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[2],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[3]);&lt;br /&gt;
&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + Protocol : %x\r\n&amp;quot;), SwapEndian_16(PICOHeader-&amp;gt;PICOType));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après cela, nous pouvons envoyer une trame sur l'interface &amp;quot;usb0&amp;quot; utilisant notre protocole. Pour cela, nous avons modifié l'outil &amp;quot;ether&amp;quot; pour observer directement l'interface &amp;quot;usb0&amp;quot; et aussi pour que le filtre accepte notre protocole. En envoyant alors la trame, la LED s'allume bien correctement : &lt;br /&gt;
[[Fichier:WhatsApp Video 2023-12-21 at 11.58.12.mp4|centré|vignette|Carte RNDIS réagissant à notre propre trame]]&lt;br /&gt;
&lt;br /&gt;
Cependant, on remarque que la LED s'allume, c'est-à-dire que la réponse est bien créée, mais elle n'est pas envoyée. En remontant chaque fonction pouvant être la cause du non-envoi de la réponse, nous avons &amp;quot;RNDIS_Task&amp;quot; que nous n'arrivons pas à comprendre. Cependant, nous n'avons pas modifié cette fonction, cela doit provenir de la trame envoyée, mais pourtant, le programme rentre bien complétement dans la fonction. À ce stade nous n'arrivons toujours pas à trouver la cause du problème.&lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2636</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2636"/>
		<updated>2023-12-28T13:12:38Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Carte FPGA/VHDL : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Matériel : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Clignotement de 2 LEDs ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs, à l'aide de deux tâches statiques, avec des périodes différentes. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et de restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 2) Ecriture de caractères sur le port série ===&lt;br /&gt;
Tout d'abord, avant de commencer la tâche, nous savions que nous devions utiliser l'UART du microcontrolleur. De plus, la tâche suivante devait utiliser aussi l'UART. Puisque 2 tâches utilisent la même ressource, il faut implémenter un système pour savoir quelle tâche utilise la ressource. Nous avons alors utiliser une sémaphore pour chaque tâche, permettant ainsi de limiter l'accès temporairement à la ressources aux autres tâches : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void semaphore_write(int action){&lt;br /&gt;
    if(action == TAKE_RESOURCE){&lt;br /&gt;
        while(1){&lt;br /&gt;
            cli();&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource Disponible */&lt;br /&gt;
            if(sem_writing &amp;gt; 0){&lt;br /&gt;
                sem_writing = 0;&lt;br /&gt;
                sei();&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource occupée */&lt;br /&gt;
            else{&lt;br /&gt;
                tasks[actuel].reason = WORKING;&lt;br /&gt;
                tasks[actuel].state = SLEEPING;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
                TIMER1_COMPA_vect();&lt;br /&gt;
            }&lt;br /&gt;
        sei();&lt;br /&gt;
        while(sem_writing == 0);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(action == DROP_RESOURCE){&lt;br /&gt;
        cli();&lt;br /&gt;
        sem_writing = 1;&lt;br /&gt;
        sei();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir implémenté cette sémaphore, il fallait que nous comprenions comment utiliser l'UART du microcontrôlleur. Pour cela, il faut initialiser correctement l'UART pour pouvoir écrire et lire en série. La fonction suivante permet d'initialiser correctement l'UART : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void init_usart(long int speed){&lt;br /&gt;
    UBRR0 = FREQUENCE/((unsigned long int)speed &amp;lt;&amp;lt; 4) -1;&lt;br /&gt;
    UCSR0B = (1 &amp;lt;&amp;lt; TXEN0 | 1 &amp;lt;&amp;lt; RXEN0);&lt;br /&gt;
    UCSR0C = (1 &amp;lt;&amp;lt; UCSZ01 | 1 &amp;lt;&amp;lt; UCSZ00);&lt;br /&gt;
    UCSR0A &amp;amp;= ~(1 &amp;lt;&amp;lt; U2X0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, une fois l'initialisation réalisée, nous pouvons réaliser la tâche utilisant les fonctions permettant d'écrire plusieurs caractères (ici &amp;quot;abc&amp;quot;) sur le port série, que l'on peut observer grâce à la commande shell ''&amp;quot;minicom -D /dev/ttyUSB0 -b 9600&amp;quot;.'' On utilise alors les fonctions suivantes pour écrire sur le port série :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void serial_send(unsigned char c){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, UDRE0);&lt;br /&gt;
    UDR0 = c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_send_str(char chaine[]){&lt;br /&gt;
    semaphore_write(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        serial_send(chaine[i]);&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_write(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut observer que la tâche fonctionne comme sur la vidéo suivante :[[Fichier:Tâche d'écriture sur le port série.mp4|vignette|Tâche d'écriture sur le port série|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 3) Lecture sur le port série ===&lt;br /&gt;
De la même façon que la tâche précédente, pour cette tâche nous devons lire les pressions de touches du clavier et les afficher sur le minicom. L'initialisation est déjà efféctuée et la sémaphore et la même que dans la partie précédente, nous ne la traiterons donc pas. On utilise alors les fonctions suivantes pour lire les pressions des touches sur le clavier, et la tâche les fait afficher ensuite : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
unsigned char serial_read(void){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, RXC0);&lt;br /&gt;
    return UDR0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_read_str(char chaine[]){&lt;br /&gt;
    semaphore_read(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        chaine[i] = serial_read();&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_read(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut alors observer les résultats grâce à la vidéo suivante : &lt;br /&gt;
[[Fichier:Tâche de lecture sur le port série.mp4|centré|vignette|Tâche de lecture sur le port série]]&lt;br /&gt;
&lt;br /&gt;
=== 4) Matrice de LEDs ===&lt;br /&gt;
Dans cette partie, nous souhaitons gérer l'affichage d'une matrice de LEDs 8x8 grâce au SPI. Il faut alors réussir à initialiser le SPI correctement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, nous avons rédiger un programme utilisé par notre tâche afin d'afficher différents caractères sur la matrice en allumant les LEDs voulues bit par bit :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void loop_matrix(char letter[8]){&lt;br /&gt;
    int temp;&lt;br /&gt;
    PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    for(short int i = 0; i &amp;lt; 8; i++){&lt;br /&gt;
            &lt;br /&gt;
        for(short int j = 0; j &amp;lt; 8; j++)&lt;br /&gt;
        {&lt;br /&gt;
            temp = letter[i] &amp;amp; (1 &amp;lt;&amp;lt; j); &lt;br /&gt;
            diplayLED(temp); //Envoir de chaque bit sur le SPI&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après vérification du bon fonctionnement de notre programme, nous avons ajouté la fonction principale dans notre fichier de gestion des tâches. Nous pouvons alors voir le changement des LEDs allumées lorsque l'on appuie sur un autre caractère grâce à la vidéo suivante :&lt;br /&gt;
[[Fichier:Matrice2.mov|centré|vignette|Affichage des caractères sur la matrice]]&lt;br /&gt;
&lt;br /&gt;
=== 5) Afficheur 7 segments ===&lt;br /&gt;
Pour le 7 segments, l'initialisation est différente. En effet, le 7 segments ne fonctionne qu'à une fréquence maximale de 250kHz, il faut alors modifier l'initialisation du SPI de la tâche pour le faire fonctionner en changeant le paramètre SPCR :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit_segments(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0) | (1 &amp;lt;&amp;lt; SPR1);    //SPR1 &amp;amp; SPR0 à 1 pour une fréquence en dessous de 250kHz (fréquence de l'afficheur 7 segments)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;En envoyant alors la lettre appuyée sur le clavier, le 7segments convertit (si c'est posible) la lettre en segments à allumer comme nous pouvons le voir sur la vidéo suivante :[[Fichier:7segments.mp4|centré|vignette|Affichage des caractères sur le 7 segments]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
=== '''1) Contrôleur de bus série SPI''' ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pour ce programme VHDL, nous avons voulu faire une communication SPI Maitre - Esclave. Pour cela =, nous nous sommes documentés sur comment fonctionnait cette communication. Il faut alors réaliser les 4 signaux MOSI, MISO, SS et SCK afin de pouvoir communiquer. On vérifie alors chacun de bits envoyé afin de gérér les signaux de contrôle et de l'entrée MISO. Ensuite, on génère les données de sortie pour la réponse. Enfin on peut assigner les sorties avec les informations que l'on a. Voici alors les processus utilisés : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
-- Processus 1 : Gestion des signaux de contrôle et de l'entrée MISO&lt;br /&gt;
    process (reset, start_transfer, MISO)&lt;br /&gt;
    begin&lt;br /&gt;
        if reset = '1' then&lt;br /&gt;
            -- En cas de réinitialisation, retour à l'état IDLE&lt;br /&gt;
            state &amp;lt;= IDLE;&lt;br /&gt;
            bit_counter &amp;lt;= 0;&lt;br /&gt;
            SS &amp;lt;= '1';&lt;br /&gt;
        elsif start_transfer = '1' then&lt;br /&gt;
            -- Au début d'une nouvelle transmission, passage à l'état TRANSFER&lt;br /&gt;
            state &amp;lt;= TRANSFER;&lt;br /&gt;
            bit_counter &amp;lt;= 0;&lt;br /&gt;
            SS &amp;lt;= '0'; -- Sélection du périphérique esclave au début de la transmission&lt;br /&gt;
        elsif state = TRANSFER then&lt;br /&gt;
            -- Déplacement du bit reçu dans le tampon&lt;br /&gt;
            received_data &amp;lt;= MISO &amp;amp; received_data(7 downto 1);&lt;br /&gt;
            bit_counter &amp;lt;= bit_counter + 1;&lt;br /&gt;
            if bit_counter = 7 then&lt;br /&gt;
                -- Si tous les bits ont été déplacés, passage à l'état DONE&lt;br /&gt;
                state &amp;lt;= DONE;&lt;br /&gt;
            end if;&lt;br /&gt;
        elsif state = DONE then&lt;br /&gt;
            -- Fin de la transmission, désélection du périphérique esclave&lt;br /&gt;
            SS &amp;lt;= '1';&lt;br /&gt;
            state &amp;lt;= IDLE;&lt;br /&gt;
        end if;&lt;br /&gt;
    end process;&lt;br /&gt;
&lt;br /&gt;
-- Processus 2 : Génération des données de sortie (data_out)&lt;br /&gt;
    process (reset, start_transfer, bit_counter)&lt;br /&gt;
    begin&lt;br /&gt;
        if reset = '1' then&lt;br /&gt;
            -- En cas de réinitialisation, les données de sortie sont mises à zéro&lt;br /&gt;
            data_out &amp;lt;= (others =&amp;gt; '0');&lt;br /&gt;
        elsif start_transfer = '1' then&lt;br /&gt;
            -- Au début d'une nouvelle transmission, envoi du premier bit&lt;br /&gt;
            data_out &amp;lt;= data_out(6 downto 0) &amp;amp; '0';&lt;br /&gt;
        elsif state = TRANSFER then&lt;br /&gt;
            -- Déplacement du bit à envoyer dans le registre de sortie&lt;br /&gt;
            data_out &amp;lt;= '0' &amp;amp; data_out(7 downto 1);&lt;br /&gt;
        end if;&lt;br /&gt;
    end process;&lt;br /&gt;
&lt;br /&gt;
-- Assignements des sorties&lt;br /&gt;
    transfer_done &amp;lt;= '1' when state = DONE else '0';&lt;br /&gt;
    clk &amp;lt;= not clk after 5 ns; -- Simulation de l'horloge (pour la démo)&lt;br /&gt;
    MOSI &amp;lt;= data_out(7);&lt;br /&gt;
    data_in &amp;lt;= received_data;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== '''2) Contrôleur VGA''' ===&lt;br /&gt;
Pour ce contrôleur, il faut utiliser le port VGA présent sur la carte Basys-3. Sur ce connecteur VGA, il y a plusieurs sorties à gérer. En effet, il y a les signaux de synchronisation HS et VS qui fonctionnent si ils ont une certaines formes d'ondes. Ces signaux doivent être à 0 pendant un certain temps. De plus nous avons les ports permettant de gérer les couleur, vert, bleu et rouge, chacun sur 4 bits. L'horloge du FPGA fonctionnant à 100MHz, nous devons la moduler à 60Hz, car l'écran fonctionne à cette fréquence. Pour cela, nous avons utilisé les IP catalogs. Ce sont des composants existants dans des librairies qui peuvent être utilisés. Dans notre cas, nous avons utilisé un composant qui permet de modifier la fréquence d’un signal.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite reconstitué le signal de HS et VS. En effet, ces signaux ont besoin d’une période très spécifique permettant de bien configurer la taille de notre écran. Nous avons donc configuré un compteur incrémenté à chaque front montant de l’horloge, ce qui permet de mettre à l’état bas nos signaux.&lt;br /&gt;
&lt;br /&gt;
Le signal HS possède un front descendant à chaque changement de pixel, et lorsque que l’on a fait toute la ligne, un front descendant est envoyé sur VS pour descendre d’une ligne. Voici les programmes fait pour créer ces signaux : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
Balayage : process(clk_pixel)&lt;br /&gt;
begin&lt;br /&gt;
    if clk_pixel'event and clk_pixel = '1' then&lt;br /&gt;
    -- Compteur horizontal&lt;br /&gt;
        if compteur_horizontal &amp;lt; 1343 then&lt;br /&gt;
            compteur_horizontal &amp;lt;= compteur_horizontal + 1;&lt;br /&gt;
        else&lt;br /&gt;
            compteur_horizontal &amp;lt;= 0;&lt;br /&gt;
            &lt;br /&gt;
        -- Compteur vertical&lt;br /&gt;
            if compteur_vertical &amp;lt; 805 then&lt;br /&gt;
                compteur_vertical &amp;lt;= compteur_vertical + 1;&lt;br /&gt;
             else&lt;br /&gt;
                compteur_vertical &amp;lt;= 0;&lt;br /&gt;
            end if;&lt;br /&gt;
        end if;&lt;br /&gt;
    end if;&lt;br /&gt;
    &lt;br /&gt;
    -- Création signal HS&lt;br /&gt;
    if compteur_horizontal &amp;gt; 1047 and compteur_horizontal &amp;lt; 1184 then&lt;br /&gt;
        HS_out &amp;lt;= '0';&lt;br /&gt;
        HS_sig &amp;lt;= '0';&lt;br /&gt;
    else&lt;br /&gt;
        HS_out &amp;lt;= '1';&lt;br /&gt;
        HS_sig &amp;lt;= '1';&lt;br /&gt;
    end if;&lt;br /&gt;
    &lt;br /&gt;
    -- Création signal VS&lt;br /&gt;
    if compteur_vertical &amp;gt; 770 and compteur_vertical &amp;lt; 777 then&lt;br /&gt;
        VS_out &amp;lt;= '0';&lt;br /&gt;
        VS_sig &amp;lt;= '0';&lt;br /&gt;
    else&lt;br /&gt;
        VS_out &amp;lt;= '1';&lt;br /&gt;
        VS_sig &amp;lt;= '1';&lt;br /&gt;
    end if;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir fait ces programmes, nous avons fait la simulation pour voir si les signaux étaient bien réalisés. Voici les simulations de ces signaux : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:VGA signal VS.png|alt=VGA signal VS|centré|vignette|VGA signal VS]]&lt;br /&gt;
[[Fichier:VGA signal HS.png|alt=VGA signal HS|centré|vignette|VGA signal HS]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir fait cela, il fallait s’occuper des sorties des couleurs. Pour cela, nous devons mettre les valeurs des canaux de couleurs au maximum lorsque les boutons correspondants sont appuyés et quand les signaux HS et VS sont eux aussi à 1. Une condition supplémentaire permet de contrôler la taille du carré à afficher. Les programmes de gestion des couleurs étant quasiment les mêmes aux exceptions des boutons à appuyer, nous ne montrerons que celui de la couleur rouge sur l’image ci-dessous : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
-- Gestion couleur rouge --&lt;br /&gt;
    if B1_in = '1' and clk_pixel'event and clk_pixel = '1' then&lt;br /&gt;
        if VS_sig = '1' and HS_sig = '1' then&lt;br /&gt;
            if compteur_horizontal &amp;gt; 400 and compteur_horizontal &amp;lt; 600 then&lt;br /&gt;
                if compteur_vertical &amp;gt; 200 and compteur_vertical &amp;lt; 400 then&lt;br /&gt;
                    red_out &amp;lt;= &amp;quot;1111&amp;quot;;&lt;br /&gt;
                else&lt;br /&gt;
                    red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
                end if;&lt;br /&gt;
            else&lt;br /&gt;
                red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
            end if;&lt;br /&gt;
        else&lt;br /&gt;
            red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
        end if;&lt;br /&gt;
    end if;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Au final, après la génération du fichier .bit, de la modification du fichier de contrainte et de l'envoi du programme sur la carte FPGA Basys-3, nous avons bien un carré pouvant changer de couleur lorsque l'on appuie sur un bouton : &lt;br /&gt;
[[Fichier:Carré qui change de couleur grâce au contrôleur VGA.mp4|centré|vignette|Carré qui change de couleur grâce au contrôleur VGA]]&lt;br /&gt;
Il nous manque alors la gestion de la couleur en mémoire, mais nous n'avons pas eu le temps de réaliser cette fonction. Cependant la gestion du contrôleur VGA et de la création des signaux HS et VS nous ont beaucoup appris sur le fonctionnement du VGA.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte était pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecté des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir réalisé le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux que l'on souhaite envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|245x245px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors routé notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :''&lt;br /&gt;
[[Fichier:Carte reconnue après un &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue après un &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue après un &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons entamé la programmation pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utilisé une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassée. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créé mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. &lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par le suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping de l'adresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut maintenant recevoir les paquets envoyés et vérifiés leur bonne réception sur le terminal. Nous avons alors utiliser l'outil &amp;quot;ether&amp;quot; afin d'observer les paquets reçues sur l'interface &amp;quot;usb0&amp;quot; créée. Pour rendre compte des paquets envoyés/reçus, nous allumons une LED à chaque ping :  &lt;br /&gt;
[[Fichier:Reception .mp4|centré|vignette|Réception de paquets IP ]]A ce moment-là, la carte allume bien les LEDs lors de la récéption des mêmes paquets que ceux implémentés dans la pile TCP/IP. Puisque l'on veut utiliser nos propres paquets avec notre protocole, nous devons ajouter dans cette pile le traitement de notre protocole. &lt;br /&gt;
&lt;br /&gt;
Tout d'abord, dans le fichier &amp;quot;EthernerProtocols.h&amp;quot;, nous avons créer notre protocole. Le notre sera &amp;quot;0x0903&amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define ETHERTYPE_PICO                   0x0903&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, il faut créer une structure représentant notre trame dans un fichier permettant son traitement. Ici, e fichier s'appelle &amp;quot;PICO.h&amp;quot;. Nous avons alors choisi d'utiliser cette structure de trame : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/** Type define for a PICO header. */&lt;br /&gt;
    typedef struct&lt;br /&gt;
    {&lt;br /&gt;
        MAC_Address_t   Destination_MAC; /**&amp;lt; MAC address of the packet recipient */&lt;br /&gt;
        MAC_Address_t   Source_MAC; /**&amp;lt; MAC address of the packet source */&lt;br /&gt;
        IP_Address_t    Destination_IP; /**&amp;lt; IP address of the packet recipient */&lt;br /&gt;
        IP_Address_t    Source_IP; /**&amp;lt; IP address of the packet source */&lt;br /&gt;
        uint16_t        PICOType; /**&amp;lt; PICO packet sub-protocol type*/&lt;br /&gt;
    }PICO_Header_t;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans le fichier c, il faut alors réaliser le traitement de cette trame pour créer la réponse : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int16_t PICO_ProcessPICOPacket(void* InDataStart,&lt;br /&gt;
                           void* OutDataStart)&lt;br /&gt;
{&lt;br /&gt;
    PICO_Header_t* PICOHeaderIN  = (PICO_Header_t*)InDataStart;&lt;br /&gt;
	PICO_Header_t* PICOHeaderOUT = (PICO_Header_t*)OutDataStart;&lt;br /&gt;
    &lt;br /&gt;
    /* Ensure that the PICO request is a PICO request packet */&lt;br /&gt;
	if (SwapEndian_16(PICOHeaderIN-&amp;gt;PICOType) == ETHERTYPE_PICO)&lt;br /&gt;
	{&lt;br /&gt;
        if (IP_COMPARE(&amp;amp;PICOHeaderIN-&amp;gt;Destination_IP, &amp;amp;ServerIPAddress)||&lt;br /&gt;
            MAC_COMPARE(&amp;amp;PICOHeaderIN-&amp;gt;Destination_MAC, &amp;amp;ServerMACAddress))&lt;br /&gt;
		{&lt;br /&gt;
            /* Fill out the PICO response header */&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Destination_MAC = PICOHeaderIN-&amp;gt;Source_MAC;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Source_MAC = ServerMACAddress;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Destination_IP = PICOHeaderIN-&amp;gt;Source_IP;&lt;br /&gt;
			PICOHeaderOUT-&amp;gt;Source_IP = ServerIPAddress;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;PICOType = PICOHeaderIN-&amp;gt;PICOType;&lt;br /&gt;
            &lt;br /&gt;
            /* Blink the LED */&lt;br /&gt;
            PORTC ^= 0x30;&lt;br /&gt;
            &lt;br /&gt;
            /* Return the size of the response so far */&lt;br /&gt;
			return sizeof(PICO_Header_t);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
            &lt;br /&gt;
    return NO_RESPONSE;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;De cette façon, lorsqu'une trame respectant notre forme et utilisant notre protocole est envoyé sur l'interface, la LED de la carte devrait clignoter.&lt;br /&gt;
&lt;br /&gt;
Enfin, il faut aussi adapter le fichier &amp;quot;ProtocolsDecoders&amp;quot; afin que la LUFA arraive à décoder notre trame : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void DecodePICOFrameHeader(void* InDataStart)&lt;br /&gt;
{&lt;br /&gt;
	PICO_Header_t* PICOHeader = (PICO_Header_t*)InDataStart;&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;   \\\r\n    PICO\r\n&amp;quot;));&lt;br /&gt;
	&lt;br /&gt;
	if (!(IP_COMPARE(&amp;amp;PICOHeader-&amp;gt;Destination_IP, &amp;amp;ServerIPAddress)) &amp;amp;&amp;amp;&lt;br /&gt;
	    !(IP_COMPARE(&amp;amp;PICOHeader-&amp;gt;Destination_IP, &amp;amp;BroadcastIPAddress)))&lt;br /&gt;
	{&lt;br /&gt;
		printf_P(PSTR(&amp;quot;  + NOT ADDRESSED TO DEVICE\r\n&amp;quot;));&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + MAC Dest: %u:%u:%u:%u:%u:%u\r\n&amp;quot;),    PICOHeader-&amp;gt;Destination_MAC.Octets[0],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[1],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[2],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[3],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[4],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[5]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + MAC Source : %u:%u:%u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Source_MAC.Octets[0],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[1],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[2],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[3],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[4],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[5]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + IP Dest : %u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Destination_IP.Octets[0],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[1],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[2],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[3]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + IP Source : %u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Source_IP.Octets[0],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[1],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[2],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[3]);&lt;br /&gt;
&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + Protocol : %x\r\n&amp;quot;), SwapEndian_16(PICOHeader-&amp;gt;PICOType));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après cela, nous pouvons envoyer une trame sur l'interface &amp;quot;usb0&amp;quot; utilisant notre protocole. Pour cela, nous avons modifié l'outil &amp;quot;ether&amp;quot; pour observer directement l'interface &amp;quot;usb0&amp;quot; et aussi pour que le filtre accepte notre protocole. En envoyant alors la trame, la LED s'allume bien correctement : &lt;br /&gt;
[[Fichier:WhatsApp Video 2023-12-21 at 11.58.12.mp4|centré|vignette|Carte RNDIS réagissant à notre propre trame]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cependant, on remarque que la LED s'allume, c'est-à-dire que la réponse est bien créée, mais elle n'est pas envoyée. En remontant chaque fonction pouvant être la cause du non-envoi de la réponse, nous avons &amp;quot;RNDIS_Task&amp;quot; que nous n'arrivons pas à comprendre. Cependant, nous n'avons pas modifié cette fonction, cela doit venir de la trame envoyée, mais pourtant le programme rentre bien complétement dans la fonction. A ce stade nous n'arrivons toujours pas à trouver la cause du problème.&lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2635</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2635"/>
		<updated>2023-12-28T13:11:03Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* 2) Soudure de la carte électronique RNDIS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Matériel : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Clignotement de 2 LEDs ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs, à l'aide de deux tâches statiques, avec des périodes différentes. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et de restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 2) Ecriture de caractères sur le port série ===&lt;br /&gt;
Tout d'abord, avant de commencer la tâche, nous savions que nous devions utiliser l'UART du microcontrolleur. De plus, la tâche suivante devait utiliser aussi l'UART. Puisque 2 tâches utilisent la même ressource, il faut implémenter un système pour savoir quelle tâche utilise la ressource. Nous avons alors utiliser une sémaphore pour chaque tâche, permettant ainsi de limiter l'accès temporairement à la ressources aux autres tâches : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void semaphore_write(int action){&lt;br /&gt;
    if(action == TAKE_RESOURCE){&lt;br /&gt;
        while(1){&lt;br /&gt;
            cli();&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource Disponible */&lt;br /&gt;
            if(sem_writing &amp;gt; 0){&lt;br /&gt;
                sem_writing = 0;&lt;br /&gt;
                sei();&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource occupée */&lt;br /&gt;
            else{&lt;br /&gt;
                tasks[actuel].reason = WORKING;&lt;br /&gt;
                tasks[actuel].state = SLEEPING;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
                TIMER1_COMPA_vect();&lt;br /&gt;
            }&lt;br /&gt;
        sei();&lt;br /&gt;
        while(sem_writing == 0);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(action == DROP_RESOURCE){&lt;br /&gt;
        cli();&lt;br /&gt;
        sem_writing = 1;&lt;br /&gt;
        sei();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir implémenté cette sémaphore, il fallait que nous comprenions comment utiliser l'UART du microcontrôlleur. Pour cela, il faut initialiser correctement l'UART pour pouvoir écrire et lire en série. La fonction suivante permet d'initialiser correctement l'UART : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void init_usart(long int speed){&lt;br /&gt;
    UBRR0 = FREQUENCE/((unsigned long int)speed &amp;lt;&amp;lt; 4) -1;&lt;br /&gt;
    UCSR0B = (1 &amp;lt;&amp;lt; TXEN0 | 1 &amp;lt;&amp;lt; RXEN0);&lt;br /&gt;
    UCSR0C = (1 &amp;lt;&amp;lt; UCSZ01 | 1 &amp;lt;&amp;lt; UCSZ00);&lt;br /&gt;
    UCSR0A &amp;amp;= ~(1 &amp;lt;&amp;lt; U2X0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, une fois l'initialisation réalisée, nous pouvons réaliser la tâche utilisant les fonctions permettant d'écrire plusieurs caractères (ici &amp;quot;abc&amp;quot;) sur le port série, que l'on peut observer grâce à la commande shell ''&amp;quot;minicom -D /dev/ttyUSB0 -b 9600&amp;quot;.'' On utilise alors les fonctions suivantes pour écrire sur le port série :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void serial_send(unsigned char c){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, UDRE0);&lt;br /&gt;
    UDR0 = c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_send_str(char chaine[]){&lt;br /&gt;
    semaphore_write(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        serial_send(chaine[i]);&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_write(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut observer que la tâche fonctionne comme sur la vidéo suivante :[[Fichier:Tâche d'écriture sur le port série.mp4|vignette|Tâche d'écriture sur le port série|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 3) Lecture sur le port série ===&lt;br /&gt;
De la même façon que la tâche précédente, pour cette tâche nous devons lire les pressions de touches du clavier et les afficher sur le minicom. L'initialisation est déjà efféctuée et la sémaphore et la même que dans la partie précédente, nous ne la traiterons donc pas. On utilise alors les fonctions suivantes pour lire les pressions des touches sur le clavier, et la tâche les fait afficher ensuite : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
unsigned char serial_read(void){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, RXC0);&lt;br /&gt;
    return UDR0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_read_str(char chaine[]){&lt;br /&gt;
    semaphore_read(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        chaine[i] = serial_read();&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_read(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut alors observer les résultats grâce à la vidéo suivante : &lt;br /&gt;
[[Fichier:Tâche de lecture sur le port série.mp4|centré|vignette|Tâche de lecture sur le port série]]&lt;br /&gt;
&lt;br /&gt;
=== 4) Matrice de LEDs ===&lt;br /&gt;
Dans cette partie, nous souhaitons gérer l'affichage d'une matrice de LEDs 8x8 grâce au SPI. Il faut alors réussir à initialiser le SPI correctement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, nous avons rédiger un programme utilisé par notre tâche afin d'afficher différents caractères sur la matrice en allumant les LEDs voulues bit par bit :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void loop_matrix(char letter[8]){&lt;br /&gt;
    int temp;&lt;br /&gt;
    PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    for(short int i = 0; i &amp;lt; 8; i++){&lt;br /&gt;
            &lt;br /&gt;
        for(short int j = 0; j &amp;lt; 8; j++)&lt;br /&gt;
        {&lt;br /&gt;
            temp = letter[i] &amp;amp; (1 &amp;lt;&amp;lt; j); &lt;br /&gt;
            diplayLED(temp); //Envoir de chaque bit sur le SPI&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après vérification du bon fonctionnement de notre programme, nous avons ajouté la fonction principale dans notre fichier de gestion des tâches. Nous pouvons alors voir le changement des LEDs allumées lorsque l'on appuie sur un autre caractère grâce à la vidéo suivante :&lt;br /&gt;
[[Fichier:Matrice2.mov|centré|vignette|Affichage des caractères sur la matrice]]&lt;br /&gt;
&lt;br /&gt;
=== 5) Afficheur 7 segments ===&lt;br /&gt;
Pour le 7 segments, l'initialisation est différente. En effet, le 7 segments ne fonctionne qu'à une fréquence maximale de 250kHz, il faut alors modifier l'initialisation du SPI de la tâche pour le faire fonctionner en changeant le paramètre SPCR :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit_segments(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0) | (1 &amp;lt;&amp;lt; SPR1);    //SPR1 &amp;amp; SPR0 à 1 pour une fréquence en dessous de 250kHz (fréquence de l'afficheur 7 segments)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;En envoyant alors la lettre appuyée sur le clavier, le 7segments convertit (si c'est posible) la lettre en segments à allumer comme nous pouvons le voir sur la vidéo suivante :[[Fichier:7segments.mp4|centré|vignette|Affichage des caractères sur le 7 segments]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
'''&amp;lt;big&amp;gt;1) Contrôleur de bus série SPI&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
Pour ce programme VHDL, nous avons voulu faire une communication SPI Maitre - Esclave. Pour cela =, nous nous sommes documentés sur comment fonctionnait cette communication. Il faut alors réaliser les 4 signaux MOSI, MISO, SS et SCK afin de pouvoir communiquer. On vérifie alors chacun de bits envoyé afin de gérér les signaux de contrôle et de l'entrée MISO. Ensuite, on génère les données de sortie pour la réponse. Enfin on peut assigner les sorties avec les informations que l'on a. Voici alors les processus utilisés : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
-- Processus 1 : Gestion des signaux de contrôle et de l'entrée MISO&lt;br /&gt;
    process (reset, start_transfer, MISO)&lt;br /&gt;
    begin&lt;br /&gt;
        if reset = '1' then&lt;br /&gt;
            -- En cas de réinitialisation, retour à l'état IDLE&lt;br /&gt;
            state &amp;lt;= IDLE;&lt;br /&gt;
            bit_counter &amp;lt;= 0;&lt;br /&gt;
            SS &amp;lt;= '1';&lt;br /&gt;
        elsif start_transfer = '1' then&lt;br /&gt;
            -- Au début d'une nouvelle transmission, passage à l'état TRANSFER&lt;br /&gt;
            state &amp;lt;= TRANSFER;&lt;br /&gt;
            bit_counter &amp;lt;= 0;&lt;br /&gt;
            SS &amp;lt;= '0'; -- Sélection du périphérique esclave au début de la transmission&lt;br /&gt;
        elsif state = TRANSFER then&lt;br /&gt;
            -- Déplacement du bit reçu dans le tampon&lt;br /&gt;
            received_data &amp;lt;= MISO &amp;amp; received_data(7 downto 1);&lt;br /&gt;
            bit_counter &amp;lt;= bit_counter + 1;&lt;br /&gt;
            if bit_counter = 7 then&lt;br /&gt;
                -- Si tous les bits ont été déplacés, passage à l'état DONE&lt;br /&gt;
                state &amp;lt;= DONE;&lt;br /&gt;
            end if;&lt;br /&gt;
        elsif state = DONE then&lt;br /&gt;
            -- Fin de la transmission, désélection du périphérique esclave&lt;br /&gt;
            SS &amp;lt;= '1';&lt;br /&gt;
            state &amp;lt;= IDLE;&lt;br /&gt;
        end if;&lt;br /&gt;
    end process;&lt;br /&gt;
&lt;br /&gt;
-- Processus 2 : Génération des données de sortie (data_out)&lt;br /&gt;
    process (reset, start_transfer, bit_counter)&lt;br /&gt;
    begin&lt;br /&gt;
        if reset = '1' then&lt;br /&gt;
            -- En cas de réinitialisation, les données de sortie sont mises à zéro&lt;br /&gt;
            data_out &amp;lt;= (others =&amp;gt; '0');&lt;br /&gt;
        elsif start_transfer = '1' then&lt;br /&gt;
            -- Au début d'une nouvelle transmission, envoi du premier bit&lt;br /&gt;
            data_out &amp;lt;= data_out(6 downto 0) &amp;amp; '0';&lt;br /&gt;
        elsif state = TRANSFER then&lt;br /&gt;
            -- Déplacement du bit à envoyer dans le registre de sortie&lt;br /&gt;
            data_out &amp;lt;= '0' &amp;amp; data_out(7 downto 1);&lt;br /&gt;
        end if;&lt;br /&gt;
    end process;&lt;br /&gt;
&lt;br /&gt;
-- Assignements des sorties&lt;br /&gt;
    transfer_done &amp;lt;= '1' when state = DONE else '0';&lt;br /&gt;
    clk &amp;lt;= not clk after 5 ns; -- Simulation de l'horloge (pour la démo)&lt;br /&gt;
    MOSI &amp;lt;= data_out(7);&lt;br /&gt;
    data_in &amp;lt;= received_data;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;'''&amp;lt;big&amp;gt;2) Contrôleur VGA&amp;lt;/big&amp;gt;'''&lt;br /&gt;
&lt;br /&gt;
Pour ce contrôleur, il faut utiliser le port VGA présent sur la carte Basys-3. Sur ce connecteur VGA, il y a plusieurs sorties à gérer. En effet, il y a les signaux de synchronisation HS et VS qui fonctionnent si ils ont une certaines formes d'ondes. Ces signaux doivent être à 0 pendant un certain temps. De plus nous avons les ports permettant de gérer les couleur, vert, bleu et rouge, chacun sur 4 bits. L'horloge du FPGA fonctionnant à 100MHz, nous devons la moduler à 60Hz, car l'écran fonctionne à cette fréquence. Pour cela, nous avons utilisé les IP catalogs. Ce sont des composants existants dans des librairies qui peuvent être utilisés. Dans notre cas, nous avons utilisé un composant qui permet de modifier la fréquence d’un signal.&lt;br /&gt;
&lt;br /&gt;
Nous avons ensuite reconstitué le signal de HS et VS. En effet, ces signaux ont besoin d’une période très spécifique permettant de bien configurer la taille de notre écran. Nous avons donc configuré un compteur incrémenté à chaque front montant de l’horloge, ce qui permet de mettre à l’état bas nos signaux.&lt;br /&gt;
&lt;br /&gt;
Le signal HS possède un front descendant à chaque changement de pixel, et lorsque que l’on a fait toute la ligne, un front descendant est envoyé sur VS pour descendre d’une ligne. Voici les programmes fait pour créer ces signaux : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
Balayage : process(clk_pixel)&lt;br /&gt;
begin&lt;br /&gt;
    if clk_pixel'event and clk_pixel = '1' then&lt;br /&gt;
    -- Compteur horizontal&lt;br /&gt;
        if compteur_horizontal &amp;lt; 1343 then&lt;br /&gt;
            compteur_horizontal &amp;lt;= compteur_horizontal + 1;&lt;br /&gt;
        else&lt;br /&gt;
            compteur_horizontal &amp;lt;= 0;&lt;br /&gt;
            &lt;br /&gt;
        -- Compteur vertical&lt;br /&gt;
            if compteur_vertical &amp;lt; 805 then&lt;br /&gt;
                compteur_vertical &amp;lt;= compteur_vertical + 1;&lt;br /&gt;
             else&lt;br /&gt;
                compteur_vertical &amp;lt;= 0;&lt;br /&gt;
            end if;&lt;br /&gt;
        end if;&lt;br /&gt;
    end if;&lt;br /&gt;
    &lt;br /&gt;
    -- Création signal HS&lt;br /&gt;
    if compteur_horizontal &amp;gt; 1047 and compteur_horizontal &amp;lt; 1184 then&lt;br /&gt;
        HS_out &amp;lt;= '0';&lt;br /&gt;
        HS_sig &amp;lt;= '0';&lt;br /&gt;
    else&lt;br /&gt;
        HS_out &amp;lt;= '1';&lt;br /&gt;
        HS_sig &amp;lt;= '1';&lt;br /&gt;
    end if;&lt;br /&gt;
    &lt;br /&gt;
    -- Création signal VS&lt;br /&gt;
    if compteur_vertical &amp;gt; 770 and compteur_vertical &amp;lt; 777 then&lt;br /&gt;
        VS_out &amp;lt;= '0';&lt;br /&gt;
        VS_sig &amp;lt;= '0';&lt;br /&gt;
    else&lt;br /&gt;
        VS_out &amp;lt;= '1';&lt;br /&gt;
        VS_sig &amp;lt;= '1';&lt;br /&gt;
    end if;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir fait ces programmes, nous avons fait la simulation pour voir si les signaux étaient bien réalisés. Voici les simulations de ces signaux : &lt;br /&gt;
&lt;br /&gt;
[[Fichier:VGA signal VS.png|alt=VGA signal VS|centré|vignette|VGA signal VS]]&lt;br /&gt;
[[Fichier:VGA signal HS.png|alt=VGA signal HS|centré|vignette|VGA signal HS]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Après avoir fait cela, il fallait s’occuper des sorties des couleurs. Pour cela, nous devons mettre les valeurs des canaux de couleurs au maximum lorsque les boutons correspondants sont appuyés et quand les signaux HS et VS sont eux aussi à 1. Une condition supplémentaire permet de contrôler la taille du carré à afficher. Les programmes de gestion des couleurs étant quasiment les mêmes aux exceptions des boutons à appuyer, nous ne montrerons que celui de la couleur rouge sur l’image ci-dessous : &amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
-- Gestion couleur rouge --&lt;br /&gt;
    if B1_in = '1' and clk_pixel'event and clk_pixel = '1' then&lt;br /&gt;
        if VS_sig = '1' and HS_sig = '1' then&lt;br /&gt;
            if compteur_horizontal &amp;gt; 400 and compteur_horizontal &amp;lt; 600 then&lt;br /&gt;
                if compteur_vertical &amp;gt; 200 and compteur_vertical &amp;lt; 400 then&lt;br /&gt;
                    red_out &amp;lt;= &amp;quot;1111&amp;quot;;&lt;br /&gt;
                else&lt;br /&gt;
                    red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
                end if;&lt;br /&gt;
            else&lt;br /&gt;
                red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
            end if;&lt;br /&gt;
        else&lt;br /&gt;
            red_out &amp;lt;= &amp;quot;0000&amp;quot;;&lt;br /&gt;
        end if;&lt;br /&gt;
    end if;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Au final, après la génération du fichier .bit, de la modification du fichier de contrainte et de l'envoi du programme sur la carte FPGA Basys-3, nous avons bien un carré pouvant changer de couleur lorsque l'on appuie sur un bouton : &lt;br /&gt;
[[Fichier:Carré qui change de couleur grâce au contrôleur VGA.mp4|centré|vignette|Carré qui change de couleur grâce au contrôleur VGA]]&lt;br /&gt;
Il nous manque alors la gestion de la couleur en mémoire, mais nous n'avons pas eu le temps de réaliser cette fonction. Cependant la gestion du contrôleur VGA et de la création des signaux HS et VS nous ont beaucoup appris sur le fonctionnement du VGA.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte était pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecté des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir réalisé le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux que l'on souhaite envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|245x245px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors routé notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :''&lt;br /&gt;
[[Fichier:Carte reconnue après un &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue après un &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue après un &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons entamé la programmation pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utilisé une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassée. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créé mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. &lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par le suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping de l'adresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut maintenant recevoir les paquets envoyés et vérifiés leur bonne réception sur le terminal. Nous avons alors utiliser l'outil &amp;quot;ether&amp;quot; afin d'observer les paquets reçues sur l'interface &amp;quot;usb0&amp;quot; créée. Pour rendre compte des paquets envoyés/reçus, nous allumons une LED à chaque ping :  &lt;br /&gt;
[[Fichier:Reception .mp4|centré|vignette|Réception de paquets IP ]]A ce moment-là, la carte allume bien les LEDs lors de la récéption des mêmes paquets que ceux implémentés dans la pile TCP/IP. Puisque l'on veut utiliser nos propres paquets avec notre protocole, nous devons ajouter dans cette pile le traitement de notre protocole. &lt;br /&gt;
&lt;br /&gt;
Tout d'abord, dans le fichier &amp;quot;EthernerProtocols.h&amp;quot;, nous avons créer notre protocole. Le notre sera &amp;quot;0x0903&amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define ETHERTYPE_PICO                   0x0903&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, il faut créer une structure représentant notre trame dans un fichier permettant son traitement. Ici, e fichier s'appelle &amp;quot;PICO.h&amp;quot;. Nous avons alors choisi d'utiliser cette structure de trame : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/** Type define for a PICO header. */&lt;br /&gt;
    typedef struct&lt;br /&gt;
    {&lt;br /&gt;
        MAC_Address_t   Destination_MAC; /**&amp;lt; MAC address of the packet recipient */&lt;br /&gt;
        MAC_Address_t   Source_MAC; /**&amp;lt; MAC address of the packet source */&lt;br /&gt;
        IP_Address_t    Destination_IP; /**&amp;lt; IP address of the packet recipient */&lt;br /&gt;
        IP_Address_t    Source_IP; /**&amp;lt; IP address of the packet source */&lt;br /&gt;
        uint16_t        PICOType; /**&amp;lt; PICO packet sub-protocol type*/&lt;br /&gt;
    }PICO_Header_t;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans le fichier c, il faut alors réaliser le traitement de cette trame pour créer la réponse : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int16_t PICO_ProcessPICOPacket(void* InDataStart,&lt;br /&gt;
                           void* OutDataStart)&lt;br /&gt;
{&lt;br /&gt;
    PICO_Header_t* PICOHeaderIN  = (PICO_Header_t*)InDataStart;&lt;br /&gt;
	PICO_Header_t* PICOHeaderOUT = (PICO_Header_t*)OutDataStart;&lt;br /&gt;
    &lt;br /&gt;
    /* Ensure that the PICO request is a PICO request packet */&lt;br /&gt;
	if (SwapEndian_16(PICOHeaderIN-&amp;gt;PICOType) == ETHERTYPE_PICO)&lt;br /&gt;
	{&lt;br /&gt;
        if (IP_COMPARE(&amp;amp;PICOHeaderIN-&amp;gt;Destination_IP, &amp;amp;ServerIPAddress)||&lt;br /&gt;
            MAC_COMPARE(&amp;amp;PICOHeaderIN-&amp;gt;Destination_MAC, &amp;amp;ServerMACAddress))&lt;br /&gt;
		{&lt;br /&gt;
            /* Fill out the PICO response header */&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Destination_MAC = PICOHeaderIN-&amp;gt;Source_MAC;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Source_MAC = ServerMACAddress;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Destination_IP = PICOHeaderIN-&amp;gt;Source_IP;&lt;br /&gt;
			PICOHeaderOUT-&amp;gt;Source_IP = ServerIPAddress;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;PICOType = PICOHeaderIN-&amp;gt;PICOType;&lt;br /&gt;
            &lt;br /&gt;
            /* Blink the LED */&lt;br /&gt;
            PORTC ^= 0x30;&lt;br /&gt;
            &lt;br /&gt;
            /* Return the size of the response so far */&lt;br /&gt;
			return sizeof(PICO_Header_t);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
            &lt;br /&gt;
    return NO_RESPONSE;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;De cette façon, lorsqu'une trame respectant notre forme et utilisant notre protocole est envoyé sur l'interface, la LED de la carte devrait clignoter.&lt;br /&gt;
&lt;br /&gt;
Enfin, il faut aussi adapter le fichier &amp;quot;ProtocolsDecoders&amp;quot; afin que la LUFA arraive à décoder notre trame : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void DecodePICOFrameHeader(void* InDataStart)&lt;br /&gt;
{&lt;br /&gt;
	PICO_Header_t* PICOHeader = (PICO_Header_t*)InDataStart;&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;   \\\r\n    PICO\r\n&amp;quot;));&lt;br /&gt;
	&lt;br /&gt;
	if (!(IP_COMPARE(&amp;amp;PICOHeader-&amp;gt;Destination_IP, &amp;amp;ServerIPAddress)) &amp;amp;&amp;amp;&lt;br /&gt;
	    !(IP_COMPARE(&amp;amp;PICOHeader-&amp;gt;Destination_IP, &amp;amp;BroadcastIPAddress)))&lt;br /&gt;
	{&lt;br /&gt;
		printf_P(PSTR(&amp;quot;  + NOT ADDRESSED TO DEVICE\r\n&amp;quot;));&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + MAC Dest: %u:%u:%u:%u:%u:%u\r\n&amp;quot;),    PICOHeader-&amp;gt;Destination_MAC.Octets[0],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[1],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[2],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[3],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[4],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[5]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + MAC Source : %u:%u:%u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Source_MAC.Octets[0],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[1],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[2],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[3],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[4],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[5]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + IP Dest : %u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Destination_IP.Octets[0],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[1],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[2],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[3]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + IP Source : %u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Source_IP.Octets[0],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[1],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[2],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[3]);&lt;br /&gt;
&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + Protocol : %x\r\n&amp;quot;), SwapEndian_16(PICOHeader-&amp;gt;PICOType));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après cela, nous pouvons envoyer une trame sur l'interface &amp;quot;usb0&amp;quot; utilisant notre protocole. Pour cela, nous avons modifié l'outil &amp;quot;ether&amp;quot; pour observer directement l'interface &amp;quot;usb0&amp;quot; et aussi pour que le filtre accepte notre protocole. En envoyant alors la trame, la LED s'allume bien correctement : &lt;br /&gt;
[[Fichier:WhatsApp Video 2023-12-21 at 11.58.12.mp4|centré|vignette|Carte RNDIS réagissant à notre propre trame]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cependant, on remarque que la LED s'allume, c'est-à-dire que la réponse est bien créée, mais elle n'est pas envoyée. En remontant chaque fonction pouvant être la cause du non-envoi de la réponse, nous avons &amp;quot;RNDIS_Task&amp;quot; que nous n'arrivons pas à comprendre. Cependant, nous n'avons pas modifié cette fonction, cela doit venir de la trame envoyée, mais pourtant le programme rentre bien complétement dans la fonction. A ce stade nous n'arrivons toujours pas à trouver la cause du problème.&lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carr%C3%A9_qui_change_de_couleur_gr%C3%A2ce_au_contr%C3%B4leur_VGA.mp4&amp;diff=2634</id>
		<title>Fichier:Carré qui change de couleur grâce au contrôleur VGA.mp4</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carr%C3%A9_qui_change_de_couleur_gr%C3%A2ce_au_contr%C3%B4leur_VGA.mp4&amp;diff=2634"/>
		<updated>2023-12-28T13:09:47Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Carré qui change de couleur grâce au contrôleur VGA&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:VGA_signal_VS.png&amp;diff=2633</id>
		<title>Fichier:VGA signal VS.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:VGA_signal_VS.png&amp;diff=2633"/>
		<updated>2023-12-28T13:00:58Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;VGA signal VS&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:VGA_signal_HS.png&amp;diff=2632</id>
		<title>Fichier:VGA signal HS.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:VGA_signal_HS.png&amp;diff=2632"/>
		<updated>2023-12-28T13:00:23Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;VGA signal HS&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2631</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2631"/>
		<updated>2023-12-28T11:37:40Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* 3) Programmation de la carte électronique RNDIS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Matériel : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Clignotement de 2 LEDs ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs, à l'aide de deux tâches statiques, avec des périodes différentes. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et de restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 2) Ecriture de caractères sur le port série ===&lt;br /&gt;
Tout d'abord, avant de commencer la tâche, nous savions que nous devions utiliser l'UART du microcontrolleur. De plus, la tâche suivante devait utiliser aussi l'UART. Puisque 2 tâches utilisent la même ressource, il faut implémenter un système pour savoir quelle tâche utilise la ressource. Nous avons alors utiliser une sémaphore pour chaque tâche, permettant ainsi de limiter l'accès temporairement à la ressources aux autres tâches : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void semaphore_write(int action){&lt;br /&gt;
    if(action == TAKE_RESOURCE){&lt;br /&gt;
        while(1){&lt;br /&gt;
            cli();&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource Disponible */&lt;br /&gt;
            if(sem_writing &amp;gt; 0){&lt;br /&gt;
                sem_writing = 0;&lt;br /&gt;
                sei();&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource occupée */&lt;br /&gt;
            else{&lt;br /&gt;
                tasks[actuel].reason = WORKING;&lt;br /&gt;
                tasks[actuel].state = SLEEPING;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
                TIMER1_COMPA_vect();&lt;br /&gt;
            }&lt;br /&gt;
        sei();&lt;br /&gt;
        while(sem_writing == 0);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(action == DROP_RESOURCE){&lt;br /&gt;
        cli();&lt;br /&gt;
        sem_writing = 1;&lt;br /&gt;
        sei();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir implémenté cette sémaphore, il fallait que nous comprenions comment utiliser l'UART du microcontrôlleur. Pour cela, il faut initialiser correctement l'UART pour pouvoir écrire et lire en série. La fonction suivante permet d'initialiser correctement l'UART : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void init_usart(long int speed){&lt;br /&gt;
    UBRR0 = FREQUENCE/((unsigned long int)speed &amp;lt;&amp;lt; 4) -1;&lt;br /&gt;
    UCSR0B = (1 &amp;lt;&amp;lt; TXEN0 | 1 &amp;lt;&amp;lt; RXEN0);&lt;br /&gt;
    UCSR0C = (1 &amp;lt;&amp;lt; UCSZ01 | 1 &amp;lt;&amp;lt; UCSZ00);&lt;br /&gt;
    UCSR0A &amp;amp;= ~(1 &amp;lt;&amp;lt; U2X0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, une fois l'initialisation réalisée, nous pouvons réaliser la tâche utilisant les fonctions permettant d'écrire plusieurs caractères (ici &amp;quot;abc&amp;quot;) sur le port série, que l'on peut observer grâce à la commande shell ''&amp;quot;minicom -D /dev/ttyUSB0 -b 9600&amp;quot;.'' On utilise alors les fonctions suivantes pour écrire sur le port série :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void serial_send(unsigned char c){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, UDRE0);&lt;br /&gt;
    UDR0 = c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_send_str(char chaine[]){&lt;br /&gt;
    semaphore_write(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        serial_send(chaine[i]);&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_write(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut observer que la tâche fonctionne comme sur la vidéo suivante :[[Fichier:Tâche d'écriture sur le port série.mp4|vignette|Tâche d'écriture sur le port série|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 3) Lecture sur le port série ===&lt;br /&gt;
De la même façon que la tâche précédente, pour cette tâche nous devons lire les pressions de touches du clavier et les afficher sur le minicom. L'initialisation est déjà efféctuée et la sémaphore et la même que dans la partie précédente, nous ne la traiterons donc pas. On utilise alors les fonctions suivantes pour lire les pressions des touches sur le clavier, et la tâche les fait afficher ensuite : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
unsigned char serial_read(void){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, RXC0);&lt;br /&gt;
    return UDR0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_read_str(char chaine[]){&lt;br /&gt;
    semaphore_read(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        chaine[i] = serial_read();&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_read(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut alors observer les résultats grâce à la vidéo suivante : &lt;br /&gt;
[[Fichier:Tâche de lecture sur le port série.mp4|centré|vignette|Tâche de lecture sur le port série]]&lt;br /&gt;
&lt;br /&gt;
=== 4) Matrice de LEDs ===&lt;br /&gt;
Dans cette partie, nous souhaitons gérer l'affichage d'une matrice de LEDs 8x8 grâce au SPI. Il faut alors réussir à initialiser le SPI correctement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, nous avons rédiger un programme utilisé par notre tâche afin d'afficher différents caractères sur la matrice en allumant les LEDs voulues bit par bit :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void loop_matrix(char letter[8]){&lt;br /&gt;
    int temp;&lt;br /&gt;
    PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    for(short int i = 0; i &amp;lt; 8; i++){&lt;br /&gt;
            &lt;br /&gt;
        for(short int j = 0; j &amp;lt; 8; j++)&lt;br /&gt;
        {&lt;br /&gt;
            temp = letter[i] &amp;amp; (1 &amp;lt;&amp;lt; j); &lt;br /&gt;
            diplayLED(temp); //Envoir de chaque bit sur le SPI&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après vérification du bon fonctionnement de notre programme, nous avons ajouté la fonction principale dans notre fichier de gestion des tâches. Nous pouvons alors voir le changement des LEDs allumées lorsque l'on appuie sur un autre caractère grâce à la vidéo suivante :&lt;br /&gt;
[[Fichier:Matrice2.mov|centré|vignette|Affichage des caractères sur la matrice]]&lt;br /&gt;
&lt;br /&gt;
=== 5) Afficheur 7 segments ===&lt;br /&gt;
Pour le 7 segments, l'initialisation est différente. En effet, le 7 segments ne fonctionne qu'à une fréquence maximale de 250kHz, il faut alors modifier l'initialisation du SPI de la tâche pour le faire fonctionner en changeant le paramètre SPCR :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit_segments(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0) | (1 &amp;lt;&amp;lt; SPR1);    //SPR1 &amp;amp; SPR0 à 1 pour une fréquence en dessous de 250kHz (fréquence de l'afficheur 7 segments)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;En envoyant alors la lettre appuyée sur le clavier, le 7segments convertit (si c'est posible) la lettre en segments à allumer comme nous pouvons le voir sur la vidéo suivante :[[Fichier:7segments.mp4|centré|vignette|Affichage des caractères sur le 7 segments]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte était pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecté des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir réalisé le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux que l'on souhaite envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|245x245px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors routé notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :''&lt;br /&gt;
[[Fichier:Carte reconnue après un &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue après un &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue après un &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons entamé la programmation pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utilisé une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassée. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créé mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. &lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par le suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping de l'adresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut maintenant recevoir les paquets envoyés et vérifiés leur bonne réception sur le terminal. Nous avons alors utiliser l'outil &amp;quot;ether&amp;quot; afin d'observer les paquets reçues sur l'interface &amp;quot;usb0&amp;quot; créée. Pour rendre compte des paquets envoyés/reçus, nous allumons une LED à chaque ping :  &lt;br /&gt;
[[Fichier:Reception .mp4|centré|vignette|Réception de paquets IP ]]A ce moment-là, la carte allume bien les LEDs lors de la récéption des mêmes paquets que ceux implémentés dans la pile TCP/IP. Puisque l'on veut utiliser nos propres paquets avec notre protocole, nous devons ajouter dans cette pile le traitement de notre protocole. &lt;br /&gt;
&lt;br /&gt;
Tout d'abord, dans le fichier &amp;quot;EthernerProtocols.h&amp;quot;, nous avons créer notre protocole. Le notre sera &amp;quot;0x0903&amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define ETHERTYPE_PICO                   0x0903&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, il faut créer une structure représentant notre trame dans un fichier permettant son traitement. Ici, e fichier s'appelle &amp;quot;PICO.h&amp;quot;. Nous avons alors choisi d'utiliser cette structure de trame : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/** Type define for a PICO header. */&lt;br /&gt;
    typedef struct&lt;br /&gt;
    {&lt;br /&gt;
        MAC_Address_t   Destination_MAC; /**&amp;lt; MAC address of the packet recipient */&lt;br /&gt;
        MAC_Address_t   Source_MAC; /**&amp;lt; MAC address of the packet source */&lt;br /&gt;
        IP_Address_t    Destination_IP; /**&amp;lt; IP address of the packet recipient */&lt;br /&gt;
        IP_Address_t    Source_IP; /**&amp;lt; IP address of the packet source */&lt;br /&gt;
        uint16_t        PICOType; /**&amp;lt; PICO packet sub-protocol type*/&lt;br /&gt;
    }PICO_Header_t;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Dans le fichier c, il faut alors réaliser le traitement de cette trame pour créer la réponse : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
int16_t PICO_ProcessPICOPacket(void* InDataStart,&lt;br /&gt;
                           void* OutDataStart)&lt;br /&gt;
{&lt;br /&gt;
    PICO_Header_t* PICOHeaderIN  = (PICO_Header_t*)InDataStart;&lt;br /&gt;
	PICO_Header_t* PICOHeaderOUT = (PICO_Header_t*)OutDataStart;&lt;br /&gt;
    &lt;br /&gt;
    /* Ensure that the PICO request is a PICO request packet */&lt;br /&gt;
	if (SwapEndian_16(PICOHeaderIN-&amp;gt;PICOType) == ETHERTYPE_PICO)&lt;br /&gt;
	{&lt;br /&gt;
        if (IP_COMPARE(&amp;amp;PICOHeaderIN-&amp;gt;Destination_IP, &amp;amp;ServerIPAddress)||&lt;br /&gt;
            MAC_COMPARE(&amp;amp;PICOHeaderIN-&amp;gt;Destination_MAC, &amp;amp;ServerMACAddress))&lt;br /&gt;
		{&lt;br /&gt;
            /* Fill out the PICO response header */&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Destination_MAC = PICOHeaderIN-&amp;gt;Source_MAC;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Source_MAC = ServerMACAddress;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;Destination_IP = PICOHeaderIN-&amp;gt;Source_IP;&lt;br /&gt;
			PICOHeaderOUT-&amp;gt;Source_IP = ServerIPAddress;&lt;br /&gt;
            PICOHeaderOUT-&amp;gt;PICOType = PICOHeaderIN-&amp;gt;PICOType;&lt;br /&gt;
            &lt;br /&gt;
            /* Blink the LED */&lt;br /&gt;
            PORTC ^= 0x30;&lt;br /&gt;
            &lt;br /&gt;
            /* Return the size of the response so far */&lt;br /&gt;
			return sizeof(PICO_Header_t);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
            &lt;br /&gt;
    return NO_RESPONSE;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;De cette façon, lorsqu'une trame respectant notre forme et utilisant notre protocole est envoyé sur l'interface, la LED de la carte devrait clignoter.&lt;br /&gt;
&lt;br /&gt;
Enfin, il faut aussi adapter le fichier &amp;quot;ProtocolsDecoders&amp;quot; afin que la LUFA arraive à décoder notre trame : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void DecodePICOFrameHeader(void* InDataStart)&lt;br /&gt;
{&lt;br /&gt;
	PICO_Header_t* PICOHeader = (PICO_Header_t*)InDataStart;&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;   \\\r\n    PICO\r\n&amp;quot;));&lt;br /&gt;
	&lt;br /&gt;
	if (!(IP_COMPARE(&amp;amp;PICOHeader-&amp;gt;Destination_IP, &amp;amp;ServerIPAddress)) &amp;amp;&amp;amp;&lt;br /&gt;
	    !(IP_COMPARE(&amp;amp;PICOHeader-&amp;gt;Destination_IP, &amp;amp;BroadcastIPAddress)))&lt;br /&gt;
	{&lt;br /&gt;
		printf_P(PSTR(&amp;quot;  + NOT ADDRESSED TO DEVICE\r\n&amp;quot;));&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + MAC Dest: %u:%u:%u:%u:%u:%u\r\n&amp;quot;),    PICOHeader-&amp;gt;Destination_MAC.Octets[0],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[1],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[2],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[3],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[4],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Destination_MAC.Octets[5]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + MAC Source : %u:%u:%u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Source_MAC.Octets[0],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[1],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[2],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[3],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[4],&lt;br /&gt;
	                                                                     PICOHeader-&amp;gt;Source_MAC.Octets[5]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + IP Dest : %u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Destination_IP.Octets[0],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[1],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[2],&lt;br /&gt;
													PICOHeader-&amp;gt;Destination_IP.Octets[3]);&lt;br /&gt;
	&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + IP Source : %u:%u:%u:%u\r\n&amp;quot;), PICOHeader-&amp;gt;Source_IP.Octets[0],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[1],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[2],&lt;br /&gt;
													  PICOHeader-&amp;gt;Source_IP.Octets[3]);&lt;br /&gt;
&lt;br /&gt;
	printf_P(PSTR(&amp;quot;  + Protocol : %x\r\n&amp;quot;), SwapEndian_16(PICOHeader-&amp;gt;PICOType));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après cela, nous pouvons envoyer une trame sur l'interface &amp;quot;usb0&amp;quot; utilisant notre protocole. Pour cela, nous avons modifié l'outil &amp;quot;ether&amp;quot; pour observer directement l'interface &amp;quot;usb0&amp;quot; et aussi pour que le filtre accepte notre protocole. En envoyant alors la trame, la LED s'allume bien correctement : &lt;br /&gt;
[[Fichier:WhatsApp Video 2023-12-21 at 11.58.12.mp4|centré|vignette|Carte RNDIS réagissant à notre propre trame]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Cependant, on remarque que la LED s'allume, c'est-à-dire que la réponse est bien créée, mais elle n'est pas envoyée. En rem&lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:WhatsApp_Video_2023-12-21_at_11.58.12.mp4&amp;diff=2630</id>
		<title>Fichier:WhatsApp Video 2023-12-21 at 11.58.12.mp4</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:WhatsApp_Video_2023-12-21_at_11.58.12.mp4&amp;diff=2630"/>
		<updated>2023-12-28T11:29:33Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Carte RNDIS réagissant à notre propre trame&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2561</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2561"/>
		<updated>2023-12-21T08:37:54Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* 3) Programmation de la carte électronique RNDIS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Matériel : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Clignotement de 2 LEDs ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs, à l'aide de deux tâches statiques, avec des périodes différentes. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et de restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 2) Ecriture de caractères sur le port série ===&lt;br /&gt;
Tout d'abord, avant de commencer la tâche, nous savions que nous devions utiliser l'UART du microcontrolleur. De plus, la tâche suivante devait utiliser aussi l'UART. Puisque 2 tâches utilisent la même ressource, il faut implémenter un système pour savoir quelle tâche utilise la ressource. Nous avons alors utiliser une sémaphore pour chaque tâche, permettant ainsi de limiter l'accès temporairement à la ressources aux autres tâches : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void semaphore_write(int action){&lt;br /&gt;
    if(action == TAKE_RESOURCE){&lt;br /&gt;
        while(1){&lt;br /&gt;
            cli();&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource Disponible */&lt;br /&gt;
            if(sem_writing &amp;gt; 0){&lt;br /&gt;
                sem_writing = 0;&lt;br /&gt;
                sei();&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource occupée */&lt;br /&gt;
            else{&lt;br /&gt;
                tasks[actuel].reason = WORKING;&lt;br /&gt;
                tasks[actuel].state = SLEEPING;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
                TIMER1_COMPA_vect();&lt;br /&gt;
            }&lt;br /&gt;
        sei();&lt;br /&gt;
        while(sem_writing == 0);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(action == DROP_RESOURCE){&lt;br /&gt;
        cli();&lt;br /&gt;
        sem_writing = 1;&lt;br /&gt;
        sei();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir implémenté cette sémaphore, il fallait que nous comprenions comment utiliser l'UART du microcontrôlleur. Pour cela, il faut initialiser correctement l'UART pour pouvoir écrire et lire en série. La fonction suivante permet d'initialiser correctement l'UART : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void init_usart(long int speed){&lt;br /&gt;
    UBRR0 = FREQUENCE/((unsigned long int)speed &amp;lt;&amp;lt; 4) -1;&lt;br /&gt;
    UCSR0B = (1 &amp;lt;&amp;lt; TXEN0 | 1 &amp;lt;&amp;lt; RXEN0);&lt;br /&gt;
    UCSR0C = (1 &amp;lt;&amp;lt; UCSZ01 | 1 &amp;lt;&amp;lt; UCSZ00);&lt;br /&gt;
    UCSR0A &amp;amp;= ~(1 &amp;lt;&amp;lt; U2X0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, une fois l'initialisation réalisée, nous pouvons réaliser la tâche utilisant les fonctions permettant d'écrire plusieurs caractères (ici &amp;quot;abc&amp;quot;) sur le port série, que l'on peut observer grâce à la commande shell ''&amp;quot;minicom -D /dev/ttyUSB0 -b 9600&amp;quot;.'' On utilise alors les fonctions suivantes pour écrire sur le port série :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void serial_send(unsigned char c){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, UDRE0);&lt;br /&gt;
    UDR0 = c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_send_str(char chaine[]){&lt;br /&gt;
    semaphore_write(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        serial_send(chaine[i]);&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_write(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut observer que la tâche fonctionne comme sur la vidéo suivante :[[Fichier:Tâche d'écriture sur le port série.mp4|vignette|Tâche d'écriture sur le port série|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 3) Lecture sur le port série ===&lt;br /&gt;
De la même façon que la tâche précédente, pour cette tâche nous devons lire les pressions de touches du clavier et les afficher sur le minicom. L'initialisation est déjà efféctuée et la sémaphore et la même que dans la partie précédente, nous ne la traiterons donc pas. On utilise alors les fonctions suivantes pour lire les pressions des touches sur le clavier, et la tâche les fait afficher ensuite : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
unsigned char serial_read(void){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, RXC0);&lt;br /&gt;
    return UDR0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_read_str(char chaine[]){&lt;br /&gt;
    semaphore_read(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        chaine[i] = serial_read();&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_read(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut alors observer les résultats grâce à la vidéo suivante : &lt;br /&gt;
[[Fichier:Tâche de lecture sur le port série.mp4|centré|vignette|Tâche de lecture sur le port série]]&lt;br /&gt;
&lt;br /&gt;
=== 4) Matrice de LEDs ===&lt;br /&gt;
Dans cette partie, nous souhaitons gérer l'affichage d'une matrice de LEDs 8x8 grâce au SPI. Il faut alors réussir à initialiser le SPI correctement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, nous avons rédiger un programme utilisé par notre tâche afin d'afficher différents caractères sur la matrice en allumant les LEDs voulues bit par bit :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void loop_matrix(char letter[8]){&lt;br /&gt;
    int temp;&lt;br /&gt;
    PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    for(short int i = 0; i &amp;lt; 8; i++){&lt;br /&gt;
            &lt;br /&gt;
        for(short int j = 0; j &amp;lt; 8; j++)&lt;br /&gt;
        {&lt;br /&gt;
            temp = letter[i] &amp;amp; (1 &amp;lt;&amp;lt; j); &lt;br /&gt;
            diplayLED(temp); //Envoir de chaque bit sur le SPI&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après vérification du bon fonctionnement de notre programme, nous avons ajouté la fonction principale dans notre fichier de gestion des tâches. Nous pouvons alors voir le changement des LEDs allumées lorsque l'on appuie sur un autre caractère grâce à la vidéo suivante :&lt;br /&gt;
[[Fichier:Matrice2.mov|centré|vignette|Affichage des caractères sur la matrice]]&lt;br /&gt;
&lt;br /&gt;
=== 5) Afficheur 7 segments ===&lt;br /&gt;
Pour le 7 segments, l'initialisation est différente. En effet, le 7 segments ne fonctionne qu'à une fréquence maximale de 250kHz, il faut alors modifier l'initialisation du SPI de la tâche pour le faire fonctionner en changeant le paramètre SPCR :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit_segments(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0) | (1 &amp;lt;&amp;lt; SPR1);    //SPR1 &amp;amp; SPR0 à 1 pour une fréquence en dessous de 250kHz (fréquence de l'afficheur 7 segments)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;En envoyant alors la lettre appuyée sur le clavier, le 7segments convertit (si c'est posible) la lettre en segments à allumer comme nous pouvons le voir sur la vidéo suivante :[[Fichier:7segments.mp4|centré|vignette|Affichage des caractères sur le 7 segments]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte était pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecté des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir réalisé le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux que l'on souhaite envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|245x245px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors routé notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :''&lt;br /&gt;
[[Fichier:Carte reconnue après un &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue après un &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue après un &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons entamé la programmation pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utilisé une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassée. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créé mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. &lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par le suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping de l'adresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut maintenant recevoir les paquets envoyés et vérifiés leur bonne réception sur le terminal. Pour rendre compte des paquets envoyés/reçus, nous allumons une LED à chaque ping :  &lt;br /&gt;
[[Fichier:Reception .mp4|centré|vignette]] &lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carte_reconnue_apr%C3%A8s_un_%22lsusb%22.png&amp;diff=2560</id>
		<title>Fichier:Carte reconnue après un &quot;lsusb&quot;.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carte_reconnue_apr%C3%A8s_un_%22lsusb%22.png&amp;diff=2560"/>
		<updated>2023-12-21T08:37:15Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Carte reconnue après un &amp;quot;lsusb&amp;quot;&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2530</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2530"/>
		<updated>2023-12-20T12:08:36Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* 2) Lecture de caractères sur le port série */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Matériel : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Clignotement de 2 LEDs ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs, à l'aide de deux tâches statiques, avec des périodes différentes. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et de restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 2) Ecriture de caractères sur le port série ===&lt;br /&gt;
Tout d'abord, avant de commencer la tâche, nous savions que nous devions utiliser l'UART du microcontrolleur. De plus, la tâche d'après devait utiliser aussi l'UART. Puisque 2 tâches utilisent la même ressource, il faut implémenter un système pour savoir quelle tâche utilise la ressource. Nous avons alors utiliser une sémaphore pour chaque tâche, permettant ainsi de limiter l'accès temporairement à la ressources aux autres tâches : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void semaphore_write(int action){&lt;br /&gt;
    if(action == TAKE_RESOURCE){&lt;br /&gt;
        while(1){&lt;br /&gt;
            cli();&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource Disponible */&lt;br /&gt;
            if(sem_writing &amp;gt; 0){&lt;br /&gt;
                sem_writing = 0;&lt;br /&gt;
                sei();&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource occupée */&lt;br /&gt;
            else{&lt;br /&gt;
                tasks[actuel].reason = WORKING;&lt;br /&gt;
                tasks[actuel].state = SLEEPING;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
                TIMER1_COMPA_vect();&lt;br /&gt;
            }&lt;br /&gt;
        sei();&lt;br /&gt;
        while(sem_writing == 0);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(action == DROP_RESOURCE){&lt;br /&gt;
        cli();&lt;br /&gt;
        sem_writing = 1;&lt;br /&gt;
        sei();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir implémenté cette sémaphore, il nous fallait comprendre comment utiliser l'UART du microcontrôlleur. Pour cela, il faut initialiser coorectement l'UART pour pouvoir écrire et lire en série. La fonction suivante permet d'initialiser correctement l'UART : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void init_usart(long int speed){&lt;br /&gt;
    UBRR0 = FREQUENCE/((unsigned long int)speed &amp;lt;&amp;lt; 4) -1;&lt;br /&gt;
    UCSR0B = (1 &amp;lt;&amp;lt; TXEN0 | 1 &amp;lt;&amp;lt; RXEN0);&lt;br /&gt;
    UCSR0C = (1 &amp;lt;&amp;lt; UCSZ01 | 1 &amp;lt;&amp;lt; UCSZ00);&lt;br /&gt;
    UCSR0A &amp;amp;= ~(1 &amp;lt;&amp;lt; U2X0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, après l'initialisation, nous pouvons réaliser la tâche utilisant les fonctions permettant d'écrire plusieurs caractères (ici &amp;quot;abc&amp;quot;) sur le port série, que l'on peut observer grâce à la commande shell ''&amp;quot;minicom -D /dev/ttyUSB0 -b 9600&amp;quot;.'' On utilise alors les fonctions suivantes pour écrire sur le port série :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void serial_send(unsigned char c){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, UDRE0);&lt;br /&gt;
    UDR0 = c;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_send_str(char chaine[]){&lt;br /&gt;
    semaphore_write(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        serial_send(chaine[i]);&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_write(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut observer que la tâche fonctionne comme sur la vidéo suivante :[[Fichier:Tâche d'écriture sur le port série.mp4|vignette|On Tâche d'écriture sur le port série|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 3) Lecture sur le port série ===&lt;br /&gt;
De la même façon que la tâche précédente, pour cette tâche nous devons lire les pressions de touches du clavier et les afficher sur le minicom. L'initialisation est déjà efféctuée et la sémaphore et la même que dans la partie précédente, nous ne la traiterons donc pas. On utilise alors les fonctions suivantes pour lire les pressions des touches du clavier, et la tâche les fait afficher ensuite : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
unsigned char serial_read(void){&lt;br /&gt;
    loop_until_bit_is_set(UCSR0A, RXC0);&lt;br /&gt;
    return UDR0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void serial_read_str(char chaine[]){&lt;br /&gt;
    semaphore_read(TAKE_RESOURCE);&lt;br /&gt;
    for(int i = 0; i &amp;lt; SIZE_CHAINE; i++){&lt;br /&gt;
        chaine[i] = serial_read();&lt;br /&gt;
    }&lt;br /&gt;
    semaphore_read(DROP_RESOURCE);   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;On peut alors observer les résultat grâce à la vidéo suivante : &lt;br /&gt;
[[Fichier:Tâche de lecture sur le port série.mp4|centré|vignette|Tâche de lecture sur le port série]]&lt;br /&gt;
&lt;br /&gt;
=== 4) Matrice de LEDs ===&lt;br /&gt;
Dans cette partie, nous souhaitons gérer l'affichage d'une matrice de LEDs 8x8 grâce au SPI. Il faut alors réussir à initialiser le SPI correctement :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Ensuite, nous avons rédiger un programme utilisé par notre tâche afin d'afficher différents caractères sur la matrice en allumant les LEDs voulues bit par bit :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void loop_matrix(char letter[8]){&lt;br /&gt;
    int temp;&lt;br /&gt;
    PORTC &amp;amp;= ~(1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    for(short int i = 0; i &amp;lt; 8; i++){&lt;br /&gt;
            &lt;br /&gt;
        for(short int j = 0; j &amp;lt; 8; j++)&lt;br /&gt;
        {&lt;br /&gt;
            temp = letter[i] &amp;amp; (1 &amp;lt;&amp;lt; j); &lt;br /&gt;
            diplayLED(temp); //Envoir de chaque bit sur le SPI&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après vérification du bon fonctionnement de notre programme, nous avons ajouté la fonction principale dans notre fichier de gestion des tâches. Nous pouvons alors voir le changment des LEDs allumées lorsque l'on appuie sur un autre caractère grâce à la vidéo suivante :&lt;br /&gt;
[[Fichier:Matrice2.mov|centré|vignette|Affichage de caractères sur la matrice]]&lt;br /&gt;
&lt;br /&gt;
=== 5) Afficheur 7 segments ===&lt;br /&gt;
Pour le 7 segments, l'initialisation est différente. En effet, le 7 segments ne fonctionne qu'à une fréquence maximale de 250kHz, il faut alors modifier l'initialisation du SPI de la tâche pour le faire fonctionner en changeant le paramètre SPCR :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void SPI_MasterInit_segments(void){&lt;br /&gt;
    DDRB |= (1 &amp;lt;&amp;lt; MOSI) | (1 &amp;lt;&amp;lt; SCK) | (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    DDRC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    PORTB |= (1 &amp;lt;&amp;lt; SS);&lt;br /&gt;
    PORTC |= (1 &amp;lt;&amp;lt; CS);&lt;br /&gt;
    SPCR = (1 &amp;lt;&amp;lt; SPE) | (1 &amp;lt;&amp;lt; MSTR) | (1 &amp;lt;&amp;lt; SPR0) | (1 &amp;lt;&amp;lt; SPR1);    //SPR1 &amp;amp; SPR0 à 1 pour une fréquence en dessous de 250kHz (fréquence de l'afficheur 7 segments)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;En envoyant alors la lettre appuyée sur le clavier, le 7segments convertit (si c'est posible) la lettre en segments à allumer comme nous pouvons le voir sur la vidéo suivante :[[Fichier:7segments.mp4|centré|vignette|Affichage des caractères sur le 7 segments]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte été pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecter des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir fais le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux qu' l'on va envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|245x245px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors router notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :'' &lt;br /&gt;
[[Fichier:Carte reconnue par le &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue par le &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue par le &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons commencer à programmer le programme pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utiliser une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassée. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créer mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. Enfn nous avond dû changer les VendorID et les productID dans certains fichiers :&lt;br /&gt;
&lt;br /&gt;
* VendorID = 0x03EB&lt;br /&gt;
* ProductID = 0x2FEF&lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par le suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping l'addresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut maintenant recevoir les paquets envoyés et leur bonne réception sur le terminal. Pour rendre compte des paquets envoyés/reçus, nous allumons une LED à chaque ping :  &lt;br /&gt;
[[Fichier:Reception .mp4|centré|vignette]] &lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:T%C3%A2che_de_lecture_sur_le_port_s%C3%A9rie.mp4&amp;diff=2529</id>
		<title>Fichier:Tâche de lecture sur le port série.mp4</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:T%C3%A2che_de_lecture_sur_le_port_s%C3%A9rie.mp4&amp;diff=2529"/>
		<updated>2023-12-20T11:58:45Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tâche de lecture sur le port série&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2528</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2528"/>
		<updated>2023-12-20T11:47:07Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* 1) Clignotement de 2 LEDs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Matériel : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Clignotement de 2 LEDs ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs, à l'aide de deux tâches statiques, avec des périodes différentes. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et de restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 2) Lecture de caractères sur le port série ===&lt;br /&gt;
Tout d'abord, avant de commencer la tâche, nous savions que nous devions utiliser l'UART du microcontrolleur. De plus, la tâche d'après devait utiliser aussi l'UART. Puisque 2 tâches utilisent la même ressource, il faut implémenter un système pour savoir quelle tâche utilise la ressource. Nous avons alors utiliser une sémaphore pour chaque tâche, permettant ainsi de limiter l'accès temporairement à la ressources aux autres tâches : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void semaphore_write(int action){&lt;br /&gt;
    if(action == TAKE_RESOURCE){&lt;br /&gt;
        while(1){&lt;br /&gt;
            cli();&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource Disponible */&lt;br /&gt;
            if(sem_writing &amp;gt; 0){&lt;br /&gt;
                sem_writing = 0;&lt;br /&gt;
                sei();&lt;br /&gt;
                break;&lt;br /&gt;
            }&lt;br /&gt;
            &lt;br /&gt;
            /** Ressource occupée */&lt;br /&gt;
            else{&lt;br /&gt;
                tasks[actuel].reason = WORKING;&lt;br /&gt;
                tasks[actuel].state = SLEEPING;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
                TIMER1_COMPA_vect();&lt;br /&gt;
            }&lt;br /&gt;
        sei();&lt;br /&gt;
        while(sem_writing == 0);&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    if(action == DROP_RESOURCE){&lt;br /&gt;
        cli();&lt;br /&gt;
        sem_writing = 1;&lt;br /&gt;
        sei();&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir implémenté cette sémaphore, il nous fallait comprendre comment utiliser l'UART du microcontrôlleur. Pour cela, il faut initialiser coorectement l'UART pour pouvoir écrire et lire en série. La fonction suivante permet d'initialiser correctement l'UART : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void init_usart(long int speed){&lt;br /&gt;
    UBRR0 = FREQUENCE/((unsigned long int)speed &amp;lt;&amp;lt; 4) -1;&lt;br /&gt;
    UCSR0B = (1 &amp;lt;&amp;lt; TXEN0 | 1 &amp;lt;&amp;lt; RXEN0);&lt;br /&gt;
    UCSR0C = (1 &amp;lt;&amp;lt; UCSZ01 | 1 &amp;lt;&amp;lt; UCSZ00);&lt;br /&gt;
    UCSR0A &amp;amp;= ~(1 &amp;lt;&amp;lt; U2X0);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, après l'initialisation, nous pouvons réaliser la tâche utilisant les fonctions permettant d'écrire plusieurs caractères (ici &amp;quot;abc&amp;quot;) sur le port série, que l'on peut observer grâce à la commande shell ''&amp;quot;minicom -D /dev/ttyUSB0 -b 9600&amp;quot;.'' On voit alors les caractères comme sur la vidéo :&lt;br /&gt;
[[Fichier:Tâche d'écriture sur le port série.mp4|vignette|Tâche d'écriture sur le port série]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 3) Ecriture sur le port série ===&lt;br /&gt;
&lt;br /&gt;
=== 4) Matrice de LEDs ===&lt;br /&gt;
Dans cette partie, nous souhaitons gérer l'affichage d'une matrice de LEDs 8x8.&lt;br /&gt;
&lt;br /&gt;
Dans un premier temps, nous avons rédiger un programme à part de notre ordonnanceur afin d'afficher différents caractères sur la matrice.&lt;br /&gt;
&lt;br /&gt;
Après vérification du bon fonctionnement de notre programme, nous avons ajouté la fonction principale dans notre fichier de gestion des tâches.  Enfin, dans cette fonction, nous y avons ajouté le fait de pouvoir lire au clavier n'importe quel caractère sur la matrice.&lt;br /&gt;
[[Fichier:Matrice2.mov|centré|vignette|Affichage de caractères sur la matrice]]&lt;br /&gt;
&lt;br /&gt;
=== 5) Afficheur 7 segments ===&lt;br /&gt;
Pour le 7 segments nous avons fait de la même manière que pour la matrice.&lt;br /&gt;
&lt;br /&gt;
Si nous appuyons sur un caractère du clavier, il s'affiche sur les quatre 7 segments de l'afficheur.&lt;br /&gt;
[[Fichier:7segments.mp4|centré|vignette|Affichage des caractères sur le 7 segments]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte été pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecter des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir fais le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux qu' l'on va envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|245x245px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors router notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :'' &lt;br /&gt;
[[Fichier:Carte reconnue par le &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue par le &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue par le &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons commencer à programmer le programme pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utiliser une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassée. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créer mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. Enfn nous avond dû changer les VendorID et les productID dans certains fichiers :&lt;br /&gt;
&lt;br /&gt;
* VendorID = 0x03EB&lt;br /&gt;
* ProductID = 0x2FEF&lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par le suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping l'addresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut maintenant recevoir les paquets envoyés et leur bonne réception sur le terminal. Pour rendre compte des paquets envoyés/reçus, nous allumons une LED à chaque ping :  &lt;br /&gt;
[[Fichier:Reception .mp4|centré|vignette]] &lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:T%C3%A2che_d%27%C3%A9criture_sur_le_port_s%C3%A9rie.mp4&amp;diff=2527</id>
		<title>Fichier:Tâche d'écriture sur le port série.mp4</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:T%C3%A2che_d%27%C3%A9criture_sur_le_port_s%C3%A9rie.mp4&amp;diff=2527"/>
		<updated>2023-12-20T11:46:32Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Tâche d'écriture sur le port série&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2492</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2492"/>
		<updated>2023-12-14T10:17:19Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* 3) Ecriture sur le port série */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Matériel : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Clignotement de 2 LEDs ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs, à l'aide de deux tâches statiques, avec des périodes différentes. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et de restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 2) Lecture de caractères sur le port série ===&lt;br /&gt;
&lt;br /&gt;
=== 3) Ecriture sur le port série ===&lt;br /&gt;
&lt;br /&gt;
=== 4) Matrice de LEDs ===&lt;br /&gt;
Dans cette partie, nous souhaitons gérer l'affichage d'une matrice de LEDs 8x8.&lt;br /&gt;
&lt;br /&gt;
Dans un premier temps, nous avons rédiger un programme à part de notre ordonnanceur afin d'afficher différents caractères sur la matrice.&lt;br /&gt;
&lt;br /&gt;
Après vérification du bon fonctionnement de notre programme, nous avons ajouté la fonction principale dans notre fichier de gestion des tâches.  Enfin, dans cette fonction, nous y avons ajouté le fait de pouvoir lire au clavier n'importe quel caractère sur la matrice.&lt;br /&gt;
[[Fichier:Matrice2.mov|centré|vignette|Affichage de caractères sur la matrice]]&lt;br /&gt;
&lt;br /&gt;
=== 5) Afficheur 7 segments ===&lt;br /&gt;
Pour le 7 segments nous avons fait de la même manière que pour la matrice.&lt;br /&gt;
&lt;br /&gt;
Si nous appuyons sur un caractère du clavier, il s'affiche sur les quatre 7 segments de l'afficheur.&lt;br /&gt;
[[Fichier:7segments.mp4|centré|vignette|Affichage des caractères sur le 7 segments]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte été pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecter des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir fais le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux qu' l'on va envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|245x245px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors router notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :'' &lt;br /&gt;
[[Fichier:Carte reconnue par le &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue par le &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue par le &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons commencer à programmer le programme pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utiliser une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassée. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créer mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. Enfn nous avond dû changer les VendorID et les productID dans certains fichiers :&lt;br /&gt;
&lt;br /&gt;
* VendorID = 0x03EB&lt;br /&gt;
* ProductID = 0x2FEF&lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par le suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping l'addresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut maintenant recevoir les paquets envoyés et leur bonne réception sur le terminal. Pour rendre compte des paquets envoyés/reçus, nous allumons une LED à chaque ping :  &lt;br /&gt;
[[Fichier:Reception .mp4|centré|vignette]] &lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2491</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2491"/>
		<updated>2023-12-14T10:14:26Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* 5) Afficheur 7 segments */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Matériel : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Clignotement de 2 LEDs ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs, à l'aide de deux tâches statiques, avec des périodes différentes. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et de restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 2) Lecture de caractères par le port série ===&lt;br /&gt;
&lt;br /&gt;
=== 3) Ecriture sur le port série ===&lt;br /&gt;
&lt;br /&gt;
=== 4) Matrice de LEDs ===&lt;br /&gt;
Dans cette partie, nous souhaitons gérer l'affichage d'une matrice de LEDs 8x8.&lt;br /&gt;
&lt;br /&gt;
Dans un premier temps, nous avons rédiger un programme à part de notre ordonnanceur afin d'afficher différents caractères sur la matrice.&lt;br /&gt;
&lt;br /&gt;
Après vérification du bon fonctionnement de notre programme, nous avons ajouté la fonction principale dans notre fichier de gestion des tâches.  Enfin, dans cette fonction, nous y avons ajouté le fait de pouvoir lire au clavier n'importe quel caractère sur la matrice.&lt;br /&gt;
[[Fichier:Matrice2.mov|centré|vignette|Affichage de caractères sur la matrice]]&lt;br /&gt;
&lt;br /&gt;
=== 5) Afficheur 7 segments ===&lt;br /&gt;
Pour le 7 segments nous avons fait de la même manière que pour la matrice.&lt;br /&gt;
&lt;br /&gt;
Si nous appuyons sur un caractère du clavier, il s'affiche sur les quatre 7 segments de l'afficheur.&lt;br /&gt;
[[Fichier:7segments.mp4|centré|vignette|Affichage des caractères sur le 7 segments]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte été pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecter des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir fais le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux qu' l'on va envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|245x245px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors router notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :'' &lt;br /&gt;
[[Fichier:Carte reconnue par le &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue par le &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue par le &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons commencer à programmer le programme pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utiliser une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassée. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créer mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. Enfn nous avond dû changer les VendorID et les productID dans certains fichiers :&lt;br /&gt;
&lt;br /&gt;
* VendorID = 0x03EB&lt;br /&gt;
* ProductID = 0x2FEF&lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par le suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping l'addresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut maintenant recevoir les paquets envoyés et leur bonne réception sur le terminal. Pour rendre compte des paquets envoyés/reçus, nous allumons une LED à chaque ping :  &lt;br /&gt;
[[Fichier:Reception .mp4|centré|vignette]] &lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2490</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2490"/>
		<updated>2023-12-14T10:13:59Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* 4) Matrice de LEDs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Matériel : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Clignotement de 2 LEDs ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs, à l'aide de deux tâches statiques, avec des périodes différentes. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et de restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
=== 2) Lecture de caractères par le port série ===&lt;br /&gt;
&lt;br /&gt;
=== 3) Ecriture sur le port série ===&lt;br /&gt;
&lt;br /&gt;
=== 4) Matrice de LEDs ===&lt;br /&gt;
Dans cette partie, nous souhaitons gérer l'affichage d'une matrice de LEDs 8x8.&lt;br /&gt;
&lt;br /&gt;
Dans un premier temps, nous avons rédiger un programme à part de notre ordonnanceur afin d'afficher différents caractères sur la matrice.&lt;br /&gt;
&lt;br /&gt;
Après vérification du bon fonctionnement de notre programme, nous avons ajouté la fonction principale dans notre fichier de gestion des tâches.  Enfin, dans cette fonction, nous y avons ajouté le fait de pouvoir lire au clavier n'importe quel caractère sur la matrice.&lt;br /&gt;
[[Fichier:Matrice2.mov|centré|vignette|Affichage de caractères sur la matrice]]&lt;br /&gt;
&lt;br /&gt;
=== 5) Afficheur 7 segments ===&lt;br /&gt;
Pour le 7 segments nous avons fait de la même manière que pour la matrice.&lt;br /&gt;
&lt;br /&gt;
Si nous appuyons sur un caractère du clavier, il s'affiche sur les quatre 7 segments de l'afficheur.&lt;br /&gt;
[[Fichier:7segments.mp4|centré|vignette]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte été pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecter des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir fais le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux qu' l'on va envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|245x245px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors router notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :'' &lt;br /&gt;
[[Fichier:Carte reconnue par le &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue par le &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue par le &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons commencer à programmer le programme pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utiliser une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassée. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créer mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. Enfn nous avond dû changer les VendorID et les productID dans certains fichiers :&lt;br /&gt;
&lt;br /&gt;
* VendorID = 0x03EB&lt;br /&gt;
* ProductID = 0x2FEF&lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par le suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping l'addresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut maintenant recevoir les paquets envoyés et leur bonne réception sur le terminal. Pour rendre compte des paquets envoyés/reçus, nous allumons une LED à chaque ping :  &lt;br /&gt;
[[Fichier:Reception .mp4|centré|vignette]] &lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2449</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2449"/>
		<updated>2023-12-11T14:49:21Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Carte fille réseau RNDIS : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ordonnanceur/SE : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Matériel ===&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== 2) Ordonnanceur ===&lt;br /&gt;
Nous avons commencé l'ordonnanceur avec l'objectif de faire clignoter dans un premier temps 2 LEDs. &lt;br /&gt;
&lt;br /&gt;
Pour cela, nous avons utilisé un ISR permettant de gérer plusieurs tâches en même temps. Avant cela, il y a des fonctions de gestion et restitution des registres afin que l'ISR commence le programme avec tous les registres à 0. Nous avons utilisé le lien suivant pour nous aider : https://tvantroys.plil.fr/IMA4/system/Multitasking%20on%20an%20AVR.pdf.  Ensuite, nous avons implémenté un &amp;quot;scheduler&amp;quot; avec tout d'abord une première version où nous utilisions des &amp;quot;_delay_ms_&amp;quot;. Par la suite, une mise à jour de ce &amp;quot;scheduler&amp;quot; s'imposait afin de supprimer les _delay_ms_ pour que chaque tâche possède son propre délai.&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void scheduler(void){&lt;br /&gt;
    for(int i = 0; i &amp;lt; MAX_TASKS; i++){&lt;br /&gt;
        if(tasks[i].state == SLEEPING &amp;amp;&amp;amp; tasks[i].reason == DELAY){&lt;br /&gt;
            uint16_t time = 20;&lt;br /&gt;
            if(TCNT1 != 0){&lt;br /&gt;
                time = TCNT1 * 200 / OCR1A / 10;&lt;br /&gt;
                TCNT1 = 0;&lt;br /&gt;
            }&lt;br /&gt;
            tasks[i].duration = tasks[i].duration - time;&lt;br /&gt;
            if(tasks[i].duration &amp;lt;= 0) { tasks[i].state = WORKING; }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    do{&lt;br /&gt;
        actuel++;&lt;br /&gt;
        if(actuel == MAX_TASKS) { actuel = 0; }&lt;br /&gt;
    } while(tasks[actuel].state == SLEEPING);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER1_COMPA_vect,ISR_NAKED){&lt;br /&gt;
    /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
    portSAVE_CONTEXT();&lt;br /&gt;
    tasks[actuel].StackPointeur = SP;&lt;br /&gt;
    /* Appel à l'ordonnanceur */&lt;br /&gt;
    scheduler();&lt;br /&gt;
    /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
    SP = tasks[actuel].StackPointeur;&lt;br /&gt;
    portRESTORE_CONTEXT();&lt;br /&gt;
    asm volatile (&amp;quot;reti&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Au final, nous arrivons à faire clignoter 2 LEDs avec deux périodes différentes : &lt;br /&gt;
[[Fichier:Clignotement des LEDs grâce à l'ordonnanceur.mov|alt=Clignotement des LEDs grâce à l'ordonnanceur|vignette|Clignotement des LEDs grâce à l'ordonnanceur|centré]]&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte été pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecter des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir fais le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux qu' l'on va envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|239x239px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors router notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :'' &lt;br /&gt;
[[Fichier:Carte reconnue par le &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue par le &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue par le &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons commencer à programmer le programme pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utiliser une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassée. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créer mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. Enfn nous avond dû changer les VendorID et les productID dans certains fichiers :&lt;br /&gt;
&lt;br /&gt;
* VendorID = 0x03EB&lt;br /&gt;
* ProductID = 0x2FEF&lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par le suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.100/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.100 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping l'addresse 10.0.0.2 pour voir si elle répond bien :  &lt;br /&gt;
[[Fichier:Ping usb0 2.png|alt=Ping vers la carte RNDIS|centré|vignette|Ping vers la carte RNDIS]]&lt;br /&gt;
Il faut alors maintenant faire &lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Ping_usb0_2.png&amp;diff=2448</id>
		<title>Fichier:Ping usb0 2.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Ping_usb0_2.png&amp;diff=2448"/>
		<updated>2023-12-11T14:46:06Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ping vers la carte RNDIS&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2125</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2125"/>
		<updated>2023-11-20T11:03:59Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* 3) Programmation de la carte électronique RNDIS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ordonnanceur/SE : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte été pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecter des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir fais le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux qu' l'on va envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|239x239px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors router notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|&lt;br /&gt;
&lt;br /&gt;
* Carte soudée&lt;br /&gt;
&lt;br /&gt;
]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :'' &lt;br /&gt;
[[Fichier:Carte reconnue par le &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue par le &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue par le &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons commencer à programmer le programme pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
Pour la programmation de la carte électronique RNDIS, nous avons utiliser une démonstration LUFA déjà existante qui implémente une pile TCP/IP. En faisant directement un &amp;quot;make&amp;quot;, nous avons remarqué que l'espace mémoire était dépassée. En effet, notre microcontrôleur ATMega16u2 n'a que 2k de mémoire.&lt;br /&gt;
&lt;br /&gt;
Pour réduire la taille du programme, nous avons déjà réduit la taille de la trame Ethernet qui est de 1500 octets à 100 octets. Ensuite nous avons réduit la pile TCP/IP en supprimant les fichiers UDP, TCP et Webserveur qui ne nous étaient pas utiles dans le fonctionnement de notre carte. Après la commande &amp;quot;make&amp;quot;, un fichier hex est bien créer mais nous avons dû changer ce fichier Makefile en conséquence pour l'adapter à notre microcontrôleur. Enfn nous avond dû changer les VendorID et les productID dans certains fichiers :&lt;br /&gt;
&lt;br /&gt;
* VendorID = 0x03EB&lt;br /&gt;
* ProductID = 0x2FEF&lt;br /&gt;
&lt;br /&gt;
Après un upload du programme sur notre carte, nous avons réussi à obtenir une nouvelle interface réseau nommée &amp;quot;usb0&amp;quot; que l'on a pu visualiser grâce à la commande &amp;quot;ip a&amp;quot;.&lt;br /&gt;
[[Fichier:Interface usb0 créée.png|alt=Interface usb0 créée|centré|vignette|397x397px|Interface usb0 créée]]&lt;br /&gt;
Par le suite, nous avons configuré cette nouvelle interface avec la commande &amp;quot;ip address add 10.0.0.2/24 dev usb0&amp;quot; qui lui ajoute l'adresse 10.0.0.2 et un masque de classe C qui convient à nos besoins. A présent, nous pouvons faire un ping sur notre carte pour voir si elle répond bien. &lt;br /&gt;
[[Fichier:Ping de la carte électronique RNDIS.png|alt=Ping de la carte électronique RNDIS|centré|vignette|350x350px|Ping de la carte électronique RNDIS]]&lt;br /&gt;
Il faut alors maintenant faire &lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Ping_de_la_carte_%C3%A9lectronique_RNDIS.png&amp;diff=2120</id>
		<title>Fichier:Ping de la carte électronique RNDIS.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Ping_de_la_carte_%C3%A9lectronique_RNDIS.png&amp;diff=2120"/>
		<updated>2023-11-20T10:57:13Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ping de la carte électronique RNDIS&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Interface_usb0_cr%C3%A9%C3%A9e.png&amp;diff=2118</id>
		<title>Fichier:Interface usb0 créée.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Interface_usb0_cr%C3%A9%C3%A9e.png&amp;diff=2118"/>
		<updated>2023-11-20T10:53:46Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Interface usb0 créée&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2051</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2051"/>
		<updated>2023-11-14T14:36:43Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* 2) Soudure de la carte électronique RNDIS */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ordonnanceur/SE : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte été pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecter des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir fais le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux qu' l'on va envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|239x239px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors router notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
Durant deux séances, nous avons réalisé la soudure de la carte électronique sur laquelle nous avons été aidés pour souder le quartz ainsi que le port USB. A noter que sur la carte, deux diodes ont été enlevées au niveau de l'USB car il était impossible de la reconnaître par notre machine grâce à la commande ''&amp;quot;lsusb&amp;quot;.'' Hormis les diodes à enlever, aucune difficulté n'a été relevée durant la soudure de la carte.&lt;br /&gt;
&lt;br /&gt;
Au final, nous avons donc une carte électronique fonctionnelle et prête à être programmée.&lt;br /&gt;
&lt;br /&gt;
Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Carte soudée.jpg|alt=Carte soudée|centré|vignette|237x237px|Carte soudée]]&lt;br /&gt;
Au final, la carte est bien reconnue grâce à la commande ''&amp;quot;lsusb&amp;quot; :'' &lt;br /&gt;
[[Fichier:Carte reconnue par le &amp;quot;lsusb&amp;quot;.png|alt=Carte reconnue par le &amp;quot;lsusb&amp;quot;|centré|vignette|Carte reconnue par le &amp;quot;lsusb&amp;quot;]]&lt;br /&gt;
Après cela, nous allons commencer à programmer le programme pour avoir une communication RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== '''3) Programmation de la carte électronique RNDIS''' ===&lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carte_reconnue_par_le_%22lsusb%22.png&amp;diff=2050</id>
		<title>Fichier:Carte reconnue par le &quot;lsusb&quot;.png</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carte_reconnue_par_le_%22lsusb%22.png&amp;diff=2050"/>
		<updated>2023-11-14T14:33:46Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Carte reconnue par le &amp;quot;lsusb&amp;quot;&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carte_soud%C3%A9e.jpg&amp;diff=2049</id>
		<title>Fichier:Carte soudée.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carte_soud%C3%A9e.jpg&amp;diff=2049"/>
		<updated>2023-11-14T14:30:30Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Carte soudée&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2011</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=2011"/>
		<updated>2023-11-06T11:16:23Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Ordonnanceur/SE : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ordonnanceur/SE : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder 2 connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte été pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecter des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir fais le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux qu' l'on va envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|239x239px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors router notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1831</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1831"/>
		<updated>2023-10-22T09:58:27Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Carte fille réseau RNDIS : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ordonnanceur/SE : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder des connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
=== 1) Création de la carte électronique RNDIS ===&lt;br /&gt;
Nous avons choisi de réaliser la carte réseau RNDIS car nous pensons que ce projet était aussi en lien avec nos cours de réseau et de système d'exploitation, cette carte été pour nous un moyen d'en apprendre plus sur ces aspects.&lt;br /&gt;
&lt;br /&gt;
La première chose à faire était de réaliser la carte électronique. Pour cela, des informations nous sont fournies. On sait alors que le microcontrôleur a utiliser doit avoir des capacités USB et que l'on peut utiliser soit un ATMega16u2, un ATMega32u4 ou un AT90USB suivant la mémoire que l'on veut disposer. Nous avons choisi d'utiliser un ATMega16u2 car nous en avions déjà utiliser un lors de notre projet en SE3 et nous étions plus à l'aise avec.&lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons commencé à faire le schéma électrique de la carte réseau. Nous avons commencé à mettre les composants pour faire fonctionner le microcontrôleur de la même façon que sur le projet de SE3. Après cela, nous avons commencé à faire les entrées et sorties. On sait que la carte va communiquer avec la carte mère via un connecteur HE10, des signaux MISO, MOSI, SCK et CS sont alors à connecter au microcontrôlleur. Nous avons choisi d'utiliser les ports suivants :&lt;br /&gt;
&lt;br /&gt;
* SCK ==&amp;gt; PB1&lt;br /&gt;
* MOSI ==&amp;gt; PB2&lt;br /&gt;
* MISO ==&amp;gt; PB3&lt;br /&gt;
* CS ==&amp;gt; PB4&lt;br /&gt;
&lt;br /&gt;
De cette façon, nous pouvons récupérer et envoyer simplement des informations depuis la carte mère. Nous avons aussi connecter des LEDs sur les ports PC4 à PC7. Les autres ports sont connectés à des testpoints. La communication RNDIS se faisant via le port USB, nous avons aussi implémenter un port USB communicant via D+ et D-. Par sécurité, nous avons aussi mis un AVR-ISP dans le cas où la programmation du microcontrôleur se fasse pas correctement. Voici alors le schéma électrique de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Schéma électrique de la carte RNDIS.jpg|alt=Schéma électrique de la carte RNDIS|centré|vignette|234x234px|Schéma électrique de la carte RNDIS]]&lt;br /&gt;
Après avoir fais le schéma électrique, nous avons fait le routage de la carte. Le routage était simple, nous avons commencé par router les parties USB et microcontôleur car nous savons comment elles doivent êtres disposées. Le plus difficile dans ce routage a été de mettre le capacités les plus proches du quartz et du microcontôleur car nous avons essayé de faire une carte compacte, et les testpoints prennent beaucoup de place sur la carte. Il fallait donc être précis sur la disposition des composants. Il fallait aussi faire attention à ce que les pistes D+ et D- soient les plus courtes et avec le moins de via possibles pour ne pas endommager les signaux qu' l'on va envoyer. Nous avons fait le plan de masse de la carte et au final nous avons réussi à compacter la carte pour qu'elle fasse une taille de 33mm x 43mm. Voici alors le routage de notre carte RNDIS.&lt;br /&gt;
[[Fichier:Routage de la carte RNDIS.jpg|alt=Routage de la carte RNDIS|centré|vignette|239x239px|Routage de la carte RNDIS]]&lt;br /&gt;
Voici donc une réprésentation 3D de notre carte RNDIS :&lt;br /&gt;
[[Fichier:Représentation 3D de notre carte RNDIS.jpg|alt=Représentation 3D de notre carte RNDIS|centré|vignette|Représentation 3D de notre carte RNDIS]]&lt;br /&gt;
Nous avons alors router notre carte, il fallait donc faire un fichier ZIP à partir de ces fichiers afin que la carte puisse être envoyée en production pour que l'on puisse souder les composants par la suite. Nous avons donc suivi les étapes de ce tutoriel : ''https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6''. &lt;br /&gt;
&lt;br /&gt;
=== 2) Soudure de la carte électronique RNDIS ===&lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Repr%C3%A9sentation_3D_de_notre_carte_RNDIS.jpg&amp;diff=1830</id>
		<title>Fichier:Représentation 3D de notre carte RNDIS.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Repr%C3%A9sentation_3D_de_notre_carte_RNDIS.jpg&amp;diff=1830"/>
		<updated>2023-10-22T09:51:42Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Représentation 3D de notre carte RNDIS&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Routage_de_la_carte_RNDIS.jpg&amp;diff=1829</id>
		<title>Fichier:Routage de la carte RNDIS.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Routage_de_la_carte_RNDIS.jpg&amp;diff=1829"/>
		<updated>2023-10-22T09:49:14Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Routage de la carte RNDIS&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Sch%C3%A9ma_%C3%A9lectrique_de_la_carte_RNDIS.jpg&amp;diff=1828</id>
		<title>Fichier:Schéma électrique de la carte RNDIS.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Sch%C3%A9ma_%C3%A9lectrique_de_la_carte_RNDIS.jpg&amp;diff=1828"/>
		<updated>2023-10-22T09:41:18Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Schéma électrique de la carte RNDIS&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Sch%C3%A9ma_elec_carte_RNDIS.jpg&amp;diff=1827</id>
		<title>Fichier:Schéma elec carte RNDIS.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Sch%C3%A9ma_elec_carte_RNDIS.jpg&amp;diff=1827"/>
		<updated>2023-10-22T09:39:44Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Schéma électrique de la carte RNDIS&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1796</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1796"/>
		<updated>2023-10-13T06:47:22Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Ordonnanceur/SE : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ordonnanceur/SE : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder des connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;https://jlcpcb.com/help/article/16-How-to-generate-Gerber-and-Drill-files-in-KiCad-6 --&amp;gt; générer le fichier zip&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1572</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1572"/>
		<updated>2023-09-19T12:22:00Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ordonnanceur/SE : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder des connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Carte soudee.jpg&lt;br /&gt;
Fichier:Connecteur soudee.jpg|Carte et connecteurs soudés&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1571</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1571"/>
		<updated>2023-09-19T12:21:25Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ordonnanceur/SE : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quel sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. Nous avons réalisé au total 3 câbles, donc un de plus que le nombre de base au cas où un des câbles ne fonctionne pas. Voici une photo des trois câbles :&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Fichier:Trois cables.jpg&lt;br /&gt;
Fichier:Câbles de côté.jpg|Photos des trois câbles&lt;br /&gt;
&amp;lt;/gallery&amp;gt;Par la suite, nous avons dû souder une carte Shield pouvant être ajoutée à un Arduino Uno. Cette carte Shield était déjà partiellement soudée. De plus nous avons dû souder des connecteurs permettant la jonction avec les cartes . Voici une photo de la carte soudée : &lt;br /&gt;
[[Fichier:Connecteur soudee.jpg|alt=Connecteurs soudés|vignette|177x177px|Connecteurs soudés]]&lt;br /&gt;
[[Fichier:Carte soudee.jpg|alt=Carte soudee|centré|vignette|Carte soudee]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
ReX : utilisez le squelette présenté en séance.&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
== Rendus : ==&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git &lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Connecteur_soudee.jpg&amp;diff=1570</id>
		<title>Fichier:Connecteur soudee.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Connecteur_soudee.jpg&amp;diff=1570"/>
		<updated>2023-09-19T12:19:44Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Connecteur soudee&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carte_soudee.jpg&amp;diff=1569</id>
		<title>Fichier:Carte soudee.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Carte_soudee.jpg&amp;diff=1569"/>
		<updated>2023-09-19T12:15:36Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Carte soudee&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:C%C3%A2bles_de_c%C3%B4t%C3%A9.jpg&amp;diff=1568</id>
		<title>Fichier:Câbles de côté.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:C%C3%A2bles_de_c%C3%B4t%C3%A9.jpg&amp;diff=1568"/>
		<updated>2023-09-19T12:08:56Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Câbles de côté&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Trois_cables.jpg&amp;diff=1567</id>
		<title>Fichier:Trois cables.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Trois_cables.jpg&amp;diff=1567"/>
		<updated>2023-09-19T12:05:59Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Trois cables&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1450</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1450"/>
		<updated>2023-09-13T15:54:17Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Ordonnanceur/SE : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CAZIN Némo &amp;amp; CEGARRA Antoine&lt;br /&gt;
&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur/SE : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quelle sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance. ### PHOTOS CABLE  ###&lt;br /&gt;
&lt;br /&gt;
&amp;lt;nowiki&amp;gt;###&amp;lt;/nowiki&amp;gt; METTRE PARTIE SOUDURE ANTOINE ###&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1449</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1449"/>
		<updated>2023-09-13T15:53:01Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CAZIN Némo &amp;amp; CEGARRA Antoine&lt;br /&gt;
&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur/SE : ==&lt;br /&gt;
Préparation de la carte Shield :&lt;br /&gt;
&lt;br /&gt;
Pour la première séance de TP, nous avons dû souder des composants sur la carte Shield fournie. Nous nous sommes alors séparés, un qui faisait la soudure, et un autre préparant les câble reliant la carte Shield aux cartes filles.&lt;br /&gt;
&lt;br /&gt;
Pour les câbles, nous avons comparé notre travail avec le câble de l'enseignant. Le plus dur était de savoir dans quelle sens mettre les fiches HE10 femelle, un renfoncement permet heureusement de savoir le sens dans lequel insérer le câble. Après cela, le câble est un peu fragile si on tire dessus, nous avons donc replier le câble et mis un bloqueur pour augmenter sa résistance.&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1432</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1432"/>
		<updated>2023-09-12T13:13:39Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CAZIN Némo &amp;amp; CEGARRA Antoine&lt;br /&gt;
&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur/SE : ==&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;br /&gt;
&lt;br /&gt;
== Note ==&lt;br /&gt;
flatpak run org.kicad.KiCad//stable --&amp;gt; Lance Kicad 7&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1429</id>
		<title>SE4Binome2023-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE4Binome2023-8&amp;diff=1429"/>
		<updated>2023-09-12T13:03:24Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : Rubrique&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;CAZIN Némo &amp;amp; CEGARRA Antoine&lt;br /&gt;
&lt;br /&gt;
Lien de notre GIT : https://archives.plil.fr/ncazin/Projet_Pico_SE4.git&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur/SE : ==&lt;br /&gt;
&lt;br /&gt;
== Carte FPGA/VHDL : ==&lt;br /&gt;
&lt;br /&gt;
== Carte électronique numérique : ==&lt;br /&gt;
&lt;br /&gt;
== Carte fille réseau RNDIS : ==&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Pico_SE4_2023/2024&amp;diff=1427</id>
		<title>Pico SE4 2023/2024</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Pico_SE4_2023/2024&amp;diff=1427"/>
		<updated>2023-09-12T12:54:55Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Réalisations des élèves */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectif =&lt;br /&gt;
&lt;br /&gt;
Pour l'année académique 2023/2024 nous vous demandons de construire un pico-ordinateur comprenant les éléments suivants :&lt;br /&gt;
* un processeur de type microcontrôleur ;&lt;br /&gt;
* un clavier ;&lt;br /&gt;
* un dispositif d'affichage ;&lt;br /&gt;
* un système d'exploitation stocké dans la mémoire flash du microcontrôleur ;&lt;br /&gt;
* une mémoire de masse allant au delà de la mémoire flash sus-citée ;&lt;br /&gt;
* un dispositif de communication avec l'extérieur.&lt;br /&gt;
&lt;br /&gt;
Pour faire en sorte que tous les éléments puissent communiquer entre eux nous vous demandons d'utiliser un bus série.&lt;br /&gt;
&lt;br /&gt;
= Compétences évaluées =&lt;br /&gt;
&lt;br /&gt;
Les compétences suivantes doivent être acquises durant ce module.&lt;br /&gt;
* Savoir comprendre, ou à défaut être actif en séances pour poser les questions pertinentes aux encadrants.&lt;br /&gt;
* Savoir produire un travail régulier et documenté durant la totalité de la période.&lt;br /&gt;
* Savoir concevoir et réaliser des cartes électroniques fonctionnelles.&lt;br /&gt;
* Savoir concevoir et programmer un circuit FPGA en VHDL.&lt;br /&gt;
* Savoir structurer et écrire des pilotes pour cartes électroniques.&lt;br /&gt;
* Savoir concevoir et implanter des primitives systèmes et un micro-système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
= Organisation du travail =&lt;br /&gt;
&lt;br /&gt;
Vous aurez, comme d'habitude, la lourde tâche de tester ce module de travaux pratiques.&lt;br /&gt;
&lt;br /&gt;
Ce sera d'autant moins facile que nous vous demandons de vous coordonner pour réaliser le pico-ordinateur : un seul exemplaire fonctionnel est attendu par groupes de 4 binômes.&lt;br /&gt;
&lt;br /&gt;
Vous allez donc devoir vous organiser pour que chaque binôme réalise une partie de l'ensemble. Cela dit des tâches identiques sont à réaliser par tous les binômes, ces tâches vous permettront de vous exercer mais aussi de tester vos réalisations spécifiques.&lt;br /&gt;
&lt;br /&gt;
== Matériel fourni ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file:2023_Bouclier_Pico.pdf||thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
Pour que chaque binôme puisse avoir un minimum d'autonomie, un matériel de base est fourni :&lt;br /&gt;
* un Arduino Uno pour prototyper le coeur d'une carte mère ;&lt;br /&gt;
* un bouclier Arduino pour disposer d'une mémoire de masse (carte SD) et de connecteurs vers les cartes filles, voir le schéma et le PCB ci-contre ;&lt;br /&gt;
* d'une matrice de LED et d'un afficheur 7-segments tous les deux gérables par SPI pour pouvoir écrire les briques de votre système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
Le projet KiCAD pour le bouclier Arduino est disponible : [[Média:2023_Bouclier_Pico.zip]]&lt;br /&gt;
&lt;br /&gt;
Les projets KiCAD pour connecter les périphériques via un connecteur sont disponibles : [[Média:2023_HE10-periph.zip]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[file:2023_Bouclier_Pico_PCB.png||thumb|center|300px]]&lt;br /&gt;
&lt;br /&gt;
Vision de la carte partiellement montée. L'accès à la carte SD est fonctionnel.&lt;br /&gt;
&lt;br /&gt;
[[file:2023_Bouclier_Pico_Test.jpg||thumb|center|300px]]&lt;br /&gt;
&lt;br /&gt;
Pour la partie programmation concernant la carte SD vous pouvez vous appuyer sur le projet ci-contre utilisant &amp;lt;code&amp;gt;avr-gcc&amp;lt;/code&amp;gt; comme compilateur : [[Fichier:TestSD_avrgcc.zip]].&lt;br /&gt;
&lt;br /&gt;
== Réalisations par binôme ==&lt;br /&gt;
&lt;br /&gt;
Chaque binôme réalise :&lt;br /&gt;
* un système d'exploitation basé sur un ordonnanceur ;&lt;br /&gt;
* une carte fille FPGA programmée par VHDL, le binôme écrit aussi le code pour que la carte puisse être gérée par le système d'exploitation ;&lt;br /&gt;
* une carte mère ou une carte fille à base de microcontrôleur, le binôme écrit aussi le code pour que la carte puisse être gérée par le système d'exploitation, le binôme peut réaliser plusieurs cartes pour maximiser sa note.&lt;br /&gt;
&lt;br /&gt;
== Réalisation par groupe de binômes ==&lt;br /&gt;
&lt;br /&gt;
Par groupe de 4 binômes vous devez réaliser un pico-ordinateur complet :&lt;br /&gt;
* une carte mère ;&lt;br /&gt;
* une carte fille FPGA/VHDL fonctionnelle et supportée par votre carte mère ;&lt;br /&gt;
* au moins 3 cartes filles fonctionnelles et supportées par votre carte mère (clavier, écran, réseau) ;&lt;br /&gt;
* vous pouvez ajouter une cinquième carte fille optionnelle de type carte son.&lt;br /&gt;
&lt;br /&gt;
= Cahier des charges =&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
Vous n'avez pas besoin d'avoir conçu et réalisé des cartes électroniques pour commencer à écrire le système d'exploitation du pico-ordinateur et en particulier l'ordonnanceur sous-jacent.&lt;br /&gt;
&lt;br /&gt;
Le principe est d'utiliser un minuteur du microcontrôleur pour lancer périodiquement une fonction d'interruption que vous allez transformer en ordonnanceur.&lt;br /&gt;
&lt;br /&gt;
Dans un premier temps vous testerez votre ordonnanceur en créant deux tâches statiques pour faire clignoter, avec des périodes différentes, deux LED du bouclier fourni.&lt;br /&gt;
&lt;br /&gt;
Par la suite vous allez complexifier votre ordonnanceur en ajoutant :&lt;br /&gt;
* une tâche de lecture de caractère par le port série (stocké en mémoire partagé) ;&lt;br /&gt;
* une tâche d'écriture sur le port série (du caractère lu sur le port série) ;&lt;br /&gt;
* une tâche d'écriture sur la matrice (du caractère lu sur le port série) ;&lt;br /&gt;
* une tâche d'écriture sur l'afficheur 7 segments (du caractère lu sur le port série).&lt;br /&gt;
&lt;br /&gt;
Les deux dernières tâches sont plus compliquées à réaliser dans la mesure où elles utilisent une ressource commune.&lt;br /&gt;
&lt;br /&gt;
== Cartes filles FPGA ==&lt;br /&gt;
&lt;br /&gt;
Les cartes filles FPGA doivent être programmées en VHDL. Tous les binômes doivent implanter en VHDL :&lt;br /&gt;
* un contrôleur de bus série SPI ;&lt;br /&gt;
* un décodeur des commandes reçues par SPI (commandes sur un octet avec éventuellement des paramètres à suivre) ;&lt;br /&gt;
* un contrôleur d'écran VGA affichant le contenu graphique de la RAM de la carte FPGA.&lt;br /&gt;
&lt;br /&gt;
A minima il faut une commande pour insérer un pixel d'une couleur donnée dans la RAM d'affichage.&lt;br /&gt;
&lt;br /&gt;
Vous pouvez aussi ajouter des fonctionnalités supplémentaires à votre carte FPGA :&lt;br /&gt;
* mémoire de masse par accès direct à une carte mémoire SD ;&lt;br /&gt;
* carte réseau Ethernet en utilisant un module PHY Ethernet.&lt;br /&gt;
&lt;br /&gt;
Pour les fonctionnalités supplémentaires vous devez prévoir des commandes supplémentaire au niveau du décodeur.&lt;br /&gt;
&lt;br /&gt;
== Cartes électroniques ==&lt;br /&gt;
&lt;br /&gt;
Vous devez réaliser deux type de cartes électroniques à base de microcontrôleur : une carte mère et des cartes filles.&lt;br /&gt;
La carte FPGA/VHDL décrite dans la section précédente est considérée comme une carte fille.&lt;br /&gt;
&lt;br /&gt;
Les cartes filles sont connectées via un bus série à la carte mère. C'est aussi la carte mère qui alimente les cartes filles.&lt;br /&gt;
Enfin la carte mère dispose d'une mémoire permanente pour stocker des fichiers.&lt;br /&gt;
&lt;br /&gt;
Les cartes filles peuvent être de différents types :&lt;br /&gt;
* carte fille clavier ;&lt;br /&gt;
* carte fille d'affichage ;&lt;br /&gt;
* carte fille série (se comporte comme un clavier et comme un dispositif d'affichage) ;&lt;br /&gt;
* carte fille réseau ;&lt;br /&gt;
* carte fille mémoire de masse (alternative à la mémoire de masse de la carte mère) ;&lt;br /&gt;
* carte fille son.&lt;br /&gt;
&lt;br /&gt;
Pour un type donné vous avez le choix entre plusieurs technologies pour réaliser votre carte. Par exemple une carte fille clavier peut être implantée par une matrice de touches ou en utilisant un clavier USB.&lt;br /&gt;
&lt;br /&gt;
== Programmation système ==&lt;br /&gt;
&lt;br /&gt;
Le système d'exploitation du pico-ordinateur doit avoir les fonctionnalités d'un DOS (Disk Operating System), à savoir :&lt;br /&gt;
* lecture des commandes tapées par l'utilisateur ;&lt;br /&gt;
* téléchargement d'exécutables ou de sources via le dispositif de communication extérieur  ;&lt;br /&gt;
* sauvegarde et chargement d'exécutables ou de sources via la mémoire de masse ;&lt;br /&gt;
* permettre l'affichage de chaînes de caractères ;&lt;br /&gt;
* comprend un interpréteur micro-python pour faire tourner les sources ;&lt;br /&gt;
* les différentes fonctionnalités sont réalisées sous forme de tâches gérées par un ordonnanceur.&lt;br /&gt;
&lt;br /&gt;
=== Commandes de base ===&lt;br /&gt;
&lt;br /&gt;
Ces commandes sont les commandes les plus simples à implanter :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Commande !! Description&lt;br /&gt;
|-&lt;br /&gt;
| VERSION || Affiche la version du système d'exploitation&lt;br /&gt;
|-&lt;br /&gt;
| DEVICES || Affiche la liste des cartes filles connectées&lt;br /&gt;
|-&lt;br /&gt;
| ECHO || Affiche les arguments de la commande&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Commandes liées aux processus ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Commande !! Description&lt;br /&gt;
|-&lt;br /&gt;
| PS || Liste les processus disponibles et leur état&lt;br /&gt;
|-&lt;br /&gt;
| SLEEP || Met un processus en sommeil&lt;br /&gt;
|-&lt;br /&gt;
| WAKE || Relance un processus dormant&lt;br /&gt;
|-&lt;br /&gt;
| EXEC || Création d'un processus à partir d'un fichier exécutable&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
La commande EXEC est complexe à réaliser, elle est optionnelle pour l'année 2023/2024.&lt;br /&gt;
&lt;br /&gt;
=== Commandes liées au système de fichiers ===&lt;br /&gt;
&lt;br /&gt;
Commandes pour gérer le système de fichiers :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Commande !! Description&lt;br /&gt;
|-&lt;br /&gt;
| FORMAT || Formate le système de fichiers&lt;br /&gt;
|-&lt;br /&gt;
| LIST || Affiche les fichiers du répertoire principal&lt;br /&gt;
|-&lt;br /&gt;
| CREATE || Création d'un fichier avec l'entrée standard&lt;br /&gt;
|-&lt;br /&gt;
| TYPE || Affiche le contenu d'un fichier&lt;br /&gt;
|-&lt;br /&gt;
| COPY || Copie un fichier&lt;br /&gt;
|-&lt;br /&gt;
| RENAME || Renomme un fichier&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Commandes liées au réseau ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Commande !! Description&lt;br /&gt;
|-&lt;br /&gt;
| REMOTE || Liste les fichiers disponibles sur le réseau&lt;br /&gt;
|-&lt;br /&gt;
| GET || Télécharge un fichier en provenance du réseau&lt;br /&gt;
|-&lt;br /&gt;
| PUT || Sauve un fichier sur le réseau&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Programmation des pilotes ==&lt;br /&gt;
&lt;br /&gt;
La programmation c'est aussi l'écriture des sous-systèmes ou des pilotes liés à chaque cartes :&lt;br /&gt;
* pour la carte mère, il faut écrire un sous-système de gestion de fichiers ;&lt;br /&gt;
* pour la carte fille comportant une matrice de touches, il faut écrire le pilote identifiant les touches actionnées et gérant l'envoi de ces touches à la carte mère ;&lt;br /&gt;
* pour la carte fille gérant un clavier USB, il faut utiliser un projet LUFA pour scanner régulièrement le clavier USB et envoyer d'éventuels événements à la carte mère ;&lt;br /&gt;
*  pour la carte fille gérant un écran LCD, il faut écrire le pilote capable de gérer l'écran et la partie récupérant les données de la carte mère ;&lt;br /&gt;
* pour la carte fille gérant une clé USB, il faut utiliser un projet LUFA pour l'accès à la clé et écrire un sous-système de gestion de fichiers ;&lt;br /&gt;
* la carte fille gérant une connexion série ne nécessite qu'un modeste pilote de communication avec la carte mère ;&lt;br /&gt;
* pour la carte fille permettant une connexion avec le monde extérieur via de simples points d'accès USB de volume (EP Bulk), il faut écrire le pilote pour communication avec la carte mère mais aussi le programme sur le PC permettant la réception ou l'envoi de fichiers ;&lt;br /&gt;
* pour la carte fille permettant une connexion Ethernet au dessus d'USB (RNDIS), il faut écrire une micro-pile réseau capable de récupérer et d'envoyer des fichiers au travers de paquets Ethernet mais aussi le programme sur le PC cible capable de comprendre ces paquets Ethernet ;&lt;br /&gt;
* pour la carte fille incluant une puce Ethernet, il faut implanter la micro-pile réseau et le programme évoquée ci-dessus mais aussi le pilote capable de gérer la puce Ethernet ;&lt;br /&gt;
* pour la carte fille son, il faut écrire la partie permettant de récupérer les échantillons, les copier en mémoire, et les jouer à la vitesse d'échantillonnage préalablement transmise.&lt;br /&gt;
&lt;br /&gt;
= Spécifications techniques =&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
Pour réaliser votre ordonnanceur commencez par programmer le minuteur 1 de l'ATMega328p de sorte à ce qu'il génère une interruption toutes&lt;br /&gt;
les 20ms. L'interruption va déclencher une fonction de gestion d'interruption (ISR pour Interrupt Service Routine). Vous utiliserez une ISR nue pour éviter les interférences du compilateur sur la pile d'exécution :&lt;br /&gt;
 ISR(TIMER1_COMPA_vect,ISR_NAKED)&lt;br /&gt;
 {&lt;br /&gt;
 /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
 ...&lt;br /&gt;
 /* Appel à l'ordonnanceur */&lt;br /&gt;
 scheduler();&lt;br /&gt;
 /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
 ...&lt;br /&gt;
 asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
 }&lt;br /&gt;
Vous constatez qu'il vous reste à écrire, dans l'ISR, le code pour sauvegarder et récupérer le contexte d'exécution d'une tâche. Pour cela réfléchissez aux éléments d'un microcontrôleur qui sont nécessaires pour l'exécution d'un programme puis réfléchissez à une méthode pour sauver l'état de ces éléments. &lt;br /&gt;
&lt;br /&gt;
Au moins dans un premier temps, les tâches seront définies de façon statique. Toutes les tâches doivent être définies dans un tableau global, seront lancées dès le démarrage du microcontrôleur et ne se termineront que lorsque le microcontrôleur sera arrêté ou relancé. Une tâche est à définir par une structure dont un des champs doit être la fonction réalisant la tâche. A vous de définir les autres champs.&lt;br /&gt;
&lt;br /&gt;
Avant de démarrer l'ordonnanceur, il faut prendre soin à ce que la récupération du contexte dans l'ISR fonctionne alors que les tâches n'auront pas encore été lancées. Il faut donc une fonction permettant d'initialiser le contexte pour chaque tâche.&lt;br /&gt;
&lt;br /&gt;
== Cartes électroniques à microcontrôleur ==&lt;br /&gt;
&lt;br /&gt;
Le bus série préconisé pour la communication entre la carte mère et les cartes filles est un bus SPI. Au niveau physique, les connexions entre cartes mères et cartes filles doivent être réalisées via des connecteurs HE-10 à 8 broches :&lt;br /&gt;
* 2 broches pour l'alimentation ;&lt;br /&gt;
* 3 broches pour les signaux SPI (MISO, MOSI, SCK) ;&lt;br /&gt;
* 1 broche pour le CS (Chip Select) ;-&lt;br /&gt;
* 1 broche pour une éventuelle ligne d'interruption ;&lt;br /&gt;
* 1 broche pour une eventuelle réinitialisation de la carte (Reset).&lt;br /&gt;
&lt;br /&gt;
Il est conseillé d'organiser les broches sur les connecteurs HE-10 sur le modèle du bouclier Arduino fourni.&lt;br /&gt;
&lt;br /&gt;
La carte mère est constituée autour d'un ATMega328p et d'une puce mémoire de type AT45DB641E de 8 Mo. Il faut réflechir à l'alimentation sachant que :&lt;br /&gt;
* l'alimentation de la carte mère doit être suffisante pour alimenter les cartes filles ;&lt;br /&gt;
* l'alimentation du microcontrôleur doit être compatible avec l'alimentation de la puce mémoire sauf à prévoir une conversion de niveaux logiques entre les deux puces ;&lt;br /&gt;
* les cartes filles d'un même pico-ordinateur doivent être alimentées avec la même tension.&lt;br /&gt;
&lt;br /&gt;
Voici quelques exemples d'architectures de cartes filles :&lt;br /&gt;
* une carte fille SPI avec un ATMega328p et une matrice de touches ;&lt;br /&gt;
* une carte fille SPI avec un AT90USB647 pour connexion à un clavier USB ou une clef USB ;&lt;br /&gt;
* une carte fille SPI avec un ATMega328p et un écran LCD 2 lignes HD44780 ;&lt;br /&gt;
* une carte fille SPI avec un ATMega16u2 pour une connexion série USB ;&lt;br /&gt;
* une carte fille SPI avec un ATMega328p et un DAC R-2R comme carte son ;&lt;br /&gt;
* une carte fille SPI avec un ATMega16u2 (ou supérieur) pour une connexion réseau (périphérique USB générique EP bulk ou périphérique USB RNDIS) ;&lt;br /&gt;
* une carte fille SPI avec un ATMega328p et un ENC28J60 pour une connexion Ethernet 10Mb/s.&lt;br /&gt;
&lt;br /&gt;
Toutes les cartes doivent permettre un accès au port série de leur microcontrôleur pour un déverminage via un FTDI. Vous devez aussi ajouter des points de test pour les lignes importantes : lignes du bus SPI, horloge, alimentations, etc.&lt;br /&gt;
&lt;br /&gt;
Toutes les cartes filles répondent à la commande SPI constituée de l'octet de commande 0x00 et de l'octet de donnée 0x00. Le résultat se lit sur le second octet de réponse et détermine le type de la carte fille. Le chiffre de poid fort de la réponse est un code magique : 0xa. Le chiffre de poid faible est donné par le tableau ci-dessous :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Chiffre !! Type de carte&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || Clavier&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || Affichage&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || Réseau&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Carte son&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Il est bon aussi de prévoir que les cartes filles puissent répondre à une commande SPI permettant de savoir si elles sont occupées ou non. L'octet de commande serait 0xFF et l'octet de donnée 0xFF. En cas de succès les deux octets de réponse sont à 0x55. Les cartes filles doivent prendre soin d'initialiser leur réponse SPI à autre chose que 0x55 lorsqu'elles se lancent dans un traitement autre qu'une écoute SPI.&lt;br /&gt;
&lt;br /&gt;
== Electronique et programmation système ==&lt;br /&gt;
 &lt;br /&gt;
=== Carte mère ===&lt;br /&gt;
&lt;br /&gt;
La carte mère doit comporter un microcontrôleur ATMega328p, une puce mémoire AT45DB641E et 5 connecteurs HE10 pour connecter une carte fille FPGA et 4 cartes filles à microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
Vous avez aussi quelques points à approfondir.&lt;br /&gt;
# La source d'alimentation de votre pico-ordinateur, le plus simple semble être un connecteur USB pour utiliser soit un PC soit une batterie comme source ;&lt;br /&gt;
# La tension d'alimentation du microcontrôleur et des cartes filles :&lt;br /&gt;
#* soit vous optez pour du 5V auquel cas il faut prévoir un régulateur de tension pour la puce mémoire et une adaptation des niveaux logiques pour cette même puce (voir le schéma des boucliers Arduino),&lt;br /&gt;
#* soit vous partez sur du 3.3V et vos cartes filles doivent tourner en 3.3V, vu que vous aurez probablement un adaptateur 5V il faut quand même prévoir un régulateur 3.3V assez costaud sur la carte mère, de plus vous ne pouvez pas dépasser 8Mhz comme horloge ;&lt;br /&gt;
# La méthode de programmation de la carte mère :&lt;br /&gt;
#* soit vous programmez le microcontrôleur via un connecteur AVR ISP, un programmateur et l'utilitaire &amp;lt;code&amp;gt;avrdude&amp;lt;/code&amp;gt; ;&lt;br /&gt;
#* soit vous ajoutez une puce pour réaliser un pont USB vers série vous pourrez alors programmer le microcontrôleur avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;, attention il faut tout de même prévoir des connecteurs AVR ISP pour charger l'amorceur sur l'ATMega328p et l'éventuel ATMega8u2 (vous utilisez cette puce pour l'USB/série plutôt qu'une puce FTDI).&lt;br /&gt;
&lt;br /&gt;
Du coté programmation vous êtes chargés d'écrire les fonctions d'accès à la mémoire, des primitives systèmes implantant un micro-système de fichiers et des primitives de communication via le bus SPI.&lt;br /&gt;
&lt;br /&gt;
Les fonctions de base d'accès à la mémoire sont facilement trouvables, par exemple sur les sites du bureau d'études systèmes embarqués des PeiP.&lt;br /&gt;
&lt;br /&gt;
Concernant le micro-système de fichiers, les fonctionnalités suivantes doivent être implantées :&lt;br /&gt;
&lt;br /&gt;
* le système de fichiers doit résider dans la mémoire de 8 Mo, les accès à la mémoire se font par blocs de 256 octets ;&lt;br /&gt;
* l'accès au système de fichiers se fait par des primitives système ;&lt;br /&gt;
* le micro-système de fichiers ne comporte qu'un répertoire : le répertoire principal, ce dernier peut comporter au maximum 64 fichiers, un fichier est caractérisé par un nom de 16 caractères au maximum, sa taille et ses blocs de données, un fichier est décrit par un maximum de 16 blocs de données ;&lt;br /&gt;
* le superbloc du système de fichiers comprend, en plus de la description du répertoire racine, une carte bit à bit des blocs de données libres, cette carte nécessite 16 blocs ;&lt;br /&gt;
* les différentes primitives à implanter sont :&lt;br /&gt;
** &amp;lt;code&amp;gt;append&amp;lt;/code&amp;gt; pour créer un fichier si non existant et ajouter des données en fin de fichier, les paramètres sont le nom du fichier, les données à ajouter et la taille des données,&lt;br /&gt;
** &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; pour lire des données dans un fichier, les paramètres sont le nom du fichier, le tableau dans lequel stocker les données, la taille du tableau et le déplacement par rapport au début du fichier,&lt;br /&gt;
** &amp;lt;code&amp;gt;remove&amp;lt;/code&amp;gt; pour détruire un fichier, le seul paramètre est le nom du fichier,&lt;br /&gt;
** &amp;lt;code&amp;gt;rename&amp;lt;/code&amp;gt; pour renommer un fichier, les paramètres sont l'ancien et le nouveau noms du fichier,&lt;br /&gt;
** &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt; pour copier un fichier, les paramètres sont le nom du fichier original et le nom de la copie.&lt;br /&gt;
&lt;br /&gt;
Les primitives pour le bus SPI doivent être :&lt;br /&gt;
* une fonction d'initialisation avec le mode SPI désiré et la vitesse d'horloge souhaitée ;&lt;br /&gt;
* une primitive pour envoyer quelques octets via le bus SPI :&lt;br /&gt;
** les paramètres de la primitive sont le tableau des octets à envoyer, le tableau des octets à recevoir, le nombre d'octets à envoyer et la spécification de la sortie CS de sélection du périphérique SPI,&lt;br /&gt;
** la primitive stocke l'opération dans une file et effectue l'envoi dès que le bus est libre,&lt;br /&gt;
** si la file est pleine la primitive peut retourner un code d'erreur sinon la primitive retourne l'identifiant unique de l'opération,&lt;br /&gt;
** les octets de réponse du périphérique sont stockés dans le tableau des octets à recevoir, si le pointeur est nul les réponses ne sont pas stockées ;&lt;br /&gt;
* une primitive pour attendre la fin d'un envoi SPI, il faut donner en unique paramètre l'identifiant de l'opération, l'attente s'effectue en mettant le processus appelant en mode sommeil et en le réveillant dès que l'opération est effectuée.&lt;br /&gt;
&lt;br /&gt;
Précisons que les tableaux stockés dans la file d'attente (requête et réponse SPI) le sont sous la forme de pointeurs. Ces pointeurs peuvent être librérés une fois l'opération effectuée.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille clavier &amp;quot;matrice de touches&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
La réalisation de la carte est simple, il s'agit de scanner une matrice de touches à l'aide d'un ATMega328p. N'oubliez pas le connecteur HE10 pour la connexion de cette carte fille à une carte mère. Sur le connecteur HE10 il faut prévoir à la fois la ligne de sélection SPI (utilisez la broche SS par défaut sur votre carte) et une ligne pour générer une interruption sur la carte mère. Vous devez faire avec l'alimentation fournie par la carte mère. Regardez aussi la problèmatique sur la programmation décrite dans la section sur la carte mère.&lt;br /&gt;
&lt;br /&gt;
Du coté programmation, c'est plus compliqué, vous êtes déjà chargés d'écrire la fonction de scan des touches :&lt;br /&gt;
* le scan des touches consiste juste à passer les lignes de la matrice en sorties, les colonnes en entrées avec résistance de charge et de rentrer dans une boucle pour passer une sortie à GND tandis que les autres restent à VCC, il suffit alors de consulter les entrées pour voir si une touche est appuyée (ou plusieurs) ;&lt;br /&gt;
* si une touche est appuyée la touche est stockée dans un tampon et la ligne d'interruption est activée ;&lt;br /&gt;
* si une requête SPI de code commande 0x01 est reçue, le nombre de touches dans le tampon est envoyé suivi des touches elles-mêmes.&lt;br /&gt;
&lt;br /&gt;
Ensuite, au niveau de la carte mère vous devez écrire la primitive gérant les claviers. Cette primitive prend en paramètre la ligne de sélection SPI du clavier ciblé et un tampon pour stocker les codes des touches. La taille du tampon est aussi passée en paramètre. La primitive prépare une transmission SPI constituée du seul octet de valeur 0x01 en prenant soin de préciser un tableau pour stocker d'éventuelles touches. Attention, la transmission SPI est constituée de l'octet 0x01 mais aussi d'autant d'octets de valeurs indéterminées qu'il est attendu d'octets dans la réponse SPI. La primitive se met alors en attente de la réponse.&lt;br /&gt;
&lt;br /&gt;
Au niveau du système d'exploitation les comportements suivants sont à implanter :&lt;br /&gt;
* à l'initialisation de la carte mère les périphériques SPI doivent être contactés pour déterminer lequels sont des claviers, des commandes SPI 0x00 sont donc envoyées avec attente des réponses SPI ;&lt;br /&gt;
* le processus SHELL toujours présent dans le système d'exploitation doit avoir le comportement suivant :&lt;br /&gt;
** si une interruption est reçue qui correspond à un périphérique clavier, le SHELL doit utiliser la primitive de lecture clavier pour obtenir la ou les touches appuyées ;&lt;br /&gt;
** dans un premier temps, les caractères reçus sont affichés en utilisant la primitive d'affichage (echo) ;&lt;br /&gt;
** à terme les lignes de caractères reçues sont analysées pour en extraire des commandes et les exécuter.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille clavier &amp;quot;USB&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Votre carte électronique doit tourner autour d'un AT90USB647 (ou supérieur). Ce microcontrôleur peut être programmé, en utilisant la bibliothèque LUFA, comme hôte USB. Il est donc possible de gérer, de cette façon un clavier USB et de faire interface avec la carte mère. Le schéma de la carte est très semblable à celui d'une carte comportant un ATMega16u2. Vous pouvez vous appuyer sur ce [https://wiki-se.plil.fr/mediawiki/index.php/SE4_2022/2023_EC5 projet keylogger]. Le plus simple est de programmer le microcontrôleur en utilisant l'utilitaire &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;, pour cela il faut prévoir, en plus d'un connecteur USB A femelle pour le clavier, un connecteur USB mâle pour la programmation.&lt;br /&gt;
&lt;br /&gt;
La programmation pour la gestion du clavier USB doit se reposer sur la démonstration &amp;lt;code&amp;gt;KeyboardHost&amp;lt;/code&amp;gt; de la bibliothèque LUFA. La conversion des modificateurs et des codes de touches en caractères ASCII sont à votre charge.&lt;br /&gt;
&lt;br /&gt;
Pour le reste de la programmation voir la section sur la carte fille &amp;quot;matrice de touches&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille écran LCD ===&lt;br /&gt;
&lt;br /&gt;
Cette carte comporte un ATMega328p et un écran LCD à base de contrôleur HD44780. L'écran LCD nécessite un potentiomètre pour régler la luminosité   des cristaux liquides. N'oubliez pas le connecteur HE10 pour la connexion de cette carte fille à une carte mère. Sur le connecteur HE10 il faut prévoir une ligne de sélection SPI. Aucune ligne d'interruption n'est nécessaire pour cette carte. Enfin il vous faut prévoir un connecteur AVR ISP pour programmer le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
Le microcontrôleur de la carte fille doit être programmé pour gérer le contrôleur HD44780 ou compatible :&lt;br /&gt;
* les écrans avec 1, 2, 3 ou 4 lignes doivent être gérés ;&lt;br /&gt;
* les caractères ASCII doivent être affichés sur l'écran ;&lt;br /&gt;
* les caractères spéciaux &amp;lt;code&amp;gt;\n&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;\r&amp;lt;/code&amp;gt; doivent être pris en compte pour le saut de ligne et le retour chariot ;&lt;br /&gt;
* les codes VT100 doivent être pris en compte, en particulier pour le déplacement du curseur doivent être pris en compte ;&lt;br /&gt;
* le contrôleur HD44780 ou compatible doit être configuré en mode défilement automatique.&lt;br /&gt;
&lt;br /&gt;
Les caractères à afficher ou spéciaux (y compris les séquences VT100) sont reçus par le bus SPI par la carte fille préfixés par le code commande 0x01. &lt;br /&gt;
&lt;br /&gt;
Au niveau de la carte mère vous devez écrire la primitive système. Cette primitive prend en paramètre la ligne de sélection SPI de l'écran ciblé et la chaîne des caractères à envoyer. La primitive prépare une transmission SPI constituée de l'octet de commande 0x01 et des octets correspondant aux caractères.&lt;br /&gt;
&lt;br /&gt;
Il ne faut pas demander un affichage si un autre affichage est en cours. C'est possible à réaliser avec la ligne prévue pour une interruption. La carte fille peut mettre cette ligne en état haut quand un affichage est en cours. Du coup la primitive peut se mettre en attente sur un état bas avant d'envoyer la requête SPI. C'est aussi possible de lancer des commandes 0xFF sur la carte jusqu'à obtenir les octets de réponse indiquant que la carte est libre.&lt;br /&gt;
&lt;br /&gt;
Cette primitive est utilisée par le système d'exploitation pour réaliser l'écho des commandes dans le SHELL et aussi par toutes les commandes qui nécessitent un affichage. Tous les écrans doivent être sollicités lors des affichages, il faut donc que le système d'exploitation scanne les périphériques SPI pour trouver les écrans comme il le fait pour les claviers.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille réseau RNDIS ===&lt;br /&gt;
&lt;br /&gt;
Le but de cette carte est de permettre au pico-ordinateur de converser avec l'extérieur. Une carte RNDIS permet de faire transister des paquets Ethernet au dessus d'une liaison USB. La carte n'a besoin que d'un microcontrôleur avec capacités USB pour fonctionner. Vous pouvez utiliser un &lt;br /&gt;
ATMega16u2, un ATMega32u4 ou un AT90USB suivant la taille mémoire dont vous souhaitez disposer. Gardez en mémoire qu'un paquet Ethernet peut comporter jusqu'à 1500 octets. La programmation du microcontrôleur se fera par DFU USB. Il est notable que la programmation du microcontrôleur et la communication vers l'extérieur se fait par le même connecteur USB.&lt;br /&gt;
&lt;br /&gt;
La communication se fait forcément via le PC auquel la carte fille est connectée par USB. Cela dit si ce PC est connecté en réseau, les fichiers auxquels le pico-ordinateur accède peuvent se trouver sur un autre PC. Si votre carte fille est correctement programmée comme carte RNDIS USB, le PC sous Linux va automatiquement créer une interface réseau &amp;lt;code&amp;gt;usb0&amp;lt;/code&amp;gt;. A vous de la démarrer avec la commande &amp;lt;code&amp;gt;ip link set usb0 up&amp;lt;/code&amp;gt; ou une commande du type &amp;lt;code&amp;gt;ip address add @IP/masque dev usb0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
La base de la programmation de cette carte est la démonstration LUFA RNDIS. Des versions de cette démonstration incluent une implantation de pile TCP/IP. A vous de voir à quel niveau vous souhaitez que votre carte réseau opère :&lt;br /&gt;
* si vous visez Ethernet, votre projet LUFA sera assez simple à écrire mais l'application sur le PC sera un peu exotique, il vous faudra utiliser la programmation socket en mode RAW ;&lt;br /&gt;
* si vous visez UDP, votre projet LUFA sera plus complexe mais l'application sur le PC pourra se faire avec des sockets en mode non connecté standard ;&lt;br /&gt;
* si vous visez TCP, votre projet LUFA sera complexe et nécessitera un microcontrôleur avec pas mal de mémoire, par contre vous pourrez utiliser des applications standard sur le PC (serveur Web ou FTP).&lt;br /&gt;
&lt;br /&gt;
Au niveau de la carte, en plus de votre pile réseau vous devez écrire les fonctions permettant de lister des fichiers distants, de les recevoir et d'en envoyer :&lt;br /&gt;
* Si la commande SPI est 0x01, la carte mère vous demande de lister les fichiers distants, vous devez donc former les paquets réseau nécessaires pour envoyer la demande, la commande SPI peut comporter un argument supplémentaire pour préciser la localisation des fichiers. A la suite d'une commande 0x01, la carte mère doit envoyer des commandes 0x11 pour récupérer tous les noms de fichiers, idéalement un nom par commande 0x11 pour ne pas déborder la mémoire du microcontrôleur. Si le fichier n'est pas le dernier la réponse SPI est 0x01 sinon 0x00.  Si vous utilisez Ethernet ou UDP, il faut prévoir un délai maximal pour la réception des paquets de sorte à ne pas bloquer la commande. En cas de non réception de paquet, il faut retourner un code SPI d'erreur, par exemple 0x02.&lt;br /&gt;
&lt;br /&gt;
* Si la commande SPI est 0x02, la carte mère souhaite récupérer un fichier. Vous devez former les paquets réseau nécessaires pour demander le fichier précisé dans la suite de la commande SPI. De la même façon que pour la liste, des commandes SPI ultérieures 0x12 doivent être envoyées pour récupérer le contenu du fichier, la carte mère précise dans la commande la taille de données qu'elle est prête à accepter par requête. Même principe pour les réponses SPI que pour les commandes 0x11. Si vous utilisez Ethernet ou UDP, il faut mettre en place le même dispositif de surveillance de perte de paquets que pour la liste.&lt;br /&gt;
&lt;br /&gt;
* Si la commande SPI est 0x03, la carte mère souhaite envoyer un fichier. Vous devez former les paquets réseau nécessaires pour préparer la réception du fichier précisé dans la suite de la commande SPI. De la même façon que pour la liste, des commandes SPI ultérieures 0x13 doivent être envoyées pour passer les fragements de fichier. Si vous utilisez Ethernet ou UDP, les paquets envoyés pour transmettre les fragments comportent un numéro de séquence. La carte mère termine par un fragment vide pour indiquer que le fichier est totalement transféré. Dans ce dernier cas un paquet particulier doit être envoyé pour indiquer la fin du fichier. Une réponse est requise pour ce paquet, cette réponse peut être un succès (tous les fragments ont été reçus) ou échec. Il convient de répercuter cette réponse en tant que réponse SPI : 0x00 pour succès ou 0x02 en cas d'erreur que ce soit une erreur remontée ou une absence de paquet réponse.&lt;br /&gt;
&lt;br /&gt;
Au niveau de la carte mère vous devez écrire les primitives système permettant de préparer et de réaliser les listes, récupération et envois de fichiers. Ces primitives sont de simples encapsulation des commandes SPI décrites ci-dessus avec attente des réponses SPI pour les commandes de chiffre de poid fort 0x1. Il faut cependant s'assurer, avant chaque requête SPI, que la carte RNDIS est libre en utilisant la commande 0xFF.&lt;br /&gt;
&lt;br /&gt;
Ces primitives sont utilisées par le système d'exploitation pour réaliser les commandes de sauvegarde et de chargement de fichiers. Il est supposé qu'il n'existe qu'une carte réseau par pico-ordinateur avec une ligne de sélection de périphérique SPI fixe.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille réseau &amp;quot;points d'accès de volume&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Cette carte est identique, au niveau électronique, à la carte réseau RNDIS. La seule différence réside dans la façon de faire transiter les paquets réseau de la carte vers le PC auquel elle est connectée en USB. Pour cette carte, il vous est proposé de faire ce transfert en utilisant deux points d'accès USB de type volume (bulk), un entrant et un sortant. Cette fois vous n'aurez pas l'aide du noyau Linux pour la création de l'interface réseau. Vous allez devoir écrire votre propre programme PC pour faire le pont entre la carte et une interface réseau virtuelle.&lt;br /&gt;
&lt;br /&gt;
Sous Linux la création d'une interface virtuelle est possible avec la fonction ci-dessous.&lt;br /&gt;
&lt;br /&gt;
 int allocateNetworkDevice(char *name,int flags){&lt;br /&gt;
 struct ifreq ifr;&lt;br /&gt;
 int fd,err;&lt;br /&gt;
 char *clonedev = &amp;quot;/dev/net/tun&amp;quot;;&lt;br /&gt;
 /* Open the clone device */&lt;br /&gt;
 if((fd=open(clonedev,O_RDWR))&amp;lt;0) return fd;&lt;br /&gt;
 /* Preparation of the struct ifr, of type &amp;quot;struct ifreq&amp;quot; */&lt;br /&gt;
 memset(&amp;amp;ifr,0,sizeof(ifr));&lt;br /&gt;
 ifr.ifr_flags=flags;   /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */&lt;br /&gt;
 if(name!=NULL) strncpy(ifr.ifr_name,name,IFNAMSIZ);&lt;br /&gt;
 /* Try to create the device */&lt;br /&gt;
 if((err=ioctl(fd,TUNSETIFF,(void *)&amp;amp;ifr))&amp;lt;0){ close(fd); return err; }&lt;br /&gt;
 /* Write back the name of the * interface to the variable &amp;quot;name&amp;quot; */&lt;br /&gt;
 if(name!=NULL) strcpy(name,ifr.ifr_name);&lt;br /&gt;
 return fd;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Le descripteur de fichier retourné est utilisable avec &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; pour récupérer les paquets Ethernet entrants et avec &amp;lt;code&amp;gt;write&amp;lt;/code&amp;gt; pour envoyer des paquets sur l'interface. Pour transmettre les paquets à la carte ou lire ceux provenant de la carte vous pouvez utiliser la bibliothèque &amp;lt;code&amp;gt;libusb-1.0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Pour le reste de la programmation liée à cette carte vous reporter à ce qui est demandé pour la carte réseau RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille réseau Ethernet ===&lt;br /&gt;
&lt;br /&gt;
Cette version de la carte réseau se connecte à un commutateur Ethernet et non pas à un PC pour communiquer avec le monde extérieur.&lt;br /&gt;
&lt;br /&gt;
Au niveau électronique une puce Ethernet ENC28J60 (ou supérieur) est supervisée par un microcontrôleur ATMega328p. Toutes les précisions concernant les cartes à base d'ATMega328p s'appliquent (voir par exemple la carte fille clavier &amp;quot;matrice de touches). Vous trouverez la documentation de la puce Ethernet à l'adresse http://ww1.microchip.com/downloads/en/devicedoc/39662c.pdf. Un exemple de programmtion de la puce ENC624J600 est disponible à l'adresse https://github.com/2xs/smews/tree/develop/targets/Arduino_ethernet/drivers. Vous pouvez vous en inspirer pour la programmation de la puce ENC28J60.&lt;br /&gt;
&lt;br /&gt;
La programmation spécifique à cette carte concerne l'envoi des paquets à la puce ENC28J60 et la récupération des paquets en provenance de la puce ENC28J60. Comme pour la liaison RNDIS, trois options s'ouvrent à vous pour l'implémentation de votre pile réseau :&lt;br /&gt;
&lt;br /&gt;
*programmation Ethernet, votre projet sera assez simple à écrire mais l'application sur le PC sera un peu exotique, il vous faudra utiliser la programmation socket en mode RAW ;&lt;br /&gt;
* programmation UDP, votre projet sera plus complexe mais l'application sur le PC pourra se faire avec des sockets en mode non connecté standard ;&lt;br /&gt;
* programmation TCP, votre projet sera plus complexe;  par contre vous pourrez utiliser des applications standard sur le PC (serveur Web ou FTP).&lt;br /&gt;
&lt;br /&gt;
Le reste de la programmation (communication avec la carte mère et ajouts dans le système d'exploitation) est identique à ce qui est décrit pour la carte réseau RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille son ===&lt;br /&gt;
 &lt;br /&gt;
D'un point de vue électronique la carte n'est pas très compliquée, elle comporte un ATMega328p comme coeur et sa spécificité est un convertisseur numérique vers analogique dit R-2R utilisant un réseau de résistance pour implanter la conversion. Utilisez au moins un DAC sur 8 bits, vous devez pouvoir pousser jusqu'à 12 bits en utilisant pratiquement toutes les sorties disponibles. En sortie du DAC utilisez un montage Darligton pour commander le haut-parleur. N'oubliez pas le connecteur HE10 pour connecter votre carte à une carte mère. Utilisez la ligne de sélection SPI par défaut pour que la carte mère puisse commander votre carte et prévoyez une ligne d'interruption. Enfin il vous faut prévoir un connecteur AVR ISP pour programmer le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
Le microcontrôleur de la carte fille doit être programmé pour pouvoir jouer des sons déjà enregistrés :&lt;br /&gt;
* des variables globales doivent être configurées pour spécifier les caractéristiques des enregistrements à jouer :&lt;br /&gt;
** précision d'échantillonnage (8 à 24 bits même si au-delà de 14 bits vous devez abandonner les bits de poids faibles),&lt;br /&gt;
** vitesse d'acquisition (vous trouverez la vitesse maximale par essais et erreurs),&lt;br /&gt;
** format des enregistrements (vous vous limiterez à un format PCM entier classique avec représentation petit-boutiste) ;&lt;br /&gt;
* une fonction permettant d'envoyer les échantillons, à la bonne vitesse, sur le DAC.&lt;br /&gt;
&lt;br /&gt;
Les échantillons sonores sont reçus par le bus SPI préfixés par le code commande 0x02. Les 2 valeurs de configuration, précision sur un octet et vitesse sur quatre octets sont envoyées préfixés par le code commande 0x01.&lt;br /&gt;
&lt;br /&gt;
Au niveau de la carte mère vous devez écrire les primitives système :&lt;br /&gt;
* la première primitive correspond au message SPI de code commande 0x01 et passe les paramètres de configuration à la carte fille ;&lt;br /&gt;
* la seconde primitive correspond au message SPI de code commande 0x02 et passe les échantillons sonores à jouer à la carte fille, la primitive s'assure auparavent que la carte n'est pas déjà occupée à jouer des échantillons avec la commande SPI 0xFF, en cas de carte occupée le code 0xFF est retourné.&lt;br /&gt;
&lt;br /&gt;
Ces primitives sont utilisées utilisée par le système d'exploitation pour implanter une nouvelle commande &amp;lt;code&amp;gt;PLAY&amp;lt;/code&amp;gt; permettant de jouer un fichier WAV :&lt;br /&gt;
* l'entête du fichier est récupéré avec la primitive &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; ;&lt;br /&gt;
* l'entête WAV est analysée pour récupérer la fréquence et la précision d'échantillonnage, ces données sont passées à la carte son via la première primitive décrite ci-dessus ;&lt;br /&gt;
* le nombre de canaux est récupéré dans l'entête, les echantillons du premier canal sont alors lus grâce à &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; et envoyés à la carte son en utilisant la seconde primitive ;&lt;br /&gt;
* si les échantillons sont envoyés trop vite et donnent lieu à un code d'erreur de la seconde primitive, les mêmes échantillons sont à nouveau envoyés et ainsi de suite ;&lt;br /&gt;
* éventuellement, si votre système d'exploitation dispose d'une primitive &amp;lt;code&amp;gt;usleep&amp;lt;/code&amp;gt; vous pouvez mettre en place un algorithme d'attente après chaque appel à la primitive, ce temps peut être calculé en fonction de la vitesse de restitution et du nombre d'échantillons envoyés.&lt;br /&gt;
&lt;br /&gt;
= Réalisations des élèves =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Numéro du binôme !! Numéro du groupe !! Elèves !! Page &lt;br /&gt;
|-&lt;br /&gt;
| Binôme 1&lt;br /&gt;
| Groupe 1&lt;br /&gt;
| Taha Nehari &amp;amp; Martin Chauveliere&lt;br /&gt;
| [[SE4Binome2023-1|Binôme 1 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 2&lt;br /&gt;
| Groupe 1&lt;br /&gt;
| Simon CRUCHET &amp;amp; Amaury BECQUET&lt;br /&gt;
| [[SE4Binome2023-2|Binôme 2 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 3&lt;br /&gt;
| Groupe 1&lt;br /&gt;
| Louis DERYCKERE &amp;amp; Romain DUHR&lt;br /&gt;
| [[SE4Binome2023-3|Binôme 3 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 4&lt;br /&gt;
| Groupe 1&lt;br /&gt;
| Thomas NAVE &amp;amp; Thibault DUYCK&lt;br /&gt;
| [[SE4Binome2023-4|Binôme 4 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 5&lt;br /&gt;
| Groupe 2&lt;br /&gt;
| Stéphane KADER ISSACK &amp;amp; Marion NORMAND&lt;br /&gt;
| [[SE4Binome2023-5|Binôme 5 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 6&lt;br /&gt;
| Groupe 2&lt;br /&gt;
| Dylan Ling&lt;br /&gt;
| [[SE4Binome2023-6|Binôme 6 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 7&lt;br /&gt;
| Groupe 2&lt;br /&gt;
| Louis Wijsman &amp;amp; Adrien Paliferro&lt;br /&gt;
| [[SE4Binome2023-7|Binôme 7 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 8&lt;br /&gt;
| Groupe 2&lt;br /&gt;
| Némo CAZIN &amp;amp; Antoine CEGARRA &lt;br /&gt;
| [[SE4Binome2023-8|Binôme 8 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 9&lt;br /&gt;
| Groupe 3&lt;br /&gt;
| Younes BENMBAREK &amp;amp; Youness EL QASTALANI&lt;br /&gt;
| [[SE4Binome2023-9|Binôme 9 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 10&lt;br /&gt;
| Groupe 3&lt;br /&gt;
| Heriniaina ANDRIANIRINTSOA &amp;amp; Chaymae RHANIM &lt;br /&gt;
| [[SE4Binome2023-10|Binôme 10 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 11&lt;br /&gt;
| Groupe 3&lt;br /&gt;
| Prénom Nom &amp;amp; Prénom Nom&lt;br /&gt;
| [[SE4Binome2023-11|Binôme 11 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Pico_SE4_2023/2024&amp;diff=1423</id>
		<title>Pico SE4 2023/2024</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Pico_SE4_2023/2024&amp;diff=1423"/>
		<updated>2023-09-12T12:45:08Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Réalisations des élèves */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Objectif =&lt;br /&gt;
&lt;br /&gt;
Pour l'année académique 2023/2024 nous vous demandons de construire un pico-ordinateur comprenant les éléments suivants :&lt;br /&gt;
* un processeur de type microcontrôleur ;&lt;br /&gt;
* un clavier ;&lt;br /&gt;
* un dispositif d'affichage ;&lt;br /&gt;
* un système d'exploitation stocké dans la mémoire flash du microcontrôleur ;&lt;br /&gt;
* une mémoire de masse allant au delà de la mémoire flash sus-citée ;&lt;br /&gt;
* un dispositif de communication avec l'extérieur.&lt;br /&gt;
&lt;br /&gt;
Pour faire en sorte que tous les éléments puissent communiquer entre eux nous vous demandons d'utiliser un bus série.&lt;br /&gt;
&lt;br /&gt;
= Compétences évaluées =&lt;br /&gt;
&lt;br /&gt;
Les compétences suivantes doivent être acquises durant ce module.&lt;br /&gt;
* Savoir comprendre, ou à défaut être actif en séances pour poser les questions pertinentes aux encadrants.&lt;br /&gt;
* Savoir produire un travail régulier et documenté durant la totalité de la période.&lt;br /&gt;
* Savoir concevoir et réaliser des cartes électroniques fonctionnelles.&lt;br /&gt;
* Savoir concevoir et programmer un circuit FPGA en VHDL.&lt;br /&gt;
* Savoir structurer et écrire des pilotes pour cartes électroniques.&lt;br /&gt;
* Savoir concevoir et implanter des primitives systèmes et un micro-système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
= Organisation du travail =&lt;br /&gt;
&lt;br /&gt;
Vous aurez, comme d'habitude, la lourde tâche de tester ce module de travaux pratiques.&lt;br /&gt;
&lt;br /&gt;
Ce sera d'autant moins facile que nous vous demandons de vous coordonner pour réaliser le pico-ordinateur : un seul exemplaire fonctionnel est attendu par groupes de 4 binômes.&lt;br /&gt;
&lt;br /&gt;
Vous allez donc devoir vous organiser pour que chaque binôme réalise une partie de l'ensemble. Cela dit des tâches identiques sont à réaliser par tous les binômes, ces tâches vous permettront de vous exercer mais aussi de tester vos réalisations spécifiques.&lt;br /&gt;
&lt;br /&gt;
== Matériel fourni ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[file:2023_Bouclier_Pico.pdf||thumb|right|400px]]&lt;br /&gt;
&lt;br /&gt;
Pour que chaque binôme puisse avoir un minimum d'autonomie, un matériel de base est fourni :&lt;br /&gt;
* un Arduino Uno pour prototyper le coeur d'une carte mère ;&lt;br /&gt;
* un bouclier Arduino pour disposer d'une mémoire de masse (carte SD) et de connecteurs vers les cartes filles, voir le schéma et le PCB ci-contre ;&lt;br /&gt;
* d'une matrice de LED et d'un afficheur 7-segments tous les deux gérables par SPI pour pouvoir écrire les briques de votre système d'exploitation.&lt;br /&gt;
&lt;br /&gt;
Le projet KiCAD pour le bouclier Arduino est disponible : [[Média:2023_Bouclier_Pico.zip]]&lt;br /&gt;
&lt;br /&gt;
Les projets KiCAD pour connecter les périphériques via un connecteur sont disponibles : [[Média:2023_HE10-periph.zip]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p style=&amp;quot;clear: both;&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[file:2023_Bouclier_Pico_PCB.png||thumb|center|300px]]&lt;br /&gt;
&lt;br /&gt;
Vision de la carte partiellement montée. L'accès à la carte SD est fonctionnel.&lt;br /&gt;
&lt;br /&gt;
[[file:2023_Bouclier_Pico_Test.jpg||thumb|center|300px]]&lt;br /&gt;
&lt;br /&gt;
Pour la partie programmation concernant la carte SD vous pouvez vous appuyer sur le projet ci-contre utilisant &amp;lt;code&amp;gt;avr-gcc&amp;lt;/code&amp;gt; comme compilateur : [[Fichier:TestSD_avrgcc.zip]].&lt;br /&gt;
&lt;br /&gt;
== Réalisations par binôme ==&lt;br /&gt;
&lt;br /&gt;
Chaque binôme réalise :&lt;br /&gt;
* un système d'exploitation basé sur un ordonnanceur ;&lt;br /&gt;
* une carte fille FPGA programmée par VHDL, le binôme écrit aussi le code pour que la carte puisse être gérée par le système d'exploitation ;&lt;br /&gt;
* une carte mère ou une carte fille à base de microcontrôleur, le binôme écrit aussi le code pour que la carte puisse être gérée par le système d'exploitation, le binôme peut réaliser plusieurs cartes pour maximiser sa note.&lt;br /&gt;
&lt;br /&gt;
== Réalisation par groupe de binômes ==&lt;br /&gt;
&lt;br /&gt;
Par groupe de 4 binômes vous devez réaliser un pico-ordinateur complet :&lt;br /&gt;
* une carte mère ;&lt;br /&gt;
* une carte fille FPGA/VHDL fonctionnelle et supportée par votre carte mère ;&lt;br /&gt;
* au moins 3 cartes filles fonctionnelles et supportées par votre carte mère (clavier, écran, réseau) ;&lt;br /&gt;
* vous pouvez ajouter une cinquième carte fille optionnelle de type carte son.&lt;br /&gt;
&lt;br /&gt;
= Cahier des charges =&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
Vous n'avez pas besoin d'avoir conçu et réalisé des cartes électroniques pour commencer à écrire le système d'exploitation du pico-ordinateur et en particulier l'ordonnanceur sous-jacent.&lt;br /&gt;
&lt;br /&gt;
Le principe est d'utiliser un minuteur du microcontrôleur pour lancer périodiquement une fonction d'interruption que vous allez transformer en ordonnanceur.&lt;br /&gt;
&lt;br /&gt;
Dans un premier temps vous testerez votre ordonnanceur en créant deux tâches statiques pour faire clignoter, avec des périodes différentes, deux LED du bouclier fourni.&lt;br /&gt;
&lt;br /&gt;
Par la suite vous allez complexifier votre ordonnanceur en ajoutant :&lt;br /&gt;
* une tâche de lecture de caractère par le port série (stocké en mémoire partagé) ;&lt;br /&gt;
* une tâche d'écriture sur le port série (du caractère lu sur le port série) ;&lt;br /&gt;
* une tâche d'écriture sur la matrice (du caractère lu sur le port série) ;&lt;br /&gt;
* une tâche d'écriture sur l'afficheur 7 segments (du caractère lu sur le port série).&lt;br /&gt;
&lt;br /&gt;
Les deux dernières tâches sont plus compliquées à réaliser dans la mesure où elles utilisent une ressource commune.&lt;br /&gt;
&lt;br /&gt;
== Cartes filles FPGA ==&lt;br /&gt;
&lt;br /&gt;
Les cartes filles FPGA doivent être programmées en VHDL. Tous les binômes doivent implanter en VHDL :&lt;br /&gt;
* un contrôleur de bus série SPI ;&lt;br /&gt;
* un décodeur des commandes reçues par SPI (commandes sur un octet avec éventuellement des paramètres à suivre) ;&lt;br /&gt;
* un contrôleur d'écran VGA affichant le contenu graphique de la RAM de la carte FPGA.&lt;br /&gt;
&lt;br /&gt;
A minima il faut une commande pour insérer un pixel d'une couleur donnée dans la RAM d'affichage.&lt;br /&gt;
&lt;br /&gt;
Vous pouvez aussi ajouter des fonctionnalités supplémentaires à votre carte FPGA :&lt;br /&gt;
* mémoire de masse par accès direct à une carte mémoire SD ;&lt;br /&gt;
* carte réseau Ethernet en utilisant un module PHY Ethernet.&lt;br /&gt;
&lt;br /&gt;
Pour les fonctionnalités supplémentaires vous devez prévoir des commandes supplémentaire au niveau du décodeur.&lt;br /&gt;
&lt;br /&gt;
== Cartes électroniques ==&lt;br /&gt;
&lt;br /&gt;
Vous devez réaliser deux type de cartes électroniques à base de microcontrôleur : une carte mère et des cartes filles.&lt;br /&gt;
La carte FPGA/VHDL décrite dans la section précédente est considérée comme une carte fille.&lt;br /&gt;
&lt;br /&gt;
Les cartes filles sont connectées via un bus série à la carte mère. C'est aussi la carte mère qui alimente les cartes filles.&lt;br /&gt;
Enfin la carte mère dispose d'une mémoire permanente pour stocker des fichiers.&lt;br /&gt;
&lt;br /&gt;
Les cartes filles peuvent être de différents types :&lt;br /&gt;
* carte fille clavier ;&lt;br /&gt;
* carte fille d'affichage ;&lt;br /&gt;
* carte fille série (se comporte comme un clavier et comme un dispositif d'affichage) ;&lt;br /&gt;
* carte fille réseau ;&lt;br /&gt;
* carte fille mémoire de masse (alternative à la mémoire de masse de la carte mère) ;&lt;br /&gt;
* carte fille son.&lt;br /&gt;
&lt;br /&gt;
Pour un type donné vous avez le choix entre plusieurs technologies pour réaliser votre carte. Par exemple une carte fille clavier peut être implantée par une matrice de touches ou en utilisant un clavier USB.&lt;br /&gt;
&lt;br /&gt;
== Programmation système ==&lt;br /&gt;
&lt;br /&gt;
Le système d'exploitation du pico-ordinateur doit avoir les fonctionnalités d'un DOS (Disk Operating System), à savoir :&lt;br /&gt;
* lecture des commandes tapées par l'utilisateur ;&lt;br /&gt;
* téléchargement d'exécutables ou de sources via le dispositif de communication extérieur  ;&lt;br /&gt;
* sauvegarde et chargement d'exécutables ou de sources via la mémoire de masse ;&lt;br /&gt;
* permettre l'affichage de chaînes de caractères ;&lt;br /&gt;
* comprend un interpréteur micro-python pour faire tourner les sources ;&lt;br /&gt;
* les différentes fonctionnalités sont réalisées sous forme de tâches gérées par un ordonnanceur.&lt;br /&gt;
&lt;br /&gt;
=== Commandes de base ===&lt;br /&gt;
&lt;br /&gt;
Ces commandes sont les commandes les plus simples à implanter :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Commande !! Description&lt;br /&gt;
|-&lt;br /&gt;
| VERSION || Affiche la version du système d'exploitation&lt;br /&gt;
|-&lt;br /&gt;
| DEVICES || Affiche la liste des cartes filles connectées&lt;br /&gt;
|-&lt;br /&gt;
| ECHO || Affiche les arguments de la commande&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Commandes liées aux processus ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Commande !! Description&lt;br /&gt;
|-&lt;br /&gt;
| PS || Liste les processus disponibles et leur état&lt;br /&gt;
|-&lt;br /&gt;
| SLEEP || Met un processus en sommeil&lt;br /&gt;
|-&lt;br /&gt;
| WAKE || Relance un processus dormant&lt;br /&gt;
|-&lt;br /&gt;
| EXEC || Création d'un processus à partir d'un fichier exécutable&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
La commande EXEC est complexe à réaliser, elle est optionnelle pour l'année 2023/2024.&lt;br /&gt;
&lt;br /&gt;
=== Commandes liées au système de fichiers ===&lt;br /&gt;
&lt;br /&gt;
Commandes pour gérer le système de fichiers :&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Commande !! Description&lt;br /&gt;
|-&lt;br /&gt;
| FORMAT || Formate le système de fichiers&lt;br /&gt;
|-&lt;br /&gt;
| LIST || Affiche les fichiers du répertoire principal&lt;br /&gt;
|-&lt;br /&gt;
| CREATE || Création d'un fichier avec l'entrée standard&lt;br /&gt;
|-&lt;br /&gt;
| TYPE || Affiche le contenu d'un fichier&lt;br /&gt;
|-&lt;br /&gt;
| COPY || Copie un fichier&lt;br /&gt;
|-&lt;br /&gt;
| RENAME || Renomme un fichier&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Commandes liées au réseau ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Commande !! Description&lt;br /&gt;
|-&lt;br /&gt;
| REMOTE || Liste les fichiers disponibles sur le réseau&lt;br /&gt;
|-&lt;br /&gt;
| GET || Télécharge un fichier en provenance du réseau&lt;br /&gt;
|-&lt;br /&gt;
| PUT || Sauve un fichier sur le réseau&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Programmation des pilotes ==&lt;br /&gt;
&lt;br /&gt;
La programmation c'est aussi l'écriture des sous-systèmes ou des pilotes liés à chaque cartes :&lt;br /&gt;
* pour la carte mère, il faut écrire un sous-système de gestion de fichiers ;&lt;br /&gt;
* pour la carte fille comportant une matrice de touches, il faut écrire le pilote identifiant les touches actionnées et gérant l'envoi de ces touches à la carte mère ;&lt;br /&gt;
* pour la carte fille gérant un clavier USB, il faut utiliser un projet LUFA pour scanner régulièrement le clavier USB et envoyer d'éventuels événements à la carte mère ;&lt;br /&gt;
*  pour la carte fille gérant un écran LCD, il faut écrire le pilote capable de gérer l'écran et la partie récupérant les données de la carte mère ;&lt;br /&gt;
* pour la carte fille gérant une clé USB, il faut utiliser un projet LUFA pour l'accès à la clé et écrire un sous-système de gestion de fichiers ;&lt;br /&gt;
* la carte fille gérant une connexion série ne nécessite qu'un modeste pilote de communication avec la carte mère ;&lt;br /&gt;
* pour la carte fille permettant une connexion avec le monde extérieur via de simples points d'accès USB de volume (EP Bulk), il faut écrire le pilote pour communication avec la carte mère mais aussi le programme sur le PC permettant la réception ou l'envoi de fichiers ;&lt;br /&gt;
* pour la carte fille permettant une connexion Ethernet au dessus d'USB (RNDIS), il faut écrire une micro-pile réseau capable de récupérer et d'envoyer des fichiers au travers de paquets Ethernet mais aussi le programme sur le PC cible capable de comprendre ces paquets Ethernet ;&lt;br /&gt;
* pour la carte fille incluant une puce Ethernet, il faut implanter la micro-pile réseau et le programme évoquée ci-dessus mais aussi le pilote capable de gérer la puce Ethernet ;&lt;br /&gt;
* pour la carte fille son, il faut écrire la partie permettant de récupérer les échantillons, les copier en mémoire, et les jouer à la vitesse d'échantillonnage préalablement transmise.&lt;br /&gt;
&lt;br /&gt;
= Spécifications techniques =&lt;br /&gt;
&lt;br /&gt;
== Ordonnanceur ==&lt;br /&gt;
&lt;br /&gt;
Pour réaliser votre ordonnanceur commencez par programmer le minuteur 1 de l'ATMega328p de sorte à ce qu'il génère une interruption toutes&lt;br /&gt;
les 20ms. L'interruption va déclencher une fonction de gestion d'interruption (ISR pour Interrupt Service Routine). Vous utiliserez une ISR nue pour éviter les interférences du compilateur sur la pile d'exécution :&lt;br /&gt;
 ISR(TIMER1_COMPA_vect,ISR_NAKED)&lt;br /&gt;
 {&lt;br /&gt;
 /* Sauvegarde du contexte de la tâche interrompue */&lt;br /&gt;
 ...&lt;br /&gt;
 /* Appel à l'ordonnanceur */&lt;br /&gt;
 scheduler();&lt;br /&gt;
 /* Récupération du contexte de la tâche ré-activée */&lt;br /&gt;
 ...&lt;br /&gt;
 asm volatile ( &amp;quot;reti&amp;quot; );&lt;br /&gt;
 }&lt;br /&gt;
Vous constatez qu'il vous reste à écrire, dans l'ISR, le code pour sauvegarder et récupérer le contexte d'exécution d'une tâche. Pour cela réfléchissez aux éléments d'un microcontrôleur qui sont nécessaires pour l'exécution d'un programme puis réfléchissez à une méthode pour sauver l'état de ces éléments. &lt;br /&gt;
&lt;br /&gt;
Au moins dans un premier temps, les tâches seront définies de façon statique. Toutes les tâches doivent être définies dans un tableau global, seront lancées dès le démarrage du microcontrôleur et ne se termineront que lorsque le microcontrôleur sera arrêté ou relancé. Une tâche est à définir par une structure dont un des champs doit être la fonction réalisant la tâche. A vous de définir les autres champs.&lt;br /&gt;
&lt;br /&gt;
Avant de démarrer l'ordonnanceur, il faut prendre soin à ce que la récupération du contexte dans l'ISR fonctionne alors que les tâches n'auront pas encore été lancées. Il faut donc une fonction permettant d'initialiser le contexte pour chaque tâche.&lt;br /&gt;
&lt;br /&gt;
== Cartes électroniques à microcontrôleur ==&lt;br /&gt;
&lt;br /&gt;
Le bus série préconisé pour la communication entre la carte mère et les cartes filles est un bus SPI. Au niveau physique, les connexions entre cartes mères et cartes filles doivent être réalisées via des connecteurs HE-10 à 8 broches :&lt;br /&gt;
* 2 broches pour l'alimentation ;&lt;br /&gt;
* 3 broches pour les signaux SPI (MISO, MOSI, SCK) ;&lt;br /&gt;
* 1 broche pour le CS (Chip Select) ;-&lt;br /&gt;
* 1 broche pour une éventuelle ligne d'interruption ;&lt;br /&gt;
* 1 broche pour une eventuelle réinitialisation de la carte (Reset).&lt;br /&gt;
&lt;br /&gt;
Il est conseillé d'organiser les broches sur les connecteurs HE-10 sur le modèle du bouclier Arduino fourni.&lt;br /&gt;
&lt;br /&gt;
La carte mère est constituée autour d'un ATMega328p et d'une puce mémoire de type AT45DB641E de 8 Mo. Il faut réflechir à l'alimentation sachant que :&lt;br /&gt;
* l'alimentation de la carte mère doit être suffisante pour alimenter les cartes filles ;&lt;br /&gt;
* l'alimentation du microcontrôleur doit être compatible avec l'alimentation de la puce mémoire sauf à prévoir une conversion de niveaux logiques entre les deux puces ;&lt;br /&gt;
* les cartes filles d'un même pico-ordinateur doivent être alimentées avec la même tension.&lt;br /&gt;
&lt;br /&gt;
Voici quelques exemples d'architectures de cartes filles :&lt;br /&gt;
* une carte fille SPI avec un ATMega328p et une matrice de touches ;&lt;br /&gt;
* une carte fille SPI avec un AT90USB647 pour connexion à un clavier USB ou une clef USB ;&lt;br /&gt;
* une carte fille SPI avec un ATMega328p et un écran LCD 2 lignes HD44780 ;&lt;br /&gt;
* une carte fille SPI avec un ATMega16u2 pour une connexion série USB ;&lt;br /&gt;
* une carte fille SPI avec un ATMega328p et un DAC R-2R comme carte son ;&lt;br /&gt;
* une carte fille SPI avec un ATMega16u2 (ou supérieur) pour une connexion réseau (périphérique USB générique EP bulk ou périphérique USB RNDIS) ;&lt;br /&gt;
* une carte fille SPI avec un ATMega328p et un ENC28J60 pour une connexion Ethernet 10Mb/s.&lt;br /&gt;
&lt;br /&gt;
Toutes les cartes doivent permettre un accès au port série de leur microcontrôleur pour un déverminage via un FTDI. Vous devez aussi ajouter des points de test pour les lignes importantes : lignes du bus SPI, horloge, alimentations, etc.&lt;br /&gt;
&lt;br /&gt;
Toutes les cartes filles répondent à la commande SPI constituée de l'octet de commande 0x00 et de l'octet de donnée 0x00. Le résultat se lit sur le second octet de réponse et détermine le type de la carte fille. Le chiffre de poid fort de la réponse est un code magique : 0xa. Le chiffre de poid faible est donné par le tableau ci-dessous :&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Chiffre !! Type de carte&lt;br /&gt;
|-&lt;br /&gt;
| 0x1 || Clavier&lt;br /&gt;
|-&lt;br /&gt;
| 0x2 || Affichage&lt;br /&gt;
|-&lt;br /&gt;
| 0x4 || Réseau&lt;br /&gt;
|-&lt;br /&gt;
| 0x8 || Carte son&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Il est bon aussi de prévoir que les cartes filles puissent répondre à une commande SPI permettant de savoir si elles sont occupées ou non. L'octet de commande serait 0xFF et l'octet de donnée 0xFF. En cas de succès les deux octets de réponse sont à 0x55. Les cartes filles doivent prendre soin d'initialiser leur réponse SPI à autre chose que 0x55 lorsqu'elles se lancent dans un traitement autre qu'une écoute SPI.&lt;br /&gt;
&lt;br /&gt;
== Electronique et programmation système ==&lt;br /&gt;
 &lt;br /&gt;
=== Carte mère ===&lt;br /&gt;
&lt;br /&gt;
La carte mère doit comporter un microcontrôleur ATMega328p, une puce mémoire AT45DB641E et 5 connecteurs HE10 pour connecter une carte fille FPGA et 4 cartes filles à microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
Vous avez aussi quelques points à approfondir.&lt;br /&gt;
# La source d'alimentation de votre pico-ordinateur, le plus simple semble être un connecteur USB pour utiliser soit un PC soit une batterie comme source ;&lt;br /&gt;
# La tension d'alimentation du microcontrôleur et des cartes filles :&lt;br /&gt;
#* soit vous optez pour du 5V auquel cas il faut prévoir un régulateur de tension pour la puce mémoire et une adaptation des niveaux logiques pour cette même puce (voir le schéma des boucliers Arduino),&lt;br /&gt;
#* soit vous partez sur du 3.3V et vos cartes filles doivent tourner en 3.3V, vu que vous aurez probablement un adaptateur 5V il faut quand même prévoir un régulateur 3.3V assez costaud sur la carte mère, de plus vous ne pouvez pas dépasser 8Mhz comme horloge ;&lt;br /&gt;
# La méthode de programmation de la carte mère :&lt;br /&gt;
#* soit vous programmez le microcontrôleur via un connecteur AVR ISP, un programmateur et l'utilitaire &amp;lt;code&amp;gt;avrdude&amp;lt;/code&amp;gt; ;&lt;br /&gt;
#* soit vous ajoutez une puce pour réaliser un pont USB vers série vous pourrez alors programmer le microcontrôleur avec &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;, attention il faut tout de même prévoir des connecteurs AVR ISP pour charger l'amorceur sur l'ATMega328p et l'éventuel ATMega8u2 (vous utilisez cette puce pour l'USB/série plutôt qu'une puce FTDI).&lt;br /&gt;
&lt;br /&gt;
Du coté programmation vous êtes chargés d'écrire les fonctions d'accès à la mémoire, des primitives systèmes implantant un micro-système de fichiers et des primitives de communication via le bus SPI.&lt;br /&gt;
&lt;br /&gt;
Les fonctions de base d'accès à la mémoire sont facilement trouvables, par exemple sur les sites du bureau d'études systèmes embarqués des PeiP.&lt;br /&gt;
&lt;br /&gt;
Concernant le micro-système de fichiers, les fonctionnalités suivantes doivent être implantées :&lt;br /&gt;
&lt;br /&gt;
* le système de fichiers doit résider dans la mémoire de 8 Mo, les accès à la mémoire se font par blocs de 256 octets ;&lt;br /&gt;
* l'accès au système de fichiers se fait par des primitives système ;&lt;br /&gt;
* le micro-système de fichiers ne comporte qu'un répertoire : le répertoire principal, ce dernier peut comporter au maximum 64 fichiers, un fichier est caractérisé par un nom de 16 caractères au maximum, sa taille et ses blocs de données, un fichier est décrit par un maximum de 16 blocs de données ;&lt;br /&gt;
* le superbloc du système de fichiers comprend, en plus de la description du répertoire racine, une carte bit à bit des blocs de données libres, cette carte nécessite 16 blocs ;&lt;br /&gt;
* les différentes primitives à implanter sont :&lt;br /&gt;
** &amp;lt;code&amp;gt;append&amp;lt;/code&amp;gt; pour créer un fichier si non existant et ajouter des données en fin de fichier, les paramètres sont le nom du fichier, les données à ajouter et la taille des données,&lt;br /&gt;
** &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; pour lire des données dans un fichier, les paramètres sont le nom du fichier, le tableau dans lequel stocker les données, la taille du tableau et le déplacement par rapport au début du fichier,&lt;br /&gt;
** &amp;lt;code&amp;gt;remove&amp;lt;/code&amp;gt; pour détruire un fichier, le seul paramètre est le nom du fichier,&lt;br /&gt;
** &amp;lt;code&amp;gt;rename&amp;lt;/code&amp;gt; pour renommer un fichier, les paramètres sont l'ancien et le nouveau noms du fichier,&lt;br /&gt;
** &amp;lt;code&amp;gt;copy&amp;lt;/code&amp;gt; pour copier un fichier, les paramètres sont le nom du fichier original et le nom de la copie.&lt;br /&gt;
&lt;br /&gt;
Les primitives pour le bus SPI doivent être :&lt;br /&gt;
* une fonction d'initialisation avec le mode SPI désiré et la vitesse d'horloge souhaitée ;&lt;br /&gt;
* une primitive pour envoyer quelques octets via le bus SPI :&lt;br /&gt;
** les paramètres de la primitive sont le tableau des octets à envoyer, le tableau des octets à recevoir, le nombre d'octets à envoyer et la spécification de la sortie CS de sélection du périphérique SPI,&lt;br /&gt;
** la primitive stocke l'opération dans une file et effectue l'envoi dès que le bus est libre,&lt;br /&gt;
** si la file est pleine la primitive peut retourner un code d'erreur sinon la primitive retourne l'identifiant unique de l'opération,&lt;br /&gt;
** les octets de réponse du périphérique sont stockés dans le tableau des octets à recevoir, si le pointeur est nul les réponses ne sont pas stockées ;&lt;br /&gt;
* une primitive pour attendre la fin d'un envoi SPI, il faut donner en unique paramètre l'identifiant de l'opération, l'attente s'effectue en mettant le processus appelant en mode sommeil et en le réveillant dès que l'opération est effectuée.&lt;br /&gt;
&lt;br /&gt;
Précisons que les tableaux stockés dans la file d'attente (requête et réponse SPI) le sont sous la forme de pointeurs. Ces pointeurs peuvent être librérés une fois l'opération effectuée.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille clavier &amp;quot;matrice de touches&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
La réalisation de la carte est simple, il s'agit de scanner une matrice de touches à l'aide d'un ATMega328p. N'oubliez pas le connecteur HE10 pour la connexion de cette carte fille à une carte mère. Sur le connecteur HE10 il faut prévoir à la fois la ligne de sélection SPI (utilisez la broche SS par défaut sur votre carte) et une ligne pour générer une interruption sur la carte mère. Vous devez faire avec l'alimentation fournie par la carte mère. Regardez aussi la problèmatique sur la programmation décrite dans la section sur la carte mère.&lt;br /&gt;
&lt;br /&gt;
Du coté programmation, c'est plus compliqué, vous êtes déjà chargés d'écrire la fonction de scan des touches :&lt;br /&gt;
* le scan des touches consiste juste à passer les lignes de la matrice en sorties, les colonnes en entrées avec résistance de charge et de rentrer dans une boucle pour passer une sortie à GND tandis que les autres restent à VCC, il suffit alors de consulter les entrées pour voir si une touche est appuyée (ou plusieurs) ;&lt;br /&gt;
* si une touche est appuyée la touche est stockée dans un tampon et la ligne d'interruption est activée ;&lt;br /&gt;
* si une requête SPI de code commande 0x01 est reçue, le nombre de touches dans le tampon est envoyé suivi des touches elles-mêmes.&lt;br /&gt;
&lt;br /&gt;
Ensuite, au niveau de la carte mère vous devez écrire la primitive gérant les claviers. Cette primitive prend en paramètre la ligne de sélection SPI du clavier ciblé et un tampon pour stocker les codes des touches. La taille du tampon est aussi passée en paramètre. La primitive prépare une transmission SPI constituée du seul octet de valeur 0x01 en prenant soin de préciser un tableau pour stocker d'éventuelles touches. Attention, la transmission SPI est constituée de l'octet 0x01 mais aussi d'autant d'octets de valeurs indéterminées qu'il est attendu d'octets dans la réponse SPI. La primitive se met alors en attente de la réponse.&lt;br /&gt;
&lt;br /&gt;
Au niveau du système d'exploitation les comportements suivants sont à implanter :&lt;br /&gt;
* à l'initialisation de la carte mère les périphériques SPI doivent être contactés pour déterminer lequels sont des claviers, des commandes SPI 0x00 sont donc envoyées avec attente des réponses SPI ;&lt;br /&gt;
* le processus SHELL toujours présent dans le système d'exploitation doit avoir le comportement suivant :&lt;br /&gt;
** si une interruption est reçue qui correspond à un périphérique clavier, le SHELL doit utiliser la primitive de lecture clavier pour obtenir la ou les touches appuyées ;&lt;br /&gt;
** dans un premier temps, les caractères reçus sont affichés en utilisant la primitive d'affichage (echo) ;&lt;br /&gt;
** à terme les lignes de caractères reçues sont analysées pour en extraire des commandes et les exécuter.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille clavier &amp;quot;USB&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Votre carte électronique doit tourner autour d'un AT90USB647 (ou supérieur). Ce microcontrôleur peut être programmé, en utilisant la bibliothèque LUFA, comme hôte USB. Il est donc possible de gérer, de cette façon un clavier USB et de faire interface avec la carte mère. Le schéma de la carte est très semblable à celui d'une carte comportant un ATMega16u2. Vous pouvez vous appuyer sur ce [https://wiki-se.plil.fr/mediawiki/index.php/SE4_2022/2023_EC5 projet keylogger]. Le plus simple est de programmer le microcontrôleur en utilisant l'utilitaire &amp;lt;code&amp;gt;dfu-programmer&amp;lt;/code&amp;gt;, pour cela il faut prévoir, en plus d'un connecteur USB A femelle pour le clavier, un connecteur USB mâle pour la programmation.&lt;br /&gt;
&lt;br /&gt;
La programmation pour la gestion du clavier USB doit se reposer sur la démonstration &amp;lt;code&amp;gt;KeyboardHost&amp;lt;/code&amp;gt; de la bibliothèque LUFA. La conversion des modificateurs et des codes de touches en caractères ASCII sont à votre charge.&lt;br /&gt;
&lt;br /&gt;
Pour le reste de la programmation voir la section sur la carte fille &amp;quot;matrice de touches&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille écran LCD ===&lt;br /&gt;
&lt;br /&gt;
Cette carte comporte un ATMega328p et un écran LCD à base de contrôleur HD44780. L'écran LCD nécessite un potentiomètre pour régler la luminosité   des cristaux liquides. N'oubliez pas le connecteur HE10 pour la connexion de cette carte fille à une carte mère. Sur le connecteur HE10 il faut prévoir une ligne de sélection SPI. Aucune ligne d'interruption n'est nécessaire pour cette carte. Enfin il vous faut prévoir un connecteur AVR ISP pour programmer le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
Le microcontrôleur de la carte fille doit être programmé pour gérer le contrôleur HD44780 ou compatible :&lt;br /&gt;
* les écrans avec 1, 2, 3 ou 4 lignes doivent être gérés ;&lt;br /&gt;
* les caractères ASCII doivent être affichés sur l'écran ;&lt;br /&gt;
* les caractères spéciaux &amp;lt;code&amp;gt;\n&amp;lt;/code&amp;gt; et &amp;lt;code&amp;gt;\r&amp;lt;/code&amp;gt; doivent être pris en compte pour le saut de ligne et le retour chariot ;&lt;br /&gt;
* les codes VT100 doivent être pris en compte, en particulier pour le déplacement du curseur doivent être pris en compte ;&lt;br /&gt;
* le contrôleur HD44780 ou compatible doit être configuré en mode défilement automatique.&lt;br /&gt;
&lt;br /&gt;
Les caractères à afficher ou spéciaux (y compris les séquences VT100) sont reçus par le bus SPI par la carte fille préfixés par le code commande 0x01. &lt;br /&gt;
&lt;br /&gt;
Au niveau de la carte mère vous devez écrire la primitive système. Cette primitive prend en paramètre la ligne de sélection SPI de l'écran ciblé et la chaîne des caractères à envoyer. La primitive prépare une transmission SPI constituée de l'octet de commande 0x01 et des octets correspondant aux caractères.&lt;br /&gt;
&lt;br /&gt;
Il ne faut pas demander un affichage si un autre affichage est en cours. C'est possible à réaliser avec la ligne prévue pour une interruption. La carte fille peut mettre cette ligne en état haut quand un affichage est en cours. Du coup la primitive peut se mettre en attente sur un état bas avant d'envoyer la requête SPI. C'est aussi possible de lancer des commandes 0xFF sur la carte jusqu'à obtenir les octets de réponse indiquant que la carte est libre.&lt;br /&gt;
&lt;br /&gt;
Cette primitive est utilisée par le système d'exploitation pour réaliser l'écho des commandes dans le SHELL et aussi par toutes les commandes qui nécessitent un affichage. Tous les écrans doivent être sollicités lors des affichages, il faut donc que le système d'exploitation scanne les périphériques SPI pour trouver les écrans comme il le fait pour les claviers.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille réseau RNDIS ===&lt;br /&gt;
&lt;br /&gt;
Le but de cette carte est de permettre au pico-ordinateur de converser avec l'extérieur. Une carte RNDIS permet de faire transister des paquets Ethernet au dessus d'une liaison USB. La carte n'a besoin que d'un microcontrôleur avec capacités USB pour fonctionner. Vous pouvez utiliser un &lt;br /&gt;
ATMega16u2, un ATMega32u4 ou un AT90USB suivant la taille mémoire dont vous souhaitez disposer. Gardez en mémoire qu'un paquet Ethernet peut comporter jusqu'à 1500 octets. La programmation du microcontrôleur se fera par DFU USB. Il est notable que la programmation du microcontrôleur et la communication vers l'extérieur se fait par le même connecteur USB.&lt;br /&gt;
&lt;br /&gt;
La communication se fait forcément via le PC auquel la carte fille est connectée par USB. Cela dit si ce PC est connecté en réseau, les fichiers auxquels le pico-ordinateur accède peuvent se trouver sur un autre PC. Si votre carte fille est correctement programmée comme carte RNDIS USB, le PC sous Linux va automatiquement créer une interface réseau &amp;lt;code&amp;gt;usb0&amp;lt;/code&amp;gt;. A vous de la démarrer avec la commande &amp;lt;code&amp;gt;ip link set usb0 up&amp;lt;/code&amp;gt; ou une commande du type &amp;lt;code&amp;gt;ip address add @IP/masque dev usb0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
La base de la programmation de cette carte est la démonstration LUFA RNDIS. Des versions de cette démonstration incluent une implantation de pile TCP/IP. A vous de voir à quel niveau vous souhaitez que votre carte réseau opère :&lt;br /&gt;
* si vous visez Ethernet, votre projet LUFA sera assez simple à écrire mais l'application sur le PC sera un peu exotique, il vous faudra utiliser la programmation socket en mode RAW ;&lt;br /&gt;
* si vous visez UDP, votre projet LUFA sera plus complexe mais l'application sur le PC pourra se faire avec des sockets en mode non connecté standard ;&lt;br /&gt;
* si vous visez TCP, votre projet LUFA sera complexe et nécessitera un microcontrôleur avec pas mal de mémoire, par contre vous pourrez utiliser des applications standard sur le PC (serveur Web ou FTP).&lt;br /&gt;
&lt;br /&gt;
Au niveau de la carte, en plus de votre pile réseau vous devez écrire les fonctions permettant de lister des fichiers distants, de les recevoir et d'en envoyer :&lt;br /&gt;
* Si la commande SPI est 0x01, la carte mère vous demande de lister les fichiers distants, vous devez donc former les paquets réseau nécessaires pour envoyer la demande, la commande SPI peut comporter un argument supplémentaire pour préciser la localisation des fichiers. A la suite d'une commande 0x01, la carte mère doit envoyer des commandes 0x11 pour récupérer tous les noms de fichiers, idéalement un nom par commande 0x11 pour ne pas déborder la mémoire du microcontrôleur. Si le fichier n'est pas le dernier la réponse SPI est 0x01 sinon 0x00.  Si vous utilisez Ethernet ou UDP, il faut prévoir un délai maximal pour la réception des paquets de sorte à ne pas bloquer la commande. En cas de non réception de paquet, il faut retourner un code SPI d'erreur, par exemple 0x02.&lt;br /&gt;
&lt;br /&gt;
* Si la commande SPI est 0x02, la carte mère souhaite récupérer un fichier. Vous devez former les paquets réseau nécessaires pour demander le fichier précisé dans la suite de la commande SPI. De la même façon que pour la liste, des commandes SPI ultérieures 0x12 doivent être envoyées pour récupérer le contenu du fichier, la carte mère précise dans la commande la taille de données qu'elle est prête à accepter par requête. Même principe pour les réponses SPI que pour les commandes 0x11. Si vous utilisez Ethernet ou UDP, il faut mettre en place le même dispositif de surveillance de perte de paquets que pour la liste.&lt;br /&gt;
&lt;br /&gt;
* Si la commande SPI est 0x03, la carte mère souhaite envoyer un fichier. Vous devez former les paquets réseau nécessaires pour préparer la réception du fichier précisé dans la suite de la commande SPI. De la même façon que pour la liste, des commandes SPI ultérieures 0x13 doivent être envoyées pour passer les fragements de fichier. Si vous utilisez Ethernet ou UDP, les paquets envoyés pour transmettre les fragments comportent un numéro de séquence. La carte mère termine par un fragment vide pour indiquer que le fichier est totalement transféré. Dans ce dernier cas un paquet particulier doit être envoyé pour indiquer la fin du fichier. Une réponse est requise pour ce paquet, cette réponse peut être un succès (tous les fragments ont été reçus) ou échec. Il convient de répercuter cette réponse en tant que réponse SPI : 0x00 pour succès ou 0x02 en cas d'erreur que ce soit une erreur remontée ou une absence de paquet réponse.&lt;br /&gt;
&lt;br /&gt;
Au niveau de la carte mère vous devez écrire les primitives système permettant de préparer et de réaliser les listes, récupération et envois de fichiers. Ces primitives sont de simples encapsulation des commandes SPI décrites ci-dessus avec attente des réponses SPI pour les commandes de chiffre de poid fort 0x1. Il faut cependant s'assurer, avant chaque requête SPI, que la carte RNDIS est libre en utilisant la commande 0xFF.&lt;br /&gt;
&lt;br /&gt;
Ces primitives sont utilisées par le système d'exploitation pour réaliser les commandes de sauvegarde et de chargement de fichiers. Il est supposé qu'il n'existe qu'une carte réseau par pico-ordinateur avec une ligne de sélection de périphérique SPI fixe.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille réseau &amp;quot;points d'accès de volume&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Cette carte est identique, au niveau électronique, à la carte réseau RNDIS. La seule différence réside dans la façon de faire transiter les paquets réseau de la carte vers le PC auquel elle est connectée en USB. Pour cette carte, il vous est proposé de faire ce transfert en utilisant deux points d'accès USB de type volume (bulk), un entrant et un sortant. Cette fois vous n'aurez pas l'aide du noyau Linux pour la création de l'interface réseau. Vous allez devoir écrire votre propre programme PC pour faire le pont entre la carte et une interface réseau virtuelle.&lt;br /&gt;
&lt;br /&gt;
Sous Linux la création d'une interface virtuelle est possible avec la fonction ci-dessous.&lt;br /&gt;
&lt;br /&gt;
 int allocateNetworkDevice(char *name,int flags){&lt;br /&gt;
 struct ifreq ifr;&lt;br /&gt;
 int fd,err;&lt;br /&gt;
 char *clonedev = &amp;quot;/dev/net/tun&amp;quot;;&lt;br /&gt;
 /* Open the clone device */&lt;br /&gt;
 if((fd=open(clonedev,O_RDWR))&amp;lt;0) return fd;&lt;br /&gt;
 /* Preparation of the struct ifr, of type &amp;quot;struct ifreq&amp;quot; */&lt;br /&gt;
 memset(&amp;amp;ifr,0,sizeof(ifr));&lt;br /&gt;
 ifr.ifr_flags=flags;   /* IFF_TUN or IFF_TAP, plus maybe IFF_NO_PI */&lt;br /&gt;
 if(name!=NULL) strncpy(ifr.ifr_name,name,IFNAMSIZ);&lt;br /&gt;
 /* Try to create the device */&lt;br /&gt;
 if((err=ioctl(fd,TUNSETIFF,(void *)&amp;amp;ifr))&amp;lt;0){ close(fd); return err; }&lt;br /&gt;
 /* Write back the name of the * interface to the variable &amp;quot;name&amp;quot; */&lt;br /&gt;
 if(name!=NULL) strcpy(name,ifr.ifr_name);&lt;br /&gt;
 return fd;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Le descripteur de fichier retourné est utilisable avec &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; pour récupérer les paquets Ethernet entrants et avec &amp;lt;code&amp;gt;write&amp;lt;/code&amp;gt; pour envoyer des paquets sur l'interface. Pour transmettre les paquets à la carte ou lire ceux provenant de la carte vous pouvez utiliser la bibliothèque &amp;lt;code&amp;gt;libusb-1.0&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Pour le reste de la programmation liée à cette carte vous reporter à ce qui est demandé pour la carte réseau RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille réseau Ethernet ===&lt;br /&gt;
&lt;br /&gt;
Cette version de la carte réseau se connecte à un commutateur Ethernet et non pas à un PC pour communiquer avec le monde extérieur.&lt;br /&gt;
&lt;br /&gt;
Au niveau électronique une puce Ethernet ENC28J60 (ou supérieur) est supervisée par un microcontrôleur ATMega328p. Toutes les précisions concernant les cartes à base d'ATMega328p s'appliquent (voir par exemple la carte fille clavier &amp;quot;matrice de touches). Vous trouverez la documentation de la puce Ethernet à l'adresse http://ww1.microchip.com/downloads/en/devicedoc/39662c.pdf. Un exemple de programmtion de la puce ENC624J600 est disponible à l'adresse https://github.com/2xs/smews/tree/develop/targets/Arduino_ethernet/drivers. Vous pouvez vous en inspirer pour la programmation de la puce ENC28J60.&lt;br /&gt;
&lt;br /&gt;
La programmation spécifique à cette carte concerne l'envoi des paquets à la puce ENC28J60 et la récupération des paquets en provenance de la puce ENC28J60. Comme pour la liaison RNDIS, trois options s'ouvrent à vous pour l'implémentation de votre pile réseau :&lt;br /&gt;
&lt;br /&gt;
*programmation Ethernet, votre projet sera assez simple à écrire mais l'application sur le PC sera un peu exotique, il vous faudra utiliser la programmation socket en mode RAW ;&lt;br /&gt;
* programmation UDP, votre projet sera plus complexe mais l'application sur le PC pourra se faire avec des sockets en mode non connecté standard ;&lt;br /&gt;
* programmation TCP, votre projet sera plus complexe;  par contre vous pourrez utiliser des applications standard sur le PC (serveur Web ou FTP).&lt;br /&gt;
&lt;br /&gt;
Le reste de la programmation (communication avec la carte mère et ajouts dans le système d'exploitation) est identique à ce qui est décrit pour la carte réseau RNDIS.&lt;br /&gt;
&lt;br /&gt;
=== Carte fille son ===&lt;br /&gt;
 &lt;br /&gt;
D'un point de vue électronique la carte n'est pas très compliquée, elle comporte un ATMega328p comme coeur et sa spécificité est un convertisseur numérique vers analogique dit R-2R utilisant un réseau de résistance pour implanter la conversion. Utilisez au moins un DAC sur 8 bits, vous devez pouvoir pousser jusqu'à 12 bits en utilisant pratiquement toutes les sorties disponibles. En sortie du DAC utilisez un montage Darligton pour commander le haut-parleur. N'oubliez pas le connecteur HE10 pour connecter votre carte à une carte mère. Utilisez la ligne de sélection SPI par défaut pour que la carte mère puisse commander votre carte et prévoyez une ligne d'interruption. Enfin il vous faut prévoir un connecteur AVR ISP pour programmer le microcontrôleur.&lt;br /&gt;
&lt;br /&gt;
Le microcontrôleur de la carte fille doit être programmé pour pouvoir jouer des sons déjà enregistrés :&lt;br /&gt;
* des variables globales doivent être configurées pour spécifier les caractéristiques des enregistrements à jouer :&lt;br /&gt;
** précision d'échantillonnage (8 à 24 bits même si au-delà de 14 bits vous devez abandonner les bits de poids faibles),&lt;br /&gt;
** vitesse d'acquisition (vous trouverez la vitesse maximale par essais et erreurs),&lt;br /&gt;
** format des enregistrements (vous vous limiterez à un format PCM entier classique avec représentation petit-boutiste) ;&lt;br /&gt;
* une fonction permettant d'envoyer les échantillons, à la bonne vitesse, sur le DAC.&lt;br /&gt;
&lt;br /&gt;
Les échantillons sonores sont reçus par le bus SPI préfixés par le code commande 0x02. Les 2 valeurs de configuration, précision sur un octet et vitesse sur quatre octets sont envoyées préfixés par le code commande 0x01.&lt;br /&gt;
&lt;br /&gt;
Au niveau de la carte mère vous devez écrire les primitives système :&lt;br /&gt;
* la première primitive correspond au message SPI de code commande 0x01 et passe les paramètres de configuration à la carte fille ;&lt;br /&gt;
* la seconde primitive correspond au message SPI de code commande 0x02 et passe les échantillons sonores à jouer à la carte fille, la primitive s'assure auparavent que la carte n'est pas déjà occupée à jouer des échantillons avec la commande SPI 0xFF, en cas de carte occupée le code 0xFF est retourné.&lt;br /&gt;
&lt;br /&gt;
Ces primitives sont utilisées utilisée par le système d'exploitation pour implanter une nouvelle commande &amp;lt;code&amp;gt;PLAY&amp;lt;/code&amp;gt; permettant de jouer un fichier WAV :&lt;br /&gt;
* l'entête du fichier est récupéré avec la primitive &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; ;&lt;br /&gt;
* l'entête WAV est analysée pour récupérer la fréquence et la précision d'échantillonnage, ces données sont passées à la carte son via la première primitive décrite ci-dessus ;&lt;br /&gt;
* le nombre de canaux est récupéré dans l'entête, les echantillons du premier canal sont alors lus grâce à &amp;lt;code&amp;gt;read&amp;lt;/code&amp;gt; et envoyés à la carte son en utilisant la seconde primitive ;&lt;br /&gt;
* si les échantillons sont envoyés trop vite et donnent lieu à un code d'erreur de la seconde primitive, les mêmes échantillons sont à nouveau envoyés et ainsi de suite ;&lt;br /&gt;
* éventuellement, si votre système d'exploitation dispose d'une primitive &amp;lt;code&amp;gt;usleep&amp;lt;/code&amp;gt; vous pouvez mettre en place un algorithme d'attente après chaque appel à la primitive, ce temps peut être calculé en fonction de la vitesse de restitution et du nombre d'échantillons envoyés.&lt;br /&gt;
&lt;br /&gt;
= Réalisations des élèves =&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Numéro du binôme !! Numéro du groupe !! Elèves !! Page &lt;br /&gt;
|-&lt;br /&gt;
| Binôme 1&lt;br /&gt;
| Groupe 1&lt;br /&gt;
| Taha Nehari &amp;amp; Martin Chauveliere&lt;br /&gt;
| [[SE4Binome2023-1|Binôme 1 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 2&lt;br /&gt;
| Groupe 1&lt;br /&gt;
| Simon CRUCHET &amp;amp; Amaury BECQUET&lt;br /&gt;
| [[SE4Binome2023-2|Binôme 2 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 3&lt;br /&gt;
| Groupe 1&lt;br /&gt;
| Louis DERYCKERE &amp;amp; Romain DUHR&lt;br /&gt;
| [[SE4Binome2023-3|Binôme 3 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 4&lt;br /&gt;
| Groupe 1&lt;br /&gt;
| Thomas NAVE &amp;amp; Thibault DUYCK&lt;br /&gt;
| [[SE4Binome2023-4|Binôme 4 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 5&lt;br /&gt;
| Groupe 2&lt;br /&gt;
| Stéphane KADER ISSACK &amp;amp; Marion NORMAND&lt;br /&gt;
| [[SE4Binome2023-5|Binôme 5 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 6&lt;br /&gt;
| Groupe 2&lt;br /&gt;
| Dylan Ling&lt;br /&gt;
| [[SE4Binome2023-6|Binôme 6 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 7&lt;br /&gt;
| Groupe 2&lt;br /&gt;
| Louis Wijsman &amp;amp; Adrien Paliferro&lt;br /&gt;
| [[SE4Binome2023-7|Binôme 7 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 8&lt;br /&gt;
| Groupe 2&lt;br /&gt;
| Némo CAZIN &amp;amp; Némo &lt;br /&gt;
| [[SE4Binome2023-8|Binôme 8 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 9&lt;br /&gt;
| Groupe 3&lt;br /&gt;
| Prénom Nom &amp;amp; Prénom Nom&lt;br /&gt;
| [[SE4Binome2023-9|Binôme 9 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 10&lt;br /&gt;
| Groupe 3&lt;br /&gt;
| Prénom Nom &amp;amp; Prénom Nom&lt;br /&gt;
| [[SE4Binome2023-10|Binôme 10 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
| Binôme 11&lt;br /&gt;
| Groupe 3&lt;br /&gt;
| Prénom Nom &amp;amp; Prénom Nom&lt;br /&gt;
| [[SE4Binome2023-11|Binôme 11 2023/2024]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE3Trinome2022-8&amp;diff=1405</id>
		<title>SE3Trinome2022-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE3Trinome2022-8&amp;diff=1405"/>
		<updated>2023-09-04T16:31:44Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : modif et correction&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= '''Projet SE3 : Premier Système''' =&lt;br /&gt;
CAZIN Némo, CEGARRA Antoine, PALIFERRO Adrien&lt;br /&gt;
&lt;br /&gt;
'''Lien du git :''' ''https://archives.plil.fr/ncazin/SE3_GROUPE_8.git''&lt;br /&gt;
&lt;br /&gt;
==Objectifs fixés :==&lt;br /&gt;
L'objectif principal de ce projet était de '''réaliser la commande d'une voiture au format 1:43''' capable d'avancer et de reculer à l'aide d'un programme informatique. Avant de commencer le projet, nous nous sommes fixé plusieurs petits objectifs afin de mener au mieux le projet.&lt;br /&gt;
&lt;br /&gt;
La voiture devait tout d'abord avancer, reculer, tourner à gauche et à droite. Des LEDs devaient être allumées lorsque la voiture effectue un déplacement.&lt;br /&gt;
&lt;br /&gt;
Pour la commande de la voiture, nous voulions qu'elle soit commandée grâce à une commande Bluetooth et pilotée depuis un smartphone. Une application devait alors être faite pour gérer les déplacements. MIT App Inventor permet de gérer des communications Bluetooth et est simple d'utilisation.&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir implémenter toutes ses fonctionnalités, nous devions réaliser une carte électronique gérée par un microcontrôleur ATMega16u2. D'autres module devaient être ajoutés pour la bonne réalisation de nos objectifs fixés.&lt;br /&gt;
&lt;br /&gt;
==La carte électronique :==&lt;br /&gt;
&lt;br /&gt;
La réalisation de la carte électronique a débuté par la création du schéma électrique sur KICAD. Nous avons implémenté ce que nous avions déjà prévu (Chargeur, moteurs, microcontrôleur...), cependant, pour certaines fonctionnalités, des composants n'étaient pas disponibles dans les librairies Sparkfun disponibles. &lt;br /&gt;
&lt;br /&gt;
Nous avons donc créé les schémas de ces composants, c'est-à-dire le module Bluetooth '''FP-BM70BLE01FC2''' ainsi que le driver du moteur '''DRV8210DRL''' grâce aux informations de leurs datasheet disponible sur Internet :  &lt;br /&gt;
&lt;br /&gt;
- Datasheet du module Bluetooth : ''https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/BM70_71-Bluetooth-Low-Energy-BLE-Module-DS60001372L.pdf'' &lt;br /&gt;
&lt;br /&gt;
- Datasheet du driver du moteur : ''https://www.ti.com/lit/ds/slvsfy8b/slvsfy8b.pdf?ts=1683016270840&amp;amp;ref_url=https%253A%252F%252Fwww.google.com%252F'' &lt;br /&gt;
&lt;br /&gt;
Au final, nous obtenons au final ce schéma correspondant :  &lt;br /&gt;
[[Fichier:Schématic voiture.jpg|alt=Schéma de la voiture|centré|vignette|Schéma de la voiture]]&lt;br /&gt;
Après avoir fait le schéma de la voiture, nous avons dû faire le routage de la carte électronique. La première chose a faire à été de prendre les côtes de la voiture afin que la carte électronique se mette bien en place dessus. De plus, nous avons dû prendre les mesures des côtes du moteur continu, celui-ci va être soudé au centre de la carte et est imposant, il fallait donc prévoir la place nécessaire que le composant prendrait.  &lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons dû réaliser les empreintes du module Bluetooth ainsi que du driver du moteur. Les mesures figurant sur leurs datasheet respectives, nous avons réussi simplement à les reproduire. Le plus compliqué a été de repérer les pâtes des composants que nous devions utiliser. Par exemple, sur le module Bluetooth, certaines entrées n'ont pas été utilisées. Nous avons aussi utilisé et adapter les empreintes des moteurs continus et pas à pas fournis par notre professeur M.Redon.  &lt;br /&gt;
&lt;br /&gt;
Après cela, nous avons commencé le routage. Nous avons commencer par router la carte le plus possible sur une seule face jusqu'à ce que ne l'on puisse plus. Sinon nous utilisions des vias afin de router sur l'autre face. Cependant, nous avons dû recommencer une seconde fois le routage, car le premier ne nous convenait pas. Nous avons aussi demandé de l'aide au professeur M.Boé afin de réaliser les plans de masse.   &lt;br /&gt;
&lt;br /&gt;
Voici une image du routage final notre carte électronique :  &lt;br /&gt;
[[Fichier:Routage voiture.jpg|alt=Routage de la carte électronique|centré|vignette|Routage de la carte électronique]]&lt;br /&gt;
Voici aussi une représentation 3D de notre carte électronique :    &lt;br /&gt;
[[Fichier:Pcb 3D.jpg|alt=Représentation 3D de notre carte électronique|centré|vignette|Représentation 3D de notre carte électronique]]&lt;br /&gt;
Le routage fini, nous avons passé commande afin de recevoir notre carte électronique et voici celle-ci avec aucune soudure :    &lt;br /&gt;
&lt;br /&gt;
Enfin, la carte étant vierge, nous devions commencer la soudure des composants. Cette partie a été très compliquée à mettre en oeuvre, car dans le groupe, aucun de nous n'avait fait de soudure dans sa vie. Nous avons donc dû apprendre à ce moment comment faire, d'où les premières soudures un peu compliquées.  &lt;br /&gt;
&lt;br /&gt;
Nous avons eu un problème de reconnaissance du microprocesseur lors de la commande &amp;quot;''lsusb&amp;quot;'', le matériel n'était pas détecté. Nous avons donc dû modifier le circuit qui comportait quelques erreurs, ainsi que remplacer les résistances et condensateurs afin de s'assurer de leur valeur. Finalement, nous avons dû changer le microprocesseur qui avec les précédents branchements avait surchauffé et était défectueux. Après avoir remplacé tous les composants, nous avons réussi à faire reconnaître le microprocesseur grâce à la commande &amp;quot;''lsusb''&amp;quot;.  Après cela, nous avons pu souder les derniers composants restants.  &lt;br /&gt;
&lt;br /&gt;
Voici une photo de notre carte avec les composants soudés :     &lt;br /&gt;
[[Fichier:Carte électronique avec les composants soudés.jpg|alt=Carte électronique avec les composants soudés|centré|vignette|Carte électronique avec les composants soudés]]&lt;br /&gt;
Nous avions fini la carte électronique, sa réalisation a pris la majeure partie de notre temps lors des séances. Il fallait donc ensuite réaliser un programme permettant de faire fonctionner et avancer la voiture.     &lt;br /&gt;
&lt;br /&gt;
Fichier ZIP de notre carte électronique : [[Fichier:Voiture CCP.zip|vignette|Voiture fichiers de routage et schéma PCB]]&lt;br /&gt;
&lt;br /&gt;
==Programme de la voiture :==&lt;br /&gt;
Le programme informatique était nécessaire pour le bon fonctionnement de la voiture, cependant comme le temps commençait à manquer, nous avons codé son programme en dehors des cours de projet.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc structuré notre code en plusieurs afin de le simplifier. Les premières fonctions permettent d'initialiser les entrées et les sorties du microcontrôleur afin de bien récupérer et envoyer les bonnes informations. De plus, dans ces fonctions, nous remettons les moteurs et les leds à LOW afin d'avoir une sécurité et qu'ils ne démarrent pas à l'initialisation. Ensuite, nous retrouvons les fonctions de déplacements. Ces fonctions gèrent les moteurs lorsqu'il faut avancer, reculer, tourner à droite, etc...&lt;br /&gt;
&lt;br /&gt;
De plus, on retrouve une fonction permettant de récupérer les informations envoyées depuis la communication Bluetooth afin de faire fonctionner la voiture à distance. Une seconde fonction permet de traiter ces informations et de faire déplacer la voiture selon l'information reçue.&lt;br /&gt;
&lt;br /&gt;
Nous pouvons aussi faire fonctionner la voiture en envoyant le programme informatique dans la voiture. Cependant, de cette manière, la voiture ne pourra pas être contrôlée et fera un trajet voulu.&lt;br /&gt;
&lt;br /&gt;
La communication Bluetooth étant un de nos objectifs fixé, nous avons dû réaliser une application afin de pouvoir utiliser la voiture à distance.&lt;br /&gt;
&lt;br /&gt;
Voici une vidéo de la carte avec une LED qui clignote : &lt;br /&gt;
[[Fichier:PCB clignote.mov|alt=LED qui clignote|centré|vignette|LED qui clignote]]&lt;br /&gt;
&lt;br /&gt;
==Application Bluetooth :==&lt;br /&gt;
Nous nous étions fixé comme objectif que la voiture devait être contrôlée grâce à une application Bluetooth. Nous avons alors décidé de réaliser cette application grâce au site '''MIT App Inventor''', ce site est simple d'utilisation et permet de gérer des communications Bluetooth facilement. De plus, le temps a été investi surtout dans la carte électronique donc apprendre et programmer par nous-même dans un langage de programmation nouveau aurait été compliqué pour nous.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé que les informations envoyées par communication Bluetooth serait sous forme hexadécimale. Le programme informatique du côté de l'ATMega16u2 recevra et traitera alors les informations reçues. &lt;br /&gt;
&lt;br /&gt;
L'application devait avoir un aspect simple d'utilisation et sobre afin de faciliter l'expérience de l'utilisateur. L'application amènerait l'utilisateur sur une page permettant de choisir à quel appareil Bluetooth se connecter. Un statut indiquant si le smartphone est connecté ou non à l'appareil est aussi présent. L'élément le plus important de la page est le bloc de déplacement, composé de 4 boutons représentant des flèches directionnelles afin de piloter la voiture.&lt;br /&gt;
&lt;br /&gt;
Lorsque nous avions terminé l'application pour piloter grâce à des flèches directionnelles, nous nous sommes rendu compte que nous pourrions réaliser aussi un pilotage par gyroscope. En effet, les informations transmises pour les déplacements restent les mêmes donc du côté du programme informatique, rien ne change. Nous avons deux moyens de piloter la voiture : une par appui sur des flèches directionnelles, et une seconde par inclinaison du smartphone. &lt;br /&gt;
&lt;br /&gt;
Voilà des captures d'écran montrant l'aspect et les fonctionnalités de l'application : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed&amp;quot; widths=&amp;quot;150&amp;quot; heights=&amp;quot;150&amp;quot;&amp;gt;&lt;br /&gt;
Fichier:App Screen Controls.jpg|Contrôle par touche&lt;br /&gt;
Fichier:App Screen Gyro.jpg|Contrôle par gyroscope&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
Pour réaliser cette application, il faut du code en interne, voici les codes que nous avons utilisé :&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed&amp;quot; widths=&amp;quot;150&amp;quot; heights=&amp;quot;150&amp;quot;&amp;gt;&lt;br /&gt;
Fichier:Connexion Bluetooth.jpg|Bloc de connexion Bluetooth&lt;br /&gt;
Fichier:Gestion des boutons.jpg|Bloc de gestion des touches&lt;br /&gt;
Fichier:Gestion gyroscope.jpg|Bloc de gestion du gyroscope&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Le fichier APK de l'application est disponible dans le GIT du projet.'''&lt;br /&gt;
&lt;br /&gt;
= '''Epreuve complémentaire CAZIN Némo''' =&lt;br /&gt;
'''Lien du git :''' ''https://archives.plil.fr/ncazin/SE3_GROUPE_8.git''&lt;br /&gt;
&lt;br /&gt;
== Introduction : ==&lt;br /&gt;
J’ai dû reprendre le projet lors de mon épreuve complémentaire de Semestre 6&lt;br /&gt;
&lt;br /&gt;
Avant cela, avec mon groupe de travail, nous avions réussi à faire clignoter une LED malgré tous les problèmes que nous avions rencontrés comme des composants qui ne fonctionnait plus sur la carte ou alors des courts-circuits à faire nous-mêmes. Je ne traiterais donc pas ici la partie du clignotement de la LED.&lt;br /&gt;
&lt;br /&gt;
== Préparation de la carte électronique : ==&lt;br /&gt;
Tout d’abord, lorsque j’ai repris le projet, je savais que les soudures des composants et du moteur continu avaient été faites, mais elles étaient fragiles du fait de la petite épaisseur des pistes reliant le moteur au driver. De plus, le voyage de la boite avec la carte électronique à l’intérieur avait complétement cassé les soudures du moteur. &lt;br /&gt;
&lt;br /&gt;
Voici l’état de la carte lors de la reprise du projet :&lt;br /&gt;
[[Fichier:Carte pas de soudure.jpg|alt=Carte avec le moteur désoudé|centré|vignette|Carte avec le moteur désoudé]]&lt;br /&gt;
J’ai donc dû refaire les soudures du moteur, ce qui a été un peu compliqué, car j’ai du mal à souder en général. Mais en m’inspirant des photos que j’avais d’avant la reprise du projet, j’ai pu mieux m’en sortir. Voilà le résultat de la soudure du moteur continu : &lt;br /&gt;
[[Fichier:Carte moteur DC.jpg|alt=Carte avec le moteur continu soudé|centré|vignette|Carte avec le moteur continu soudé]]&lt;br /&gt;
Après cela, j’ai voulu continuer mon travail en faisant les soudures du moteur pas-à-pas. Ce moteur est très petit et les soudures à faire devaient être très précises. Pour que ce soit plus simple, j’ai utilisé 4 pins que j’ai soudé à la carte et sur les pins, des câbles sont reliés jusqu’aux quatre liaisons du moteur. Le moteur est alors déporté de la carte, mais ce n’est pas très important, car on veut juste le voir fonctionner et aucune roue n’est attachée. Ces soudures étaient vraiment compliquées à réaliser, car elles étaient très minutieuses à réaliser et souvent des soudures se cassaient lorsque j’en soudais une autre. &lt;br /&gt;
&lt;br /&gt;
Voilà le résultat de la soudure du moteur pas à pas : &lt;br /&gt;
[[Fichier:Carte moteur pap.jpg|alt=Carte avec le moteur pas-à-pas soudé|centré|vignette|Carte avec le moteur pas-à-pas soudé]]Après avoir soudé tous les composants que je souhaitais, j'ai vérifié les anciennes soudures pour voir s'il n'y avait pas des câbles qui étaient cassés à cause du voyage. Après vérification, tout était bon et je pouvais commencer la programmation.&lt;br /&gt;
&lt;br /&gt;
== Problèmes eu pendant la programmation de la carte sur ordinateur : ==&lt;br /&gt;
J'ai rencontré plusieurs problèmes lors de la programmation et lors de la reconnaissance de la carte par les machines. &lt;br /&gt;
&lt;br /&gt;
Tout d'abord, il faut savoir que j'ai commencé développer mes programmes informatiques sur les machines de l’école à distance grâce à l’outil : '''https://tp-info.polytech-lille.fr/#'''&lt;br /&gt;
&lt;br /&gt;
Ensuite, le premier problème était que certaines bibliothèques utilisées, notamment '''''&amp;lt;avr/io.h&amp;gt;''''' ne sont pas trouvables, ce qui fait que la compilation d'un de mes fichiers de test ne peut pas être réalisée. J'ai comme hypothèse que soit la librairie n'est pas installée sur les machines des salles de TP en C10X, soit il faut être en superutilisateur pour pouvoir compiler le fichier d'après les notes que j'ai des cours. Je ne peux pas me mettre en superutilisateur car il faut le mot de passe de la machine locale que je ne connais pas. Pour contourner ce problème, j'ai défini comme constantes toutes les variables utilisées mais ce n'est qu'une solution temporaire qui ne marchera peut-être pas lors de l'envoi du programme sur la carte, mais au moins j'ai réussi à compiler mes fichiers.&lt;br /&gt;
[[Fichier:Erreur include.jpg|alt=Message de l'erreur reçu par rapport à la librairie &amp;lt;avr/io.h&amp;gt;|centré|vignette|Message de l'erreur reçu par rapport à la librairie &amp;lt;avr/io.h&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Enfin, pour le second problème, j’ai voulu voir si la carte était reconnue depuis les machines à distance grâce à la commande shell « '''''lsusb''''' ». Cependant, lorsque je me connecte sur ces machines, les périphériques USB de mon ordinateur ne sont pas reconnus. En faisant plusieurs essais pour résoudre ce problème, j’ai compris que ce n’était pas possible et donc qu’il fallait passer par une autre méthode. Sois-je faisais directement la programmation sur Windows, mais télécharger les dépendances et le compilateur C était compliqué. Sois-je téléchargeais une machine virtuelle Ubuntu pour être directement sur un système Linux et plus simplement programmer. J’ai donc choisi la première option, car je craignais que la machine virtuelle ne reconnaisse pas elle aussi les périphériques USB.&lt;br /&gt;
&lt;br /&gt;
J’ai donc modifié l’option développeur de mon Windows afin de pouvoir télécharger un environnement terminal Ubuntu qui fonctionne grâce à Windows Subsystem for Linux (WSL). J’ai alors rencontré une erreur lors du lancement du terminal Ubuntu : &lt;br /&gt;
[[Fichier:Erreur Ubuntu.jpg|alt=Erreur WSL pour Ubuntu|centré|vignette|Erreur WSL pour Ubuntu]]&lt;br /&gt;
J’ai alors trouvé une documentation de Microsoft sur le WSL qui m’a permis de résoudre ce problème ('''https://learn.microsoft.com/fr-fr/windows/wsl/troubleshooting'''). Après cela, j’ai voulu donc tester la commande « '''''lsusb''''' » mais encore une fois, une nouvelle erreur apparaît :&lt;br /&gt;
[[Fichier:Erreur libusb.jpg|alt=Erreur de la libusb sur Ubuntu|centré|vignette|Erreur de la libusb sur Ubuntu]]&lt;br /&gt;
J’ai donc télécharger la librairie libusb grâce à la commande « '''''sudo apt-get install libusb-1.0-0-dev''''' » que j’ai trouvé grâce aux informations de ce site : '''https://askubuntu.com/questions/629619/how-to-install-libusb''' , mais même en faisant cette commande, j’ai toujours eu la même erreur. Donc à ce stade du projet, cette solution n'était pas viable et devait être plus approfondie.&lt;br /&gt;
&lt;br /&gt;
En parallèle, j'ai essayé d'installer une machine virtuelle Ubuntu sur mon ordinateur, mais Oracle VM VirtualBox n'accepte que les fichiers .xml alors que je me suis procuré un fichier .iso. Après avoir téléchargé le bon fichier, j'ai dû faire la manipulation de la première méthode pour me retrouver avec la même erreur de la libusb.&lt;br /&gt;
&lt;br /&gt;
Après des essais directement réalisés sur les machines de l'école, j'ai remarqué que le microprocesseur n'était pas reconnu. Il doit y avoir donc une soudure ou une connexion qui a dû se casser, ou alors le microprocesseur qui ne fonctionne plus comme nous l'avions déjà eu au début du projet.&lt;br /&gt;
&lt;br /&gt;
== Programmation du moteur continu : ==&lt;br /&gt;
J’ai donc commencé par la partie du moteur continu, car c’est sur cette partie que nous nous sommes arrêtés.&lt;br /&gt;
&lt;br /&gt;
Afin de faire fonctionner le moteur, je devais faire un programme informatique afin de gérer cette fonctionnalité. J’ai tout d’abord créé une fonction pour initialiser les ports du moteur comme étant des sorties. Ensuite, j’ai créé une fonction « avancer » où je mets un des ports sous tension et l’autre non. Pour la fonction « reculer », il s’agit de la même chose mais il faut inverser quel port est sous tension. Enfin pour la fonction « arrêter », il suffit de mettre les deux ports à 0.&lt;br /&gt;
&lt;br /&gt;
Voici donc le code pour faire fonctionner le moteur de cette façon :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR DC AVEC PORT ///&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
    &lt;br /&gt;
void initMotDC_Port(void){&lt;br /&gt;
    DDRB |= (1&amp;lt;&amp;lt;PB7);                   //PMW2 en OUTPUT&lt;br /&gt;
    DDRD |= (1&amp;lt;&amp;lt;PD0);                   //PMW1 en OUTPUT&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7);                     //PMW2 à LOW&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0);                     //PMW1 à LOW&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
////////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR DC AVEC PORT ///&lt;br /&gt;
////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void move_forwards(void){&lt;br /&gt;
    PORTB=(1&amp;lt;&amp;lt;PB7); //MOT1 à HIGH&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0); //MOT2 à LOW&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void move_backwards(void){&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7); //MOT1 à LOW&lt;br /&gt;
    PORTD=(1&amp;lt;&amp;lt;PD0); //MOT2 à HIGH&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void stop(void){&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7); //MOT1 à LOW&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0); //MOT2 à LOW   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir fait cela, je me suis demandé si nous pouvions contrôler la vitesse du moteur. J’ai alors regardé trouver une page d’un cours de PSE ('''https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme053.html''') expliquant comment fonctionne les actionneurs simples grâce aux signaux PWM (Pulse Width Modulation). Une partie du programme pour l’initialisation des ports était donnée, cependant, il s’agissait de la gestion des sorties que je ne comprenais pas (OCR0A, OCR0B …), j’ai donc dû effectuer plusieurs recherches sur cette partie. Voici donc le code pour faire fonctionner le moteur de cette autre façon :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR DC AVEC OCR1 ///&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void initMotDC_OCR(void){&lt;br /&gt;
    DDRB |= (1&amp;lt;&amp;lt;PB7);                   //PMW2 en OUTPUT&lt;br /&gt;
    DDRD |= (1&amp;lt;&amp;lt;PD0);                   //PMW1 en OUTPUT&lt;br /&gt;
    TCCR1A |= (1&amp;lt;&amp;lt;COM1A1)|(1&amp;lt;&amp;lt;COM1C1);  // Les ports PWM se comportent normalement&lt;br /&gt;
    TCCR1A |= (1&amp;lt;&amp;lt;WGM11)|(1&amp;lt;&amp;lt;WGM10);    // Minuteur mis en mode PWM&lt;br /&gt;
    TCCR1B |= (1&amp;lt;&amp;lt;CS10);                // Pas de pré-diviseur, démarre le compteur&lt;br /&gt;
&lt;br /&gt;
///////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR DC AVEC OCR ///&lt;br /&gt;
///////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void move_forwards_OCR(void){&lt;br /&gt;
    OCR1A = 512;&lt;br /&gt;
    OCR1C = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void move_backwards_OCR(void){&lt;br /&gt;
    OCR1A = 0;&lt;br /&gt;
    OCR1C = 512;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void stop_OCR(void){&lt;br /&gt;
    OCR1A = 0;&lt;br /&gt;
    OCR1C = 0;   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation du moteur pas à pas : ==&lt;br /&gt;
Comme je n'avais jamais travaillé sur un moteur pas à pas, j'ai voulu comprendre son fonctionnement. Après plusieurs recherches, j'ai compris que le moteur était constitué d'un rotor magnétique et de bobines. Nous avons ici un moteur pas à pas bipolaire, avec 4 sorties. Le moteur fonctionne par pas successifs comme une montre, ce qui signifie qu'il faut jouer avec chacune des sorties afin de le faire tourner pas par pas. En partant de ce principe, nous pouvons programmer une fonction pour que chaque sortie soit sous tension les unes à la suite des autres.&lt;br /&gt;
&lt;br /&gt;
Voici le programme pour faire tourner le moteur pas à pas dans un sens :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
///////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR PAS A PAS ///&lt;br /&gt;
///////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void initMotStepper(void){&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR PAS A PAS ///&lt;br /&gt;
/////////////////////////////////&lt;br /&gt;
    &lt;br /&gt;
void stepper_left(void){&lt;br /&gt;
    for(int i = 0; i&amp;lt;=100; i++){&lt;br /&gt;
        //M1_A+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC5);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Pour aller dans l'autre sens, il suffit d'inverser le sens des broches des sorties :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void stepper_right(void){&lt;br /&gt;
    for(int i = 0; i&amp;lt;=100; i++){&lt;br /&gt;
        //M1_B+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC7);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Voici ma documentation :&lt;br /&gt;
&lt;br /&gt;
- '''https://www.tme.eu/fr/news/library-articles/page/41861/Moteur-pas-a-pas-types-et-exemples-dapplications-des-moteurs-pas-a-pas/'''&lt;br /&gt;
&lt;br /&gt;
- '''https://www.youtube.com/watch?v=655p1N9tSKQ'''&lt;br /&gt;
&lt;br /&gt;
- '''http://www.micropython.fr/modules_center/moteurs/pas_a_pas/moteur_pap/#le-principe-dun-moteur-pas-a-pas'''&lt;br /&gt;
&lt;br /&gt;
== Programmation de la communication Bluetooth : ==&lt;br /&gt;
La partie Bluetooth était un de nos objectifs du début de projet afin de contrôler la voiture à distance et grâce à une application. Pour cela, j’ai dû refaire des recherches sur le sujet afin de mieux comprendre comment je pourrai faire. J’ai donc dû regarder la documentation de l’atmega16u2 et des cours en ligne d’autres universités pour bien comprendre. C’est alors que j’ai compris que la communication série UART permettrait de répondre à mes besoins. J’ai donc écrit une fonction qui permet l’initialisation de la communication série UART en activant la transmission (TX) et la réception (RX). Ensuite, dans cette même fonction, j’ai dû définir le format de la trame, elle est donc composée de 8 bits, c’est-à-dire un octet avec un bit d’arrêt.&lt;br /&gt;
&lt;br /&gt;
Nous n’avons besoin que de recevoir des informations sur la communication série UART, pas d’en envoyer. C’est pour cela que j’ai donc dû faire une seconde fonction permettant de recevoir les informations de l’application sur le port RX de l’Atmega16u2.&lt;br /&gt;
&lt;br /&gt;
Voici le code de la communication UART :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION COMMUNICATION UART ///&lt;br /&gt;
/////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void UART_init(unsigned int baud_rate){&lt;br /&gt;
    // Calculer la valeur de UBRR en fonction du baud_rate&lt;br /&gt;
    unsigned int ubrr_val = FREQ_CPU / (16UL * baud_rate) - 1;    &lt;br /&gt;
    // Définir les valeurs UBRRH et UBRRL&lt;br /&gt;
    UBRRH = (unsigned char)(ubrr_val &amp;gt;&amp;gt; 8);&lt;br /&gt;
    UBRRL = (unsigned char)ubrr_val;&lt;br /&gt;
    // Activer la transmission et la réception&lt;br /&gt;
    UCSRB = (1 &amp;lt;&amp;lt; TXEN) | (1 &amp;lt;&amp;lt; RXEN);&lt;br /&gt;
    // Définir le format de trame: 8 bits de données, 1 bit d'arrêt&lt;br /&gt;
    UCSRC = (1 &amp;lt;&amp;lt; URSEL) | (1 &amp;lt;&amp;lt; UCSZ1) | (1 &amp;lt;&amp;lt; UCSZ0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/////////////////////////////////////&lt;br /&gt;
/// RECUPERATION DES DONNEES UART ///&lt;br /&gt;
/////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
int UART_receiver(void) {&lt;br /&gt;
    // Attendre que le tampon d'entrée soit plein&lt;br /&gt;
    while (!(UCSRA &amp;amp; (1 &amp;lt;&amp;lt; RXC)));&lt;br /&gt;
    // Lire le caractère du tampon d'entrée&lt;br /&gt;
    return UDR;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Cette fonction ne pouvait pas être testée, car l’antenne Bluetooth n’est pas présente sur la carte électronique de la voiture. Cependant, ces recherches m’ont permis de mieux comprendre la communication série UART que j’avais mal comprise lors des TP du semestre 6.&lt;br /&gt;
&lt;br /&gt;
== Programmation USB/LUFA ==&lt;br /&gt;
Pour cette partie de la programmation via USB/LUFA, j’ai repris le fichier utilisé lors de notre cours de TPI. Ce fichier avait quelques modifications à faire avant d’être utilisé. Tout d’abord, j’ai dû changer les Vendor ID et Product ID de la carte électronique, car celles utilisées maintenant n’est pas la même que pendant le cours de TPI. Normalement grâce à la commande &amp;quot;'''''lsusb -vvv&amp;quot;''''', on peut trouver le microcontrôleur utilisé et ces ID, mais nous les avions déjà noté auparavant. On trouve alors :&lt;br /&gt;
&lt;br /&gt;
-       VENDOR ID : 0x03EB  &lt;br /&gt;
&lt;br /&gt;
-       PRODUCT ID : 0x2FEF&lt;br /&gt;
&lt;br /&gt;
Ensuite, des modifications étaient à faire sur les fichiers du descripteur. En effet, celui-ci avait du code qui faisait référence au joystick utilisé en TPI. J’ai donc juste gardé les fonctions qui faisaient référence aux actionneurs.&lt;br /&gt;
&lt;br /&gt;
De plus, afin de pouvoir gérer les actionneurs, j’ai préparé en amont comment ils seront activés grâce aux octets à envoyer. Cependant, j’ai décidé d’utiliser qu’un seul octet de contrôle, car 2 était beaucoup trop pour les simples fonctions que nous avions. Nous avons alors un seul octet ayant chaque bit qui représente une fonction de contrôle de la voiture avec de droite à gauche :&lt;br /&gt;
&lt;br /&gt;
-       Bit 0 : Allume la LED&lt;br /&gt;
&lt;br /&gt;
-       Bit 1 : Fait avancer la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 2 : Fait reculer la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 3 : Fait tourner dans un sens la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 4 : Fait tourner dans l’autre sens la voiture&lt;br /&gt;
&lt;br /&gt;
Par exemple, le schéma ci-dessous permet d’allumer la LED de la voiture, de la faire reculer, et en même temps de la faire tourner dans un sens :&lt;br /&gt;
[[Fichier:USB exemple.png|alt=Exemple d'octet|centré|vignette|Exemple d'octet ]]&lt;br /&gt;
Voici d'ailleurs le code du programme traitant chaque bit de l'octet pour exécuter les fonctions voulues : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void actionneurs_gestion(void){&lt;br /&gt;
	Endpoint_SelectEndpoint(ACT_EPADDR);&lt;br /&gt;
	if (Endpoint_IsOUTReceived()){&lt;br /&gt;
		if (Endpoint_IsReadWriteAllowed()){&lt;br /&gt;
		  	uint16_t ACT_Report = Endpoint_Read_16_LE();&lt;br /&gt;
&lt;br /&gt;
            //CONTROLE DES LEDS&lt;br /&gt;
            if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;0))&lt;br /&gt;
                led_on();&lt;br /&gt;
            else &lt;br /&gt;
                led_off();&lt;br /&gt;
        &lt;br /&gt;
			//CONTROLE DU MOTEUR DC&lt;br /&gt;
			if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;1))&lt;br /&gt;
                move_forwards();&lt;br /&gt;
            else if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;2))&lt;br /&gt;
                move_backwards();	&lt;br /&gt;
			else&lt;br /&gt;
                stop();&lt;br /&gt;
            &lt;br /&gt;
            //CONTROLE DU MOTEUR PAS A PAS&lt;br /&gt;
            if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;3))&lt;br /&gt;
                stepper_left();&lt;br /&gt;
            else if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;4))&lt;br /&gt;
                stepper_right();&lt;br /&gt;
		}&lt;br /&gt;
		/* Handshake the OUT Endpoint - clear endpoint and ready for next report */&lt;br /&gt;
		Endpoint_ClearOUT();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, nous avons juste à envoyer l’octet de notre choix afin de gérer comme on veut les actionneurs. &lt;br /&gt;
&lt;br /&gt;
En retravaillant sur cette partie, j’ai mieux compris le fonctionnement de la libusb que je n’avais pas beaucoup compris lors du cours de TPI. J’ai pu me documenter sur le sujet en faisant beaucoup de recherche, et même d’apprendre des nouvelles façons de travailler avec le langage C et d’avoir une meilleure syntaxe de programmation.&lt;br /&gt;
&lt;br /&gt;
== Conclusion de mon travail durant l'épreuve complémentaire : ==&lt;br /&gt;
J'ai rencontré beaucoup de problèmes durant cette épreuve complémentaire. J'en ai résolu la plupart, mais certains étaient beaucoup trop compliqués et m'ont fait passer beaucoup de temps dessus. Il fallait donc que je m'organise pour ne pas passer tout le projet à résoudre certains problèmes et mettre de côté le nécessaire.&lt;br /&gt;
&lt;br /&gt;
Principalement, je trouve que je me suis bien débrouillé. J'ai surtout pu me remettre à jour en programmation du langage C et sur la libusb. J'ai pu aussi améliorer mes compétences en soudure et en gestion de projet. Mais surtout, j'ai dû faire beaucoup de recherches pour bien comprendre certains aspects qui étaient nécessaires. En général, j'ai beaucoup appris durant cette épreuve et j'ai pu mettre en avant ma détermination à finir le projet.&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE3Trinome2022-8&amp;diff=1394</id>
		<title>SE3Trinome2022-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE3Trinome2022-8&amp;diff=1394"/>
		<updated>2023-09-04T08:33:16Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Connexion de la carte sur ordinateur : */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= '''Projet SE3 : Premier Système''' =&lt;br /&gt;
CAZIN Némo, CEGARRA Antoine, PALIFERRO Adrien&lt;br /&gt;
&lt;br /&gt;
'''Lien du git :''' ''https://archives.plil.fr/ncazin/SE3_GROUPE_8.git''&lt;br /&gt;
&lt;br /&gt;
==Objectifs fixés :==&lt;br /&gt;
L'objectif principal de ce projet était de '''réaliser la commande d'une voiture au format 1:43''' capable d'avancer et de reculer à l'aide d'un programme informatique. Avant de commencer le projet, nous nous sommes fixé plusieurs petits objectifs afin de mener au mieux le projet.&lt;br /&gt;
&lt;br /&gt;
La voiture devait tout d'abord avancer, reculer, tourner à gauche et à droite. Des LEDs devaient être allumées lorsque la voiture effectue un déplacement.&lt;br /&gt;
&lt;br /&gt;
Pour la commande de la voiture, nous voulions qu'elle soit commandée grâce à une commande Bluetooth et pilotée depuis un smartphone. Une application devait alors être faite pour gérer les déplacements. MIT App Inventor permet de gérer des communications Bluetooth et est simple d'utilisation.&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir implémenter toutes ses fonctionnalités, nous devions réaliser une carte électronique gérée par un microcontrôleur ATMega16u2. D'autres module devaient être ajoutés pour la bonne réalisation de nos objectifs fixés.&lt;br /&gt;
&lt;br /&gt;
==La carte électronique :==&lt;br /&gt;
&lt;br /&gt;
La réalisation de la carte électronique a débuté par la création du schéma électrique sur KICAD. Nous avons implémenté ce que nous avions déjà prévu (Chargeur, moteurs, microcontrôleur...), cependant, pour certaines fonctionnalités, des composants n'étaient pas disponibles dans les librairies Sparkfun disponibles. &lt;br /&gt;
&lt;br /&gt;
Nous avons donc créé les schémas de ces composants, c'est-à-dire le module Bluetooth '''FP-BM70BLE01FC2''' ainsi que le driver du moteur '''DRV8210DRL''' grâce aux informations de leurs datasheet disponible sur Internet :  &lt;br /&gt;
&lt;br /&gt;
- Datasheet du module Bluetooth : ''https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/BM70_71-Bluetooth-Low-Energy-BLE-Module-DS60001372L.pdf'' &lt;br /&gt;
&lt;br /&gt;
- Datasheet du driver du moteur : ''https://www.ti.com/lit/ds/slvsfy8b/slvsfy8b.pdf?ts=1683016270840&amp;amp;ref_url=https%253A%252F%252Fwww.google.com%252F'' &lt;br /&gt;
&lt;br /&gt;
Au final, nous obtenons au final ce schéma correspondant :  &lt;br /&gt;
[[Fichier:Schématic voiture.jpg|alt=Schéma de la voiture|centré|vignette|Schéma de la voiture]]&lt;br /&gt;
Après avoir fait le schéma de la voiture, nous avons dû faire le routage de la carte électronique. La première chose a faire à été de prendre les côtes de la voiture afin que la carte électronique se mette bien en place dessus. De plus, nous avons dû prendre les mesures des côtes du moteur continu, celui-ci va être soudé au centre de la carte et est imposant, il fallait donc prévoir la place nécessaire que le composant prendrait.  &lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons dû réaliser les empreintes du module Bluetooth ainsi que du driver du moteur. Les mesures figurant sur leurs datasheet respectives, nous avons réussi simplement à les reproduire. Le plus compliqué a été de repérer les pâtes des composants que nous devions utiliser. Par exemple, sur le module Bluetooth, certaines entrées n'ont pas été utilisées. Nous avons aussi utilisé et adapter les empreintes des moteurs continus et pas à pas fournis par notre professeur M.Redon.  &lt;br /&gt;
&lt;br /&gt;
Après cela, nous avons commencé le routage. Nous avons commencer par router la carte le plus possible sur une seule face jusqu'à ce que ne l'on puisse plus. Sinon nous utilisions des vias afin de router sur l'autre face. Cependant, nous avons dû recommencer une seconde fois le routage, car le premier ne nous convenait pas. Nous avons aussi demandé de l'aide au professeur M.Boé afin de réaliser les plans de masse.   &lt;br /&gt;
&lt;br /&gt;
Voici une image du routage final notre carte électronique :  &lt;br /&gt;
[[Fichier:Routage voiture.jpg|alt=Routage de la carte électronique|centré|vignette|Routage de la carte électronique]]&lt;br /&gt;
Voici aussi une représentation 3D de notre carte électronique :    &lt;br /&gt;
[[Fichier:Pcb 3D.jpg|alt=Représentation 3D de notre carte électronique|centré|vignette|Représentation 3D de notre carte électronique]]&lt;br /&gt;
Le routage fini, nous avons passé commande afin de recevoir notre carte électronique et voici celle-ci avec aucune soudure :    &lt;br /&gt;
&lt;br /&gt;
Enfin, la carte étant vierge, nous devions commencer la soudure des composants. Cette partie a été très compliquée à mettre en oeuvre, car dans le groupe, aucun de nous n'avait fait de soudure dans sa vie. Nous avons donc dû apprendre à ce moment comment faire, d'où les premières soudures un peu compliquées.  &lt;br /&gt;
&lt;br /&gt;
Nous avons eu un problème de reconnaissance du microprocesseur lors de la commande &amp;quot;''lsusb&amp;quot;'', le matériel n'était pas détecté. Nous avons donc dû modifier le circuit qui comportait quelques erreurs, ainsi que remplacer les résistances et condensateurs afin de s'assurer de leur valeur. Finalement, nous avons dû changer le microprocesseur qui avec les précédents branchements avait surchauffé et était défectueux. Après avoir remplacé tous les composants, nous avons réussi à faire reconnaître le microprocesseur grâce à la commande &amp;quot;''lsusb''&amp;quot;.  Après cela, nous avons pu souder les derniers composants restants.  &lt;br /&gt;
&lt;br /&gt;
Voici une photo de notre carte avec les composants soudés :     &lt;br /&gt;
[[Fichier:Carte électronique avec les composants soudés.jpg|alt=Carte électronique avec les composants soudés|centré|vignette|Carte électronique avec les composants soudés]]&lt;br /&gt;
Nous avions fini la carte électronique, sa réalisation a pris la majeure partie de notre temps lors des séances. Il fallait donc ensuite réaliser un programme permettant de faire fonctionner et avancer la voiture.     &lt;br /&gt;
&lt;br /&gt;
Fichier ZIP de notre carte électronique : [[Fichier:Voiture CCP.zip|vignette|Voiture fichiers de routage et schéma PCB]]&lt;br /&gt;
&lt;br /&gt;
==Programme de la voiture :==&lt;br /&gt;
Le programme informatique était nécessaire pour le bon fonctionnement de la voiture, cependant comme le temps commençait à manquer, nous avons codé son programme en dehors des cours de projet.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc structuré notre code en plusieurs afin de le simplifier. Les premières fonctions permettent d'initialiser les entrées et les sorties du microcontrôleur afin de bien récupérer et envoyer les bonnes informations. De plus, dans ces fonctions, nous remettons les moteurs et les leds à LOW afin d'avoir une sécurité et qu'ils ne démarrent pas à l'initialisation. Ensuite, nous retrouvons les fonctions de déplacements. Ces fonctions gèrent les moteurs lorsqu'il faut avancer, reculer, tourner à droite, etc...&lt;br /&gt;
&lt;br /&gt;
De plus, on retrouve une fonction permettant de récupérer les informations envoyées depuis la communication Bluetooth afin de faire fonctionner la voiture à distance. Une seconde fonction permet de traiter ces informations et de faire déplacer la voiture selon l'information reçue.&lt;br /&gt;
&lt;br /&gt;
Nous pouvons aussi faire fonctionner la voiture en envoyant le programme informatique dans la voiture. Cependant, de cette manière, la voiture ne pourra pas être contrôlée et fera un trajet voulu.&lt;br /&gt;
&lt;br /&gt;
La communication Bluetooth étant un de nos objectifs fixé, nous avons dû réaliser une application afin de pouvoir utiliser la voiture à distance.&lt;br /&gt;
&lt;br /&gt;
Voici une vidéo de la carte avec une LED qui clignote : &lt;br /&gt;
[[Fichier:PCB clignote.mov|alt=LED qui clignote|centré|vignette|LED qui clignote]]&lt;br /&gt;
&lt;br /&gt;
==Application Bluetooth :==&lt;br /&gt;
Nous nous étions fixé comme objectif que la voiture devait être contrôlée grâce à une application Bluetooth. Nous avons alors décidé de réaliser cette application grâce au site '''MIT App Inventor''', ce site est simple d'utilisation et permet de gérer des communications Bluetooth facilement. De plus, le temps a été investi surtout dans la carte électronique donc apprendre et programmer par nous-même dans un langage de programmation nouveau aurait été compliqué pour nous.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé que les informations envoyées par communication Bluetooth serait sous forme hexadécimale. Le programme informatique du côté de l'ATMega16u2 recevra et traitera alors les informations reçues. &lt;br /&gt;
&lt;br /&gt;
L'application devait avoir un aspect simple d'utilisation et sobre afin de faciliter l'expérience de l'utilisateur. L'application amènerait l'utilisateur sur une page permettant de choisir à quel appareil Bluetooth se connecter. Un statut indiquant si le smartphone est connecté ou non à l'appareil est aussi présent. L'élément le plus important de la page est le bloc de déplacement, composé de 4 boutons représentant des flèches directionnelles afin de piloter la voiture.&lt;br /&gt;
&lt;br /&gt;
Lorsque nous avions terminé l'application pour piloter grâce à des flèches directionnelles, nous nous sommes rendu compte que nous pourrions réaliser aussi un pilotage par gyroscope. En effet, les informations transmises pour les déplacements restent les mêmes donc du côté du programme informatique, rien ne change. Nous avons deux moyens de piloter la voiture : une par appui sur des flèches directionnelles, et une seconde par inclinaison du smartphone. &lt;br /&gt;
&lt;br /&gt;
Voilà des captures d'écran montrant l'aspect et les fonctionnalités de l'application : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed&amp;quot; widths=&amp;quot;150&amp;quot; heights=&amp;quot;150&amp;quot;&amp;gt;&lt;br /&gt;
Fichier:App Screen Controls.jpg|Contrôle par touche&lt;br /&gt;
Fichier:App Screen Gyro.jpg|Contrôle par gyroscope&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
Pour réaliser cette application, il faut du code en interne, voici les codes que nous avons utilisé :&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed&amp;quot; widths=&amp;quot;150&amp;quot; heights=&amp;quot;150&amp;quot;&amp;gt;&lt;br /&gt;
Fichier:Connexion Bluetooth.jpg|Bloc de connexion Bluetooth&lt;br /&gt;
Fichier:Gestion des boutons.jpg|Bloc de gestion des touches&lt;br /&gt;
Fichier:Gestion gyroscope.jpg|Bloc de gestion du gyroscope&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Le fichier APK de l'application est disponible dans le GIT du projet.'''&lt;br /&gt;
&lt;br /&gt;
= '''Epreuve complémentaire CAZIN Némo''' =&lt;br /&gt;
&lt;br /&gt;
== Introduction : ==&lt;br /&gt;
J’ai dû reprendre le projet lors de mon épreuve complémentaire de Semestre 6&lt;br /&gt;
&lt;br /&gt;
Avant cela, avec mon groupe de travail, nous avions réussi à faire clignoter une LED malgré tous les problèmes que nous avons rencontrés comme des composants qui ne fonctionnait plus sur la carte ou alors des courts circuits à faire nous-mêmes. Je ne traiterais donc pas ici la partie du clignotement de la LED.&lt;br /&gt;
&lt;br /&gt;
== Préparation de la carte électronique : ==&lt;br /&gt;
Tout d’abord, lorsque j’ai repris le projet, je savais que les soudures des composants et du moteur continu avait été faites mais elles étaient fragiles du fait de la petite épaisseur des pistes reliant le moteur au driver. Cependant, le voyage de la boite avec la carte électronique à l’intérieur avait complétement cassé les soudures du moteur. &lt;br /&gt;
&lt;br /&gt;
Voici l’état de la carte lors de la reprise du projet :&lt;br /&gt;
[[Fichier:Carte pas de soudure.jpg|alt=Carte avec le moteur désoudé|centré|vignette|Carte avec le moteur désoudé]]&lt;br /&gt;
J’ai donc dû refaire les soudures du moteur, ce qui a été un peu compliqué car j’ai du mal à souder en général. Mais en m’inspirant des photos que j’avais d’avant la reprise du projet, j’ai pu mieux m’en sortir. Voilà le résultat de la soudure du moteur continu : &lt;br /&gt;
[[Fichier:Carte moteur DC.jpg|alt=Carte avec le moteur continu soudé|centré|vignette|Carte avec le moteur continu soudé]]&lt;br /&gt;
Après cela, j’ai voulu continuer mon travail en faisant les soudures du moteur pas-à-pas. Ce moteur est très petit et les soudures à faire devaient être très précises. Pour que ce soit plus simples, j’ai utilisé 4 pins que j’ai souder à la carte et sur les pins, des câbles sont reliés jusqu’aux quatre liaisons du moteur. Le moteur est alors déporté de la carte mais ce n’est pas très important car on veut juste le voir fonctionner et aucunes roues n’est attachées. Ces soudures étaient vraiment compliquées à réaliser car elles étaient très minutieuses et souvent des soudures se cassaient lorsque j’en soudais une autre. &lt;br /&gt;
&lt;br /&gt;
Voilà le résultat de la soudure du moteur pas à pas : &lt;br /&gt;
[[Fichier:Carte moteur pap.jpg|alt=Carte avec le moteur pas-à-pas soudé|centré|vignette|Carte avec le moteur pas-à-pas soudé]]&lt;br /&gt;
&lt;br /&gt;
== Problèmes eu pendant la programmation de la carte sur ordinateur : ==&lt;br /&gt;
J'ai rencontré plusieurs problèmes lors de la programmation de mes programmes et lors de la reconnaissance de la carte par les machines. &lt;br /&gt;
&lt;br /&gt;
Tout d'abord, il faut savoir que j'ai commencé développer mes programmes informatiques sur les machines de l’école à distance grâce à l’outil : '''https://tp-info.polytech-lille.fr/#'''&lt;br /&gt;
&lt;br /&gt;
Ensuite, le premier problème était que certaines bibliothèques utilisées, notamment '''''&amp;lt;avr/io.h&amp;gt;''''' ne sont pas trouvables, ce qui fait que la compilation d'un de mes fichiers de test ne peut pas être réalisée. J'ai comme hypothèse que soit la librairie n'est pas installée sur les machines des salles de TP en C10X, soit il faut être en superutilisateur pour pouvoir compiler le fichier d'après les notes que j'avais des cours. Je ne peux pas me mettre en superutilisateur car il faut le mot de passe de la machine locale que je ne connais pas. Pour contourner ce problème, j'ai défini comme constantes toutes les variables utilisées mais ce n'est qu'une solution temporaire qui ne marchera peut-être pas lors de l'envoi du programme sur la carte, mais au moins j'ai réussi à compiler mes fichiers.&lt;br /&gt;
[[Fichier:Erreur include.jpg|alt=Message de l'erreur reçu par rapport à la librairie &amp;lt;avr/io.h&amp;gt;|centré|vignette|Message de l'erreur reçu par rapport à la librairie &amp;lt;avr/io.h&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Enfin, pour le second problème, j’ai voulu voir si la carte était reconnue depuis les machines à distance grâce à la commande shell « '''''lsusb''''' ». Cependant, lorsque je me connecte sur ces machines, les périphériques USB de mon ordinateur ne sont pas reconnus. En faisant plusieurs essais pour résoudre ce problème, j’ai compris que ce n’était pas possible et donc qu’il fallait passer par une autre méthode. Sois-je faisais directement la programmation sur Windows mais télécharger les dépendances et le compilateur C allait être compliqué. Sois-je téléchargeais une machine virtuelle Ubuntu pour être directement sur un système Linux et plus simplement programmer. J’ai donc choisi la première option car je craignais que la machine virtuelle ne reconnaisse pas elle aussi les périphériques USB.&lt;br /&gt;
&lt;br /&gt;
J’ai donc modifié l’option développeur de mon Windows afin de pouvoir télécharger un environnement terminal Ubuntu qui fonctionne grâce à Windows Subsystem for Linux (WSL). J’ai alors rencontré une erreur lors du lancement du terminal Ubuntu : &lt;br /&gt;
[[Fichier:Erreur Ubuntu.jpg|alt=Erreur WSL pour Ubuntu|centré|vignette|Erreur WSL pour Ubuntu]]&lt;br /&gt;
J’ai alors trouvé une documentation de Microsoft sur le WSL qui m’a permis de résoudre ce problème ('''https://learn.microsoft.com/fr-fr/windows/wsl/troubleshooting'''). Après cela, j’ai voulu donc tester la commande « '''''lsusb''''' » mais encore une fois, une nouvelle erreur apparaît :&lt;br /&gt;
[[Fichier:Erreur libusb.jpg|alt=Erreur de la libusb sur Ubuntu|centré|vignette|Erreur de la libusb sur Ubuntu]]&lt;br /&gt;
J’ai donc télécharger la librairie libusb grâce à la commande « '''''sudo apt-get install libusb-1.0-0-dev''''' » que j’ai trouver grâce aux informations de ce site : '''https://askubuntu.com/questions/629619/how-to-install-libusb''' mais même en faisant cette commande, j’ai toujours eu la même erreur. Donc à ce stade du projet, je ne peux donc pas transférer et tester mes programmes, je vais continuer à chercher une solution.&lt;br /&gt;
&lt;br /&gt;
En parallèle, j'ai essayé d'installer une machine virtuelle Ubuntu sur mon ordinateur, mais Oracle VM VirtualBox n'accepte que les fichiers .xml alors que je me suis procuré un fichier .iso&lt;br /&gt;
&lt;br /&gt;
== Programmation du moteur continu : ==&lt;br /&gt;
J’ai donc commencé par la partie du moteur continu car c’est sur cette partie que nous nous sommes arrêtés.&lt;br /&gt;
&lt;br /&gt;
Afin de faire fonctionner le moteur, je devais faire un programme informatique afin de gérer cette fonctionnalité. J’ai tout d’abord créé une fonction pour initialiser les ports du moteur comme étant des sorties. Ensuite, j’ai créé une fonction « avancer » où je mets un des ports sous tension et l’autre non. Pour la fonction « reculer », il s’agit de la même chose mais il faut inverser quel port est sous tension. Enfin pour la fonction « arrêter », il suffit de mettre les deux ports à 0.&lt;br /&gt;
&lt;br /&gt;
Voici donc le code pour faire fonctionner le moteur de cette façon :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR DC AVEC PORT ///&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
    &lt;br /&gt;
void initMotDC_Port(void){&lt;br /&gt;
    DDRB |= (1&amp;lt;&amp;lt;PB7);                   //PMW2 en OUTPUT&lt;br /&gt;
    DDRD |= (1&amp;lt;&amp;lt;PD0);                   //PMW1 en OUTPUT&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7);                     //PMW2 à LOW&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0);                     //PMW1 à LOW&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
////////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR DC AVEC PORT ///&lt;br /&gt;
////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void move_forwards(void){&lt;br /&gt;
    PORTB=(1&amp;lt;&amp;lt;PB7); //MOT1 à HIGH&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0); //MOT2 à LOW&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void move_backwards(void){&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7); //MOT1 à LOW&lt;br /&gt;
    PORTD=(1&amp;lt;&amp;lt;PD0); //MOT2 à HIGH&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void stop(void){&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7); //MOT1 à LOW&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0); //MOT2 à LOW   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir fait cela, je me suis demander si nous pouvions contrôler la vitesse du moteur. J’ai alors regardé trouver une page d’un cours de PSE ('''https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme053.html''')expliquant comment fonctionne les actionneurs simples grâce au signaux PWM (Pulse Width Modulation). Une partie du programme pour l’initialisation des ports était donnée, cependant il s’agissait de la gestion des sorties que je ne comprenais pas (OCR0A, OCR0B …), j’ai donc dû effectuer plusieurs recherches sur cette partie.  Voici donc le code pour faire fonctionner le moteur de cette autre façon :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR DC AVEC OCR1 ///&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void initMotDC_OCR(void){&lt;br /&gt;
    DDRB |= (1&amp;lt;&amp;lt;PB7);                   //PMW2 en OUTPUT&lt;br /&gt;
    DDRD |= (1&amp;lt;&amp;lt;PD0);                   //PMW1 en OUTPUT&lt;br /&gt;
    TCCR1A |= (1&amp;lt;&amp;lt;COM1A1)|(1&amp;lt;&amp;lt;COM1C1);  // Les ports PWM se comportent normalement&lt;br /&gt;
    TCCR1A |= (1&amp;lt;&amp;lt;WGM11)|(1&amp;lt;&amp;lt;WGM10);    // Minuteur mis en mode PWM&lt;br /&gt;
    TCCR1B |= (1&amp;lt;&amp;lt;CS10);                // Pas de pré-diviseur, démarre le compteur&lt;br /&gt;
&lt;br /&gt;
///////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR DC AVEC OCR ///&lt;br /&gt;
///////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void move_forwards_OCR(void){&lt;br /&gt;
    OCR1A = 512;&lt;br /&gt;
    OCR1C = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void move_backwards_OCR(void){&lt;br /&gt;
    OCR1A = 0;&lt;br /&gt;
    OCR1C = 512;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void stop_OCR(void){&lt;br /&gt;
    OCR1A = 0;&lt;br /&gt;
    OCR1C = 0;   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation du moteur pas à pas : ==&lt;br /&gt;
Comme je n'avais jamais travaillé sur un moteur pas à pas, j'ai voulu comprendre son fonctionnement. Après plusieurs recherches, j'ai compris que le moteur était constitué d'un rotor magnétique et de bobines. Nous avons ici un moteur pas à pas bipolaire, avec 4 sorties. Le moteur fonctionne par pas succesifs comme une montre, ce qui signifie qu'il faut jouer avec chacune des sorties afin de faire le faire tourner pas par pas. En partant de ce principe nous pouvons programmer une fonction pour que chaque sorties soit sous tension les unes à la suite des autres.&lt;br /&gt;
&lt;br /&gt;
Voici le programme pour faire tourner le moteur pas à pas dans un sens :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
///////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR PAS A PAS ///&lt;br /&gt;
///////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void initMotStepper(void){&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR PAS A PAS ///&lt;br /&gt;
/////////////////////////////////&lt;br /&gt;
    &lt;br /&gt;
void stepper_left(void){&lt;br /&gt;
    for(int i = 0; i&amp;lt;=100; i++){&lt;br /&gt;
        //M1_A+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC5);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Pour aller dans l'autre sens, il suffit d'inverser le sens des broches des sorties :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void stepper_right(void){&lt;br /&gt;
    for(int i = 0; i&amp;lt;=100; i++){&lt;br /&gt;
        //M1_B+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC7);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Voici ma documentation :&lt;br /&gt;
&lt;br /&gt;
- '''https://www.tme.eu/fr/news/library-articles/page/41861/Moteur-pas-a-pas-types-et-exemples-dapplications-des-moteurs-pas-a-pas/'''&lt;br /&gt;
&lt;br /&gt;
- '''https://www.youtube.com/watch?v=655p1N9tSKQ'''&lt;br /&gt;
&lt;br /&gt;
- '''http://www.micropython.fr/modules_center/moteurs/pas_a_pas/moteur_pap/#le-principe-dun-moteur-pas-a-pas'''&lt;br /&gt;
&lt;br /&gt;
== Programmation de la communication Bluetooth : ==&lt;br /&gt;
La partie Bluetooth était un de nos objectifs du début de projet afin de contrôler la voiture à distance et grâce à une application. Pour cela, j’ai dû refaire des recherches sur le sujet afin de mieux comprendre comment je pourrai faire. J’ai donc dû regarder la documentation de l’atmega16u2 et des cours en ligne d’autres universités pour bien comprendre. C’est alors que j’ai compris que la communication série UART permettrait de répondre à mes besoins. J’ai donc écrit une fonction qui permet l’initialisation de la communication série UART en activant la transmission (TX) et la réception (RX). Ensuite dans cette même fonction j’ai dû définir le format de la trame, elle est donc composée de 8 bits, c’est-à-dire un octet avec un bit d’arrêt.&lt;br /&gt;
&lt;br /&gt;
Nous n’avons besoin que de recevoir des informations sur la communication série UART, pas d’en envoyer. C’est pour cela que j’ai donc dû faire une seconde fonction permettant de recevoir les informations de l’application sur le port RX de l’Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Voici le code de la communication UART :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION COMMUNICATION UART ///&lt;br /&gt;
/////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void UART_init(unsigned int baud_rate){&lt;br /&gt;
    // Calculer la valeur de UBRR en fonction du baud_rate&lt;br /&gt;
    unsigned int ubrr_val = FREQ_CPU / (16UL * baud_rate) - 1;    &lt;br /&gt;
    // Définir les valeurs UBRRH et UBRRL&lt;br /&gt;
    UBRRH = (unsigned char)(ubrr_val &amp;gt;&amp;gt; 8);&lt;br /&gt;
    UBRRL = (unsigned char)ubrr_val;&lt;br /&gt;
    // Activer la transmission et la réception&lt;br /&gt;
    UCSRB = (1 &amp;lt;&amp;lt; TXEN) | (1 &amp;lt;&amp;lt; RXEN);&lt;br /&gt;
    // Définir le format de trame: 8 bits de données, 1 bit d'arrêt&lt;br /&gt;
    UCSRC = (1 &amp;lt;&amp;lt; URSEL) | (1 &amp;lt;&amp;lt; UCSZ1) | (1 &amp;lt;&amp;lt; UCSZ0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/////////////////////////////////////&lt;br /&gt;
/// RECUPERATION DES DONNEES UART ///&lt;br /&gt;
/////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
int UART_receiver(void) {&lt;br /&gt;
    // Attendre que le tampon d'entrée soit plein&lt;br /&gt;
    while (!(UCSRA &amp;amp; (1 &amp;lt;&amp;lt; RXC)));&lt;br /&gt;
    // Lire le caractère du tampon d'entrée&lt;br /&gt;
    return UDR;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Cette fonction ne pouvait pas être testée car l’antenne Bluetooth n’est pas présente sur la carte électronique de la voiture. Cependant, ces recherches m’ont permis de mieux comprendre la communication série UART que j’avais mal compris lors des TP du semestre 6.&lt;br /&gt;
&lt;br /&gt;
== Programmation USB/LUFA ==&lt;br /&gt;
Pour cette partie de la programmation via USB/LUFA, j’ai repris le fichier utilisé lors de notre cours de TPI. Ce fichier avait quelques modifications à faire avant d’être utilisé. Tout d’abord, j’ai dû changer les ID Vendor et Product de la carte électronique car celle utilisée maintenant n’est pas la même que pendant le cours de TPI. Normalement grâce à la commande &amp;quot;'''''lsusb -vvv&amp;quot;''''', on peut trouver le microcontrôleur utilisé et ces ID, mais nous les avions déjà noté auparavant. On trouve alors :&lt;br /&gt;
&lt;br /&gt;
-       ID VENDOR : 0x03EB  &lt;br /&gt;
&lt;br /&gt;
-       ID PRODUCT : 0x2FEF&lt;br /&gt;
&lt;br /&gt;
Ensuite, des modifications étaient à faire sur les fichiers du descripteur. En effet, celui-ci avait du code qui faisait référence au joystick utilisé en TPI. J’ai donc juste gardé les fonctions qui faisaient référence aux actionneurs.&lt;br /&gt;
&lt;br /&gt;
De plus, afin de pouvoir gérer les actionneurs, j’ai préparé en amont comment ils seront activés grâce aux octets à envoyer. Cependant, j’ai décidé d’utiliser qu’un seul octet de contrôle car 2 était beaucoup trop pour les simples fonctions que nous avions. Nous avons alors un seul octet ayant chaque bit qui représente une fonction de contrôle de la voiture avec de droite à gauche :&lt;br /&gt;
&lt;br /&gt;
-       Bit 0 à Allume la LED&lt;br /&gt;
&lt;br /&gt;
-       Bit 1 à Fait avancer la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 2 à Fait reculer la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 3 à Fait tourner dans un sens la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 4 à Fait tourner dans l’autre sens la voiture&lt;br /&gt;
&lt;br /&gt;
Par exemple, le schéma ci-dessous permet d’allumer la LED de la voiture, de la faire reculer, et en même temps de la faire tourner dans un sens :&lt;br /&gt;
[[Fichier:USB exemple.png|alt=Exemple d'octet|centré|vignette|Exemple d'octet ]]&lt;br /&gt;
Voici d'ailleurs le code du programme traitant chaque bits de l'octet pour éxécuter les fonctions voulues : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void actionneurs_gestion(void){&lt;br /&gt;
	Endpoint_SelectEndpoint(ACT_EPADDR);&lt;br /&gt;
	if (Endpoint_IsOUTReceived()){&lt;br /&gt;
		if (Endpoint_IsReadWriteAllowed()){&lt;br /&gt;
		  	uint16_t ACT_Report = Endpoint_Read_16_LE();&lt;br /&gt;
&lt;br /&gt;
            //CONTROLE DES LEDS&lt;br /&gt;
            if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;0))&lt;br /&gt;
                led_on();&lt;br /&gt;
            else &lt;br /&gt;
                led_off();&lt;br /&gt;
        &lt;br /&gt;
			//CONTROLE DU MOTEUR DC&lt;br /&gt;
			if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;1))&lt;br /&gt;
                move_forwards();&lt;br /&gt;
            else if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;2))&lt;br /&gt;
                move_backwards();	&lt;br /&gt;
			else&lt;br /&gt;
                stop();&lt;br /&gt;
            &lt;br /&gt;
            //CONTROLE DU MOTEUR PAS A PAS&lt;br /&gt;
            if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;3))&lt;br /&gt;
                stepper_left();&lt;br /&gt;
            else if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;4))&lt;br /&gt;
                stepper_right();&lt;br /&gt;
		}&lt;br /&gt;
		/* Handshake the OUT Endpoint - clear endpoint and ready for next report */&lt;br /&gt;
		Endpoint_ClearOUT();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, nous avons juste à envoyer l’octet de notre choix afin de gérer comme on le veut les actionneurs. &lt;br /&gt;
&lt;br /&gt;
En retravaillant sur cette partie, j’ai mieux compris le fonctionnement de la libusb que je n’avais pas beaucoup compris lors du TPI. J’ai pu me documenter sur le sujet en faisant beaucoup de recherche et même d’apprendre des nouvelles façons de travailler avec le langage C et d’avoir une meilleure syntaxe de programmation.&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Erreur_include.jpg&amp;diff=1393</id>
		<title>Fichier:Erreur include.jpg</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=Fichier:Erreur_include.jpg&amp;diff=1393"/>
		<updated>2023-09-04T08:21:12Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Erreur include&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE3Trinome2022-8&amp;diff=1385</id>
		<title>SE3Trinome2022-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE3Trinome2022-8&amp;diff=1385"/>
		<updated>2023-09-01T13:41:40Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : /* Epreuve complémentaire CAZIN Némo */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= '''Projet SE3 : Premier Système''' =&lt;br /&gt;
CAZIN Némo, CEGARRA Antoine, PALIFERRO Adrien&lt;br /&gt;
&lt;br /&gt;
'''Lien du git :''' ''https://archives.plil.fr/ncazin/SE3_GROUPE_8.git''&lt;br /&gt;
&lt;br /&gt;
==Objectifs fixés :==&lt;br /&gt;
L'objectif principal de ce projet était de '''réaliser la commande d'une voiture au format 1:43''' capable d'avancer et de reculer à l'aide d'un programme informatique. Avant de commencer le projet, nous nous sommes fixé plusieurs petits objectifs afin de mener au mieux le projet.&lt;br /&gt;
&lt;br /&gt;
La voiture devait tout d'abord avancer, reculer, tourner à gauche et à droite. Des LEDs devaient être allumées lorsque la voiture effectue un déplacement.&lt;br /&gt;
&lt;br /&gt;
Pour la commande de la voiture, nous voulions qu'elle soit commandée grâce à une commande Bluetooth et pilotée depuis un smartphone. Une application devait alors être faite pour gérer les déplacements. MIT App Inventor permet de gérer des communications Bluetooth et est simple d'utilisation.&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir implémenter toutes ses fonctionnalités, nous devions réaliser une carte électronique gérée par un microcontrôleur ATMega16u2. D'autres module devaient être ajoutés pour la bonne réalisation de nos objectifs fixés.&lt;br /&gt;
&lt;br /&gt;
==La carte électronique :==&lt;br /&gt;
&lt;br /&gt;
La réalisation de la carte électronique a débuté par la création du schéma électrique sur KICAD. Nous avons implémenté ce que nous avions déjà prévu (Chargeur, moteurs, microcontrôleur...), cependant, pour certaines fonctionnalités, des composants n'étaient pas disponibles dans les librairies Sparkfun disponibles. &lt;br /&gt;
&lt;br /&gt;
Nous avons donc créé les schémas de ces composants, c'est-à-dire le module Bluetooth '''FP-BM70BLE01FC2''' ainsi que le driver du moteur '''DRV8210DRL''' grâce aux informations de leurs datasheet disponible sur Internet :  &lt;br /&gt;
&lt;br /&gt;
- Datasheet du module Bluetooth : ''https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/BM70_71-Bluetooth-Low-Energy-BLE-Module-DS60001372L.pdf'' &lt;br /&gt;
&lt;br /&gt;
- Datasheet du driver du moteur : ''https://www.ti.com/lit/ds/slvsfy8b/slvsfy8b.pdf?ts=1683016270840&amp;amp;ref_url=https%253A%252F%252Fwww.google.com%252F'' &lt;br /&gt;
&lt;br /&gt;
Au final, nous obtenons au final ce schéma correspondant :  &lt;br /&gt;
[[Fichier:Schématic voiture.jpg|alt=Schéma de la voiture|centré|vignette|Schéma de la voiture]]&lt;br /&gt;
Après avoir fait le schéma de la voiture, nous avons dû faire le routage de la carte électronique. La première chose a faire à été de prendre les côtes de la voiture afin que la carte électronique se mette bien en place dessus. De plus, nous avons dû prendre les mesures des côtes du moteur continu, celui-ci va être soudé au centre de la carte et est imposant, il fallait donc prévoir la place nécessaire que le composant prendrait.  &lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons dû réaliser les empreintes du module Bluetooth ainsi que du driver du moteur. Les mesures figurant sur leurs datasheet respectives, nous avons réussi simplement à les reproduire. Le plus compliqué a été de repérer les pâtes des composants que nous devions utiliser. Par exemple, sur le module Bluetooth, certaines entrées n'ont pas été utilisées. Nous avons aussi utilisé et adapter les empreintes des moteurs continus et pas à pas fournis par notre professeur M.Redon.  &lt;br /&gt;
&lt;br /&gt;
Après cela, nous avons commencé le routage. Nous avons commencer par router la carte le plus possible sur une seule face jusqu'à ce que ne l'on puisse plus. Sinon nous utilisions des vias afin de router sur l'autre face. Cependant, nous avons dû recommencer une seconde fois le routage, car le premier ne nous convenait pas. Nous avons aussi demandé de l'aide au professeur M.Boé afin de réaliser les plans de masse.   &lt;br /&gt;
&lt;br /&gt;
Voici une image du routage final notre carte électronique :  &lt;br /&gt;
[[Fichier:Routage voiture.jpg|alt=Routage de la carte électronique|centré|vignette|Routage de la carte électronique]]&lt;br /&gt;
Voici aussi une représentation 3D de notre carte électronique :    &lt;br /&gt;
[[Fichier:Pcb 3D.jpg|alt=Représentation 3D de notre carte électronique|centré|vignette|Représentation 3D de notre carte électronique]]&lt;br /&gt;
Le routage fini, nous avons passé commande afin de recevoir notre carte électronique et voici celle-ci avec aucune soudure :    &lt;br /&gt;
&lt;br /&gt;
Enfin, la carte étant vierge, nous devions commencer la soudure des composants. Cette partie a été très compliquée à mettre en oeuvre, car dans le groupe, aucun de nous n'avait fait de soudure dans sa vie. Nous avons donc dû apprendre à ce moment comment faire, d'où les premières soudures un peu compliquées.  &lt;br /&gt;
&lt;br /&gt;
Nous avons eu un problème de reconnaissance du microprocesseur lors de la commande &amp;quot;''lsusb&amp;quot;'', le matériel n'était pas détecté. Nous avons donc dû modifier le circuit qui comportait quelques erreurs, ainsi que remplacer les résistances et condensateurs afin de s'assurer de leur valeur. Finalement, nous avons dû changer le microprocesseur qui avec les précédents branchements avait surchauffé et était défectueux. Après avoir remplacé tous les composants, nous avons réussi à faire reconnaître le microprocesseur grâce à la commande &amp;quot;''lsusb''&amp;quot;.  Après cela, nous avons pu souder les derniers composants restants.  &lt;br /&gt;
&lt;br /&gt;
Voici une photo de notre carte avec les composants soudés :     &lt;br /&gt;
[[Fichier:Carte électronique avec les composants soudés.jpg|alt=Carte électronique avec les composants soudés|centré|vignette|Carte électronique avec les composants soudés]]&lt;br /&gt;
Nous avions fini la carte électronique, sa réalisation a pris la majeure partie de notre temps lors des séances. Il fallait donc ensuite réaliser un programme permettant de faire fonctionner et avancer la voiture.     &lt;br /&gt;
&lt;br /&gt;
Fichier ZIP de notre carte électronique : [[Fichier:Voiture CCP.zip|vignette|Voiture fichiers de routage et schéma PCB]]&lt;br /&gt;
&lt;br /&gt;
==Programme de la voiture :==&lt;br /&gt;
Le programme informatique était nécessaire pour le bon fonctionnement de la voiture, cependant comme le temps commençait à manquer, nous avons codé son programme en dehors des cours de projet.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc structuré notre code en plusieurs afin de le simplifier. Les premières fonctions permettent d'initialiser les entrées et les sorties du microcontrôleur afin de bien récupérer et envoyer les bonnes informations. De plus, dans ces fonctions, nous remettons les moteurs et les leds à LOW afin d'avoir une sécurité et qu'ils ne démarrent pas à l'initialisation. Ensuite, nous retrouvons les fonctions de déplacements. Ces fonctions gèrent les moteurs lorsqu'il faut avancer, reculer, tourner à droite, etc...&lt;br /&gt;
&lt;br /&gt;
De plus, on retrouve une fonction permettant de récupérer les informations envoyées depuis la communication Bluetooth afin de faire fonctionner la voiture à distance. Une seconde fonction permet de traiter ces informations et de faire déplacer la voiture selon l'information reçue.&lt;br /&gt;
&lt;br /&gt;
Nous pouvons aussi faire fonctionner la voiture en envoyant le programme informatique dans la voiture. Cependant, de cette manière, la voiture ne pourra pas être contrôlée et fera un trajet voulu.&lt;br /&gt;
&lt;br /&gt;
La communication Bluetooth étant un de nos objectifs fixé, nous avons dû réaliser une application afin de pouvoir utiliser la voiture à distance.&lt;br /&gt;
&lt;br /&gt;
Voici une vidéo de la carte avec une LED qui clignote : &lt;br /&gt;
[[Fichier:PCB clignote.mov|alt=LED qui clignote|centré|vignette|LED qui clignote]]&lt;br /&gt;
&lt;br /&gt;
==Application Bluetooth :==&lt;br /&gt;
Nous nous étions fixé comme objectif que la voiture devait être contrôlée grâce à une application Bluetooth. Nous avons alors décidé de réaliser cette application grâce au site '''MIT App Inventor''', ce site est simple d'utilisation et permet de gérer des communications Bluetooth facilement. De plus, le temps a été investi surtout dans la carte électronique donc apprendre et programmer par nous-même dans un langage de programmation nouveau aurait été compliqué pour nous.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé que les informations envoyées par communication Bluetooth serait sous forme hexadécimale. Le programme informatique du côté de l'ATMega16u2 recevra et traitera alors les informations reçues. &lt;br /&gt;
&lt;br /&gt;
L'application devait avoir un aspect simple d'utilisation et sobre afin de faciliter l'expérience de l'utilisateur. L'application amènerait l'utilisateur sur une page permettant de choisir à quel appareil Bluetooth se connecter. Un statut indiquant si le smartphone est connecté ou non à l'appareil est aussi présent. L'élément le plus important de la page est le bloc de déplacement, composé de 4 boutons représentant des flèches directionnelles afin de piloter la voiture.&lt;br /&gt;
&lt;br /&gt;
Lorsque nous avions terminé l'application pour piloter grâce à des flèches directionnelles, nous nous sommes rendu compte que nous pourrions réaliser aussi un pilotage par gyroscope. En effet, les informations transmises pour les déplacements restent les mêmes donc du côté du programme informatique, rien ne change. Nous avons deux moyens de piloter la voiture : une par appui sur des flèches directionnelles, et une seconde par inclinaison du smartphone. &lt;br /&gt;
&lt;br /&gt;
Voilà des captures d'écran montrant l'aspect et les fonctionnalités de l'application : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed&amp;quot; widths=&amp;quot;150&amp;quot; heights=&amp;quot;150&amp;quot;&amp;gt;&lt;br /&gt;
Fichier:App Screen Controls.jpg|Contrôle par touche&lt;br /&gt;
Fichier:App Screen Gyro.jpg|Contrôle par gyroscope&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
Pour réaliser cette application, il faut du code en interne, voici les codes que nous avons utilisé :&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed&amp;quot; widths=&amp;quot;150&amp;quot; heights=&amp;quot;150&amp;quot;&amp;gt;&lt;br /&gt;
Fichier:Connexion Bluetooth.jpg|Bloc de connexion Bluetooth&lt;br /&gt;
Fichier:Gestion des boutons.jpg|Bloc de gestion des touches&lt;br /&gt;
Fichier:Gestion gyroscope.jpg|Bloc de gestion du gyroscope&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Le fichier APK de l'application est disponible dans le GIT du projet.'''&lt;br /&gt;
&lt;br /&gt;
= '''Epreuve complémentaire CAZIN Némo''' =&lt;br /&gt;
&lt;br /&gt;
== Introduction : ==&lt;br /&gt;
J’ai dû reprendre le projet lors de mon épreuve complémentaire de Semestre 6&lt;br /&gt;
&lt;br /&gt;
Avant cela, avec mon groupe de travail, nous avions réussi à faire clignoter une LED malgré tous les problèmes que nous avons rencontrés comme des composants qui ne fonctionnait plus sur la carte ou alors des courts circuits à faire nous-mêmes. Je ne traiterais donc pas ici la partie du clignotement de la LED.&lt;br /&gt;
&lt;br /&gt;
== Préparation de la carte électronique : ==&lt;br /&gt;
Tout d’abord, lorsque j’ai repris le projet, je savais que les soudures des composants et du moteur continu avait été faites mais elles étaient fragiles du fait de la petite épaisseur des pistes reliant le moteur au driver. Cependant, le voyage de la boite avec la carte électronique à l’intérieur avait complétement cassé les soudures du moteur. &lt;br /&gt;
&lt;br /&gt;
Voici l’état de la carte lors de la reprise du projet :&lt;br /&gt;
[[Fichier:Carte pas de soudure.jpg|alt=Carte avec le moteur désoudé|centré|vignette|Carte avec le moteur désoudé]]&lt;br /&gt;
J’ai donc dû refaire les soudures du moteur, ce qui a été un peu compliqué car j’ai du mal à souder en général. Mais en m’inspirant des photos que j’avais d’avant la reprise du projet, j’ai pu mieux m’en sortir. Voilà le résultat de la soudure du moteur continu : &lt;br /&gt;
[[Fichier:Carte moteur DC.jpg|alt=Carte avec le moteur continu soudé|centré|vignette|Carte avec le moteur continu soudé]]&lt;br /&gt;
Après cela, j’ai voulu continuer mon travail en faisant les soudures du moteur pas-à-pas. Ce moteur est très petit et les soudures à faire devaient être très précises. Pour que ce soit plus simples, j’ai utilisé 4 pins que j’ai souder à la carte et sur les pins, des câbles sont reliés jusqu’aux quatre liaisons du moteur. Le moteur est alors déporté de la carte mais ce n’est pas très important car on veut juste le voir fonctionner et aucunes roues n’est attachées. Ces soudures étaient vraiment compliquées à réaliser car elles étaient très minutieuses et souvent des soudures se cassaient lorsque j’en soudais une autre. &lt;br /&gt;
&lt;br /&gt;
Voilà le résultat de la soudure du moteur pas à pas : &lt;br /&gt;
[[Fichier:Carte moteur pap.jpg|alt=Carte avec le moteur pas-à-pas soudé|centré|vignette|Carte avec le moteur pas-à-pas soudé]]&lt;br /&gt;
&lt;br /&gt;
== Connexion de la carte sur ordinateur : ==&lt;br /&gt;
Avant de commencer la programmation, j’ai voulu voir si la carte était toujours détectée grâce à la commande shell « '''''lsusb''''' » afin de savoir si le microcontrôleur n’avait pas lui aussi eu un problème pendant le voyage. J’ai alors rencontré plusieurs problèmes.&lt;br /&gt;
&lt;br /&gt;
En effet, j’avais commencé à développer mes programmes informatiques sur les machines de l’école à distance grâce à l’outil : '''https://tp-info.polytech-lille.fr/#''' . J’ai donc voulu voir si la carte était reconnue aussi depuis les machines à distances.&lt;br /&gt;
&lt;br /&gt;
Cependant, lorsque je me connecte sur ces machines, les périphériques USB de mon ordinateur ne sont pas reconnus. En faisant plusieurs essais pour résoudre ce problème, j’ai compris que ce n’était pas possible et donc qu’il fallait passer par une autre méthode. Sois-je faisais directement la programmation sur Windows mais télécharger les dépendances et le compilateur C allait être compliqué. Sois-je téléchargeais une machine virtuelle Ubuntu pour être directement sur un système Linux et plus simplement programmer. J’ai donc choisi la première option car je craignais que la machine virtuelle ne reconnaisse pas elle aussi les périphériques USB.&lt;br /&gt;
&lt;br /&gt;
J’ai donc modifié l’option développeur de mon Windows afin de pouvoir télécharger un environnement terminal Ubuntu qui fonctionne grâce à Windows Subsystem for Linux (WSL). J’ai alors rencontré une erreur lors du lancement du terminal Ubuntu : &lt;br /&gt;
[[Fichier:Erreur Ubuntu.jpg|alt=Erreur WSL pour Ubuntu|centré|vignette|Erreur WSL pour Ubuntu]]&lt;br /&gt;
J’ai alors trouvé une documentation de Microsoft sur le WSL qui m’a permis de résoudre ce problème ('''https://learn.microsoft.com/fr-fr/windows/wsl/troubleshooting'''). Après cela, j’ai voulu donc tester la commande « '''''lsusb''''' » mais encore une fois, une nouvelle erreur apparaît :&lt;br /&gt;
[[Fichier:Erreur libusb.jpg|alt=Erreur de la libusb sur Ubuntu|centré|vignette|Erreur de la libusb sur Ubuntu]]&lt;br /&gt;
J’ai donc télécharger la librairie libusb grâce à la commande « '''''sudo apt-get install libusb-1.0-0-dev''''' » que j’ai trouver grâce aux informations de ce site : '''https://askubuntu.com/questions/629619/how-to-install-libusb''' mais même en faisant cette commande, j’ai toujours eu la même erreur. Donc à ce stade du projet, je ne peux donc pas transférer et tester mes programmes, je vais continuer à chercher une solution.&lt;br /&gt;
&lt;br /&gt;
== Programmation du moteur continu : ==&lt;br /&gt;
J’ai donc commencé par la partie du moteur continu car c’est sur cette partie que nous nous sommes arrêtés.&lt;br /&gt;
&lt;br /&gt;
Afin de faire fonctionner le moteur, je devais faire un programme informatique afin de gérer cette fonctionnalité. J’ai tout d’abord créé une fonction pour initialiser les ports du moteur comme étant des sorties. Ensuite, j’ai créé une fonction « avancer » où je mets un des ports sous tension et l’autre non. Pour la fonction « reculer », il s’agit de la même chose mais il faut inverser quel port est sous tension. Enfin pour la fonction « arrêter », il suffit de mettre les deux ports à 0.&lt;br /&gt;
&lt;br /&gt;
Voici donc le code pour faire fonctionner le moteur de cette façon :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR DC AVEC PORT ///&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
    &lt;br /&gt;
void initMotDC_Port(void){&lt;br /&gt;
    DDRB |= (1&amp;lt;&amp;lt;PB7);                   //PMW2 en OUTPUT&lt;br /&gt;
    DDRD |= (1&amp;lt;&amp;lt;PD0);                   //PMW1 en OUTPUT&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7);                     //PMW2 à LOW&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0);                     //PMW1 à LOW&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
////////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR DC AVEC PORT ///&lt;br /&gt;
////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void move_forwards(void){&lt;br /&gt;
    PORTB=(1&amp;lt;&amp;lt;PB7); //MOT1 à HIGH&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0); //MOT2 à LOW&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void move_backwards(void){&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7); //MOT1 à LOW&lt;br /&gt;
    PORTD=(1&amp;lt;&amp;lt;PD0); //MOT2 à HIGH&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void stop(void){&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7); //MOT1 à LOW&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0); //MOT2 à LOW   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir fait cela, je me suis demander si nous pouvions contrôler la vitesse du moteur. J’ai alors regardé trouver une page d’un cours de PSE ('''https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme053.html''')expliquant comment fonctionne les actionneurs simples grâce au signaux PWM (Pulse Width Modulation). Une partie du programme pour l’initialisation des ports était donnée, cependant il s’agissait de la gestion des sorties que je ne comprenais pas (OCR0A, OCR0B …), j’ai donc dû effectuer plusieurs recherches sur cette partie.  &lt;br /&gt;
&lt;br /&gt;
Voici donc le code pour faire fonctionner le moteur de cette autre façon :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR DC AVEC OCR1 ///&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void initMotDC_OCR(void){&lt;br /&gt;
    DDRB |= (1&amp;lt;&amp;lt;PB7);                   //PMW2 en OUTPUT&lt;br /&gt;
    DDRD |= (1&amp;lt;&amp;lt;PD0);                   //PMW1 en OUTPUT&lt;br /&gt;
    TCCR1A |= (1&amp;lt;&amp;lt;COM1A1)|(1&amp;lt;&amp;lt;COM1C1);  // Les ports PWM se comportent normalement&lt;br /&gt;
    TCCR1A |= (1&amp;lt;&amp;lt;WGM11)|(1&amp;lt;&amp;lt;WGM10);    // Minuteur mis en mode PWM&lt;br /&gt;
    TCCR1B |= (1&amp;lt;&amp;lt;CS10);                // Pas de pré-diviseur, démarre le compteur&lt;br /&gt;
&lt;br /&gt;
///////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR DC AVEC OCR ///&lt;br /&gt;
///////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void move_forwards_OCR(void){&lt;br /&gt;
    OCR1A = 512;&lt;br /&gt;
    OCR1C = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void move_backwards_OCR(void){&lt;br /&gt;
    OCR1A = 0;&lt;br /&gt;
    OCR1C = 512;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void stop_OCR(void){&lt;br /&gt;
    OCR1A = 0;&lt;br /&gt;
    OCR1C = 0;   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation du moteur pas à pas : ==&lt;br /&gt;
Comme je n'avais jamais travaillé sur un moteur pas à pas, j'ai voulu comprendre son fonctionnement. Après plusieurs recherches, j'ai compris que le moteur était constitué d'un rotor magnétique et de bobines. Nous avons ici un moteur pas à pas bipolaire, avec 4 sorties. Le moteur fonctionne par pas succesifs comme une montre, ce qui signigie qu'il faut jouer avec chacune des sorties afin de faire le faire tourner pas par pas. En partant de ce principe nous pouvons programmer une fonction pour que chaque sorties soit sous tension les unes à la suite des autres.&lt;br /&gt;
&lt;br /&gt;
Voici le programme pour faire tourner le moteur pas à pas dans un sens :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
///////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR PAS A PAS ///&lt;br /&gt;
///////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void initMotStepper(void){&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR PAS A PAS ///&lt;br /&gt;
/////////////////////////////////&lt;br /&gt;
    &lt;br /&gt;
void stepper_left(void){&lt;br /&gt;
    for(int i = 0; i&amp;lt;=100; i++){&lt;br /&gt;
        //M1_A+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC5);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Pour aller dans l'autre sens, il suffit d'inverser le sens des broches de sorties :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void stepper_right(void){&lt;br /&gt;
    for(int i = 0; i&amp;lt;=100; i++){&lt;br /&gt;
        //M1_B+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC7);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Voici ma documentation :&lt;br /&gt;
&lt;br /&gt;
- '''https://www.tme.eu/fr/news/library-articles/page/41861/Moteur-pas-a-pas-types-et-exemples-dapplications-des-moteurs-pas-a-pas/'''&lt;br /&gt;
&lt;br /&gt;
- '''https://www.youtube.com/watch?v=655p1N9tSKQ'''&lt;br /&gt;
&lt;br /&gt;
- '''http://www.micropython.fr/modules_center/moteurs/pas_a_pas/moteur_pap/#le-principe-dun-moteur-pas-a-pas'''&lt;br /&gt;
&lt;br /&gt;
== Programmation de la communication Bluetooth : ==&lt;br /&gt;
La partie Bluetooth était un de nos objectifs du début de projet afin de contrôler la voiture à distance et grâce à une application. Pour cela, j’ai dû refaire des recherches sur le sujet afin d’avancer. J’ai donc dû regarder la documentation de l’atmega16u2 et des cours d’autres universités pour bien comprendre. C’est alors que j’ai compris que la communication série UART permettrait de répondre à mes besoins. J’ai donc écrit une fonction qui permet l’initialisation de la communication série UART en activant la transmission (TX) et la réception (RX). Ensuite dans cette même fonction j’ai dû définir le format de la trame, elle est donc composée de 8 bits, c’est-à-dire un octet avec un bit d’arrêt.&lt;br /&gt;
&lt;br /&gt;
Nous n’avons besoin que de recevoir des informations sur la communication série UART, pas d’en envoyer. C’est pour cela que j’ai donc dû faire une seconde fonction permettant de recevoir les informations de l’application sur le port RX de l’Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Voici le code de la communication UART :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION COMMUNICATION UART ///&lt;br /&gt;
/////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void UART_init(unsigned int baud_rate){&lt;br /&gt;
    // Calculer la valeur de UBRR en fonction du baud_rate&lt;br /&gt;
    unsigned int ubrr_val = FREQ_CPU / (16UL * baud_rate) - 1;    &lt;br /&gt;
    // Définir les valeurs UBRRH et UBRRL&lt;br /&gt;
    UBRRH = (unsigned char)(ubrr_val &amp;gt;&amp;gt; 8);&lt;br /&gt;
    UBRRL = (unsigned char)ubrr_val;&lt;br /&gt;
    // Activer la transmission et la réception&lt;br /&gt;
    UCSRB = (1 &amp;lt;&amp;lt; TXEN) | (1 &amp;lt;&amp;lt; RXEN);&lt;br /&gt;
    // Définir le format de trame: 8 bits de données, 1 bit d'arrêt&lt;br /&gt;
    UCSRC = (1 &amp;lt;&amp;lt; URSEL) | (1 &amp;lt;&amp;lt; UCSZ1) | (1 &amp;lt;&amp;lt; UCSZ0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/////////////////////////////////////&lt;br /&gt;
/// RECUPERATION DES DONNEES UART ///&lt;br /&gt;
/////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
int UART_receiver(void) {&lt;br /&gt;
    // Attendre que le tampon d'entrée soit plein&lt;br /&gt;
    while (!(UCSRA &amp;amp; (1 &amp;lt;&amp;lt; RXC)));&lt;br /&gt;
    // Lire le caractère du tampon d'entrée&lt;br /&gt;
    return UDR;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Cette fonction ne pouvait pas être testée car l’antenne Bluetooth n’est pas présente sur la carte électronique de la voiture. Cependant, ces recherches m’ont permis de mieux comprendre la communication série UART que j’avais mal compris lors des TP du semestre 6.&lt;br /&gt;
&lt;br /&gt;
== Programmation USB/LUFA ==&lt;br /&gt;
Pour cette partie de la programmation via USB/LUFA, j’ai repris le fichier utilisé lors de notre cours de TPI. Ce fichier avait quelques modifications à faire avant d’être utilisé. Tout d’abord, j’ai dû changer les ID Vendor et Product de la carte électronique car celle utilisée maintenant n’est pas la même que pendant le cours de TPI. Normalement grâce à la commande &amp;quot;'''''lsusb -vvv&amp;quot;''''', on peut trouver le microcontrôleur utilisé et ces ID, mais nous les avions déjà noté auparavant. On trouve alors :&lt;br /&gt;
&lt;br /&gt;
-       ID VENDOR : 0x03EB  &lt;br /&gt;
&lt;br /&gt;
-       ID PRODUCT : 0x2FEF&lt;br /&gt;
&lt;br /&gt;
Ensuite, des modifications étaient à faire sur les fichiers du descripteur. En effet, celui-ci avait du code qui faisait référence au joystick utilisé en TPI. J’ai donc juste gardé les fonctions qui faisaient référence aux actionneurs.&lt;br /&gt;
&lt;br /&gt;
De plus, afin de pouvoir gérer les actionneurs, j’ai préparé en amont comment ils seront activés grâce aux octets à envoyer. Cependant, j’ai décidé d’utiliser qu’un seul octet de contrôle car 2 était beaucoup trop pour les simples fonctions que nous avions. Nous avons alors un seul octet ayant chaque bit qui représente une fonction de contrôle de la voiture avec de droite à gauche :&lt;br /&gt;
&lt;br /&gt;
-       Bit 0 à Allume la LED&lt;br /&gt;
&lt;br /&gt;
-       Bit 1 à Fait avancer la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 2 à Fait reculer la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 3 à Fait tourner dans un sens la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 4 à Fait tourner dans l’autre sens la voiture&lt;br /&gt;
&lt;br /&gt;
Par exemple, le schéma ci-dessous permet d’allumer la LED de la voiture, de la faire reculer, et en même temps de la faire tourner dans un sens :&lt;br /&gt;
[[Fichier:USB exemple.png|alt=Exemple d'octet|centré|vignette|Exemple d'octet ]]&lt;br /&gt;
Voici d'ailleurs le code du programme traitant chaque bits de l'octet pour éxécuter les fonctions voulues : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void actionneurs_gestion(void){&lt;br /&gt;
	Endpoint_SelectEndpoint(ACT_EPADDR);&lt;br /&gt;
	if (Endpoint_IsOUTReceived()){&lt;br /&gt;
		if (Endpoint_IsReadWriteAllowed()){&lt;br /&gt;
		  	uint16_t ACT_Report = Endpoint_Read_16_LE();&lt;br /&gt;
&lt;br /&gt;
            //CONTROLE DES LEDS&lt;br /&gt;
            if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;0))&lt;br /&gt;
                led_on();&lt;br /&gt;
            else &lt;br /&gt;
                led_off();&lt;br /&gt;
        &lt;br /&gt;
			//CONTROLE DU MOTEUR DC&lt;br /&gt;
			if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;1))&lt;br /&gt;
                move_forwards();&lt;br /&gt;
            else if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;2))&lt;br /&gt;
                move_backwards();	&lt;br /&gt;
			else&lt;br /&gt;
                stop();&lt;br /&gt;
            &lt;br /&gt;
            //CONTROLE DU MOTEUR PAS A PAS&lt;br /&gt;
            if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;3))&lt;br /&gt;
                stepper_left();&lt;br /&gt;
            else if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;4))&lt;br /&gt;
                stepper_right();&lt;br /&gt;
		}&lt;br /&gt;
		/* Handshake the OUT Endpoint - clear endpoint and ready for next report */&lt;br /&gt;
		Endpoint_ClearOUT();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, nous avons juste à envoyer l’octet de notre choix afin de gérer comme on le veut les actionneurs. &lt;br /&gt;
&lt;br /&gt;
En retravaillant sur cette partie, j’ai mieux compris le fonctionnement de la libusb que je n’avais pas beaucoup compris lors du TPI. J’ai pu me documenter sur le sujet en faisant beaucoup de recherche et même d’apprendre des nouvelles façons de travailler avec le langage C et d’avoir une meilleure syntaxe de programmation.&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
	<entry>
		<id>https://projets-se.plil.fr/mediawiki/index.php?title=SE3Trinome2022-8&amp;diff=1384</id>
		<title>SE3Trinome2022-8</title>
		<link rel="alternate" type="text/html" href="https://projets-se.plil.fr/mediawiki/index.php?title=SE3Trinome2022-8&amp;diff=1384"/>
		<updated>2023-09-01T13:35:40Z</updated>

		<summary type="html">&lt;p&gt;Ncazin : Rédaction rattrapages&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= '''Projet SE3 : Premier Système''' =&lt;br /&gt;
CAZIN Némo, CEGARRA Antoine, PALIFERRO Adrien&lt;br /&gt;
&lt;br /&gt;
'''Lien du git :''' ''https://archives.plil.fr/ncazin/SE3_GROUPE_8.git''&lt;br /&gt;
&lt;br /&gt;
==Objectifs fixés :==&lt;br /&gt;
L'objectif principal de ce projet était de '''réaliser la commande d'une voiture au format 1:43''' capable d'avancer et de reculer à l'aide d'un programme informatique. Avant de commencer le projet, nous nous sommes fixé plusieurs petits objectifs afin de mener au mieux le projet.&lt;br /&gt;
&lt;br /&gt;
La voiture devait tout d'abord avancer, reculer, tourner à gauche et à droite. Des LEDs devaient être allumées lorsque la voiture effectue un déplacement.&lt;br /&gt;
&lt;br /&gt;
Pour la commande de la voiture, nous voulions qu'elle soit commandée grâce à une commande Bluetooth et pilotée depuis un smartphone. Une application devait alors être faite pour gérer les déplacements. MIT App Inventor permet de gérer des communications Bluetooth et est simple d'utilisation.&lt;br /&gt;
&lt;br /&gt;
Afin de pouvoir implémenter toutes ses fonctionnalités, nous devions réaliser une carte électronique gérée par un microcontrôleur ATMega16u2. D'autres module devaient être ajoutés pour la bonne réalisation de nos objectifs fixés.&lt;br /&gt;
&lt;br /&gt;
==La carte électronique :==&lt;br /&gt;
&lt;br /&gt;
La réalisation de la carte électronique a débuté par la création du schéma électrique sur KICAD. Nous avons implémenté ce que nous avions déjà prévu (Chargeur, moteurs, microcontrôleur...), cependant, pour certaines fonctionnalités, des composants n'étaient pas disponibles dans les librairies Sparkfun disponibles. &lt;br /&gt;
&lt;br /&gt;
Nous avons donc créé les schémas de ces composants, c'est-à-dire le module Bluetooth '''FP-BM70BLE01FC2''' ainsi que le driver du moteur '''DRV8210DRL''' grâce aux informations de leurs datasheet disponible sur Internet :  &lt;br /&gt;
&lt;br /&gt;
- Datasheet du module Bluetooth : ''https://ww1.microchip.com/downloads/aemDocuments/documents/OTH/ProductDocuments/DataSheets/BM70_71-Bluetooth-Low-Energy-BLE-Module-DS60001372L.pdf'' &lt;br /&gt;
&lt;br /&gt;
- Datasheet du driver du moteur : ''https://www.ti.com/lit/ds/slvsfy8b/slvsfy8b.pdf?ts=1683016270840&amp;amp;ref_url=https%253A%252F%252Fwww.google.com%252F'' &lt;br /&gt;
&lt;br /&gt;
Au final, nous obtenons au final ce schéma correspondant :  &lt;br /&gt;
[[Fichier:Schématic voiture.jpg|alt=Schéma de la voiture|centré|vignette|Schéma de la voiture]]&lt;br /&gt;
Après avoir fait le schéma de la voiture, nous avons dû faire le routage de la carte électronique. La première chose a faire à été de prendre les côtes de la voiture afin que la carte électronique se mette bien en place dessus. De plus, nous avons dû prendre les mesures des côtes du moteur continu, celui-ci va être soudé au centre de la carte et est imposant, il fallait donc prévoir la place nécessaire que le composant prendrait.  &lt;br /&gt;
&lt;br /&gt;
Ensuite, nous avons dû réaliser les empreintes du module Bluetooth ainsi que du driver du moteur. Les mesures figurant sur leurs datasheet respectives, nous avons réussi simplement à les reproduire. Le plus compliqué a été de repérer les pâtes des composants que nous devions utiliser. Par exemple, sur le module Bluetooth, certaines entrées n'ont pas été utilisées. Nous avons aussi utilisé et adapter les empreintes des moteurs continus et pas à pas fournis par notre professeur M.Redon.  &lt;br /&gt;
&lt;br /&gt;
Après cela, nous avons commencé le routage. Nous avons commencer par router la carte le plus possible sur une seule face jusqu'à ce que ne l'on puisse plus. Sinon nous utilisions des vias afin de router sur l'autre face. Cependant, nous avons dû recommencer une seconde fois le routage, car le premier ne nous convenait pas. Nous avons aussi demandé de l'aide au professeur M.Boé afin de réaliser les plans de masse.   &lt;br /&gt;
&lt;br /&gt;
Voici une image du routage final notre carte électronique :  &lt;br /&gt;
[[Fichier:Routage voiture.jpg|alt=Routage de la carte électronique|centré|vignette|Routage de la carte électronique]]&lt;br /&gt;
Voici aussi une représentation 3D de notre carte électronique :    &lt;br /&gt;
[[Fichier:Pcb 3D.jpg|alt=Représentation 3D de notre carte électronique|centré|vignette|Représentation 3D de notre carte électronique]]&lt;br /&gt;
Le routage fini, nous avons passé commande afin de recevoir notre carte électronique et voici celle-ci avec aucune soudure :    &lt;br /&gt;
&lt;br /&gt;
Enfin, la carte étant vierge, nous devions commencer la soudure des composants. Cette partie a été très compliquée à mettre en oeuvre, car dans le groupe, aucun de nous n'avait fait de soudure dans sa vie. Nous avons donc dû apprendre à ce moment comment faire, d'où les premières soudures un peu compliquées.  &lt;br /&gt;
&lt;br /&gt;
Nous avons eu un problème de reconnaissance du microprocesseur lors de la commande &amp;quot;''lsusb&amp;quot;'', le matériel n'était pas détecté. Nous avons donc dû modifier le circuit qui comportait quelques erreurs, ainsi que remplacer les résistances et condensateurs afin de s'assurer de leur valeur. Finalement, nous avons dû changer le microprocesseur qui avec les précédents branchements avait surchauffé et était défectueux. Après avoir remplacé tous les composants, nous avons réussi à faire reconnaître le microprocesseur grâce à la commande &amp;quot;''lsusb''&amp;quot;.  Après cela, nous avons pu souder les derniers composants restants.  &lt;br /&gt;
&lt;br /&gt;
Voici une photo de notre carte avec les composants soudés :     &lt;br /&gt;
[[Fichier:Carte électronique avec les composants soudés.jpg|alt=Carte électronique avec les composants soudés|centré|vignette|Carte électronique avec les composants soudés]]&lt;br /&gt;
Nous avions fini la carte électronique, sa réalisation a pris la majeure partie de notre temps lors des séances. Il fallait donc ensuite réaliser un programme permettant de faire fonctionner et avancer la voiture.     &lt;br /&gt;
&lt;br /&gt;
Fichier ZIP de notre carte électronique : [[Fichier:Voiture CCP.zip|vignette|Voiture fichiers de routage et schéma PCB]]&lt;br /&gt;
&lt;br /&gt;
==Programme de la voiture :==&lt;br /&gt;
Le programme informatique était nécessaire pour le bon fonctionnement de la voiture, cependant comme le temps commençait à manquer, nous avons codé son programme en dehors des cours de projet.&lt;br /&gt;
&lt;br /&gt;
Nous avons donc structuré notre code en plusieurs afin de le simplifier. Les premières fonctions permettent d'initialiser les entrées et les sorties du microcontrôleur afin de bien récupérer et envoyer les bonnes informations. De plus, dans ces fonctions, nous remettons les moteurs et les leds à LOW afin d'avoir une sécurité et qu'ils ne démarrent pas à l'initialisation. Ensuite, nous retrouvons les fonctions de déplacements. Ces fonctions gèrent les moteurs lorsqu'il faut avancer, reculer, tourner à droite, etc...&lt;br /&gt;
&lt;br /&gt;
De plus, on retrouve une fonction permettant de récupérer les informations envoyées depuis la communication Bluetooth afin de faire fonctionner la voiture à distance. Une seconde fonction permet de traiter ces informations et de faire déplacer la voiture selon l'information reçue.&lt;br /&gt;
&lt;br /&gt;
Nous pouvons aussi faire fonctionner la voiture en envoyant le programme informatique dans la voiture. Cependant, de cette manière, la voiture ne pourra pas être contrôlée et fera un trajet voulu.&lt;br /&gt;
&lt;br /&gt;
La communication Bluetooth étant un de nos objectifs fixé, nous avons dû réaliser une application afin de pouvoir utiliser la voiture à distance.&lt;br /&gt;
&lt;br /&gt;
Voici une vidéo de la carte avec une LED qui clignote : &lt;br /&gt;
[[Fichier:PCB clignote.mov|alt=LED qui clignote|centré|vignette|LED qui clignote]]&lt;br /&gt;
&lt;br /&gt;
==Application Bluetooth :==&lt;br /&gt;
Nous nous étions fixé comme objectif que la voiture devait être contrôlée grâce à une application Bluetooth. Nous avons alors décidé de réaliser cette application grâce au site '''MIT App Inventor''', ce site est simple d'utilisation et permet de gérer des communications Bluetooth facilement. De plus, le temps a été investi surtout dans la carte électronique donc apprendre et programmer par nous-même dans un langage de programmation nouveau aurait été compliqué pour nous.&lt;br /&gt;
&lt;br /&gt;
Nous avons décidé que les informations envoyées par communication Bluetooth serait sous forme hexadécimale. Le programme informatique du côté de l'ATMega16u2 recevra et traitera alors les informations reçues. &lt;br /&gt;
&lt;br /&gt;
L'application devait avoir un aspect simple d'utilisation et sobre afin de faciliter l'expérience de l'utilisateur. L'application amènerait l'utilisateur sur une page permettant de choisir à quel appareil Bluetooth se connecter. Un statut indiquant si le smartphone est connecté ou non à l'appareil est aussi présent. L'élément le plus important de la page est le bloc de déplacement, composé de 4 boutons représentant des flèches directionnelles afin de piloter la voiture.&lt;br /&gt;
&lt;br /&gt;
Lorsque nous avions terminé l'application pour piloter grâce à des flèches directionnelles, nous nous sommes rendu compte que nous pourrions réaliser aussi un pilotage par gyroscope. En effet, les informations transmises pour les déplacements restent les mêmes donc du côté du programme informatique, rien ne change. Nous avons deux moyens de piloter la voiture : une par appui sur des flèches directionnelles, et une seconde par inclinaison du smartphone. &lt;br /&gt;
&lt;br /&gt;
Voilà des captures d'écran montrant l'aspect et les fonctionnalités de l'application : &lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed&amp;quot; widths=&amp;quot;150&amp;quot; heights=&amp;quot;150&amp;quot;&amp;gt;&lt;br /&gt;
Fichier:App Screen Controls.jpg|Contrôle par touche&lt;br /&gt;
Fichier:App Screen Gyro.jpg|Contrôle par gyroscope&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
Pour réaliser cette application, il faut du code en interne, voici les codes que nous avons utilisé :&lt;br /&gt;
&amp;lt;gallery mode=&amp;quot;packed&amp;quot; widths=&amp;quot;150&amp;quot; heights=&amp;quot;150&amp;quot;&amp;gt;&lt;br /&gt;
Fichier:Connexion Bluetooth.jpg|Bloc de connexion Bluetooth&lt;br /&gt;
Fichier:Gestion des boutons.jpg|Bloc de gestion des touches&lt;br /&gt;
Fichier:Gestion gyroscope.jpg|Bloc de gestion du gyroscope&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Le fichier APK de l'application est disponible dans le GIT du projet.'''&lt;br /&gt;
&lt;br /&gt;
= Epreuve complémentaire CAZIN Némo =&lt;br /&gt;
&lt;br /&gt;
== Introduction : ==&lt;br /&gt;
J’ai dû reprendre le projet lors de mon épreuve complémentaire de Semestre 6&lt;br /&gt;
&lt;br /&gt;
Avant cela, avec mon groupe de travail, nous avions réussi à faire clignoter une LED malgré tous les problèmes que nous avons rencontrés comme des composants qui ne fonctionnait plus sur la carte ou alors des courts circuits à faire nous-mêmes. Je ne traiterais donc pas ici la partie du clignotement de la LED.&lt;br /&gt;
&lt;br /&gt;
== Préparation de la carte électronique : ==&lt;br /&gt;
Tout d’abord, lorsque j’ai repris le projet, je savais que les soudures des composants et du moteur continu avait été faites mais elles étaient fragiles du fait de la petite épaisseur des pistes reliant le moteur au driver. Cependant, le voyage de la boite avec la carte électronique à l’intérieur avait complétement cassé les soudures du moteur. &lt;br /&gt;
&lt;br /&gt;
Voici l’état de la carte lors de la reprise du projet :&lt;br /&gt;
[[Fichier:Carte pas de soudure.jpg|alt=Carte avec le moteur désoudé|centré|vignette|Carte avec le moteur désoudé]]&lt;br /&gt;
J’ai donc dû refaire les soudures du moteur, ce qui a été un peu compliqué car j’ai du mal à souder en général. Mais en m’inspirant des photos que j’avais d’avant la reprise du projet, j’ai pu mieux m’en sortir. Voilà le résultat de la soudure du moteur continu : &lt;br /&gt;
[[Fichier:Carte moteur DC.jpg|alt=Carte avec le moteur continu soudé|centré|vignette|Carte avec le moteur continu soudé]]&lt;br /&gt;
Après cela, j’ai voulu continuer mon travail en faisant les soudures du moteur pas-à-pas. Ce moteur est très petit et les soudures à faire devaient être très précises. Pour que ce soit plus simples, j’ai utilisé 4 pins que j’ai souder à la carte et sur les pins, des câbles sont reliés jusqu’aux quatre liaisons du moteur. Le moteur est alors déporté de la carte mais ce n’est pas très important car on veut juste le voir fonctionner et aucunes roues n’est attachées. Ces soudures étaient vraiment compliquées à réaliser car elles étaient très minutieuses et souvent des soudures se cassaient lorsque j’en soudais une autre. &lt;br /&gt;
&lt;br /&gt;
Voilà le résultat de la soudure du moteur pas à pas : &lt;br /&gt;
[[Fichier:Carte moteur pap.jpg|alt=Carte avec le moteur pas-à-pas soudé|centré|vignette|Carte avec le moteur pas-à-pas soudé]]&lt;br /&gt;
&lt;br /&gt;
== Connexion de la carte sur ordinateur : ==&lt;br /&gt;
Avant de commencer la programmation, j’ai voulu voir si la carte était toujours détectée grâce à la commande shell « '''''lsusb''''' » afin de savoir si le microcontrôleur n’avait pas lui aussi eu un problème pendant le voyage. J’ai alors rencontré plusieurs problèmes.&lt;br /&gt;
&lt;br /&gt;
En effet, j’avais commencé à développer mes programmes informatiques sur les machines de l’école à distance grâce à l’outil : '''https://tp-info.polytech-lille.fr/#''' . J’ai donc voulu voir si la carte était reconnue aussi depuis les machines à distances.&lt;br /&gt;
&lt;br /&gt;
Cependant, lorsque je me connecte sur ces machines, les périphériques USB de mon ordinateur ne sont pas reconnus. En faisant plusieurs essais pour résoudre ce problème, j’ai compris que ce n’était pas possible et donc qu’il fallait passer par une autre méthode. Sois-je faisais directement la programmation sur Windows mais télécharger les dépendances et le compilateur C allait être compliqué. Sois-je téléchargeais une machine virtuelle Ubuntu pour être directement sur un système Linux et plus simplement programmer. J’ai donc choisi la première option car je craignais que la machine virtuelle ne reconnaisse pas elle aussi les périphériques USB.&lt;br /&gt;
&lt;br /&gt;
J’ai donc modifié l’option développeur de mon Windows afin de pouvoir télécharger un environnement terminal Ubuntu qui fonctionne grâce à Windows Subsystem for Linux (WSL). J’ai alors rencontré une erreur lors du lancement du terminal Ubuntu : &lt;br /&gt;
[[Fichier:Erreur Ubuntu.jpg|alt=Erreur WSL pour Ubuntu|centré|vignette|Erreur WSL pour Ubuntu]]&lt;br /&gt;
J’ai alors trouvé une documentation de Microsoft sur le WSL qui m’a permis de résoudre ce problème ('''https://learn.microsoft.com/fr-fr/windows/wsl/troubleshooting'''). Après cela, j’ai voulu donc tester la commande « '''''lsusb''''' » mais encore une fois, une nouvelle erreur apparaît :&lt;br /&gt;
[[Fichier:Erreur libusb.jpg|alt=Erreur de la libusb sur Ubuntu|centré|vignette|Erreur de la libusb sur Ubuntu]]&lt;br /&gt;
J’ai donc télécharger la librairie libusb grâce à la commande « '''''sudo apt-get install libusb-1.0-0-dev''''' » que j’ai trouver grâce aux informations de ce site : '''https://askubuntu.com/questions/629619/how-to-install-libusb''' mais même en faisant cette commande, j’ai toujours eu la même erreur. Donc à ce stade du projet, je ne peux donc pas transférer et tester mes programmes, je vais continuer à chercher une solution.&lt;br /&gt;
&lt;br /&gt;
== Programmation du moteur continu : ==&lt;br /&gt;
J’ai donc commencé par la partie du moteur continu car c’est sur cette partie que nous nous sommes arrêtés.&lt;br /&gt;
&lt;br /&gt;
Afin de faire fonctionner le moteur, je devais faire un programme informatique afin de gérer cette fonctionnalité. J’ai tout d’abord créé une fonction pour initialiser les ports du moteur comme étant des sorties. Ensuite, j’ai créé une fonction « avancer » où je mets un des ports sous tension et l’autre non. Pour la fonction « reculer », il s’agit de la même chose mais il faut inverser quel port est sous tension. Enfin pour la fonction « arrêter », il suffit de mettre les deux ports à 0.&lt;br /&gt;
&lt;br /&gt;
Voici donc le code pour faire fonctionner le moteur de cette façon :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR DC AVEC PORT ///&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
    &lt;br /&gt;
void initMotDC_Port(void){&lt;br /&gt;
    DDRB |= (1&amp;lt;&amp;lt;PB7);                   //PMW2 en OUTPUT&lt;br /&gt;
    DDRD |= (1&amp;lt;&amp;lt;PD0);                   //PMW1 en OUTPUT&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7);                     //PMW2 à LOW&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0);                     //PMW1 à LOW&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
////////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR DC AVEC PORT ///&lt;br /&gt;
////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void move_forwards(void){&lt;br /&gt;
    PORTB=(1&amp;lt;&amp;lt;PB7); //MOT1 à HIGH&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0); //MOT2 à LOW&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void move_backwards(void){&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7); //MOT1 à LOW&lt;br /&gt;
    PORTD=(1&amp;lt;&amp;lt;PD0); //MOT2 à HIGH&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void stop(void){&lt;br /&gt;
    PORTB=(0&amp;lt;&amp;lt;PB7); //MOT1 à LOW&lt;br /&gt;
    PORTD=(0&amp;lt;&amp;lt;PD0); //MOT2 à LOW   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Après avoir fait cela, je me suis demander si nous pouvions contrôler la vitesse du moteur. J’ai alors regardé trouver une page d’un cours de PSE ('''https://rex.plil.fr/Enseignement/Systeme/Systeme.PSE/systeme053.html''')expliquant comment fonctionne les actionneurs simples grâce au signaux PWM (Pulse Width Modulation). Une partie du programme pour l’initialisation des ports était donnée, cependant il s’agissait de la gestion des sorties que je ne comprenais pas (OCR0A, OCR0B …), j’ai donc dû effectuer plusieurs recherches sur cette partie.  &lt;br /&gt;
&lt;br /&gt;
Voici donc le code pour faire fonctionner le moteur de cette autre façon :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR DC AVEC OCR1 ///&lt;br /&gt;
//////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void initMotDC_OCR(void){&lt;br /&gt;
    DDRB |= (1&amp;lt;&amp;lt;PB7);                   //PMW2 en OUTPUT&lt;br /&gt;
    DDRD |= (1&amp;lt;&amp;lt;PD0);                   //PMW1 en OUTPUT&lt;br /&gt;
    TCCR1A |= (1&amp;lt;&amp;lt;COM1A1)|(1&amp;lt;&amp;lt;COM1C1);  // Les ports PWM se comportent normalement&lt;br /&gt;
    TCCR1A |= (1&amp;lt;&amp;lt;WGM11)|(1&amp;lt;&amp;lt;WGM10);    // Minuteur mis en mode PWM&lt;br /&gt;
    TCCR1B |= (1&amp;lt;&amp;lt;CS10);                // Pas de pré-diviseur, démarre le compteur&lt;br /&gt;
&lt;br /&gt;
///////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR DC AVEC OCR ///&lt;br /&gt;
///////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void move_forwards_OCR(void){&lt;br /&gt;
    OCR1A = 512;&lt;br /&gt;
    OCR1C = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void move_backwards_OCR(void){&lt;br /&gt;
    OCR1A = 0;&lt;br /&gt;
    OCR1C = 512;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void stop_OCR(void){&lt;br /&gt;
    OCR1A = 0;&lt;br /&gt;
    OCR1C = 0;   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmation du moteur pas à pas : ==&lt;br /&gt;
Comme je n'avais jamais travaillé sur un moteur pas à pas, j'ai voulu comprendre son fonctionnement. Après plusieurs recherches, j'ai compris que le moteur était constitué d'un rotor magnétique et de bobines. Nous avons ici un moteur pas à pas bipolaire, avec 4 sorties. Le moteur fonctionne par pas succesifs comme une montre, ce qui signigie qu'il faut jouer avec chacune des sorties afin de faire le faire tourner pas par pas. En partant de ce principe nous pouvons programmer une fonction pour que chaque sorties soit sous tension les unes à la suite des autres.&lt;br /&gt;
&lt;br /&gt;
Voici le programme pour faire tourner le moteur pas à pas dans un sens :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
///////////////////////////////////////&lt;br /&gt;
/// INITIALISATION MOTEUR PAS A PAS ///&lt;br /&gt;
///////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void initMotStepper(void){&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
    DDRC |= (1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/////////////////////////////////&lt;br /&gt;
/// CONTROLE MOTEUR PAS A PAS ///&lt;br /&gt;
/////////////////////////////////&lt;br /&gt;
    &lt;br /&gt;
void stepper_left(void){&lt;br /&gt;
    for(int i = 0; i&amp;lt;=100; i++){&lt;br /&gt;
        //M1_A+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC5);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Pour aller dans l'autre sens, il suffit d'inverser le sens des broches de sorties :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void stepper_right(void){&lt;br /&gt;
    for(int i = 0; i&amp;lt;=100; i++){&lt;br /&gt;
        //M1_B+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC5);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC6);&lt;br /&gt;
        &lt;br /&gt;
        //M1_B- à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC4);&lt;br /&gt;
        &lt;br /&gt;
        //M1_A+ à 1 puis 0&lt;br /&gt;
        PORTC=(1&amp;lt;&amp;lt;PC7);&lt;br /&gt;
        _delay_ms(5);&lt;br /&gt;
        PORTC=(0&amp;lt;&amp;lt;PC7);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Voici ma documentation :&lt;br /&gt;
&lt;br /&gt;
- '''https://www.tme.eu/fr/news/library-articles/page/41861/Moteur-pas-a-pas-types-et-exemples-dapplications-des-moteurs-pas-a-pas/'''&lt;br /&gt;
&lt;br /&gt;
- '''https://www.youtube.com/watch?v=655p1N9tSKQ'''&lt;br /&gt;
&lt;br /&gt;
- '''http://www.micropython.fr/modules_center/moteurs/pas_a_pas/moteur_pap/#le-principe-dun-moteur-pas-a-pas'''&lt;br /&gt;
&lt;br /&gt;
== Programmation de la communication Bluetooth : ==&lt;br /&gt;
La partie Bluetooth était un de nos objectifs du début de projet afin de contrôler la voiture à distance et grâce à une application. Pour cela, j’ai dû refaire des recherches sur le sujet afin d’avancer. J’ai donc dû regarder la documentation de l’atmega16u2 et des cours d’autres universités pour bien comprendre. C’est alors que j’ai compris que la communication série UART permettrait de répondre à mes besoins. J’ai donc écrit une fonction qui permet l’initialisation de la communication série UART en activant la transmission (TX) et la réception (RX). Ensuite dans cette même fonction j’ai dû définir le format de la trame, elle est donc composée de 8 bits, c’est-à-dire un octet avec un bit d’arrêt.&lt;br /&gt;
&lt;br /&gt;
Nous n’avons besoin que de recevoir des informations sur la communication série UART, pas d’en envoyer. C’est pour cela que j’ai donc dû faire une seconde fonction permettant de recevoir les informations de l’application sur le port RX de l’Atmega16U2.&lt;br /&gt;
&lt;br /&gt;
Voici le code de la communication UART :&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/////////////////////////////////////////&lt;br /&gt;
/// INITIALISATION COMMUNICATION UART ///&lt;br /&gt;
/////////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
void UART_init(unsigned int baud_rate){&lt;br /&gt;
    // Calculer la valeur de UBRR en fonction du baud_rate&lt;br /&gt;
    unsigned int ubrr_val = FREQ_CPU / (16UL * baud_rate) - 1;    &lt;br /&gt;
    // Définir les valeurs UBRRH et UBRRL&lt;br /&gt;
    UBRRH = (unsigned char)(ubrr_val &amp;gt;&amp;gt; 8);&lt;br /&gt;
    UBRRL = (unsigned char)ubrr_val;&lt;br /&gt;
    // Activer la transmission et la réception&lt;br /&gt;
    UCSRB = (1 &amp;lt;&amp;lt; TXEN) | (1 &amp;lt;&amp;lt; RXEN);&lt;br /&gt;
    // Définir le format de trame: 8 bits de données, 1 bit d'arrêt&lt;br /&gt;
    UCSRC = (1 &amp;lt;&amp;lt; URSEL) | (1 &amp;lt;&amp;lt; UCSZ1) | (1 &amp;lt;&amp;lt; UCSZ0);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/////////////////////////////////////&lt;br /&gt;
/// RECUPERATION DES DONNEES UART ///&lt;br /&gt;
/////////////////////////////////////&lt;br /&gt;
&lt;br /&gt;
int UART_receiver(void) {&lt;br /&gt;
    // Attendre que le tampon d'entrée soit plein&lt;br /&gt;
    while (!(UCSRA &amp;amp; (1 &amp;lt;&amp;lt; RXC)));&lt;br /&gt;
    // Lire le caractère du tampon d'entrée&lt;br /&gt;
    return UDR;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Cette fonction ne pouvait pas être testée car l’antenne Bluetooth n’est pas présente sur la carte électronique de la voiture. Cependant, ces recherches m’ont permis de mieux comprendre la communication série UART que j’avais mal compris lors des TP du semestre 6.&lt;br /&gt;
&lt;br /&gt;
== Programmation USB/LUFA ==&lt;br /&gt;
Pour cette partie de la programmation via USB/LUFA, j’ai repris le fichier utilisé lors de notre cours de TPI. Ce fichier avait quelques modifications à faire avant d’être utilisé. Tout d’abord, j’ai dû changer les ID Vendor et Product de la carte électronique car celle utilisée maintenant n’est pas la même que pendant le cours de TPI. Normalement grâce à la commande &amp;quot;'''''lsusb -vvv&amp;quot;''''', on peut trouver le microcontrôleur utilisé et ces ID, mais nous les avions déjà noté auparavant. On trouve alors :&lt;br /&gt;
&lt;br /&gt;
-       ID VENDOR : 0x03EB  &lt;br /&gt;
&lt;br /&gt;
-       ID PRODUCT : 0x2FEF&lt;br /&gt;
&lt;br /&gt;
Ensuite, des modifications étaient à faire sur les fichiers du descripteur. En effet, celui-ci avait du code qui faisait référence au joystick utilisé en TPI. J’ai donc juste gardé les fonctions qui faisaient référence aux actionneurs.&lt;br /&gt;
&lt;br /&gt;
De plus, afin de pouvoir gérer les actionneurs, j’ai préparé en amont comment ils seront activés grâce aux octets à envoyer. Cependant, j’ai décidé d’utiliser qu’un seul octet de contrôle car 2 était beaucoup trop pour les simples fonctions que nous avions. Nous avons alors un seul octet ayant chaque bit qui représente une fonction de contrôle de la voiture avec de droite à gauche :&lt;br /&gt;
&lt;br /&gt;
-       Bit 0 à Allume la LED&lt;br /&gt;
&lt;br /&gt;
-       Bit 1 à Fait avancer la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 2 à Fait reculer la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 3 à Fait tourner dans un sens la voiture&lt;br /&gt;
&lt;br /&gt;
-       Bit 4 à Fait tourner dans l’autre sens la voiture&lt;br /&gt;
&lt;br /&gt;
Par exemple, le schéma ci-dessous permet d’allumer la LED de la voiture, de la faire reculer, et en même temps de la faire tourner dans un sens :&lt;br /&gt;
[[Fichier:USB exemple.png|alt=Exemple d'octet|centré|vignette|Exemple d'octet ]]&lt;br /&gt;
Voici d'ailleurs le code du programme traitant chaque bits de l'octet pour éxécuter les fonctions voulues : &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void actionneurs_gestion(void){&lt;br /&gt;
	Endpoint_SelectEndpoint(ACT_EPADDR);&lt;br /&gt;
	if (Endpoint_IsOUTReceived()){&lt;br /&gt;
		if (Endpoint_IsReadWriteAllowed()){&lt;br /&gt;
		  	uint16_t ACT_Report = Endpoint_Read_16_LE();&lt;br /&gt;
&lt;br /&gt;
            //CONTROLE DES LEDS&lt;br /&gt;
            if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;0))&lt;br /&gt;
                led_on();&lt;br /&gt;
            else &lt;br /&gt;
                led_off();&lt;br /&gt;
        &lt;br /&gt;
			//CONTROLE DU MOTEUR DC&lt;br /&gt;
			if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;1))&lt;br /&gt;
                move_forwards();&lt;br /&gt;
            else if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;2))&lt;br /&gt;
                move_backwards();	&lt;br /&gt;
			else&lt;br /&gt;
                stop();&lt;br /&gt;
            &lt;br /&gt;
            //CONTROLE DU MOTEUR PAS A PAS&lt;br /&gt;
            if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;3))&lt;br /&gt;
                stepper_left();&lt;br /&gt;
            else if(ACT_Report &amp;amp; (1&amp;lt;&amp;lt;4))&lt;br /&gt;
                stepper_right();&lt;br /&gt;
		}&lt;br /&gt;
		/* Handshake the OUT Endpoint - clear endpoint and ready for next report */&lt;br /&gt;
		Endpoint_ClearOUT();&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;Enfin, nous avons juste à envoyer l’octet de notre choix afin de gérer comme on le veut les actionneurs. &lt;br /&gt;
&lt;br /&gt;
En retravaillant sur cette partie, j’ai mieux compris le fonctionnement de la libusb que je n’avais pas beaucoup compris lors du TPI. J’ai pu me documenter sur le sujet en faisant beaucoup de recherche et même d’apprendre des nouvelles façons de travailler avec le langage C et d’avoir une meilleure syntaxe de programmation.&lt;/div&gt;</summary>
		<author><name>Ncazin</name></author>
	</entry>
</feed>