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