Autor Tema: Dimmer DMX 8 Chanel  (Leído 3015 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado Joseph90

  • PIC12
  • **
  • Mensajes: 89
Dimmer DMX 8 Chanel
« en: 07 de Septiembre de 2015, 11:26:09 »
Hola amigos del foro aqui les comparto el esquema y el código en CCS de un dimmer contrololado por DMX de 8 canales. Ya lo he construido y probado y funciona de maravilla. El aparato no difiere en mucho a los dimmers profesionales y funciona como tal.
Posee 8 interruptores en los cuales se selecciona la dirección base del equipo, al ser 8 solo se puede direccionar hasta la dirección 255. Si se selecciona la dirección 0, el equipo entra en modo manual a través del potenciómetro que posee variando la intensidad de los 8 canales al mismo nivel.
Tiene además un precalentamiento que dura alrededor de 3 min. Usa un PIC16f74 a 20 MHz.
Lo que aparece en la parte de arriba del esquema es el detector de cero, el cual no tiene muchas complicaciones salvo que la resistencia de 22k sea de al menos de 1W  de potencia.
Para entrar el DMX al PIC es necesario usar un driver, ya sea el RS485 ó 75176, no aparece en el esquema pero en la red pueden encontrar como conectarlo.
Las ocho salidas estan en el puerto D del PIC y en mi caso he usado 8 módulos de potencia optoacoplados originales de dimmer que me ha regalado un colega por lo que la conexión se hace a través de solo una resistencia. Anteriormente he usado triacs de potencia con optotriacs, y ha funcionado pero me he encontrado con el problema de que le metía ruido al audio. Eso se soluciona colocando una bobina en serie con la carga pero ya que me han dado los módulos originales solo ha sido conectar ;-) ;-).
La recepción DMX es basada en la de Mark del foro de CCS.
Quiero agradecer especialmente a KILLERJC por su ayuda con el código  ;-).

El esquema es el siguiente:


« Última modificación: 07 de Septiembre de 2015, 11:32:49 por Joseph90 »
El problema del hombre no está en la boma atómica, sino en su corazón. Albert Einstein.

Desconectado Joseph90

  • PIC12
  • **
  • Mensajes: 89
Re: Dimmer DMX 8 Chanel
« Respuesta #1 en: 07 de Septiembre de 2015, 11:35:00 »
Y el código es el siguiente:

Código: [Seleccionar]
#include <Dimmer v3.0 8CHDMX.h>
/***********************************************************************/
/***************DECLARACIONES PARA DMX512*******************************/
#define WAIT_FOR_NEXT_BYTE 0
#define WAIT_FOR_BREAK     1
#define WAIT_FOR_START     2     //MAQUINA DE ESTADOS
#define RECEIVE_DATA       3

#byte SPBRG = 0x99
#byte RCSTA = 0x18   //Registros de recepcion de la usart
#byte TXSTA = 0x98
#byte RCREG = 0x1a
#byte PIR1  = 0x0c  
#byte PIE1  = 0x8c
#byte INTCON = 0x0b

#byte T1CON = 0X10

#bit SPEN   = RCSTA.7   //Serial port enable bit
#bit RX9   = RCSTA.6    // 9-bit receive enable
#bit SREN   = RCSTA.5   //En modo asyncrono no se tiene en cuenta
#bit CREN   = RCSTA.4   // Continuos receive enable bit
#bit ADDEN   = RCSTA.3    //Addres detected enable bit
#bit FERR   = RCSTA.2   //Frame error bit
#bit OERR   = RCSTA.1   //Overrun error bit
#bit RX9D   = RCSTA.0   //El noveno bit

#bit TMR1ON = T1CON.0   // empleo TMR1ON en vez de enable/disable_interrupt(TIMER1) porque el compilador
                        // no le da la gana de trabajar esta sentencia (no modifica TMR1ON????)

#bit BRGH   = TXSTA.2
#bit SYNC    = TXSTA.4
#bit RCIF  = PIR1.5
#bit RCIE  = PIE1.5
#bit GIE    = INTCON.7
#bit PEIE   = INTCON.6
#bit INTEDG = 0x81.6

/******************************************************************************/
/***************DECLARACIONES PARA DIMMERIZACION*******************************/

const int8 CH_DMX=8; //cantidad de canales a almacenar
int8 OFFSET=3; // direccion base del receptor al tener solo 8 interruptores solo se puede direccionar hasta el canal 255
#define DMX_LED PIN_E2      // led de indicacion de Rx DMX
 
int8 Rx_Buffer[CH_DMX]={255,255,255,255,255,255,255,255};      // en este arreglo se almacenan los datos DMX captados por el receptor
                                                                //tiene inicialmente la menor intensidad  
                                
