He estado tratando de hacer que un Arduino replique la señal remota de mi aire acondicionado durante bastante tiempo y casi me doy por vencido solo por lo molesta que es esta tarea. Lo primero es lo primero:
El Arduino que estoy usando es el Mega 2560 que usa el chip Mega2560 AVR , y el receptor IR es el VS1838b (nivel lógico bajo).
La frecuencia de la portadora IR es de 38 KHz (13 ciclos de temporizador de EE. UU.), y la velocidad máxima a la que he podido obtener lecturas confiables del Arduino es de alrededor de 250 KHz (4 ciclos de temporizador de EE. UU.). Las señales IR se decodifican a través de la longitud de una señal corrupta por una señal portadora de 38 KHz, pero el VS1838b devuelve solo la longitud de la señal (sin la porción de 38 KHz).
El Mega tiene 8192 bytes de memoria, lo que significa que necesito ser muy eficiente. Las impresiones en serie están fuera de discusión, ya que agregan un retraso significativo al programa que afectaría la lectura. He estado usando una matriz de bytes, almacenando la información secuencialmente de izquierda a derecha, pero esto significa que puedo tener un máximo de 64 000 muestras.
El LED IR que estoy usando es completamente funcional, y la velocidad de lectura/escritura de Arduino es suficiente, ya que pude abrir un control remoto de CA, soldar un cable a uno de los terminales IR del control remoto, conectarlo a un Arduino y retransmitir ese resultado a mi LED IR.
Así es como se configura el temporizador:
void setup()
{
// Serial.begin (115200);
pinMode(8, INPUT);
pinMode(4, OUTPUT);
TCCR1A = B00000000;
TCCR1B = B00001001; // CTC mode with 1:1 prescaler
TIMSK1 = B00000010; // Enables Timer 1 A compare interrupt
OCR1A = 0x003E; // 3E = 4us, 7F = 8us, 9F = 10us, CF = 13us, 19F = 26us
}
Pensé que sería una implementación fácil. Todo lo que tenía que hacer era copiar la señal exactamente como se leyó (directamente desde el control remoto de CA), y funcionaría bien (aparte de ser ineficiente en el almacenamiento). Copié la señal en 4 ciclos de uS, así:
ISR (TIMER1_COMPA_vect)
{
temp = temp << 1;
if (PINH == 32)
temp++;
j++;
if (j == 8)
{
store[k] = temp;
k++;
j = 0;
temp = 0;
}
if (k == len)
{
k = 0;
j = 0;
flag = 1;
StopTimer();
}
}
Donde PINH == 32 es el pin de recepción para el control remoto de CA (32 porque estoy leyendo directamente desde el registro). Luego, usando la misma interrupción del temporizador, escribí la señal cuando terminó de leer:
ISR (TIMER1_COMPA_vect)
{
if (k == len)
{
StopTimer();
CLR(5);
k = 0;
flag = 1;
}
if (bitRead(store[k], j) == 1)
{
SET(5);
}
else
{
CLR(5);
}
j--;
if (j == -1)
{
k++;
j = 7;
}
}
Pero esto no funcionó y no tenía idea de por qué. Luego traté de usar el VS1838b y lo combiné con una frecuencia PWM fija de 38 KHz a través del temporizador, y activé/desactivé el temporizador según las lecturas del sensor.
Pensé que tal vez el programa estaba afectando la frecuencia PWM de alguna manera, así que usé un Arduino diferente para escribir la frecuencia PWM y otro para leer el VS1838b. Luego conecté la escritura PWM fija de 38 KHz a la base de un transistor TIP41C, el pin de control Arduino al colector.
No sé cuál podría ser la causa, verifiqué dos veces la hoja de datos del temporizador, incluso calibré manualmente el temporizador usando las funciones micros (), pero nada parece funcionar. ¿Hay algo que estoy haciendo fundamentalmente mal?
editar: simplifiqué el circuito y subí fotos de cómo se ve. Básicamente, D10 es una entrada para el sensor VS1838b, el temporizador usa D6 para escribir una frecuencia PWM de 38 KHz y D3 se usa para generar el resultado NOT del sensor. El código se ve así:
#define CLR(x) (PORTD&=(~(1<<x)))
#define SET(x) (PORTD|=(1<<x))
#define TOGGLE(x) (PORTD^=(1<<x))
void setup()
{
Serial.begin(2000000);
pinMode(10, INPUT);
pinMode(3, OUTPUT);
pinMode(6, OUTPUT);
TCCR1A = B00000000;
TCCR1B = B00001001;
TIMSK1 = B00000010;
OCR1A = 0x00CF; // 3E = 4us, 7F = 8us, 9F = 10us, CF = 13us, 19F = 26us
}
void loop()
{
if ((PINB && B00000100) == 0)
{
SET(3);
}
else
{
CLR(3);
}
}
ISR (TIMER1_COMPA_vect)
{
TOGGLE(6);
}
Y sigue sin funcionar.
IR es algo así como la radio AM, un poco. Tienes una señal y un portador, pero una cosa de onda cuadrada. Tú y la señal y el portador juntos. Para transmitir necesitas hacer esto al revés. Aunque me las arreglé para romper esto con un PIC en un punto, asuma que no puede y no se moleste. Básicamente, necesita generar un portador (38Khz) y junto con su señal, pulsos de ms o fracciones de. Suponga que esto no siempre es posible dentro de una MCU, debe evaluar cada mcu para ver si puede hacerlo de alguna manera.
Para algunos, usa el temporizador para generar una señal (no está usando esto para interrumpir el bit bang, está generando la señal en sí) y luego algunos le permiten activar la salida en función de otro temporizador o algo más. Algunos STM32 tienen específicamente un temporizador IR que es esencialmente una puerta entre dos temporizadores.
Puede lograrlo con un PWM, donde genera un ciclo de trabajo del 50% a veces y un ciclo de trabajo del 0% a veces, cronometrando cada uno.
Algunos pueden obtener esto con un controlador SPI usando el mosi enviando una cantidad de 0x55 y otros valores para generar la cantidad correcta de ciclos de reloj y luego la cantidad correcta de ceros para generar los espacios. Esta es probablemente la forma más fácil de hacerlo, si la MCU tiene un fifo lo suficientemente profundo o una forma de dma y usted tiene suficientes ciclos o memoria para mantener alimentado el fifo/dma.
O simplemente podría poner una puerta discreta y fuera de la mcu...
Luego, como cualquier otro LED, alimenta esta señal de salida al LED IR con una resistencia para limitar/controlar el voltaje a través del LED.
Si no tiene un alcance, encontrará esto extremadamente difícil. Es posible que deba reducir la velocidad ajustando sus divisores y luego alimentarlo a otra placa mcu o raspberry pi o fpga o algo que se use como un analizador lógico casero para examinar el tiempo. Los buenos osciloscopios son muy económicos en estos días, por lo que vale la pena obtener uno de cuatro canales si planea continuar trabajando con mcu (esto cubrirá uart, spi (dos líneas de datos), i2c y una serie de otras cosas) (aprenda a leer los protocolos, no use el software que intenta leerlos por usted, fallan tanto como tienen éxito y empeoran la vida, estos protocolos son fáciles de leer a partir de las señales sin procesar).
No estoy seguro de cuál era el problema, pero mi lógica inicial era correcta.
Para solucionarlo, cambié los microcontroladores del Arduino Nano al nuevo Arduino Nano Every, cambié el LED IR por uno nuevo (aunque el anterior supuestamente funcionaba) y reescribí el código usando el nuevo Arduino (la misma lógica pero con el nuevo temporizador Atmega4809):
// Macros for easier bit manipulation
#define CLR(x) (VPORTB.OUT&=(~(1<<x)))
#define SET(x) (VPORTB.OUT|=(1<<x))
#define TOGGLE(x) (VPORTB.OUT^=(1<<x))
void setup()
{
pinMode(5, OUTPUT); // IR LED output
pinMode(9, INPUT); // VS1838b input sensor
TCA0.SINGLE.PER = 0x00D2;
TCA0.SINGLE.CMP1 = 0x00D2;
TCA0.SINGLE.INTCTRL = B00100000;
TCA0.SINGLE.CTRLA = B00000001;
}
void loop()
{
}
ISR(TCA0_CMP1_vect) {
TCA0.SINGLE.INTFLAGS |= B00100000;
if ((VPORTB.IN & B00000001) == 0)
{
TOGGLE(2);
}
else
{
CLR(2);
}
}
Esto ahora funciona. ¡Gracias a todos por su ayuda!
Tony Estuardo EE75
Tony Estuardo EE75
alex rd
mmmm
alex rd
Kartman
alex rd