Como supeditar el encendido de una TV al de un descodificador,Blueray u otros dispositivos ( parte 1)


Puede parecer  extraño , pero cada vez tenemos dispositivos  conectados a nuestro TV  que  suelen ser  el origen de  vídeo  por defecto  como pueden ser dispositivos Android   TV, reproductores blueray, etc.  o   sobre todo descodificadores de TV  

En este sentido  podría ser interesante  supeditar  automáticamente el  encendido  de la TV  al de la fuente de vídeo ( normalmente un descodificador de TV) , para lo cual   vamos a intentar implementar una solución que lo automatice

Pensando en una solución , una aproximación  podría ser basarse en  las señales de infrarrojos entre el TV  y la fuente de vídeo ,pero esto conlleva mucha complejidad pues en el mercado existe una infinidad de marcas  y modelos de  dispositivos diferentes , que haría  muy difícil  contemplar un método practico para resolverlo , así  que debemos pensar en otra solución …

Pensando  en la variación del consumo de un dispositivo  ,una solución puede pasar por detectar  esa variación  de consumo   y con ello  sabremos si debemos o no activar la TV , para lo cual nos puede basta el sensor   ACS712    , un  Modulo Sensor de corriente para Arduino con un rango de medida máximo de 5 Amperios ( suficiente para la mayoría de los dispositivos  que conectaremos al TV) 

Este sensor esta basado  en efecto Hall   que detecta el campo magnético que se produce por inducción de la corriente que circula por la línea que se está midiendo , por lo que no hay disipación de potencia a través de este como ocurriría  con soluciones clásicas  que  usarían una resistencia de valor bajo  en serie  para medir la corriente que circula por ella  y el circuito (pero  con el consiguiente disipación  de potencia en esta )

Concretamente  en las pruebas  junto a un Arduino UNO , usaremos el  chip sensor  ACS712ELC-05A  alimentado  con  5V a través del propio Arduino ( lleva un led a bordo como e indicador de energia) 


El modulo puede medir los positivos y negativos de máximo 5 amperios, correspondiente a la salida analógica 185mV / A   entregando una salida de voltaje proporcional a la corriente, Dependiendo la aplicación podemos usar otros módulos  como el ACS712-05A, ACS712-20A o el ACS712-30A, para rangos de 5, 20 o 30 amperios respectivamente

El  ACS712  podemos encontrarlo en módulos, los cuales nos facilitan sus conexiones, Este modulo  trae una bornera para conectar la línea que queremos medir ( el descodificador)  y 3 pines por el otro extremo: dos para conectar la alimentación y un pin para la salida analógica.

Para las conexiones en el módulo debe  guiarse por los nombres de los pines, en algunos modelos vienen en diferente orden pero marcados en la serigrafia como Gnd,Out  y Vcc . En nuestro caso Vcc ira al pin +5V de Arduino, GND al GND del Arduino y  Out lo conectaremos al pin analógico de Arduino  A0 

En los terminales opuestos del  ACS712  conectaremos  en serie la alimentación del Descodificador ,o dispositivo que  vaya a controlar  la TV . Para medir la corriente se  debe conectar en serie con el dispositivo o carga, nunca conectar en paralelo a la fuente de voltaje.

 

 

El rango de corriente que podemos medir y sensibilidad varían dependiendo del modelo del integrado, existen tres modelos los cuales detallamos a continuación:

Modelo Rango Sensibilidad
ACS712ELCTR-05B-T -5 a 5 A 185 mV/A
ACS712ELCTR-20A-T -20 a 20 A 100 mV/A
ACS712ELCTR-30A-T -30 a 30 A 66 mV/A

El sensor  ACS712  nos entrega un valor de 2.5 voltios para una corriente de 0A y a partir de allí incrementa proporcionalmente de acuerdo a la sensibilidad, teniendo una relación lineal entre la salida de voltaje del sensor y la corriente. Dicha relación es una línea recta en una gráfica Voltaje vs Corriente donde la pendiente es la sensibilidad y la intersección en el eje Y es 2.5 voltios. La ecuación de la recta seria la siguiente

Donde la pendiente es m y equivale a la Sensibilidad