int8 Ch_Rx=0;                    // contador del  Canal que se esta recibiendo  
int8 Id_Buffer=0;                // contador del canal que se esta almacenando en el buffer de RX
                                 // si se almacenan mas de 250 ch debe de ser de 16
#define TIMER0  229               // son 255 tramos de 32.7 us cada uno
#define TIMER1  55550            // valor medio 55600, debe  ser calibrado en tiempo real     //**********PARAMETRO A AJUSTAR**************************************
                                 // debido a que la sensiblidad del detector de cruce por cero puede variar de un modelo a  otro.
                                 // por tanto hay que evitar el disparo continue al proximo semiciclo, lo cual provocar'ia que el triac
                                 // conduciera TODO el semicilo...
int8 HEAT=220;                 // Este valor permite que la intensidad NUNCA SEA CERO. (DEFECTO: 240) //**********PARAMETRO A AJUSTAR**************************************
#define PREHEAT 250                // TIEMPO DE PRECALENTAMIENTO, este par'ametro tiene  //**********PARAMETRO A AJUSTAR**************************************
                                 //que ser ajustado en tiempo real porque aunque el delay
                                 // en el main es de 200ms demora mucho mas debido
                                 //a las frecuentes interrupciones, lo que alarga
                                 // notablemente el tiempo. Se debe poner un valor mas
                                 // alto para aumentar el tiempo de precalentamento.
int8 contador=0;

/*Definimos una union que es como una struct pero con la diferencia de
que sus componentes se almacenan en la misma posicion de memoria.
Esto significa  que el byte rcsta.byte esta formado por 8 bits los cuales
hemos definido id?nticos a los bits del registro de estado de la usart: RCSTA
para hacer una copia despues de leer el buffer de recepcion, no antes segun mi programa,
antes segun datasheeat y el programa de marcos*/
union
  {
    unsigned char _byte;         // Al parecer en ccs 5 no puede ser llamado byte
    struct {
        unsigned char RX9D:1; //bit0
        unsigned char OERR:1;
        unsigned char FERR:1;
        unsigned char ADDEN:1;
        unsigned char CREN:1;
        unsigned char SREN:1;
        unsigned char RX9:1;
        unsigned char SPEN:1; //bit7
    } bits ;
  }rcsta2;                       // en ccs 5 no puede ser llamado rcsta pues ya hay una var con ese nombre


/*********************PARA DIMMERIZACION**********************************************/

/**************************************************************************************/

#int_TIMER0
void TIMER0_isr(void){
      set_timer0(TIMER0);
      if (Rx_Buffer[0]==contador) output_high(PIN_D0);
      if (Rx_Buffer[1]==contador) output_high(PIN_D1);
      if (Rx_Buffer[2]==contador) output_high(PIN_D2);
      if (Rx_Buffer[3]==contador) output_high(PIN_D3);
      if (Rx_Buffer[4]==contador) output_high(PIN_D4);
      if (Rx_Buffer[5]==contador) output_high(PIN_D5);
      if (Rx_Buffer[6]==contador) output_high(PIN_D6);
      if (Rx_Buffer[7]==contador) output_high(PIN_D7);
      contador++;
      if (contador>=HEAT) output_d(0xff);    //VER EXPLICACI'ON EN LA DECLARACION DE HEAT  
}
#int_TIMER1
void TIMER1_isr(void){
       disable_interrupts(INT_TIMER0);      // LOS DESHABILITO exepcto el de  EXT_INT
//       disable_interrupts(INT_TIMER1);
       TMR1ON=0;
       output_d(0x00);  
}

#INT_EXT
void  EXT_isr(void)
{
   set_timer0(TIMER0);// este timer se mantendra activo hasta que se cumpla el timer 1
   enable_interrupts(INT_TIMER0);
   set_timer1(TIMER1);  // timer para garantizar que no pase de 8.33 ms O SEA AL OTRO SEMICICLO
   enable_interrupts(INT_TIMER1);
   TMR1ON=1;
   contador=0;
   INTEDG=!INTEDG;  /*CAMBIO EL FLANCO PARA EL PROXIMO SEMICICLO*/
}

void main()
{
   int8 temp;
  
   set_tris_a(0xff); //completo de entrada;
   set_tris_b(0xff);
   set_tris_c(0xff);
   set_tris_d(0x00);
   set_tris_e(0x00);
   setup_adc_ports(AN0_AN1_AN3);   //tres canales, solo empleo AN0
   setup_adc(ADC_CLOCK_DIV_32);  

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4);
   setup_timer_1(T1_INTERNAL|T1_DIV_BY_4);
   disable_interrupts(INT_TIMER0);      // LOS DESHABILITO, NO LOS NECESITO AHORA
