Luces de colores en Windows 10 IoT Core con la librería PWM

En el artículo de este mes vamos a conectar un LED RGB a nuestro dispositivo IoT y desarrollaremos una aplicación para asignar un color de la paleta al LED.

Introducción

Cuando conectamos un LED al bus GPIO  de nuestro dispositivo IoT, el código que escribimos para gestionar ese LED puede hacer dos cosas: encender o apagar el LED. En el caso de utilizar un LED RGB podremos encender y apagar los 3 diodos que lleva el LED. Si recordamos un poco nuestras clases de combinatoria esto nos da un total de 23 colores diferentes:

 000  100  010  110
 001  101  011  111

Con sólo 8 colores no nos acercamos a los 16 millones de colores que tenemos en la paleta RGB, sobretodo sabiendo que si controlamos la intensidad de cada uno de los diodos por separado podríamos tener infinidad de tonos de color. Para hacer esto existen diferentes técnicas. Hace muchos años se utilizaba una técnica llamada Resistor Ladder que consiste en conectar una salida en paralelo a una ristra de resistencias combinadas de tal manera que cada “bit” suma un valor de voltaje según la posición en la que está:

Resistor Ladder DAC

Esto es útil en el caso de que quieras hacer un "Poor Man’s DAC"™ (en aquellos años yo era estudiante y las tarjetas de sonido eran muy caras, pero podías hacer sonar tu PC con un conversor casero y los juegos ganaban mucho con sonido real de 8 bits en lugar del buzzer que incorporaban aquellos trastos maravillosos), pero hacer un conversor de este tipo es muy aparatoso y no tiene demasiada precisión.

Ahora que os habéis dado cuenta de lo antiguo que soy vamos a por la segunda opción. Un chip DAC que convierte la señal digital de n bits a una diferencia de potencial. Hoy en día no son muy caros y podríamos poner 3 conversores, pero, igual que en el caso anterior, necesitaríamos tener unos cuantos bits en paralelo para cada LED, de forma que si ocupamos todos los pins del GPIO disponibles nos quedan unos 6 bits por diodo y un cableado un tanto aparatoso. Para no ocupar tantos pines podríamos utilizar el interfaz SPI y un conversor DAC con SPI, pero en la Raspberry Pi sólo tenemos un pin SPI, así que tendríamos que multiplexar y se complicaría el circuito de nuevo.

Simulando una señal analógica con un solo pin

Existe otra técnica que permite simular con un solo pin una señal analógica, utilizada de forma habitual para controlar la velocidad de los motores en robots y también para los amplificadores digitales. Se llama PWM, siglas de Pulse Width Modulation, y consiste en encender y apagar muy rápidamente el pin digital, controlando el porcentaje de tiempo que está el LED encendido y apagado dentro de cada ciclo según el valor que le queramos dar. Gracias a que el cerebro humano no es capaz de distinguir estas diferencias discretas a partir de unos 85Hz (ver POV) percibimos estos pulsos como diferencias de intensidad contínua.

Para esta solución también existen integrados que hacen eso por nosotros, como podemos ver por ejemplo en el FEZ Hat, que lleva una salida PWM. Pero como nosotros somos desarrolladores podemos pensar en otra solución, que es realizarlo directamente por software.

La librería PWM

Aunque podríamos programarlo nosotros fácilmente, disponemos de una librería hecha por el equipo de Windows 10 IoT Core, lista para utilizarla en nuestras aplicaciones universales. Podemos utilizar tanto el paquete de NuGet como descargarnos el código fuente de GitHub en https://www.github.com/ms-iot/BusProviders. Esta librería nos permite utilizar fácilmente algunos módulos de PWM como el PCA9685, o bien hacer la simulación por software. Esto nos permitirá controlar los colores del LED y conseguir muchas más tonalidades.

Al añadir la librería tendremos unas cuantas clases que nos van a permitir trabajar con el LED como si tuvieramos salida analógica:

  • PwmController: es la clase principal que nos permite controlar el chip o software PWM
  • PwmProviderSoftware: esta clase nos permite generar por software un PWM
  • PwmPin: que usaremos en lugar del GpioPin, pues nos da acceso al pin en modo PWM

Abrir y configurar el controlador es tan sencillo como pedir una instancia y a partir del objeto podremos abrir los pins en modo PWM:

 var controller=(await PwmController.GetControllersAsync(PwmProviderSoftware.GetPwmProvider())).FirstOrDefault();
if (controller!= null)
{
    controller.SetDesiredFrequency(100);
    var pinR = controller.OpenPin(5);
    var pinG = controller.OpenPin(13);
    var pinB = controller.OpenPin(6);
    _led = new RgbLed(pinR, pinG, pinB);
    _led.Color = Colors.Green;
    _led.On();
}

El método SetDesiredFrequency nos permite definir los hercios a los que queremos utilizar el pin, es decir, cuántas veces por segundo vamos a encender y apagar el pin para conseguir el efecto que queremos. A más frecuencia, menos se notará el parpadeo del led, aunque en teoría cualquier cosa por encima de los 50Hz ya no deberíamos notarla.

He creado la clase RgbLed para poder configurar y controlar el LED, como con el método que convierte un color a las señales que tenemos que enviar al pin:

 
private void updateLed()
{
    double[] colorValue = new double[] { Color.R, Color.G, Color.B };
    for (int i = 0; i < colorValue.Length; i++)
    {
        colorValue[i] /= 255d;
        _pins[i].SetActiveDutyCyclePercentage(colorValue[i]);
    }
}

Aquí configuro cada uno de los pines con el porcentaje de tiempo en el que va a estar el pin encendido durante cada ciclo, a más valor más intensidad del LED.

Código de ejemplo

El código completo del ejemplo está en mi cuenta de GitHub, podéis hacer un fork y empezar a jugar con todo tipo de dispositivos que sean susceptibles de este uso: motores, buzzers, elecroimanes y un largo etcétera de elementos analógicos.

https://www.github.com/jmservera/RgbLed

¿Quieres aprender más?

En ms-iot hay muchas más librerías que te permitirán llevar tus proyectos de IoT a otro nivel. Si quieres aprender más puedes:

  • Venir a la dotNetConference 2016, el mayor evento que hacemos en España para y por desarrolladores .Net. (si lees esto después del 24 de febrero en la web tendrás las presentaciones del evento)
  • Visitar ms-iot en GitHub y nuestro portal Windows On Devices
  • Para empezar, aquí tienes un vídeo de introducción a IoT Core de nuestros compañeros de México:

Y para acabar, un reto…

Cuando pruebes este código se te ocurrirán muchas cosas. Recuerda que además de tener un UI para controlar las luces también puedes crear una aplicación en Azure que envíe mensajes al dispositivo a través de IoT Hub.

¡Ahora es vuestro turno!

Juan Manuel Servera

Developer eXperience

@jmservera