Despejando tendremos la ecuación para hallar la corriente a partir de la lectura del sensor:

 

Para realizar la lectura de corriente simplemente se necesita leer la entrada analógica y con la formula antes expuesta obtener la corriente.

A continuación se muestra el código para un realizar la lectura de corriente:

float Sensibilidad=0.185; 
//sensibilidad en Voltios
/Amperio para sensor de 5A void setup()
{    Serial.begin(9600); }
void loop()
{    float voltajeSensor= analogRead(A0)*(5.0 / 1023.0);
//lectura del sensor   
 float I=(voltajeSensor-2.5)/Sensibilidad;
//Ecuación  para obtener la corriente
 Serial.print("Corriente: ");
 Serial.println(I,3);
 delay(200);     
}

En nuestro caso estamos trabajando con un sensor de 5A ( ACS712  )  por eso usamos el valor de sensibilidad de 0.185V/A que es el equivalente 185mV/A que nos da el fabricante, si están trabajando con el sensor de 20A, reemplazar el valor de la sensibilidad por 0.100 V/A.

 

Existen varios tipos de filtros, que dependiendo de la complejidad pueden consumir recursos en la programación de nuestro Arduino, en nuestro caso  simplemente usaremos la media aritmética de varias lecturas consecutivas, implementar el promedio de las lecturas en Arduino es sencillo y fácil de entender, simplemente hay que sumar las lecturas y dividirlas en un  número de muestras suficiente.
La cantidad de muestras para calcular el promedio depende del nivel de ruido que tengan .En nuestro ejemplo con 200.000 son un valor lo suficiente bueno  para que nos de un resultado bastante preciso

El programa mejorado  seria el siguiente:

float Sensibilidad=0.185; 
//sensibilidad en Voltios/Amperio para sensor de 5A void setup()
{    Serial.begin(9600);
}
void loop()
{
 float I=get_corriente(200000);//obtenemos la corriente promedio de 200.00 muestras
 Serial.print("Corriente: ");
 Serial.println(I,3);
 delay(100);     
}
float get_corriente(int n_muestras)
{
 float voltajeSensor;
 float corriente=0;
 for(int i=0;i<n_muestras;i++)
 {    voltajeSensor = analogRead(A0) * (5.0 / 1023.0);
////lectura del sensor   
 corriente=corriente+(voltajeSensor-2.5)/Sensibilidad;
//Ecuación  para obtener la corriente  
}
 corriente=corriente/n_muestras;
 return(corriente);
}

 

 

Como  el error que obtenemos  aun con el numero tan elevado de muestras es grande, debemos de recalibrar y hallar los valores reales puesto que los valores que nos da el fabricante no son exactos.

Recordemos la ecuación que usamos para hallar la corriente:

En esta ecuación solo tenemos dos constantes: los 2.5 que es el voltaje del sensor cuando la corriente es 0V y la sensibilidad, que equivale a la pendiente de la recta Voltaje Vs Corriente; tenemos que calcular los valores reales de estas dos constantes. Al ser una recta, basta con obtener dos puntos y con estos podemos calcular constantes.

Para esto necesitamos un polimetro en la escala de Intensidad   ( debe ser de buena precisión, ya que este será la herramienta para calibrar)  . El polimetro, el ACS712  y la carga deben de conectarse en serie. 

Después de conectar el aparato de medida y el  sensor, debemos de tomar lecturas de voltaje del sensor, esto se hace con el siguiente programa.

void setup() 
{  
 Serial.begin(9600);
} void loop()
{  
float voltajeSensor =get_voltage(10000);
//obtenemos voltaje del sensor(10000 muestras)
 Serial.print("Voltaje del sensor: ");
 Serial.println(voltajeSensor ,3);
     }
float get_voltage(int n_muestras)
{  float voltage=0;  
 for(int i=0;i<n_muestras;i++)
 {    
voltage =voltage+analogRead(A0) * (5.0 / 1023.0);    
 }  voltage=voltage/n_muestras;  return(voltage);
}

El primer punto que debemos medir es para una corriente de 0 amperios: esta es una de las constantes, en nuestro caso 2.527, que corresponde al punto P1(2.527,0)

