domingo, 28 de diciembre de 2014

Dimmer con un potenciometro. analogRead()

Hola a todos.

Vamos explicar en esta entrada como hacer un dimmer más "clásico", esta vez con el uso de un potenciómetro.

Potenciómetro


Un potenciometro no es más que una resistencia cuyo valor es variable. ¿Así de sencillo?

Bueno, más o menos, después se pueden clasificar según su construcción, su aplicación, o su ley de variación. Pero no nos extenderemos aquí. Recomiendo la lectura de algún capítulo de electrónica básica, o la búsqueda en internet. La entrada de wikipedia, es muy generalista pero nos puede dar una idea básica de sus usos.
Para nuestra aplicación usaremos un potenciómetro rotatorio lineal de 10kohms. 

En este supuesto  lo usaremos como un divisor de tensión. Es decir, conectaremos un extremo a 5V (Vcc) y el otro a masa (GND). El cursor lo llevaremos a una entrada analógica del Arduino. 
Con este montaje lo que tendremos en la entrada del Arduino es una tensión que oscilará entre los 0 y los 5V.
Con este voltaje que variaremos a voluntad pilotaremos el led de salida. El esquema del montaje es el siguiente:



analogRead ()


Esta función será la que utilizaremos para hacer funcionar nuestro circuito. Como hemos explicado, hemos realizado un montaje que aplicará un voltaje variable a la entrada del Arduino. Ahora toca leerlo para actuar en consecuencia.
Nuestro Arduino , tiene 6 pins que pueden actuar como un convensor analógico-digital de 10 bits. Son los pins que van del A0..A5. Con una resolución de 10 bits, los valores enteros que obtendremos irán del 0 al 1023. 
La resolución en volts, sera 5V/1024 , o sea de 0,0049V o 4,9mV por unidad.
El Arduino necesita 100us para realizar una lectura , por lo que la frecuencia de muestro que obtendremos como máximo es de 10KHz. 
Existen maneras de configurar de manera diferente estas entradas , pero las veremos más adelante, en otras aplicaciones.
La función solo necesita un parámetro y es el pin de entrada, que en el caso del Arduino UNO, será un número entre 0 y 5.
Un curiosidad es que no hace falta configurar el pin como entrada para realizar lecturas, aunque lo más adecuado y siguiendo con el patrón de programación definido hasta ahora, declararemos siempre los pines en la cabecera del programa.

Si picais este programa, vereis en el IDLE , el valor entero del conversor. Cargar el programa, realizar el montaje expuesto, y dentro de herramientas buscar el monitor serial.

Vereis, como si actuais sobre el potenciometro obtenemos diferentes valores en el monitor serial. Han de estar coprendidos entre 0 y 1023. Es posible que por las tolerancias de los componentes no obtengamos los valores extremos.
El programa lo puedes descargar desde aquí.

//Conversor AD, lee la lectura de un potenciometro
// en el pin A0 y nos estrega la lectura
// En el serial monitor
int POT = 0;   //Cursor potenciometro en pin 0.  
int valor = 0; // variable que almacenara el valor

void setup()
{
  Serial.begin(9600);          //  setup serial
}

void loop()
{
  valor = analogRead(POT);  // leemos el potenciometro
  Serial.println(valor);    // lo visualizamos en el monitor serial
}

Muy bien, pero nuestro led no se enciende. Esto no debería ser una sorpresa, no hemos definido ningún puerto de salida, ni actuado sobre ningún pin.

Ahora que hemos visto como actua el  conversor AD y hemos obtenido el valor de la señal de entrada, hay que trasladarlo a nuestra salida, el led.

Aquí nos surge otra dificultad. Si recordáis la entrada donde explicábamos el funcionamiento de la modulación por ancho de pulsos ( PWM aquí). La función analogWrite, esperaba un valor entre 0 y 255. 
Resumiendo, tenemos un convensor AD en la entrada de 10bits, y en la salida de tan solo 8 bits, es decir, solo acepta valores entre 0 y 255. No podemos decir que la salida es "igual " a la entrada, hay que escalarla primero. 
Una de las soluciones más extendidas cuando queremos hacer que la salida sea proporcional a la entrada, como en este caso, es dividir la entrada entre 4 antes de la función analogWrite().

