DMX Shield

Este shield nos permitirá conectar una placa Arduino a una red de datos DMX, como las usadas en sistemas de iluminación. Podemos consultar las características en la página Conceptinetics o, si el enlace no está disponible desde aquí.

Tendríamos a grandes rasgos una placa que:
- Funciona a 5V
- Chip de adaptador de señal: MAX485
- No está isolada
- Funciona con diferentes librerías DMX
- Tiene integrados dos conectores DMX tipo XLR de 3 pines

CARACTERISTICAS

Como se ha comentado, este modelo de shield lleva el chip MAX485 de la casa Maxim (datasheet). La función de este chip es convertir los nieveles de tensión en la red DMX, a valores 0-5V entendibles por la placa Arduino.
Este shield se conectará mediante sus pines, específicamente diseñados mas largos de lo normal, a la placa arduino (UNO y MEGA por ejemplo), quedando colocado encima de esta.
Para programar este shield usaremos la librería DMX Library desarrollada por el fabricante del shield o, cualquier otra compatible. En el ejemplo que montaremos explicaré algunos cambios que necesitaremos hacer en la librería para que funcione correctamente.
Lleva dos conectores XLR soldados directamente a la placa. Aunque la entrada sería la hembra y la salida el macho, podemos usarlos indistintamente. Recordemos que la placa no está isolada, por lo que comparte tierra con el sistema DMX al que lo conectemos.

PINEADO

Sorprendentemente este shield tiene soldados los conectores XLR (neutrik) de entrada/salida de la señal DMX como podemos ver en la imagen de la derecha.
El pineado de estos conectores es el estándar:
Pin 1: Masa
Pin 2: Data -
Pin 3: Data +
No tenemos más conectores de este shield, ya que su principal función es que la placa Arduino interprete la señal si estamos configurados como receptor o la genere si estamos como emisor DMX.

BOTONES

Este shield de la marca Conceptinetics y modelo CTC-DRA-10-1, no tiene ningún botón disponible en su superficie.

LED's INDICADORES

Igualmente tampoco tiene ningún indicador led.

JUMPER

Este shield tiene cuatro jumper para configurarlo y su función es la siguiente:
Jumper EN - /EN: Este jumper habilita o desabilita el shield completamente.
Su función básicamente es permitir programar el Arduino al cual ha sido pinchado, ya que en la mayoría de los casos usaremos la uart del Arduino (en nuestro caso asi será) y en el caso por ejemplo del Arduino UNO solo tenemos una uart. Evidentemente mientras esta el jumper en la posición /EN, el shield estará desactivado, por lo que podremos usar la uart del Arduino UNO para las tareas habituales, como programarlo.
Una vez programado el sketch ponemos el jumper en la posición EN y en este momento el shield se habilita de nuevo y toma el control de la uart del Arduino UNO para mandar o recibir los datos de la señal DMX.
Mientras estemos en este estado y el shield habilitado y funcionando, el Arduino UNO no podrá ser programado ni podremos enviar o recibir comunicación serie (ordenes Serial) desde el IDE. Pero OJO, hay una excepción a esto, y se verá en los dos últimos jumper.

Jumper Slave - DE: Este jumper define si el shield es un receptor DMX siempre o lo podemos elegir desde nuestro programa.
Cuando esta en la posición Slave tenemos el shield esclavizado para trabajar solo como receptor DMX independientemente de lo que diga el sketch. SOLO funcionara como receptor.
Si lo ponemos en la posición DE estamos habilitando el pin 2 del shield para que desde nuestro programa podamos definir si la placa es receptora o emisora de señal DMX. En nuestro ejemplo lo usaremos y tendremos que informar a la librería del pin usado para esta función (en nuestro caso la constante RXEN_PIN que veremos mas adelante en el ejmeplo)

Jumper TX-io - TX-uart: Este jumper define si vamos a usar la uart por defecto para la transmisión, o un pin aparte para generar una uart por software.
Cuando esta en la posición TX-uart la linea de transmisión será el pin 1, que es la salida de la uart del Arduino UNO. Esta será la posición más normal ya que usará la uart incluida en la placa Arduino.
Si lo ponemos en la posición TX-io estaremos mandando la linea de transmisión por el pin 4. Este pin es una entrada/salida normal y no va destinada a ninguna uart de la placa Arduino. Para que funcione deberemos programar una uart en nuestro sketch, pero esto lo veremos en otro montaje.

