O tocador de MP3 testado utiliza um protocolo muito comum, que costuma ser chamado de "NEC". Os detalhes estão aqui, vejamos um resumo:
- Quando o LED IR for acionado, a frequência deve ser 38KHz e o duty de 1/3.
- No começo de cada código acionamos o LED por 9 ms e o apagamos por 4,5ms (isto serve para ajustar o controle de ganho do receptor).
- Em seguida transmitimos um endereço de 8 bits duas vezes, invertendo os bits na segunda vez.
- Depois, enviamos o comando de 8 bits também duas vezes, invertendo os bits na segunda vez.
- Para fechar o código, acionamos o LED por 560µs e o desligamos.
- Para transmitir um "1" acionamos o LED por 560µs e o desligamos por 1690µs.
- Para transmitir um "0" acionamos o LED por 560µs e o desligamos por 560µs (ou seja estamos codificando por "distância de pulso").
O hardware é bastante simples, um LED IR TIL32 com o catodo ligado ao pino GND do Arduino UNO e o anodo ligado através de um resistor de 220 ohms ao pino 3 do Arduino UNO.
Nosso primeiro desafio é gerar o sinal de 38KHz com duty de 1/3. Para isto vamos programar o Timer2, que é quem gera o PWM para o pino 3 no ATmega328 (isto muda para outros modelos do ATmega, como o usado no Arduino Mega).
const int PINO_LED = 3;
// Prepara o PWM para gerar um sinal de 38KHz com duty cycle de 1/3
static void preparaPWM () {
uint8_t pwmval = F_CPU / 2000 / 38; // contagem para gerar 38KHz
pinMode (PINO_LED, OUTPUT);
digitalWrite (PINO_LED, LOW); // não ativar o IR
TCCR2A = _BV(WGM20); // PWM, não conectado ao pino
TCCR2B = _BV(WGM22) | _BV(CS20); // sem prescalling, phase correct
OCR2A = pwmval; // periodo
OCR2B = pwmval / 3; // tempo com sinal alto
}
Feito isto, ligar e desligar o LED é feito conectando ou desconectando o PWM ao pino:// Transmite por t microsegundos
static void txIR (int t) {
TCCR2A |= _BV(COM2B1); // conecta PWM ao pino
delayMicroseconds(t);
}
// Silencio por t microsegundos
static void silencioIR (int t) {
TCCR2A &= ~(_BV(COM2B1)); // desconecta PWM ao pino
delayMicroseconds(t);
}
Feita esta infraestrutura, a rotina para enviar um comando fica simples:static void enviaCmd (unsigned long dados) {
// transmissão inicial para ajuste do AGC
txIR (9000);
silencioIR (4500);
// Envia os 32 bits de dados (endereço e comando)
for (int i = 0; i < 32; i++) {
if (dados & 0x80000000) {
txIR (560);
silencioIR (1690);
}
else {
txIR (560);
silencioIR (560);
}
dados <<= 1;
}
// Fecha o código
txIR (560);
silencioIR (0); // para desligar o IR
}
Para completar, um programa principal de teste que envia o comando mute a cada 10 segundos:void setup () {
preparaPWM ();
}
void loop () {
enviaCmd (0x00FFE21D);
delay (10000);
}
Você deve estar se perguntando como eu descobri que o controle remoto do tocador usa o padrão NEC e qual era o código do mute. Eu simplesmente usei uma biblioteca pronta (aqui) que veremos com mais detalhes no próximo post. A maior parte do código apresentado é uma adaptação do que a biblioteca faz internamente. 
Nenhum comentário:
Postar um comentário