Muy bien, ahora con todo este rollo post-turrones y cava, como quedará el programa. Primero el algoritmo de lo que deseamos:


  1. Capturar la entrada analógica con el conversor AD de 10 bits,
  2. Escalarla dividiendo la entrada entre 4, para preparar la señal para el conversor de 8 bits,
  3. Generar la señal de salida, proporcional a la entrada
  4. Cambiar la salida cada vez que lo haga la entrada, indefinidamente.
Ahora sí, mi propuesta para realizar el ejercicio sería la siguiente:


// Ejemplo Dimmer con un potenciometro
// Conectamos el cursor de un potenciometro
// al pin A0, y sus extremos uno a VCC
// y el otro a GND o masa
// EL led de salida al pin 9 a traves de una
// resistencia de 220 ohmioa

const int LED = 9; // pin para el LED
const int POT = 0; // pin para el pulsador
int brillo = 0;
void setup() 
{
pinMode(LED, OUTPUT); // LED es una salida
pinMode(POT, INPUT); // Entrada analogica
}
void loop() {
 brillo =  analogRead(POT); // leemos la caida de tension en el pot
 brillo = brillo/4; // lo escalamos para el conversor DA
 analogWrite (LED,brillo); // escribimos la salida del PWM
}

Lo puedes descargar desde aquí.
En este ejemplo tenemos mayor control sobre la luminosidad del led que con el pulsador, sin embargo  
siempre existirá un consumo de corriente en el potenciómetro por lo que no es el más eficiente energéticamente.
Esta entrada es  más potente de lo que parece, porque ahora podemos leer cualquier entrada analógica, por tanto todo tipo de sensores que den una respuesta analógica, temperatura, humedad, luminosidad, etc, usan este tipo de procedimiento para leer sus señales. En las siguientes entradas experimentaremos con algunos de ellos.

Os dejo un vídeo con el montaje. Casi se me olvidada mis mejores deseos para el 2015.
¡Feliz año nuevo!



4 comentarios:

  1. Hola David!! estoy haciendo un proyecto (hace ya meses) y me estanque, a ver si puedes ayudarme, estoy haciendo un coche a escala 1:18 y le puse toda la instalación de luces led, mi intención es que funcionen como la iluminación de un coche real, utilizo arduino nano y mando a distancia, me falta por añadir al programa, dos leds, una es la de dentro del habitáculo, cuando abres la puerta se enciende la luz y cuando la cierras se apaga pero, quiero que se apague poco a poco, sabrías como hacer?? yo se hacerlo pero fuera del programa, a la hora de insertarlo, no me sale.
    Gracias

    ResponderEliminar
  2. De forma genérica, llamemos a la variable de la salida de arduino luz_interior. Deberás asignar primero una salida compatible con PWM, digamos la 3.


    Definimos esas variables:

    cons int luz_interior =3;

    En el setup lo definimos:

    pinMode( luz_interior, OUTPUT);
    analogWrite (luz_interior,0);//apagado

    Desde el punto del programa que la quieras encender, deberás hacerlo de la siguiente manera:

    analogWrite (luz_interior,255); //Lo encendemos con un pulso PWM,

    Para apagarlo progresivamente, desde el punto de programa que decides apagarlo inserta algo así:

    for ( x = 255 ; x < 1; x--)

    {
    analogWrite (luz_interior,x);
    microdelay(100);
    }

    Juega con de valor del delay para lograr el efecto de apagado progresivo que buscas.
    Espero que puedas solucionarlo de esta manera.

    Un saludo


    ResponderEliminar
    Respuestas
    1. Muchas gracias por responder David, el caso es que el programa lo tengo con arrays, habría manera de que pudieras ver lo que tengo hasta ahora?? he intentado hacer lo que me dices pero no me ha salido....

      Eliminar
  3. Si quieres puedes pasármelo por mail, a arduinopractico@gmail.com.

    Un saludo

    ResponderEliminar