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
- }
- // 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);
- }
- 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
- }
- void setup () {
- preparaPWM ();
- }
- void loop () {
- enviaCmd (0x00FFE21D);
- delay (10000);
- }
Nenhum comentário:
Postar um comentário