« SE3 2025/2026 EC3 » : différence entre les versions

De wiki-se.plil.fr
Aller à la navigation Aller à la recherche
Aucun résumé des modifications
Ligne 20 : Ligne 20 :
= Travail réalisé =
= Travail réalisé =


=== <span style="color:#800020;font-weight: bold;">1. blink.c </span> ===
=== <span style="color:#800020;font-weight: bold;">1. Youssef_servo.c </span> ===
<syntaxhighlight lang="c" line="1">
<syntaxhighlight lang="c" line="1">
#ifndef F_CPU
#ifndef F_CPU

Version du 1 mars 2026 à 21:18

Objectifs

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

Travail réalisé

1. Youssef_servo.c

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

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

#define LATCH PD4  // Signal de validation 
#define CLOCK PD7  // Signal d'horloge 
#define DATA  PB0  // Fil de données 

volatile uint16_t angle = 90; 
const uint8_t segments[] = {~0x3F,~0x06,~0x5B,~0x4F,~0x66,~0x6D,~0x7D,~0x07,~0x7F,~0x6F}; 
//Le symbole '~' inverse les bits car l'afficheur s'allume avec du 0V

void envoyer(uint8_t val) {
    for (uint8_t i = 0; i < 8; i++) {
        // On vérifie chaque bit de l'octet du plus grand au plus petit
        if (val & (1 << (7 - i))){
            PORTB |= (1 << DATA);  // On envoie un 1 (5V)
        } else {
            PORTB &= ~(1 << DATA); // On envoie un 0 (0V)
        }
        
        // On actionne l'horloge  manuellement pour faire avancer le bit
        PORTD |= (1 << CLOCK); 
        PORTD &= ~(1 << CLOCK);
    }
}

ISR(TIMER2_COMPA_vect) {
    // static permet de garder en mémoire quel digit (0, 1 ou 2) on doit allumer
    static uint8_t digit = 0;
    
    // On extrait le bon chiffre du nombre total Centaines, Dizaines et Unités
    uint8_t val = (digit == 0) ? (angle/100) : (digit == 1) ? (angle/10)%10 : (angle%10);

    PORTD &= ~(1 << LATCH);      // On bloque l'affichage le temps de préparer les données
    envoyer(segments[val]);       // chiffre
    envoyer(1 << digit);          // digit
    PORTD |= (1 << LATCH);       // On déverrouille pour afficher le résultat final

    // On prépare le tour suivant 
    digit = (digit + 1) % 3;
}

int main(void) {

    // On définit les pins comme des sorties (DDR = 1)
    DDRD |= (1<<LATCH) | (1<<CLOCK) | (1<<PD6) | (1<<PD3);
    DDRB |= (1<<DATA);
    
    // On force le buzzer au silence
    PORTD |= (1<<PD3); 

    // On active les résistances internes
    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
    
    // On règle une alerte toutes les 1 milliseconde pour changer de chiffre
    TCCR2A = (1<<WGM21);           // Mode CTC 
    TIMSK2 |= (1<<OCIE2A);         // On active l'alerte
    OCR2A = 249;                   // Cible 
    TCCR2B = (1<<CS22);            

    sei(); // On autorise les alertes à fonctionner
    
    uint8_t pos = 23; 


    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
        
        // Calcul pour transformer la valeur technique en un chiffre lisible (0-180)
        angle = (uint32_t)(pos - 8) * 180 / 30; 
        
        _delay_ms(100); // Délai pour le réglage du servo soit pas rapide
    }
}

Documents Rendus