//   disable_interrupts(INT_TIMER1);
   TMR1ON=0;
   output_D(0);
  
/*       CHEQUEANDO DIRECCION BASE*/  
   temp= input_b();              
   temp= temp&0x3E;   //3e mascara pues solo necesito del bit 1 al 5 (ver esquema)
   temp= temp>>1;     // corro hacia la DER 1 lugar para  ubicarlo en la parte BAJA
   OFFSET= input_c();
   OFFSET=OFFSET&0x07; // solo me interesan los 3 Lsb  
   OFFSET=OFFSET<<5; //LO SUBO A LA PARTE ALTA
   OFFSET=OFFSET|temp; // tengo ya la direcci'on
/*                                */
   INTEDG=1;
   RCIE=0;           //  deshabilito receive interrupt(CERO) no se utiliza, estoy por encuesta
   enable_interrupts(INT_EXT);         // Habilito la interrupcion externa
   GIE=1;            // enable all interrupts
   PEIE=1;           // enable peripheral interrupts
   HEAT=200;
   for (int i=0;i<=PREHEAT;i++){    // Estamos en precalentamiento
      output_high(DMX_LED);         // LED parpadeando
      delay_ms(100);
      output_low(DMX_LED);
      delay_ms(100);
   }
   HEAT=220;
   if (OFFSET==0){      /*La dimmerizaci'on es por el potenciometro*/
      output_high(DMX_LED);   // se mantendr'a siempre activo, indicando que la fuente es el potenciometro.    
      while(1){
            set_adc_channel(0);
            delay_ms(50);
            RX_Buffer[0]=255-read_adc();
            for (int i=1;i<=7;i++){
                RX_Buffer[i]=RX_Buffer[0];      //igualo todos los canales al valor dado por el POT
            }
      }
   }
   ELSE
{
  
   SPBRG=0x04;       // SPBRG=0 implica que a 20Mhz el baudrate=250.000 baud
   BRGH=1;         // BRGH=1 implica High speed.
   SYNC=0;           // enable aSYNChronous reception
   SPEN=1;           // serial port enabled
   RX9=1;            // 9 bit reception
   CREN=1;           // enable reception
   ADDEN=0;
   FERR=1;
   OERR=1;
   output_low(DMX_LED);
   /* Maquina de estados para determinar el inicio de la trama dmx*/
   static int8 Rx_State = WAIT_FOR_BREAK;
   int8 data;   //El dato que estamos recibiendo se almacena temporalmente aqui

while (1){
  
   while (RCIF) //Nos quedamos leyendo el dato tanto tiempo como este presente
   {
          /*Leemos el registro de estado de la usart y se lo asignamos
           al byte rcsta.byte. Leemos el dato */
           data = RCREG;
           rcsta2._byte = RCSTA;

           if (rcsta2.bits.OERR)   //Miramos si hay un buffer overrun
           {
               //Si hay Overrun entonces hay que resetear la l?gica de recepcion
               CREN = 0;
               CREN = 1;
               /* Como hemos recibido un overrun hemos de esperar un byte correcto
               antes de buscar la se?al de break */
               Rx_State = WAIT_FOR_NEXT_BYTE;
           }

           switch (Rx_State)
           {
               case WAIT_FOR_BREAK:
               if (rcsta2.bits.FERR) //Miramos si hay un error de trama
               {
                   /*Si recibimos un error de trama, hay que asegurarse que el dato es 0.
                     Esto significa que hemos recibido una se?al de break de como m?nimo 44us.
                     Hay que acordarse que trabajamos a 250Kbits lo cual implica un tbit de 4us
                     SI enviamos 11 bits( start+8bit datos+2stop)esto son 44us*/
                     if (!data)
                     Rx_State = WAIT_FOR_START;
               }
               break;
               case WAIT_FOR_START:
               /*Comprobamos si hay error en la trama. Si recibimos un error
                  tenemos que esperar a recibir un byte correcto antes de que
                  empezemos a buscar nuestra se?al de break */
               if (rcsta2.bits.FERR)
                  Rx_State = WAIT_FOR_NEXT_BYTE;
                 /* El byte de start de nuestro paquete siempre empieza por 0. */
               else
               {
                     if (!data)
                     {
                              // ESTAMOS EN EL BYTE DE START, EL CANAL ES 0    
                              /*En este punto debermos determinar donde de la trama DMX queremos empezar
                              a recibir datos basandonos en una direccion de offset. */
                     Ch_Rx=0;
                     Id_buffer=0;
                     Rx_State = RECEIVE_DATA;
                     output_high(DMX_LED);
                     }
               }
               break;
      
               case WAIT_FOR_NEXT_BYTE:
               if (!rcsta2.bits.FERR){            
                     Rx_State = WAIT_FOR_BREAK;
               }
               break;

               case RECEIVE_DATA:
                     /*Comprobamos si hay error de trama. Si nosotros recibimos un error de trama
                     esto puede ser el inicio de un nuevo paquete o un verdadero error de trama */
               if (rcsta2.bits.FERR)
               {
                      /* Si es el inicio de un nuevo paquete el dato debe ser 0 sino es un error
                        en la trama */
                     if (!data){
                        Rx_State = WAIT_FOR_START;
                     }
               else
                     Rx_State = WAIT_FOR_NEXT_BYTE;
               }
               else
               {
                     Ch_Rx++;
                     /* ALmacenamos el dato recibido en el buffer de recepcion si esta en el rango especificado */
                     if (Ch_Rx>=OFFSET)   {
                           Rx_Buffer[Id_Buffer]=255-data;
                           Id_Buffer++;
                     }
              
                     /*Comprobamos si hemos recibido todos nuestros datos */
                     if(Id_Buffer>=CH_DMX)
                     {
                           /* Hemos recibido todos los datos*/
                           Rx_State= WAIT_FOR_BREAK;
                     }
                     output_low(DMX_LED);
               }
               break;
        
           }
   }
}     // CIERRE DEL WHILE(1)  
}     // cierre del else
  
}



