SE3 2025/2026 EC3

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

Objectifs

Réaliser le programme du devoir surveillé concernant la programmation en C sur microcontrôleur AVR : Réaliser le programme "capteurs et actionneurs" du cours/TP concernant la programmation en C sur microcontrôleur AVR :

  • contrôlez un servo-moteur en utilisant le minuteur 0 ;
  • l’utilisateur utilise deux boutons pour changer l’angle ;
  • affichez l’angle de rotation sur les 7-segments :
    • 3 afficheurs doivent être utilisés ;
    • utilisez la persistence rétinienne ;
    • utilisez les interruptions générées par un second minuteur.

Matériel nécessaire

  • Arduino Uno avec câble USB ;
  • bouclier multi-fonctions ;
  • servo-moteur.

Historique

  • 02/03/2026:Branchement du matériel (Arduino,Shield et servo-moteur) et code pour faire bouger le moteur avec les deux boutons.

Travail réalisé


Jour 1 : Moteur et Boutons

Pour cette première étape, j’ai choisi d’avancer progressivement. L’objectif était simplement de lire les boutons S1 et S2 afin de commander la rotation du servo-moteur dans les deux sens.


Configuration des boutons

En consultant la datasheet ATmega328P,la section 13.2.1 (page 59),

  • Lorsqu’une broche est configurée en entrée DDR = 0 et que l’on écrit un 1 dans le registre PORT correspondant, la résistance pull-up interne est activée. Cela maintient la broche à 5V au repos.

on a donc :

  • Bouton non appuyé : niveau 1
  • Bouton appuyé : niveau 0

C’est pour cette raison que, dans la boucle principale, je teste un état logique bas 0 pour détecter un appui.


Désactivation du buzzer du shield

Au démarrage, le buzzer du shield émettait un signal sonore en continu. Après vérification, celui-ci est piloté par un transistor PNP Q1. Pour le désactiver, il faut imposer un niveau logique haut (5V) sur la broche de commande. D’après la table 13-1 (page 60), cela se fait en configurant la broche en sortie DDR = 1 et en forçant le bit correspondant du registre PORT à 1. J’ai donc configuré la broche PD3 en sortie et fixé son état à 1 dès l’initialisation du programme.


Génération du signal PWM pour le servo

Le servo-moteur nécessite un signal PWM d’environ 60 Hz.

J’ai utilisé le Timer 0 en mode Fast PWM (Mode 3), en activant les bits WGM01 et WGM00, conformément à la table 14-8 (page 86).

  • Dans ce mode, le compteur évolue de 0 à 255.
  • Pour que le signal soit transmis sur la broche PD6 (OC0A), j’ai activé le bit COM0A1 (table 14-3, page 84). "If one or both of the COM0A1:0 bits are set, the OC0A output overrides the normal port functionality of the I/O pin it is connected to."

Étant donné que le microcontrôleur fonctionne à 16 MHz, j’ai appliqué un prescaler de 1024 via les bits CS02 et CS00 (page 87). Le calcul de la fréquence obtenue est le suivant :

La fréquence obtenue est donc d’environ 61 Hz, ce qui est compatible avec les exigences d’un servo-moteur standard.


Justification des valeurs matérielles pour le servo Hitec HS-422

Le moteur utilisé pour ce projet est un servo Hitec HS-422. En étudiant ses spécifications techniques officielles, le constructeur définit la plage de fonctionnement suivante :

  • Le point central (neutre) est fixé à 1500 µs (1,5 ms).
  • La plage d'impulsion garantie (Pulse Width) s'étend de 900 µs (0,9 ms) à 2100 µs (2,1 ms).

Calcul des valeurs du registre OCR0A : Notre horloge Arduino fonctionne à 16 MHz. Avec un prescaler de 1024, la durée d'une seule incrémentation (un "tic") du Timer 0 est de :

Pour trouver la valeur technique à envoyer au registre, on divise le temps d'impulsion du constructeur par la durée de notre tic :

  • Point central (1,5 ms) :

. En arrondissant, on obtient notre position de démarrage 23.

  • Butée minimale constructeur (0,9 ms) :

. La limite officielle basse est de 14.

  • Butée maximale constructeur (2,1 ms) :

. La limite officielle haute est de 33.

Dans le code final, les limites ont été étendues de 8 à 38, correspondant environ à 0,5 ms et 2,4 ms pour exploiter le maximum la mécanique du servo.


Code du Jour 1

#ifndef F_CPU
#define F_CPU 16000000UL // On définit la vitesse de l'horloge 
#endif

#include <avr/io.h>
#include <util/delay.h>

int main(void) {
    // On définit les pins comme des sorties (DDR = 1)
    DDRD |= (1<<PD6) | (1<<PD3);
    
    // On force le buzzer au silence
    PORTD |= (1<<PD3); 

    // On active les résistances internes pour les boutons
    PORTC |= (1<<PC1) | (1<<PC2);

    // On crée un signal PWM rapide pour piloter le servo sur la pin D6
    TCCR0A = (1<<COM0A1) | (1<<WGM01) | (1<<WGM00); 
    TCCR0B = (1<<CS02) | (1<<CS00); // On ralentit le chrono pour avoir du 61Hz
    
    uint8_t pos = 23; // Valeur de démarrage (moteur à l'arrêt)

    while (1) {
        // Lecture des boutons  
        if (!(PINC & (1<<PC1)) && pos > 8)  pos--; // Bouton S1 diminue
        if (!(PINC & (1<<PC2)) && pos < 38) pos++; // Bouton S2 augmente
        
        OCR0A = pos; // On envoie l'ordre de vitesse au moteur
        
        _delay_ms(100); // Délai pour que le réglage du servo ne soit pas trop rapide
    }
}

Document utilisés