Para hallar la segunda constante necesitamos una segunda medida, se recomienda que no sea cercano al valor de la primera medida, en nuestro caso usaremos una carga cuya corriente es superior a 1 amperio.Como se observa en el sensor  un voltaje de 2.687, y en el amperímetro medimos 1.155A, este sería nuestro segundo punto P2(2.687,1.155) ,

Para calcular la sensibilidad simplemente calculamos la pendiente.

Teniendo estos dos valores la ecuación para calcular la corriente es:

Donde sensibilidad=0.139 V/A

Con estos nuevos valores debemos trabajar los ejemplos anteriores

Tener en cuenta que cada sensor tiene su propia característica

Otra forma puede ser en tomar varios puntos y al final aplicar regresión y hallara la ecuación de la recta.

 

 

Con estos dos valores  contemplados en el programa, toca  ejecutar el programa  y observar la salida  del monitor serie    en función de cuando activamos el descodificador  y lo apaguemos . En nuestro caso , las lecturas son inferiores a 0.207 cuando esta en stand-bye    , superando este valor  cuando esta encendido

Estos valores   son precisamente  los que podemos usar como umbral  para activar o desactivar un pin de salida  por ejemplo para activar/desactivar  un rele que  a su vez alimente  al TV

Con todos estos cambios , el código final del programa que detecta  si se enciende o no el descodificador es el siguiente:

 

 

const int sensorPin = A0; // seleccionar la entrada para el sensor
int sensorValue; // variable que almacena el valor raw (0 a 1023)
float value;
float Sensibilidad=0.185; //sensibilidad en Voltios/Amperio para sensor de 5A

void setup() {

// Iniciamos comunicacion serie
Serial.begin(9600);
}


void loop() {

float I=get_corriente(200000);//obtenemos la corriente promedio de 500 muestras

if (I<0.207)
{Serial.print(«Apagado: «);  // aqui podemos desactivar un pin binario de salida  para deactivar  un rel
Serial.println(I,3);
delay(100);
}
else
{Serial.print(«Encendido: «);// aquí podemos activar un pin binario de salida  para activar  un relé
Serial.println(I,3);
delay(100);
}


}