Espero les sirva, saludos desde Cuba....
El problema del hombre no está en la boma atómica, sino en su corazón. Albert Einstein.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Dimmer DMX 8 Chanel
« Respuesta #2 en: 07 de Septiembre de 2015, 13:11:29 »
Gracias por nombrarme aunque no recuerdo haber ayudado en algo asi  :shock: . Espero que no te confundas de persona.

En fin, todo el merito es tuyo ya que lograste tu cometido y que funcionara como vos querias. Y gracias por compartir.

Desconectado Joseph90

  • PIC12
  • **
  • Mensajes: 89
Re: Dimmer DMX 8 Chanel
« Respuesta #3 en: 07 de Septiembre de 2015, 14:47:11 »
No no me confundo KILLERJC, mira este enlace: http://www.todopic.com.ar/foros/index.php?topic=19672.120 especialmente en la parte en la que dices:
Citar
La que quedaba era no usar la interrupcion de la UART y de los pines de entrada. Y en main un bucle leyendo sus flags y actuar acorde a lo que se necesita, pero jamas interrumpiendo la generacion del timer.

Gracias a eso funciona el dimmer correctamente pues de esa manera la interrupcion de la UART no me interrumpe los timer, lo cual se complica teniendo en cuenta que el micro que estoy usando no tiene prioridad de interrupciones.
Esa idea parece sencilla pero a mi por alguna extraña razón no se me había ocurrido :? :shock:

Saludos...
El problema del hombre no está en la boma atómica, sino en su corazón. Albert Einstein.

Desconectado stk500

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 4923
Re: Dimmer DMX 8 Chanel
« Respuesta #4 en: 07 de Septiembre de 2015, 15:00:28 »
Joseph90 me alegro muchos que lo haya logrados!!
Es posible que ponga Fotos de la placa,Esquemas o mejor un Video Funcionando?
Saludos

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re: Dimmer DMX 8 Chanel
« Respuesta #5 en: 07 de Septiembre de 2015, 15:40:18 »
Ni me acordaba, cuando iba leyendo el tema, me acorde que era algo de la UART, pero claro, eso fue en abril :P

Desconectado Joseph90

  • PIC12
  • **
  • Mensajes: 89
Re: Dimmer DMX 8 Chanel
« Respuesta #6 en: 08 de Septiembre de 2015, 10:19:07 »
Pues si me he tardado un poquito pero al fin ha funcionado. Poner un video funcionando me será dificil pues mi conexión no es tan buena para ello pero pronto les pongo unas fotos del aparato y el circuito el cual es muy simple.
Ahora estoy diseñando una consola DMX como dicen por aca: "con todos los metales" :D :D. Resulta que el colega que me reglaló los módulos de potencia me ha dado el chasis con los faders, led y botones de una consola Regia de 8 canales así que le estoy haciendo una electrónica y quiero lograr que funcione igual a la regia orginal o mejor, pues la puedo personalizar a mi gusto :lol: :lol:. Ya les contaré como me va.

Saludos y muchas gracias por todo.....
El problema del hombre no está en la boma atómica, sino en su corazón. Albert Einstein.


 

anything