Liste materiel
Composants nécessaires
- Pour le kit final
- 1 Capteur infrarouge, Vishay, 40 KHz, AGC2 : TSOP31240
- 1 Microcontrôleur, 8bit, 128 B RAM, 2 Ko, 20MHz, DIP 8, série ATtiny25 : ATTINY25-20PU (Microchip)
- Pour programmer et tester le kit
- 1 Carte Arduino
- 1 Platine d’expérimentation
- 1 capacité (> 1 uF)
- 15 Fils male/male
- (Optionnel) 1 résistance de 1 KOhms et une LED
Programmer le microcontrôleur
Préparez le montage suivant :
Figure 1, Schéma électronique pour programmer et tester le kit.
Ensuite on programme le microcontrôleur avec le code qui suit. Si vous ne savez pas comment flasher le microcontrôleur alors vous trouverez sur le site web des « Instructables » comment programmer l’ATtiny (lien : https://www.instructables.com/How-to-Program-an-Attiny85-From-an-Arduino-Uno/)
Code source à compiler et flasher :
//-----------------------------------------------------------------------------
// MIT License
//
// Copyright (c) 2023, 2024 Nicolas HEBERT
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions :
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//-----------------------------------------------------------------------------
//
// Pobot Robotic Sophia Antipolis
//
// Code compatible IR SONY remote control
// 40 KHz main freq.
// decode first 4 characters
// use :
// - key 9 : to re-program OFF key
// - key 0 : to re-program ON key
//
// Note : Do not forget to “burn bootloader” with clock set
// to “internal at 8MHz” before any programing. Else the timer setting
//. Will be incorrect, and the decoder will not decode correctly.
//
//-----------------------------------------------------------------------------
#include <EEPROM.h>
#define SIGNAL_START_PIN PB4
#define IR_SENSOR_PIN PB3
#define EEPROM_ADDR_KEY_ON 0
#define EEPROM_ADDR_KEY_OFF 1
static volatile uint8_t code_len, code ;
enum KEY_VALUES { OFF, ON, REPROG_OFF, REPROG_ON} ;
static volatile enum KEY_VALUES key[4] ;
enum IR_STATES { WAIT_START, ACQ} ;
static volatile enum IR_STATES ir_state ;
void init_timer() {
// Configure Timer0 at 5kHz (for fuse set as internal clk 8MHz)
TCCR1 = (1 << CTC1) + 5 ; // CTC mode + prescaler PCK/16
// boring part ... look at ATiny datasheet
TCNT1 = 0 ; GTCCR = _BV(PSR1) ;
OCR1A = 99 ; OCR1C = 99 ;
TCNT1 = 0 ; GTCCR = 0 ;
TIMSK = (1 << OCIE1A) ;
// end boring part
}
void code_capture() {
static uint8_t count = 0 ;
if(!digitalRead(IR_SENSOR_PIN)) {
count++ ;
} else {
// Configure Timer0 5kHz. internal at 8MHz
// 0 logic -> ir@0 for 2-3 pulses,
// 1 logic -> 5-6 pulses,
// Start logic -> 11-12 pulses
if(count > 0){
if(ir_state == WAIT_START) {
code_len = 0 ;
if(count >= 11 && count <= 12) {
ir_state = ACQ ;
}
} else {
code_len++ ;
code = code << 1 ; // push
if(count >= 6 && count <= 7)
code++ ;
}
count = 0 ;
}
}
}
void process_msg() {
static char reprog = 0 ;
if(reprog !=0) {
if((code & 0xF) != key[REPROG_OFF] &&
(code & 0xF) != key[REPROG_ON]) {
//noInterrupts() ; // need because we hang the ISR function with long eeprom write and delay
if(reprog == 1) {
key[OFF] = code & 0xF ;
} else {
key[ON] = code & 0xF ;
}
//EEPROM.write(EEPROM_ADDR_KEY_ON, key[ON]) ;
//digitalWrite(SIGNAL_START_PIN, LOW) ;
reprog = 0 ;
for(int x=0 ; x<10 ; x++) {
digitalWrite(SIGNAL_START_PIN, HIGH) ;
delay(10000) ; // to slow down the process a little bit
digitalWrite(SIGNAL_START_PIN, LOW) ;
delay(10000) ;
}
//interrupts() ;
}
} else {
if((code & 0xF) == key[ON]) {
digitalWrite(SIGNAL_START_PIN, HIGH) ;
/* noInterrupts() ; // need because we hang the ISR function with long eeprom write and delay
for(int x=0 ; x<10 ; x++) {
digitalWrite(SIGNAL_START_PIN, HIGH) ;
delay(1000) ;
digitalWrite(SIGNAL_START_PIN, LOW) ;
delay(3000) ;
}
interrupts() ;*/
} else if((code & 0xF) == key[OFF]){
digitalWrite(SIGNAL_START_PIN, LOW) ;
/* noInterrupts() ; // need because we hang the ISR function with long eeprom write and delay
for(int x=0 ; x<10 ; x++) {
digitalWrite(SIGNAL_START_PIN, HIGH) ;
delay(2000) ;
digitalWrite(SIGNAL_START_PIN, LOW) ;
delay(10000) ;
}
interrupts() ;*/
} else if ((code & 0xF) == key[REPROG_OFF]) { // re program mode active
/*noInterrupts() ; // need because we hang the ISR function with long eeprom write and delay
for(int x=0 ; x<4 ; x++) {
digitalWrite(SIGNAL_START_PIN, HIGH) ;
delay(2000) ;
digitalWrite(SIGNAL_START_PIN, LOW) ;
delay(2000) ;
}
interrupts() ;*/
reprog = 1 ;
} else if ((code & 0xF) == key[REPROG_ON]) { // re program mode active
reprog = 2 ;
}
}
}
ISR(TIMER1_COMPA_vect) {
noInterrupts() ;
code_capture() ;
if(code_len == 4) {
ir_state = WAIT_START ;
process_msg() ;
}
interrupts() ;
}
char key_to_code(char key){
char code = 0 ;
for(uint8_t i=0 ; i<4 ; i++) {
code += ((((key+9)%10) >> i) & 0x1) << (3-i) ;
}
return code ;
}
void setup() {
pinMode(IR_SENSOR_PIN, INPUT) ;
digitalWrite(SIGNAL_START_PIN, LOW) ;
pinMode(SIGNAL_START_PIN, OUTPUT) ;
//EEPROM.write(EEPROM_ADDR_KEY_ON, key_to_code(2)) ;
//EEPROM.write(EEPROM_ADDR_KEY_OFF, key_to_code(3)) ;
key[ON] = EEPROM.read(EEPROM_ADDR_KEY_ON) ;
key[OFF] = EEPROM.read(EEPROM_ADDR_KEY_OFF) ;
key[REPROG_OFF] = key_to_code(0) ; // LSB first, so 8 is 1 (code len 4)
key[REPROG_ON] = key_to_code(9) ;
init_timer() ;
ir_state = WAIT_START ;
sei() ; // Enable Int.
}
void loop() {}
Ce code est un décodeur de télécommande infrarouge compatible avec les télécommandes SONY utilisant une fréquence de porteuse de 40 kHz.
Le décodeur est conçu pour décoder les quatre premiers caractères du signal infrarouge reçu.
Voici une explication détaillée du fonctionnement du code :
- Les broches utilisées sont définies avec les noms SIGNAL_START_PIN et IR_SENSOR_PIN.
- Deux adresses EEPROM sont définies pour stocker les valeurs des touches ON et OFF de la télécommande.
- La fonction ISR(TIMER1_COMPA_vect) est une interruption appelée lorsque le Timer0 déclenche une comparaison. Elle appelle la fonction code_capture() et vérifie si la longueur du code atteint 4 pour appeler la fonction process_msg().
- La fonction init_timer() configure le Timer0 à une fréquence de 5 kHz avec un prédiviseur de 16. Cela est utilisé ensuite comme une interuption periodique pour décoder le signal infrarouge.
- La fonction code_capture() est appelée à chaque fois qu’un front descendant est détecté sur la broche IR_SENSOR_PIN. Elle compte le nombre de fronts descendants pour déterminer la longueur du code reçu et stocke le code dans la variable « code ».
- La fonction process_msg() est appelée lorsque la longueur du code atteint 4. Elle vérifie si le code correspond à l’une des touches enregistrées et effectue les actions correspondantes. Si la touche REPROG_OFF ou REPROG_ON est détectée, le mode de reprogrammation est activé, ce qui permet de changer la touche ON ou OFF enregistrée.
- Dans la fonction setup(), les broches sont configurées en entrée ou en sortie, les valeurs des touches sont lues à partir de l’EEPROM, le Timer0 est initialisé, et finalement l’interruption est activée.
- La fonction loop() est vide car le programme principal ne fait rien en boucle.
En résumé, ce code configure un décodeur infrarouge pour recevoir des signaux provenant d’une télécommande SONY et effectuer des actions en fonction des touches détectées. Il permet également de reprogrammer la touche ON et OFF enregistrées en utilisant les touches 9 et 0 de la télécommande.
Utiliser le kit dans votre robot
Préparez le montage suivant :
Figure 2, Schéma électronique d’un kit fini
Le kit control la broche 8 de l’Arduino avec le signal de start/stop. Contrairement au module actuellement utilisé dans les compétions, nous proposons une amélioration significative. Notre nouvelle solution permet désormais de réaliser des arrêts et des redémarrages multiples du robot, offrant ainsi une flexibilité accrue pendant la phase d’optimisation du code.
Figure 3, Exemple de kit pour robot dans sa colle...
Il vous est possible d’élaborer un petit circuit électronique et de le partager à votre guise. À cette fin, vous pouvez utiliser le récepteur Vishay CMS qui présente des propriétés de réception encore supérieures à celles de sa version traversante présenté ici. De même il existe des versions CMS du microcontrôleur plus intéressant. N’hésitez pas à nous en parler, nous pourrons mettre en lien vos schéma ainsi que des liens vers vos kits sur cette page.
Si une personne envisage de faire un kit télécommande + récepteur infra rouge ? Nous serions ravi d’ajouter un lien dans cet article.
Auteur : Nicolas HEBERT, membre de l’association Pobot.