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

De wiki-se.plil.fr
Aller à la navigation Aller à la recherche
Balise : Révocation manuelle
Aucun résumé des modifications
Ligne 19 : Ligne 19 :


= Travail réalisé =
= Travail réalisé =
=== <span style="color:#800020;font-weight: bold;">1. blink.c </span> ===
<syntaxhighlight lang="c" line="1">
#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
    }
}
</syntaxhighlight>


= Documents Rendus =
= Documents Rendus =

Version du 1 mars 2026 à 21:15

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. blink.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