Jumper RX-io - RX-uart: Este jumper define si vamos a usar la uart por defecto para la recepción, o un pin aparte para generar una uart por software.
Cuando esta en la posición RX-uart la linea de recepción será el pin 0, que es la entrada a la uart del Arduino UNO. Esta será la posición más normal ya que usará la uart incluida en la placa Arduino.
Si lo ponemos en la posición RX-io estaremos mandando la linea de recepción por el pin 3. Este pin es una entrada/salida normal y no va destinada a ninguna uart de la placa Arduino. Para que funcione deberemos programar una uart en nuestro sketch, pero esto como la anterior lo veremos en otro montaje.


PROBEMOS EL DMX SHIELD

Ahora viene lo más importante. Vamos a probar nuestro DMX Shield conectándolo a un Arduino UNO R3 y programándolo como generador de DMX. Vamos a generar solo diez canales DMX y modificaremos tres de ellos. El canal 1 y 2 llevara el estado de dos pulsadores (pulsado=255 y no pulsado=0) y el canal 3 llevara el valor leído de un potenciómetro por una entrada analógica (entre 0 y 255) e igualmente encenderemos el led del pin 13 cuando el valor leído del potenciómetro sea mayor de cero.
Esto nos dará una idea de si nuestro shield funciona correctamente y podremos seguir avanzando en su programación para otros proyectos.

Lo primero será descargarnos la librería que recomienda el fabricante del shield y ver una modificación que podemos hacer en ella, ademas de ver como se instala en el ordenador para que aparezca correctamente en el IDE y podamos usarla.
Iremos a la página web: DMX Library for Arduino y descargaremos la última versión de la ibrería, en el momento de escribir estas lineas es la versión 3.2Alpha. Si no funciona descargaremos esta versión desde aquí.

Una vez descargada tenemos varias opciones para instalarla o añadirla a nuestro IDE y poder usarla en los sketch que realicemos. En mi caso descomprimo el ZIP y genera el árbol de carpetas que vemos a la izquierda. Esta carpeta principal "Conceptinetics" la copiaremos, dependiendo del sistema operativo que usemos, en uno de los siguientes lugares:
Windows 10: soltaremos esta carpeta en "Documentos/Arduino/libraries"
MacOs: soltaremos esta carpeta en "Documentos/Arduino/libraries"
Linux Ubuntu 16.04: soltaremos esta carpeta en "Carpeta personal/Arduino/libraries"
Podemos ver en el video, al final de la página, mas detalladamente como se copia la librería en su sitio.

Una vez copiada la librería ya tenemos el IDE preparado para utilizar fácilmente el shield como generador o receptor DMX.
Solo debemos conocer una caracteristica de la librería y es la posibilidad de poder elegir la uart de la placa Arduino que vamos a usar para comunicarnos con el Shield DMX. Abrimos con un editor de textos el archivo "Conceptinetics.h" que tenemos en la carpeta de la librería. Buscamos las lineas de configuración que vemos en la imagen de la derecha y comprobamos que la librería esta diseñada para poder comunicarse con placas Arduino con hasta 4 uart (como por ejemplo la MEGA2560).
Tenemos estas cuatro lineas de código de las cuales solo tiene que estar activa una de ellas. En el ejemplo que vamos a realizar vamos a usar una placa Arduino UNO y solo tiene una uart, por lo que dejamos activa la linea "#define USE_DMX_SERIAL_0", que indica a la librería que usaremos la primera y única uart de la placa Arduino UNO. Las otras tres lineas las dejaremos con las barras dobles para que no se ejecuten.

ESQUEMA

En es esquema podemos ver:
- Un Arduino UNO R3 que estará alimentado por el ordenador a través del puerto USB.
- Un Shield DMX pinchado encima del Arduino UNO.
- Tendremos una placa protoboard con los siguientes componentes:
• Un potenciómetro de 4K7 conectado entre Vcc y masa para usarse como divisor de tensión y conseguir en su pin central un voltaje entre 0 y 5V. Esto lo mandamos a la entrada AD0 del Arduino UNO para ser leído y poder usarlo en nuestro sketch.
• Dos resistencias de 2K7 que llevan a masa las entradas 8 y 9 del Arduino UNO y un pulsador en cada una para llevar a nivel alto cuando los pulsemos.


