81
Vos projets / Re : Identification des trains par infrarouge
« Dernier message par bobyAndCo le mai 02, 2025, 05:13:45 pm »Bonjour JPM06,
L'hypothèse du 4/8 ne se justifie sans doute pas. Peut-être même n'y a t'il pas besoin de contrôle. Mais ça, c'est ça vérifier selon le taux d'erreurs aux essais.
J'ai malheureusement pas beaucoup de temps et peut-être pas les composants, mais j'ai commencé à écrire un code simple mais complet pour un émetteur sur ATTiny. J'ai même ajouté un checksum très sommaire mais certainement suffisant.
bit de start + data + checksum + bit de stop.
Si quelqu'un veut tester avec un UNO je peux fournir le code, il y a juste les ports à changer (à priori)
Sans garantie cependant pour le UNO
Christophe
L'hypothèse du 4/8 ne se justifie sans doute pas. Peut-être même n'y a t'il pas besoin de contrôle. Mais ça, c'est ça vérifier selon le taux d'erreurs aux essais.
J'ai malheureusement pas beaucoup de temps et peut-être pas les composants, mais j'ai commencé à écrire un code simple mais complet pour un émetteur sur ATTiny. J'ai même ajouté un checksum très sommaire mais certainement suffisant.
bit de start + data + checksum + bit de stop.
Code: [Sélectionner]
/*
idTrainIr38kHzATTiny_emetteur
Identification de trains avec led IR à 38Khz
Programme pour ATTiny 25/45/85
_______
(Reset) -|1 8|- Vcc
PB3 -|2 7|- PB2
PB4 -|3 6|- PB1 ← LED IR (OC0B)
GND -|4 5|- PB0
-------
*/
// Définition de la broche utilisée pour la LED IR (PB1 = pin 6)
#define LED_BIT PB1
#define LED_DDR DDRB
#define LED_PORT PORTB
// Octet d'identification du convoi
const byte identifiant = 0x5A; // Exemple
void setup() {
// Configurer la broche PB1 comme sortie (celle connectée à la LED IR)
LED_DDR |= (1 << LED_BIT);
// Initialiser le Timer0 en PWM à 38 kHz sur OC0B (PB1)
setup38kHzPWM();
}
void loop() {
byte checksum = identifiant ^ 0xA5; // XOR avec une constante arbitraire 0xA5
// Émission d'une trame IR : Start + ID + Checksum + Stop
sendStartBit();
sendByte(identifiant);
sendByte(checksum);
sendStopBit();
delay(500);
}
// Configuration du Timer0 pour produire du PWM à 38 kHz sur OC0B (PB1)
void setup38kHzPWM() {
// Mode Fast PWM avec TOP = OCR0A (Mode 7 : WGM02 + WGM01 + WGM00)
// OCR0A définit la période → fréquence = 16MHz / (2 × (OCR0A + 1))
TCCR0A = _BV(WGM01) | _BV(WGM00) | _BV(COM0B1); // Sortie sur OC0B activée
TCCR0B = _BV(WGM02) | _BV(CS00); // Pas de préscaler (division par 1)
// Pour 38 kHz : OCR0A = 210 → période ≈ 26.3 µs
OCR0A = 210;
// Rapport cyclique 50 % → OCR0B = moitié de OCR0A
OCR0B = 105;
}
// Active ou désactive le signal PWM sur OC0B (PB1)
void enablePWM(bool on) {
if (on) {
// Active le lien entre le Timer0 et la broche PB1
TCCR0A |= _BV(COM0B1);
} else {
// Déconnecte le Timer0 de la broche
TCCR0A &= ~_BV(COM0B1);
// Force la broche PB1 à l'état LOW (éteint la LED IR)
LED_PORT &= ~(1 << LED_BIT);
}
}
// Envoie un octet (8 bits) bit par bit, MSB en premier
void sendByte(byte data) {
for (int i = 7; i >= 0; i--) {
if (data & (1 << i))
sendBit1();
else
sendBit0();
}
}
// Envoie un bit logique '1' : 600 µs burst + 600 µs silence
void sendBit1() {
enablePWM(true); // Allume la LED IR (signal 38 kHz)
delayMicroseconds(600); // Durée du burst
enablePWM(false); // Éteint la LED
delayMicroseconds(600); // Rien
}
// Envoie un bit logique '0' : 600 µs burst + 1600 µs silence
void sendBit0() {
enablePWM(true); // Allume la LED IR
delayMicroseconds(600); // Durée du burst
enablePWM(false); // Éteint la LED
delayMicroseconds(1600); // Espace long
}
// Envoie un bit de start (synchronisation) : burst de 2400 µs
void sendStartBit() {
enablePWM(true); // Allume la LED IR
delayMicroseconds(2400); // Long burst = signal de synchronisation
enablePWM(false); // Éteint la LED
delayMicroseconds(600); // Pause après start
}
// Envoie un bit de stop
void sendStopBit() {
enablePWM(false); // LED éteinte
delayMicroseconds(2000); // fin
}
Si quelqu'un veut tester avec un UNO je peux fournir le code, il y a juste les ports à changer (à priori)
Code: [Sélectionner]
#define LED_BIT PB1
#define LED_DDR DDRB
#define LED_PORT PORTB
Code: [Sélectionner]
void setup38kHzPWM() {
// Timer2 en mode Phase Correct PWM à 38 kHz sur OC2B (D3)
TCCR2A = _BV(WGM21) | _BV(COM2B1); // COM2B1 = PWM activé
TCCR2B = _BV(WGM22) | _BV(CS20); // CS20 = pas de prescaler
OCR2A = 210; // Fréquence = 16MHz / (2 * (OCR2A + 1)) ≈ 38 kHz ≈ 26.3 µs
OCR2B = 105; // 50 % de duty cycle
}
// Active ou désactive le PWM sur D3
void enablePWM(bool on) {
if (on)
TCCR2A |= _BV(COM2B1); // Activer sortie OC2B
else {
TCCR2A &= ~_BV(COM2B1); // Désactiver OC2B
LED_PORT &= ~(1 << LED_BIT); // Mettre D3 à LOW
}
}
Sans garantie cependant pour le UNO
Christophe