Decodificadores DCC decoder


DCC_decoder es una librería creada por MynaBay y se puede encontrar en github. La única pega que tiene esta librería es que no es programable desde la vía de programación o desde la vía principal. Pero esto no es un fallo en sí, de hecho también es uno de sus fuertes. Con DCC decoder solo hay dos estados, 1 y 0. Por eso su uso es muy utilizado en desvíos e iluminación

Para hacer uso de la librería, primero tenemos que descargar la librería, y como toda librería de arduino la colocaremos en la carpeta que tengamos asociada a las librerías de Arduino. En mi caso ~/Arduino/libraries/

No creo que haga falta decir que necesita un versión del IDE Arduino 1.6 o superior, pero por si acaso lo comento. Cuando arranquemos el IDE ya podremos empezar a trastear con los ejemplos:

  • DCC_Basic_Acc_Decoder.pde
  • DCC_Monitor.pde

Voy a intentar diseccionar estos archivos para que quede más claro que es lo que hace cada parte.

Archivo DCC_Basic_Acc_Decoder.pde

En la cabecera de este archivo tenemos la llamada a la librería y el número de la interrupción, en este caso la 0


#include <DCC_Decoder.h>

#define kDCC_INTERRUPT		0 // Pin 2

Lo siguiente que encontramos es la estructura de datos que tendrá cada accesorio como la dirección, estado de la salida o si es digital o analógico la estructura es la siguiente:


	typedef struct
{
    int               address;                // Dirección de respuesta
    byte              output;                 // Estado de la salida 1=on, 0=off
    int               outputPin;              // Salida de Arduino que queremos operar
    boolean           isDigital;              // true=digital, false=analógico. Si es analógico complete el campo analogValue
    boolean           isFlasher;              // true=Salida flash, false=sin timer, sin flash.
    byte              analogValue;            // Valor para usar en salida de tipo analógica.
    int               durationMilli;          // Milliseconds para activar la salida. Con 0 no se apaga automaticamente
    
    unsigned long     onMilli;                // Usado internamente para temporizador
    unsigned long     offMilli;               // 
} DCCAccessoryAddress;

En el ejemplo tenemos definidas 8 salidas las podemos ver en la función:


void ConfigureDecoder()

La funcion void ConfigureDecoder() es la encargada configurar cada una de las salidas que queramos utilizar y al final, con un bucle for, pone el pines de salida como OUTPUT con pinMode:


	
	// Salida analógica en la dirección 714, inicia apagada con pin de salida 5
	// con una duración de 500 milisegundos
	gAddresses[0].address = 714;
    gAddresses[0].output = 0;
    gAddresses[0].outputPin = 5;
    gAddresses[0].isDigital = false;	// Salida analógica
    gAddresses[0].isFlasher = false;	
    gAddresses[0].analogValue = 250;	// valor analógico máximo
    gAddresses[0].durationMilli = 500;
    
    // Salida digital en la direccion 715, inicia apaga con pin de salida 6
    gAddresses[1].address = 715;
    gAddresses[1].output = 0;
    gAddresses[1].outputPin = 6;
    gAddresses[1].isDigital = true;		// Salida digital
    gAddresses[1].isFlasher = false;
    gAddresses[1].analogValue = 0;		// 0 por ser salida digital.
    gAddresses[1].durationMilli = 500;

          // Configurar pines de salida
    for(int i=0; i<(int)(sizeof(gAddresses)/sizeof(gAddresses[0])); i++)
    {
        if( gAddresses[i].outputPin ) 					// Si es verdadero
        {
            pinMode( gAddresses[i].outputPin, OUTPUT ); // Pone el pin especificado como salida
        }
        gAddresses[i].onMilli = 0;		// Temporizadores a 0
        gAddresses[i].offMilli = 0;
    }

Si seguimos bajando lineas en el archivo, llegamos a la función encargada de devolver los datos "traducidos" por la librería:


	void BasicAccDecoderPacket_Handler(int address, boolean activate, byte data)

Esta función se activa mediante interrupción. Una interrupción, a groso modo, es un pin del microcontrolador que cuando reciba una señal, dejara cualquier tarea que este haciendo y hara lo que le hayamos especificado. Sabiendo esto, la interrupcion la maneja la librería y lo tenemos que configurar en el setup():


	DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, boolean);
	DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT);	// Configura la interrupción con la que se comunica el decodificador 

El tema de la interrupcion lo comentaré al final ya que hay debido al tiempo que hace que no se actualiza la librería creo que hay cosas que se podrían mejorar. Por el momento seguiremos con el ejemplo el setup completo, donde activamos la comunicación serial y llamamos a la configuración de las salidas del decodificador con ConfigureDecoder().


	Serial.begin(115200); 	// Velocidad de comunicación serial
	DCC.SetBasicAccessoryDecoderPacketHandler(BasicAccDecoderPacket_Handler, boolean);
	ConfigureDecoder();		// Llama a la función de configuración de salidas
	DCC.SetupDecoder( 0x00, 0x00, kDCC_INTERRUPT);	// Configura la interrupción con la que se comunica el decodificador

El resto del programa es el loop() principal donde se llama a DCC.loop() que es la funcion loop de la librería.

Si bien el programa de ejemplo nos da para los accesorios básicos como luces, desvíos con un sistema que permita funcionar con un 1 o un 0. Bueno para mi, esto no fue suficiente así que añadí algunas partes para poder controlar servos. Esta modificación incluye la librería Servo.h además de incluir los archivos en los que tengo definidos los desvíos y accesorios. Esto esta mejor exlicado en la entrada de esta página llamada Organizar elementos DCC en Arduino


#include <DCC_Decoder.h>		// Librería DCC Decoder
#include <Servo.h>				// Librería para uso de servos
#include "listaAccesorios.h"	// Lista de accesorios definidos

Esto hace que también haya cambios ya que hay nuevos parametros relacionados con los servos en la estructura de datos como set_point o angulo:


struct accItem {
  int direccion;    // Direccion DCC del accesorio
  byte output;      // Estado del accesorio DCC: 1=on, 0=off
  byte outputPin0;  // Pin de salida para funcion adicional ( No se puede conectar un servo aqui)
  byte outputPin1;  // Pin de salida para funcion adicional ( No se puede conectar un servo aqui)
  byte anguloOff;   // Posición para DCC=off
  byte anguloOn;    // Posición para DCC=on
  Servo servo;
  boolean estado;
  byte angulo;
};
accItem acc[maxservos];