Este es el montaje terminado

PROGRAMACIÓN

A continuación tenemos el código fuente del Sketch terminado para consultarlo. Se puede escribir copiándolo o descargarlo desde aquí

CÓDIGO ARDUINO
/*
  DMX_Master.ino - Example code for using the Conceptinetics DMX library
  Copyright (c) 2013 W.A. van der Meeren <danny@illogic.nl>.  All right reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 3 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

// Cargo la librería para poder usarla
#include <Conceptinetics.h>


//
// CTC-DRA-13-1 ISOLATED DMX-RDM SHIELD JUMPER INSTRUCTIONS
//
// If you are using the above mentioned shield you should 
// place the RXEN jumper towards pin number 2, this allows the
// master controller to put to iso shield into transmit 
// (DMX Master) mode 
//
//
// The !EN Jumper should be either placed in the G (GROUND) 
// position to enable the shield circuitry 
//   OR
// if one of the pins is selected the selected pin should be
// set to OUTPUT mode and set to LOGIC LOW in order for the 
// shield to work
//


//
// The master will control 100 Channels (1-100)
// 
// depending on the ammount of memory you have free you can choose
// to enlarge or schrink the ammount of channels (minimum is 1)
//
// Este es el número de canales que vamos a transmitir. Puede ser desde 1 a 512.
// En nuestro montaje solo vamos a transmitir 10 canales (1 al 10)
#define DMX_MASTER_CHANNELS   10 

//
// Pin number to change read or write mode on the shield
//
// Definimos el número de pin que controla el modo de funcionamiento del shield (lectura o escritura)
#define RXEN_PIN                2

// Defino las constantes y variables que luego usaré en el programa
const int pulsador1=8;        //pin donde conectaremos el pulsador que activará el canal 1
const int pulsador2=9;        //pin donde conectaremos el pulsador que activará el canal 2
const int potenciometro=A0;   //pin donde conectaremos el potenciómetro que activará el canal 3
int valor_pot=0;              //inicializamos la variable que leerá el valor del potenciómetro


// Configure a DMX master controller, the master controller
// will use the RXEN_PIN to control its write operation 
// on the bus
// Configura el sistema como Master para generar la señal de DMX
DMX_Master        dmx_master ( DMX_MASTER_CHANNELS, RXEN_PIN );


// the setup routine runs once when you press reset:
void setup() {             

  // Configuramos los pines de entrada y salida
  pinMode(pulsador1,INPUT);
  pinMode(pulsador2,INPUT);
  pinMode(LED_BUILTIN,OUTPUT);  //recordar que LED_BUILTIN es el pin donde está el led integrado
                                //normalmente en el pin 13
  
  // Enable DMX master interface and start transmitting
  // Habilita la placa y comienza la transmisión
  dmx_master.enable ();  
  
}

// the loop routine runs over and over again forever:
void loop() 
{
  // Leemos el estado de los pulsadores y el potenciómetro
  int pulsador_1 = digitalRead(pulsador1);
  int pulsador_2 = digitalRead(pulsador2);
  valor_pot = analogRead(potenciometro);

  valor_pot = map(valor_pot, 0, 1023, 0, 255); //mapeamos los valores leidos en el rango 0-1023 al rango 0-255

  //mandamos el valor del potenciómetro al canal 3 del DMX
  dmx_master.setChannelValue (3, valor_pot);

  //encendemos el led del arduino cuando el potenciómetro esta a más de 0
  if (valor_pot == 0)
  {
      digitalWrite(LED_BUILTIN,LOW);
  }
  else
  {
      digitalWrite(LED_BUILTIN,HIGH);
  }
    
  //si el pulsador 1 está pulsado el valor del canal 1 será 255
  if (pulsador_1)
  {
      dmx_master.setChannelValue (1, 255);
  }
  else  //si no será de 0
  {
      dmx_master.setChannelValue (1, 0);
  }

  //si el pulsador 2 está pulsado el valor del canal 2 será 255
  if (pulsador_2)
  {
      dmx_master.setChannelValue (2, 255);
  }
  else  //si no será de 0
  {
      dmx_master.setChannelValue (2, 0);
  }

}

CÓDIGO ARDUINO

SISTEMAS DMX

Antes de seguir vamos a hacer una breve explicación del protocolo DMX.
En un sistema DMX (Digital Multiplex) solo puede haber un generador o master que genera el flujo de datos en el sistema. En un sistema DMX estándar podemos transmitir hasta 512 canales independientes. Esto no significa que tengamos que transmitirlos todos, también podemos transmitir, por ejemplo solo 10 canales (como en nuestro caso).
El proceso de transmisión es bastante sencillo, básicamente se transmiten uno detrás de otro: el número de canal y su valor asociado. Detectar que el transmisor no es consciente de si estos datos son recibidos por el aparato o sistema receptor, simplemente los transmite y cada receptor ya cojera el canal que necesite y su valor. Lo normal es que los receptores tengan asignado un número de canal sin repetirse y podamos controlarlos independientemente, aunque tenemos al opción de asignar a dos o más receptores el mismo valor de canal y que reaccionen al mismo tiempo los dos.

EXPLICACIÓN CÓDIGO

Lo primero es cargar la librería:

// Cargo la librería para poder usarla
#include <Conceptinetics.h>

Con esta linea estamos cargando en el IDE la librería que instalamos para que este disponible en nuestro Sketch.
Ahora vamos a definir dos constantes basadas en el comando #define para asignarles el valor del número de canales a transmitir y el número de pin que usa el Shield para pasar de modo master o transmisor a modo esclavo o receptor.

// Este es el número de canales que vamos a transmitir. Puede ser desde 1 a 512.
// En nuestro montaje solo vamos a transmitir 10 canales (1 al 10)
#define DMX_MASTER_CHANNELS   10

// // Pin number to change read or write mode on the shield
// // Definimos el número de pin que controla el modo de funcionamiento del shield (lectura o escritura)
#define RXEN_PIN                2

Esto tiene la ventaja de poder usar las constantes en el programa y si mas adelante las queremos modificar, solo tendremos que hacerlo en la declaración de los #define y no hacerlo en todo el programa.
Lo siguiente es definir tres constantes y una variable tipo int.

// Defino las constantes y variables que luego usaré en el programa
const int pulsador1=8;            //pin donde conectaremos el pulsador que activará el canal 1
const int pulsador2=9;            //pin donde conectaremos el pulsador que activará el canal 2
const int potenciometro=A0;   //pin donde conectaremos el potenciómetro que activará el canal 3
int valor_pot=0;                    //inicializamos la variable que leerá el valor del potenciómetro

Como vemos hemos asignado los pines e entrada de los pulsadores (8 y 9), pin de entrada de la lectura analógica del potenciómetro (A0) y se a preparado una variable para almacenar el valor leído del potenciómetro, que ademas se a inicializado con el valor 0.
Lo siguiente es inicializar y configurar el controlador DMX_Master con las constantes que hemos definido al principio:

// Configura el sistema como Master para generar la señal de DMX
DMX_Master        dmx_master ( DMX_MASTER_CHANNELS, RXEN_PIN );

Aquí hemos creado el controlador dmx_master (podríamos haber elegido cualquier otro nombre) del tipo DMX_Master (este tipo de controlador esta definido en la librería) con las variables que nos pide (número de canales y pin de lectura/escritura). Ahora el controlador dmx_master esta creado y listo para usarse en todo el Sketch.
Dentro de nuestro void setup vamos a informar a la placa Arduino de, en el caso de los pines, si son de entrada o salida. Ademas usaremos nuestro primer comando del controlador dmx_master para indicarle que empiece a transmitir desde este momento. El código queda así:

void setup() {             
 // Configuramos los pines de entrada y salida
 pinMode(pulsador1,INPUT);
 pinMode(pulsador2,INPUT);
 pinMode(LED_BUILTIN,OUTPUT);  //recordar que LED_BUILTIN es el pin donde está el led integrado
                                                   //normalmente en el pin 13

 // Enable DMX master interface and start transmitting
 // Habilita la placa y comienza la transmisión
 dmx_master.enable ();  
}

Hecho esto hemos terminado con el void setup y pasamos al programa que se repetira mientras tengamos el Arduino encendido, y como ya sabemos es el código que se encuentra dentro de las llaves de void loop.
Lo primero es leer el estado de los pulsadores y del potenciómetro y mapear el valor leído al rango que nos interesa. Ponemos el código y lo comentamos después:

 // Leemos el estado de los pulsadores y el potenciómetro
 int pulsador_1 = digitalRead(pulsador1);
 int pulsador_2 = digitalRead(pulsador2);
 valor_pot = analogRead(potenciometro);
 valor_pot = map(valor_pot, 0, 1023, 0, 255); //mapeamos los valores leidos en el rango 0-1023 al rango 0-255

- La primera linea lee el valor digital (0-1) de la entrada definida por la constante "pulsador1" (entrada 8) y se la asigna a una variable tipo int que acabamos de crear llamada "pulsador_1".
- La segunda linea hace lo mismo con la entrada 9 y almacena el valor leido en la variable "pulsador_2".
- La tercera linea lee el valor analógico de la entrada definida por la constante "potenciometro" (entrada A0) y se asigna a la variable que creamos antes para almacenar este valor leído llamada "valor_pot".
El valor que acabamos de leer al tener una profundidad de 10bits, puede ir desde 0 a 1023, una vez convertido el valor analógico leído a su valor digital por el conversor A/D del Arduino UNO. Como los valores de los canales DMX solo pueden ir desde 0 a 255, vamos a adecuar el valor leído a este rango. Para ello usaremos la función map que recibe cinco parámetros (valor a convertir, rango de entrada y rango de salida) y devuelve el valor convertido, que volvemos a grabar en la misma variable en la que almacenamos el valor leído.
Con esto ya tenemos leídos los valores de los pulsadores y del potenciómetro, ademas este último mapeado al valor adecuado para asignarlo a un canal DMX.
Ahora vamos a definir que canales vamos a modificar con los valores que tenemos disponibles:
- El canal 1 del DMX llevará la información del pulsador 1: valor=0 si el pulsador esta sin pulsar y valor=255 si esta pulsado.
- El canal 2 del DMX llevará la información del pulsador 2: valor=0 si el pulsador esta sin pulsar y valor=255 si esta pulsado.
- El canal 3 del DMX llevará la información del potenciómetro: valores de 0 a 255 segun lo ajustemos.
Según esta última premisa el siguiente código mandará el valor del potenciómetro al canal 3 como habíamos previsto:

 //mandamos el valor del potenciómetro al canal 3 del DMX
 dmx_master.setChannelValue (3, valor_pot);

Ahora solo nos queda mandar los valores 0 o 255 a los canales 1 y 2 del DMX según el estado de los pulsadores y esto lo conseguimos con el siguiente código:

 //encendemos el led del arduino cuando el potenciómetro esta a más de 0
 if (valor_pot == 0)
 {
     digitalWrite(LED_BUILTIN,LOW);
 }
 else
 {
     digitalWrite(LED_BUILTIN,HIGH);
 }

     //si el pulsador 1 está pulsado el valor del canal 1 será 255
 if (pulsador_1)
 {
     dmx_master.setChannelValue (1, 255);
 }
 else  //si no será de 0
 {
     dmx_master.setChannelValue (1, 0);
 }

 //si el pulsador 2 está pulsado el valor del canal 2 será 255
 if (pulsador_2)
 {
     dmx_master.setChannelValue (2, 255);
 }
 else  //si no será de 0
 {
     dmx_master.setChannelValue (2, 0);
 }

Al principio de este pequeño trozo de código tenemos una parte que se encarga de encender el led de la salida digital 13 del Arduino UNO. Así podemos ver si el código esta corriendo sin problemas y no se ha quedado colgado. La condición que miramos es, cuando el valor del potenciómetro es igual a 0. Cuando sea 0 y solo 0 el led estará apagado, en cualquier otro valor o sea desde 1 a 255, el led estará encendido.
Después tenemos dos condicionales if-else que se encargan de enviar el valor correcto a los canales 1 y 2 dependiendo del estado de los pulsadores.

Con esto ya tenemos el sketch terminado y lo podemos enviar de la manera habitual.

Enviando el Sketch...

Una vez enviado tenemos las placas funcionando y generando una señal DMX válida para que cualquier aparato o receptor DMX la interprete. En el siguiente vídeo podemos ver el proceso completo.