float get_corriente(int n_muestras)
{
float voltajeSensor;
float corriente=0;
for(int i=0;i
{
voltajeSensor = analogRead(sensorPin) * (5.0 / 1023.0);////lectura del sensor
corriente=corriente+(voltajeSensor-2.5)/Sensibilidad; //Ecuación para obtener la corriente
}
corriente=corriente/n_muestras;
return(corriente);
}

// cambio de escala entre floats
float fmap(float x, float in_min, float in_max, float out_min, float out_max)
{
return (x – in_min) * (out_max – out_min) / (in_max – in_min) + out_min;
}

 

 

 

Como emular un mando con Arduino


A veces   puede ser  interesante emular del comportamiento  de un mando infrarrojo  con el fin de automatizar procesos  que de otra manera  seria mucho mas complejo . Como ejemplo típico de dispositivos que podemos controlar vía infrarojos, hablamos de  reproductores de cámaras, televisores, DVD, VCR, lectores de blueray, equipos de sonidos, descodificadores  y  un largo etcétera 

Aunque pueda parecer descabellado repetir las mismas señales desde una placa Arduino , lo cierto  es que no es descabellado querer emular este comportamiento , porque  podemos  hacer cosas  que seria muy dificultoso  sin la ayuda del procesamiento de señales de infrarojos como por ejemplo  encender automáticamente  el Aire Acondicionado  cuando la temperatura  suba un determinado valor , o se desconecte a una determinadas horas ,  se apague  cuando no haya movimiento  y un largo  etcétera 

Como paso previo  debemos analizar las señales infrarrojas emitidas por el mando usado para el control de ese dispositivo  por lo que deberemos averiguar  cómo recibir los códigos y luego una vez conocidas intentar ver como transmitirlas.

Para nuestra tarea necesitamos :

  • 1 x Arduino (cualquier versión sirve  siempre que pueda procesar señales  «PWM» )
  • 1 x LED IR   (usted puede conseguir éstos de cualquier TV remoto)
  • 1 x receptor IR (usted puede conseguir éstos de cualquier TV remoto)

 

Preparación para recibir señales

Para el análisis  de las señales infrarrojas  producidas por el mando del  dispositivo a controlar en primer lugar necesitaremos  un receptor de infrarrojos ,   que bien  puede proceder de   uno reciclado de cualquier viejo proyecto que ya no utilice  o bien adquirido específicamente  en el comercio

Una interesante opción son los famosos kits para Arduino que integran por unos 4€  todo los necesario para habilitar la comunicación en los dos sentidos  gracias a un led IRDa, un receptor IRDA  y un mando para pruebas.

Kit Modulo Receptor Infrarojo IR Protocolo Nec con Mando a Distancia Arduino

Como sugerencia  para captar el código correcto , deberíamos poner el receptor IR y el mando en una caja opaca  o algo que sea oscuro  lo cual  asegurará que habrá el mínimo de interferencias y  podremos tener el código más claro para que no tengamos que programar  nuestro  Arduino  muchas veces para una simple tarea. También, asegúrese de que estar alejados de personas viendo la televisión.

Realmente el circuito es bastante sencillo pues únicamente tendremos que alimentar con 5v DC  ( que podemos tomar directamente desde nuestro Arduino )   y luego conectar la salida del receptor digital al pin digital A2 de Arduino

 

Una vez montado el simple circuito del receptor de infrarrojo es hora de  subir el programa a su Arduino  para  poder descodificar la señal infrarroja .

El siguiente programa utiliza el Arduino y un PNA4602 para descifrar IR recibido lo cual se  puede utilizar para hacer un receptor de infrarrojos. (buscando un código en particular) o transmisor (pulsando un LED IR a ~ 38KHz para el duraciones detectadas,

Este código es de dominio público (visite http://www.ladyada.net y adafruit.com), pero en esta ocasión se ha traducido para que sea mas legible y fácil de entender:


// Necesitamos usar los métodos de lectura de pin ‘raw’  porque el tiempo es muy importante aquí y el digitalRead () es un  procedimiento s más lento!

IRpin_PIN PIND
IRpin 2

// el pulso máximo que escucharemos: 65 milisegundos es mucho tiempo
MAXPULSE 65000

// lo que debería ser nuestra resolución de tiempo, más grande es mejor ya que es más ‘preciso’ – pero demasiado grande y no se conseguirá  tiempo exacto
RESOLUTION 20

// almacenaremos hasta 100 pares de pulsos (esto son muchos )
uint16_t pulses[100][2]; // par es pulso alto  y bajo 
uint8_t currentpulse = 0; // indice para pulsos que estamos almacenando

void setup(void)

{
Serial.begin(9600);
Serial.println(«Ready to decode IR!»);
}

void loop(void)

{

// tiempo de almacenamiento temporal
uint16_t highpulse, lowpulse;

//empezar sin pulso 
highpulse = lowpulse = 0;

//esto es demasiado lento!
while (IRpin_PIN & (1 << IRpin)) {
// pin esta a nivel alto

// continúa otros microsegundos
highpulse++;
delayMicroseconds(RESOLUTION);

// Si el pulso es demasiado largo, ‘se agotó el tiempo’ – o bien nada / se recibió o el código está terminado, así que imprima lo que  hemos obtenido hasta ahora, y luego reiniciamos
if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
printpulses();
currentpulse=0;
return;
}
}
// no nos detuvimos, así que escondamos la lectura
pulses[currentpulse][0] = highpulse;

// lo mismo que arriba
while (! (IRpin_PIN & _BV(IRpin))) {
// pin esta aun bajo
lowpulse++;
delayMicroseconds(RESOLUTION);
if ((lowpulse >= MAXPULSE) && (currentpulse != 0)) {
printpulses();
currentpulse=0;
return;
}
}
pulses[currentpulse][1] = lowpulse;

// leemos un pulso alto-bajo con éxito, ¡continuamos!
currentpulse++;
}

void printpulses(void) {
Serial.println(«\n\r\n\rReceived: \n\rOFF \tON»);
for (uint8_t i = 0; i < currentpulse; i++) {
Serial.print(pulses[i][0] * RESOLUTION, DEC);
Serial.print(» usec, «);
Serial.print(pulses[i][1] * RESOLUTION, DEC);
Serial.println(» usec»);
}
}


Una vez que hemos subido el código anterior  y  todo está configurado correctamente, abrir el serial monitor haciendo clic en el botón en el programa de Arduino que es el botón de un círculo en la imagen y  ya estára en marcha así que ahora usted necesitará encontrar un control remoto que desee usar para controlar algo con Arduino

El proceso  esquemáticamente  a seguir es el siguiente :

  1. Encontrar el mando a distancia del dispositivo  que quiere controla
  2. Ejecutar el código del  receptor anteriormente citado
  3. Presione el botón del mando cuyo  código desea obtener 
  4. Ver el Monitor Serial
  5. Pegar el todo el código del monitor serie  en un editor de texto 
  6. Repetir los paso 3, 4 6  con todos los botones del mando que desee descodificar 

 Interpretando las señales

Una vez siga la secuencia de paso anteriores recibirá un montón de números seguidos por «usecs» o «usec».
Asegúrese de que ha copiado la señal que se desea formateando la salida para más fácil referencia.

Se verá algo como esto:
500 usec, 300 usec
600 usec, usec 1200

Pero habrá números mucho más que eso.

Ahora en el programa emisor  verá esto bastantes veces:

delayMicroseconds();
pulseIR();

Es decir tenemos que  tomar el primer número y poner paréntesis en delayMicroseconds(«here»); el  valor obtenido en el monitor
y a su vez   tomar el segundo número de la misma línea como el de la delayMicroseconds()  valorar y poner en el paréntesis de pulseIR(); valor.

Veamos otro ejemplo .Si conseguimos esto en el monitor serial:

OFF ON
1660 usec, usec 580
1640 usec, usec 560

Ahroa para poner los  correspondiente valores en sus áreas correspondientes lo haremos asi :

delayMicroseconds(1660);
pulseIR(580);
delayMicroseconds(1640);
pulseIR(560);

Como puede apreciar ,la  tarea de transcripción  es muy fácil.

Una vez que tenga los códigos que desee, abra un nuevo  archivo IR_SEND.pde en el programa de Arduino y luego tendremos que  poner  los valores que tiene del monitor de serie entre paréntesis haciéndolo  del mismo modo  que hemos visto anteriormente .

Ahora, una vez que tenemos los códigos que desea y haya cargado el programa con la señal que desea enviar, todo lo que tiene que hacer es conectar el LED IR al pin 13 y luego a tierra  No necesita la resistencia si tiene un Duemilanove Arduino porque tiene una resistencia integrada para PIN 13, por lo que no tiene que preocuparse.


Como ejemplo veamos este código cuando se presiona el botón para subir el canal en un  control remoto de Comcast. . Aquí está el código de Serial Monitor: Recibido:

OFF  ON
36328 usec, 280 usec
820 usec, 300 usec
1580 usec, 320 usec
640 usec, 240 usec
2740 usec, 240 usec
1280 usec, 240 usec
1240 usec, 240 usec
1120 usec, 240 usec
2600 usec, 240 usec
12740 usec, 240 usec
840 usec, 240 usec
980 usec, 240 usec
700 usec, 240 usec
700 usec, 240 usec
720 usec, 240 usec
2460 usec, 260 usec
700 usec, 240 usec
700 usec, 240 usec
14904 usec, 260 usec
820 usec, 240 usec
1660 usec, 240 usec
700 usec, 260 usec
2740 usec, 240 usec
1240 usec, 240 usec
1260 usec, 240 usec
1100 usec, 240 usec
2620 usec, 240 usec
12720 usec, 260 usec
840 usec, 220 usec
2080 usec, 240 usec
1780 usec, 260 usec
700 usec, 240 usec
700 usec, 240 usec
2480 usec, 240 usec
700 usec, 240 usec
700 usec, 240 usec

Aquí está el código realizado a partir de los datos en bruto anteriores  pero no se  asociado al código  

En el siguiente  programa   se ha introducido  un detalla original ; Arduino cambiará el canal cada diez segundos para que se puedan hacer otras cosas , Por ejemplo mientras se ve televisión y esta haciendo otras cosa  así  no tendrá que cambiar el canal de modo que el sw  recorrerá los canales para que tenga las manos libres. (todos sabemos que presionar un botón es tan difícil, ¿por qué no hacerlo de forma automática?)

 

He aquí el programa realizado por Wally_Z:


int IRledPin =  13;    // LED conectado al pin digital 13

// El método setup () se ejecuta una vez, cuando comienza el boceto

void setup()   {               
  // initializa  el pin como salida :
  pinMode(IRledPin, OUTPUT);     

  Serial.begin(9600);
}

void loop()                    
{
  SendChannelUpCode();

  delay(20*1000);  // espera veinte segundos (20 segundos * 1000 milisegundos) Cambia este valor para diferentes intervalos.

}

// Este procedimiento envía un pulso de 38KHz al IRledPin  para un cierto  numero de microsegundos. Usaremos esto siempre que tengamos que enviar códigos.

void pulseIR(long microsecs)

{
  // contaremos desde la cantidad de microsegundos que se nos dice que esperemos

  cli();  // esto apaga cualquier interrupción de fond

  while (microsecs > 0) {
   // 38 kHz tiene aproximadamente 13 microsegundos de alto y 13 microsegundos de bajo
   digitalWrite(IRledPin, HIGH);  //Esto lleva alrededor de 3 microsegundos
   delayMicroseconds(10);         // esperar 10 microseconds
   digitalWrite(IRledPin, LOW);   // esto toma sobre 3 microseconds
   delayMicroseconds(10);         // esperar   10 microseconds

   // asi que  26 microseconds  todo junto
   microsecs -= 26;
  }

  sei();  // esto devuelve el control
}

void SendChannelUpCode()

{
  // Este es el código para CHANNEL + para TV COMCAST.
 
  delayMicroseconds(36328);      //Tiempo libre (columna IZQUIERDA)      
  pulseIR(280);                               //Tiempo en (columna DERECHA) <——- NO MEZCLAR ESTOS ARRIBA
  delayMicroseconds(820);
  pulseIR(300);
  delayMicroseconds(1580);
  pulseIR(320);
  delayMicroseconds(640);
  pulseIR(240);
  delayMicroseconds(1280);
  pulseIR(240);
  delayMicroseconds(1240);
  pulseIR(240);
  delayMicroseconds(1120);
  pulseIR(240);
  delayMicroseconds(2600);
  pulseIR(240);
  delayMicroseconds(12740);
  pulseIR(240);
  delayMicroseconds(840);
  pulseIR(240);
  delayMicroseconds(980);
  pulseIR(240);
  delayMicroseconds(700);
  pulseIR(240);
  delayMicroseconds(700);
  pulseIR(240);
  delayMicroseconds(720);
  pulseIR(240);
  delayMicroseconds(2460);
  pulseIR(240);
  delayMicroseconds(700);
  pulseIR(240);
  delayMicroseconds(700);
  pulseIR(240);
  delayMicroseconds(14904);
  pulseIR(240);
  delayMicroseconds(820);
  pulseIR(240);
  delayMicroseconds(1600);
  pulseIR(240);
  delayMicroseconds(700);
  pulseIR(260);
  delayMicroseconds(2740);
  pulseIR(240);
  delayMicroseconds(1240);
  pulseIR(240);
  delayMicroseconds(1260);
  pulseIR(240);
  delayMicroseconds(1100);
  pulseIR(240);
  delayMicroseconds(2620);
  pulseIR(240);
  delayMicroseconds(12720);
  pulseIR(260);
  delayMicroseconds(840);
  pulseIR(220);
  delayMicroseconds(2080);
  pulseIR(240);
  delayMicroseconds(1780);
  pulseIR(260);
  delayMicroseconds(700);
  pulseIR(240);
  delayMicroseconds(700);
  pulseIR(240);
  delayMicroseconds(2480);
  pulseIR(240);
  delayMicroseconds(700);
  pulseIR(240);
  delayMicroseconds(700);
  pulseIR(240);
}

 

Via Instrucables.com