« SE3 2025/2026 EC3 » : différence entre les versions
Aucun résumé des modifications |
|||
| Ligne 1 : | Ligne 1 : | ||
= | <br> | ||
<span style="color:#800020;font-size: 1.2em; font-weight: bold;">Jour 1 : Moteur et Boutons</span> | |||
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. | |||
<br> | |||
<span style="color:#800020;font-size: 1.2em; font-weight: bold;">Configuration des boutons</span> | |||
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. | ||
<br> | |||
<span style="color:#800020;font-size: 1.2em; font-weight: bold;">Désactivation du buzzer du shield</span> | |||
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. | |||
<br> | |||
<span style="color:#800020;font-size: 1.2em; font-weight: bold;">Génération du signal PWM pour le servo</span> | |||
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 : | |||
<math>f = \frac{16\,000\,000}{1024 \times 256} \approx 61 \text{ Hz}</math> | |||
La fréquence obtenue est donc d’environ 61 Hz, ce qui est compatible avec les exigences d’un servo-moteur standard. | |||
<br> | |||
<span style="color:#800020;font-size: 1.2em; font-weight: bold;">Justification des valeurs matérielles pour le servo Hitec HS-422</span> | |||
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 : | |||
<math>T_{tic} = \frac{1024}{16\,000\,000} = 0,000064 \text{ s} = 0,064 \text{ ms}</math> | |||
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) :''' | |||
<math>\frac{1,5}{0,064} = 23,43</math>. En arrondissant, on obtient notre position de démarrage 23. | |||
* '''Butée minimale constructeur (0,9 ms) :''' | |||
<math>\frac{0,9}{0,064} = 14,06</math>. La limite officielle basse est de 14. | |||
* '''Butée maximale constructeur (2,1 ms) :''' | |||
<math>\frac{2,1}{0,064} = 32,81</math>. 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.'' | |||
<br> | |||
<span style="color:#800020;font-size: 1.2em; font-weight: bold;">Code du Jour 1</span> | |||
<syntaxhighlight lang="c" line="1"> | <syntaxhighlight lang="c" line="1"> | ||
#ifndef F_CPU | #ifndef F_CPU | ||
| Ligne 27 : | Ligne 72 : | ||
#include <avr/io.h> | #include <avr/io.h> | ||
#include <util/delay.h> | #include <util/delay.h> | ||
int main(void) { | int main(void) { | ||
// On définit les pins comme des sorties (DDR = 1) | // On définit les pins comme des sorties (DDR = 1) | ||
DDRD |= | DDRD |= (1<<PD6) | (1<<PD3); | ||
// On force le buzzer au silence | // On force le buzzer au silence | ||
PORTD |= (1<<PD3); | PORTD |= (1<<PD3); | ||
// On active les résistances internes | // On active les résistances internes pour les boutons | ||
PORTC |= (1<<PC1) | (1<<PC2); | PORTC |= (1<<PC1) | (1<<PC2); | ||
| Ligne 85 : | Ligne 88 : | ||
TCCR0B = (1<<CS02) | (1<<CS00); // On ralentit le chrono pour avoir du 61Hz | 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) { | while (1) { | ||
// Lecture des boutons | // Lecture des boutons | ||
if (!(PINC & (1<<PC1)) && pos > 8) pos--; // Bouton S1 | if (!(PINC & (1<<PC1)) && pos > 8) pos--; // Bouton S1 diminue | ||
if (!(PINC & (1<<PC2)) && pos < 38) pos++; // Bouton S2 | if (!(PINC & (1<<PC2)) && pos < 38) pos++; // Bouton S2 augmente | ||
OCR0A = pos; // On envoie l'ordre de vitesse au moteur | 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 | |||
_delay_ms(100); // Délai pour le réglage du servo soit pas rapide | |||
} | } | ||
} | } | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Version du 2 mars 2026 à 22:31
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
}
}