(http://www.micropic.es/images/imagenes/ReceptorDMX.jpg)
Revisa si tienes bien asignada la ruta al ejecutable del compilador en "Project/set language tool locations"Gracias Amigo Duende_azul!
Todavía no ha salido ninguna versión de CCS mejor que la 3.249, así que compila con ella y verás como va fino, fino.
Ea, pues ya sólo falta que nos pongas las fotos de tu cacharroSorry manolo!
Cualquiera que tenga 28 pines te servirá. Realmente el programa utiliza muy pocos recursos: sólo la interrupción del timer y la de la usart.Gracias Manolo!
Tendrás que adaptar algunas cosas, porque está pensado para usar oscilador interno a 8MHz, pero seguro que lo consigues fácilmente.
si te digo la verdad, estaba pensando en gastarme un dineral en una mesa de iluminacion... pero visto todo esto, me parece que lo invertire en otra cosa... la verdad que es una pasada!!! con lo que a mi me gustaria llegar a mis actuaciones con un portatil y poder manejar videoproyecciones, audio y luz todo desde alli... un verdadero sueño! y cada vez veo que se hace mas realidad... ya tenia las videoproyecciones y parte del sonido controladas desde el, ahora intentare tambien la luz.Hola amigo Marttyn!
el unico problema que veo por ahora es el puerto paralelo. mi portatil o es muy moderno o es una mierda, pero no lo trae. ya me tocaba la moral el no poder usar mi programador de pics, pero ahora me va a incordiar bastante mas! todo esto se podra adaptar a usb?
me gustaria saber, si no es mucho preguntar, por que se intereso nuestro amigo manolo en la interface dmx? acaso es el productor musical de camela? o dedica el tiempo libre a tocar con un coro eclesiastico satanico? :D
sea como sea, cosa que a el le interesa, a mi tambien me interesa!.... leds rgb, libreria para display de 7 seg, dmx... manolo, el dia que hagas un proyecto con servos, sabes que tambien estare ahi, no? :mrgreen:
salu2
Muchas Gracias STK500 por la explicacion, ahora me esta entrando mas ganas de hecharle una mano a esto de los DMX512, ummmm. :D :D :D. Si sigo asi me va a faltar manos para todo lo que quiero hacer :D :D :D :D:D :D Te lo creo Amigo ! :D :D
Ojalá que así sea. El DMX es uno de esos protocolos "úsese u olvídese". Quiero decir que por ejemplo para los que trabajamos en esto diariamente de forma profesional (como stk500 también) el DMX ya es una forma natural del trabajo, pero si alguien no lo necesita o no trabaja en ello a veces sólo queda el aprendizaje, la curiosidad, pero al final del día se da uno cuenta de que ¡no hay nada que controlar! El campo es amplísimo así ue siempre habrá una aplicación por ahí para encontrarle.
Marttyn, si lo que quieres es lo que me imagino, este es tu protocolo. Y claro, con servos también podrás usarlo.
yo personalmente veo que por el precio y el trabajo que me dara, mejor lo compro hecho, estando probado, acabado profesional y con software y todo... por unos 70€ ya lo hay, con envio incluido. yo lo busque en ebay, pones "usb dmx" y en las preferencias de busqueda pon que quieres buscar en articulos de todo el mundo. te lo envian de alemania.Hola marttyn!
ahora... si lo quieres como aficionado, y como proyecto, puede ser interesante y aprenderas cosas...
salu2
pero claro, cada led rgb necesita 3 pines del micro.., es decir 30 pines para 10 leds
es la unica menera de conseguirlo? y sobre todo, necesitare generar 30 PWM... es eso posible con algun PIC 16?
Si utilizas drivers para leds sólo ocupas tres pines (DATA, CLOCK, y LATCH) independientemente del número de leds que vayas a manejar. El PWM lo haces pero en software volcando en cada actualización los valores para todos los leds. Con un PIC 16 es más que suficiente.
a que te refieres con drivers para leds? nunca use uno de esos, son integrados que se encangan del PWM de cada led? los hay para RGB? o es indiferente?
salu2 y gracias por la info!
Hola Amigos!, para los que le interese la lectura DMX pero en ensamblador, pueden mirar aquí http://www.todopic.com.ar/foros/index.php?topic=12494.0 (http://www.todopic.com.ar/foros/index.php?topic=12494.0)
está probado y actualmente lo estoy empleando... normalmente, la consola de sonido y luces esta a unos 30 metros del escenario, y las maquinas de humo que tengo, no son DMX (y estan en el escenario) , asi que las adapté, y las disparo de la misma consola de luces,.... ahora una pregunta, o necesidad, que realmente no se si existe en el mercado... hay algun dispositivo, que "reuna" 2 o mas señales DMX, y obtener una unica salida?
Les digo esto, porque actualmente empleo 3 lineas DMX, y que es engorroso por el cableado ( a veces empleo canales disponibles de la manguera de microfonos o envios de audio)
La idea seria leer cada dato, almacenarlos en memoria, verificando que sean distintas direcciones (logicamente) para luego "retransmitirlas" por una sola salida...
lo que no sé, es como "sincronizar" las velocidades... creo que necesitaria un dspic :?
Un abrazo
Norberto
si quiere te envio el MCU programado y probados y tu hace la platina con los demas componente, asi que ya sabe y no me llore mas:D :D :D ok a tu gentil propuesta!!!! ja ja, trataremos de no lorar más, y aprender a usar el freestyler
Si usamos el mismo esquema que en mi ReceptorDMX con un PIC18F que tenga 2 usart es bastante sencillo.
Cada USART levanta una interrupción pero ambas escribirían en el mismo array de 512 bytes.
En cada interrupción ser programará la lógica de escritura en la RAM, de manera que respondan a los criterios discriminatorios que comentaba JCC40.
Mientras tanto, un Timer podría estar escupiendo la trama DMX recompuesta en otra interrupción.
Realmente el protocolo DMX es tan lento para un PIC que le daría tiempo hasta de tomarse unas copitas mientras hace toda esa tarea.
Aquí puedes ver todos los PIC18F, y verás una columna llamada "Digital Communication" en la que observas el nº de puertos USART, MSSP, SPI... que tiene cada PIC.por lo que veo todas las Serie TQPF tiene doble USART.... y encontre 18F6720 este manolo donde yo compro y lo pedire que tu dice nos sirve :lol: :lol: :lol: :lol:
Por ejemplo, el PIC18F65J10
#include <16F628A.h>
#FUSES WDT //Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#use delay(clock=20000000,RESTART_WDT) // Utilizo clock de 20MHz porque me facilita la elección exacta del baudrate a 250k y tenia el cristal
/************************************************************************
* Registros USART *
************************************************************************/
#byte SPBRG= 0x99 // Registros para el pic 16F628
#byte RCSTA= 0x18 // Aqui se han modificado las direcciones correspondientes para el 628
#byte TXSTA= 0x98
#byte RCREG= 0x1A
#byte PIR1= 0x0C
#byte PIE1= 0x8C
#bit SPEN= RCSTA.7
#bit RX9= RCSTA.6
#bit SREN= RCSTA.5
#bit CREN= RCSTA.4
#bit ADDEN= RCSTA.3
#bit FERR= RCSTA.2
#bit OERR= RCSTA.1
#bit RX9D= RCSTA.0
#bit BRGH= TXSTA.2
#bit SYNC= TXSTA.4
#bit RCIF= PIR1.5
#bit RCIE= PIE1.5
/************************************************************************
* Estados protocolo DMX *
************************************************************************/
#define DMX_ESPERA_BYTE 0
#define DMX_ESPERA_BREAK 1
#define DMX_ESPERA_START 2
#define DMX_ESPERA_DATO 3
#define DMX_RECEPCION_DATOS 4
/************************************************************************
* Variables globales y constantes *
************************************************************************/
//--------------------Se han quitado las variables que no utilizo--------------------------------------
int8 DMX_Estado = DMX_ESPERA_BREAK; // Estado de la máquina de estados
int8 DatoRX; // Dato genérico recibido en USART
int8 DMX_Indice = 0; // Apuntador a una posición de la trama DMX
#define TotalCanales 3 // Total canales a almacenar en este caso solo interesan los 3 primeros
int8 TramaDMX[TotalCanales]; // Trama completa de valores DMX
union // Estructura para hacer una copia del registro RCSTA
{
unsigned char registro;
struct {
unsigned char RX9D:1;
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;
} bits ;
}Copia_RCSTA;
/************************************************************************
* Interrupción Timer 0: *
************************************************************************/
#int_Timer0
TIMER0_isr()
{
}
/************************************************************************
* Interrupción RDA: dato recibido por la USART *
* Esta interrupción se activa cada vez que se recibe un dato en la *
* USART. Mediante el control de una máquina de estados se determina *
* la validez y el significado del dato recibido, y se obra en *
* consecuencia. *
************************************************************************/
//--------La interrupción de la USART no se ha modificado, esta tal cual el receptor de Nocturno----------------
//--------solo cambia el hecho de que TotalCanales vale 3 en lugar de 512----------------------------------------
#int_rda
void Dato_Recibido_USART(void)
{
while (RCIF) // ejecutamos mientras haya un dato pendiente de procesar
{
// Hacemos una copia del registro RCSTA porque sus bits cambian de valor
// al leer RCREG y modificar CREN
Copia_RCSTA.registro = RCSTA;
// En RCREG está el dato que acaba de recibir la USART
DatoRX = RCREG;
// Si se reciben más de 3 bytes sin haberlos procesado, se produce un error
// de Overrun. En este caso, se borra el error reiniciando CREN y dejamos
// la interrupción preparada para procesar la siguiente trama DMX
if (Copia_RCSTA.bits.OERR)
{
CREN=0;
CREN=1;
DMX_Estado = DMX_ESPERA_BYTE;
return;
}
// Máquina de estados
switch (DMX_Estado)
{
case DMX_ESPERA_BYTE: // si estamos en este estado y hay error FRAME
// es que nos ha pillado en medio de un Byte. Hay que seguir esperando
// hasta que desaparezca el error.
if (!Copia_RCSTA.bits.FERR)
// Ha llegado un byte. Ahora esperaremos la señal Break
DMX_Estado = DMX_ESPERA_BREAK;
break;
case DMX_ESPERA_BREAK: // estamos esperando la señal Break
// Esta señal se identifica porque aparece el error de Frame
if (Copia_RCSTA.bits.FERR)
// Tras recibir el error de Break, hay que esperar un byte de valor 0
if (!DatoRX)
DMX_Estado = DMX_ESPERA_START;
break;
case DMX_ESPERA_START: // ya hemos recibido el Break y ahora hay que
// esperar un Byte con valor 0, que será la señal de Start
// Mientras tanto, si recibimos un error de Frame, hay que volver a
// empezar para recibir la señal de comienzo de trama.
if (Copia_RCSTA.bits.FERR)
DMX_Estado = DMX_ESPERA_BYTE;
else {
if (!DatoRX)
{
// Llegados a este punto, ya hemos recibido el Byte Start=0
// y comenzamos la trama de valores DMX.
DMX_Indice = 0;
DMX_Estado = DMX_RECEPCION_DATOS;
} else
// Si el dato recibido no es 0, volvemos a empezar
DMX_Estado = DMX_ESPERA_BREAK;
}
break;
case DMX_RECEPCION_DATOS:
// En este estado estamos recibiendo la trama de datos DMX
// Si se detecta un error de Frame es que ha habido un error y estamos
// al principio
if (Copia_RCSTA.bits.FERR)
if (!DatoRX)
DMX_Estado = DMX_ESPERA_START;
else
DMX_Estado = DMX_ESPERA_BYTE;
else
{
// Almacenamos el dato recibido en nuestro array
TramaDMX[DMX_Indice++] = DatoRX;
// Si ha llegado al final de la capacidad, cambiamos al estado de espera
// de nueva trama
if (DMX_Indice >= TotalCanales)
DMX_Estado = DMX_ESPERA_BREAK;
}
break;
}
}
return;
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_wdt(WDT_18MS);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(False);
// Activamos las interrupciones de recepción de la USART y del Timer0
enable_interrupts(INT_RDA);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
// Configuración de la USART
SPBRG=4; // A 20Mhz el baudrate es 250.000, sale de la tabla de la hoja de datos del 16F628
BRGH=1; // Seleccionamos high speed
SYNC=0; // Transmisión asíncrona
SPEN=1; // Activamos la USART
RX9=1; // 9 bit para la recepcion
SREN=0; // Desactiva recepción de un byte
CREN=1; // Recepción activada
ADDEN=0; // Desactivada la autodetección de dirección
FERR=0; // No hay error de frame con 1 se activa
OERR=0; // No hay error de overrun con 1 se activa
//-----------------------------------------------------------
delay_ms(1000); // delay de 1 seg y enciendo un led en el pin B7 para saber que por lo menos está corriendo el programa
output_high(pin_B7);
while(1) {
if (TramaDMX[0]>128)output_high(pin_B4); // La idea es hacer PWM pero primero quiero recibir la señal DMX exitosamente
else output_low(pin_B4); // por eso primero trabajo ON-OFF a la mitad del potenciómetro
if (TramaDMX[1]>128)output_high(pin_B5);
else output_low(pin_B5); // Los valores de TramaDMX 0, 1 y 2 deberian corresponderse con los canales 1, 2 y 3
if (TramaDMX[2]>128)output_high(pin_B6);
else output_low(pin_B6);
delay_ms(25); // pequeña espera y refresco del Watchdog automático
}
}
Gracias por vuestras palabras. (Akenafab, esas pilas son las que venden en la cadena de supermercados Mercadona, seguro que muchos de mis compatriotas las conocen. Jesús, el conector no lo venden en Mercadona :D)
Ya he subido el código fuente y el esquemático, que podéis descargar aquí: Descargas de ReceptorDMX (http://www.micropic.es/index.php?option=com_remository&Itemid=27&func=select&id=48)
(http://img512.imageshack.us/img512/9342/receptordmxqf9.th.jpg) (http://img512.imageshack.us/my.php?image=receptordmxqf9.jpg)
Del código fuente pegaré aquí sólo la rutina de atención a la interrupción de la USART, que es donde está el meollo de la cuestión. El programa completo está disponible para descargar en el link que puse antes. El código está comentado, así que me ahorro explicarlo.
Si necesitáis algo más, no tenéis más que decirlo.Código: C
/************************************************************************ * Interrupción RDA: dato recibido por la USART * * Esta interrupción se activa cada vez que se recibe un dato en la * * USART. Mediante el control de una máquina de estados se determina * * la validez y el significado del dato recibido, y se obra en * * consecuencia. * ************************************************************************/ #int_rda void Dato_Recibido_USART(void) { while (RCIF) // ejecutamos mientras haya un dato pendiente de procesar { // Hacemos una copia del registro RCSTA porque sus bits cambian de valor // al leer RCREG y modificar CREN Copia_RCSTA.registro = RCSTA; // En RCREG está el dato que acaba de recibir la USART DatoRX = RCREG; // Si se reciben más de 3 bytes sin haberlos procesado, se produce un error // de Overrun. En este caso, se borra el error reiniciando CREN y dejamos // la interrupción preparada para procesar la siguiente trama DMX if (Copia_RCSTA.bits.OERR) { CREN=0; CREN=1; DMX_Estado = DMX_ESPERA_BYTE; return; } // Máquina de estados switch (DMX_Estado) { case DMX_ESPERA_BYTE: // si estamos en este estado y hay error FRAME // es que nos ha pillado en medio de un Byte. Hay que seguir esperando // hasta que desaparezca el error. if (!Copia_RCSTA.bits.FERR) // Ha llegado un byte. Ahora esperaremos la señal Break DMX_Estado = DMX_ESPERA_BREAK; break; case DMX_ESPERA_BREAK: // estamos esperando la señal Break // Esta señal se identifica porque aparece el error de Frame if (Copia_RCSTA.bits.FERR) // Tras recibir el error de Break, hay que esperar un byte de valor 0 if (!DatoRX) DMX_Estado = DMX_ESPERA_START; break; case DMX_ESPERA_START: // ya hemos recibido el Break y ahora hay que // esperar un Byte con valor 0, que será la señal de Start // Mientras tanto, si recibimos un error de Frame, hay que volver a // empezar para recibir la señal de comienzo de trama. if (Copia_RCSTA.bits.FERR) DMX_Estado = DMX_ESPERA_BYTE; else { if (!DatoRX) { // Llegados a este punto, ya hemos recibido el Byte Start=0 // y comenzamos la trama de valores DMX. DMX_Indice = 0; DMX_Estado = DMX_RECEPCION_DATOS; } else // Si el dato recibido no es 0, volvemos a empezar DMX_Estado = DMX_ESPERA_BREAK; } break; case DMX_RECEPCION_DATOS: // En este estado estamos recibiendo la trama de datos DMX // Si se detecta un error de Frame es que ha habido un error y estamos // al principio if (Copia_RCSTA.bits.FERR) if (!DatoRX) DMX_Estado = DMX_ESPERA_START; else DMX_Estado = DMX_ESPERA_BYTE; else { // Almacenamos el dato recibido en nuestro array TramaDMX[DMX_Indice++] = DatoRX; // Si ha llegado al final de la capacidad, cambiamos al estado de espera // de nueva trama if (DMX_Indice >= TotalCanales) DMX_Estado = DMX_ESPERA_BREAK; } break; } } return; }
#include <16F628A.h>
#FUSES WDT //Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#use delay(clock=20000000,RESTART_WDT) // Utilizo clock de 20MHz porque me facilita la elección exacta del baudrate a 250k y tenia el cristal
/************************************************************************
* Registros USART *
************************************************************************/
#byte SPBRG= 0x99 // Registros para el pic 16F628
#byte RCSTA= 0x18 // Aqui se han modificado las direcciones correspondientes para el 628
#byte TXSTA= 0x98
#byte RCREG= 0x1A
#byte PIR1= 0x0C
#byte PIE1= 0x8C
#bit SPEN= RCSTA.7
#bit RX9= RCSTA.6
#bit SREN= RCSTA.5
#bit CREN= RCSTA.4
#bit ADDEN= RCSTA.3
#bit FERR= RCSTA.2
#bit OERR= RCSTA.1
#bit RX9D= RCSTA.0
#bit BRGH= TXSTA.2
#bit SYNC= TXSTA.4
#bit RCIF= PIR1.5
#bit RCIE= PIE1.5
/************************************************************************
* Estados protocolo DMX *
************************************************************************/
#define DMX_ESPERA_BYTE 0
#define DMX_ESPERA_BREAK 1
#define DMX_ESPERA_START 2
#define DMX_ESPERA_DATO 3
#define DMX_RECEPCION_DATOS 4
/************************************************************************
* Variables globales y constantes *
************************************************************************/
//--------------------Se han quitado las variables que no utilizo--------------------------------------
int8 DMX_Estado = DMX_ESPERA_BREAK; // Estado de la máquina de estados
int8 DatoRX; // Dato genérico recibido en USART
int8 DMX_Indice = 0; // Apuntador a una posición de la trama DMX
int8 Ticks = 0;
#define TotalCanales 9 // Total canales a almacenar en este caso solo interesan los 3 primeros
int8 TramaDMX[TotalCanales]= {0,0,0,0,0,0,0,0,0}; // Trama completa de valores DMX
int8 r1,g1,b1,r2,g2,b2,r3,g3,b3;
union // Estructura para hacer una copia del registro RCSTA
{
unsigned char registro;
struct {
unsigned char RX9D:1;
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;
} bits ;
}Copia_RCSTA;
/************************************************************************
* Interrupción Timer 0: *
************************************************************************/
#int_Timer0
TIMER0_isr()
{
Ticks++;
if (Ticks==0)
{
r1 = TramaDMX[0];
g1 = TramaDMX[1];
b1 = TramaDMX[2];
r2 = TramaDMX[3];
g2 = TramaDMX[4];
b2 = TramaDMX[5];
r3 = TramaDMX[6];
g3 = TramaDMX[7];
b3 = TramaDMX[8];
output_high(pin_A1);
output_high(pin_A0);
output_high(pin_B7);
output_high(pin_B4);
output_high(pin_B5);
output_high(pin_B6);
output_high(pin_A2);
output_high(pin_A3);
output_high(pin_B3);
}
if(Ticks==r1)
output_low(pin_A2);
if(Ticks==g1)
output_low(pin_A3);
if(Ticks==b1)
output_low(pin_B3);
if(Ticks==r2)
output_low(pin_B4);
if(Ticks==g2)
output_low(pin_B5);
if(Ticks==b2)
output_low(pin_B6);
if(Ticks==r3)
output_low(pin_B7);
if(Ticks==g3)
output_low(pin_A0);
if(Ticks==b3)
output_low(pin_A1);
set_timer0(128);
}
/************************************************************************
* Interrupción RDA: dato recibido por la USART *
* Esta interrupción se activa cada vez que se recibe un dato en la *
* USART. Mediante el control de una máquina de estados se determina *
* la validez y el significado del dato recibido, y se obra en *
* consecuencia. *
************************************************************************/
//--------La interrupción de la USART no se ha modificado, esta tal cual el receptor de Nocturno----------------
//--------solo cambia el hecho de que TotalCanales vale 3 en lugar de 512----------------------------------------
#int_rda
void Dato_Recibido_USART(void)
{
while (RCIF) // ejecutamos mientras haya un dato pendiente de procesar
{
// Hacemos una copia del registro RCSTA porque sus bits cambian de valor
// al leer RCREG y modificar CREN
Copia_RCSTA.registro = RCSTA;
// En RCREG está el dato que acaba de recibir la USART
DatoRX = RCREG;
// Si se reciben más de 3 bytes sin haberlos procesado, se produce un error
// de Overrun. En este caso, se borra el error reiniciando CREN y dejamos
// la interrupción preparada para procesar la siguiente trama DMX
if (Copia_RCSTA.bits.OERR)
{
CREN=0;
CREN=1;
DMX_Estado = DMX_ESPERA_BYTE;
return;
}
// Máquina de estados
switch (DMX_Estado)
{
case DMX_ESPERA_BYTE: // si estamos en este estado y hay error FRAME
// es que nos ha pillado en medio de un Byte. Hay que seguir esperando
// hasta que desaparezca el error.
if (!Copia_RCSTA.bits.FERR)
// Ha llegado un byte. Ahora esperaremos la señal Break
DMX_Estado = DMX_ESPERA_BREAK;
break;
case DMX_ESPERA_BREAK: // estamos esperando la señal Break
// Esta señal se identifica porque aparece el error de Frame
if (Copia_RCSTA.bits.FERR)
// Tras recibir el error de Break, hay que esperar un byte de valor 0
if (!DatoRX)
DMX_Estado = DMX_ESPERA_START;
break;
case DMX_ESPERA_START: // ya hemos recibido el Break y ahora hay que
// esperar un Byte con valor 0, que será la señal de Start
// Mientras tanto, si recibimos un error de Frame, hay que volver a
// empezar para recibir la señal de comienzo de trama.
if (Copia_RCSTA.bits.FERR)
DMX_Estado = DMX_ESPERA_BYTE;
else {
if (!DatoRX)
{
// Llegados a este punto, ya hemos recibido el Byte Start=0
// y comenzamos la trama de valores DMX.
DMX_Indice = 0;
DMX_Estado = DMX_RECEPCION_DATOS;
} else
// Si el dato recibido no es 0, volvemos a empezar
DMX_Estado = DMX_ESPERA_BREAK;
}
break;
case DMX_RECEPCION_DATOS:
// En este estado estamos recibiendo la trama de datos DMX
// Si se detecta un error de Frame es que ha habido un error y estamos
// al principio
if (Copia_RCSTA.bits.FERR)
if (!DatoRX)
DMX_Estado = DMX_ESPERA_START;
else
DMX_Estado = DMX_ESPERA_BYTE;
else
{
// Almacenamos el dato recibido en nuestro array
TramaDMX[DMX_Indice++] = DatoRX;
// Si ha llegado al final de la capacidad, cambiamos al estado de espera
// de nueva trama
if (DMX_Indice >= TotalCanales)
DMX_Estado = DMX_ESPERA_BREAK;
}
break;
}
}
return;
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_wdt(WDT_18MS);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(False);
// Configuración de la USART
SPBRG=4; // A 20Mhz el baudrate es 250.000, sale de la tabla de la hoja de datos del 16F628
BRGH=1; // Seleccionamos high speed
SYNC=0; // Transmisión asíncrona
SPEN=1; // Activamos la USART
RX9=1; // 9 bit para la recepcion
SREN=0; // Desactiva recepción de un byte
CREN=1; // Recepción activada
ADDEN=0; // Desactivada la autodetección de dirección
FERR=0; // No hay error de frame con 1 se activa
OERR=0; // No hay error de overrun con 1 se activa
// Activamos las interrupciones de recepción de la USART y del Timer0
enable_interrupts(INT_RDA);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
//-----------------------------------------------------------
set_timer0(128);
while(1){ delay_ms(5000);}
}
Lo tienes aquí (http://micropic.es/index.php?option=com_remository&Itemid=77&func=fileinfo&id=142)
Hola a todos, primero que nada, un capo el Sr. Nocturno!. Tu codigo y documentacion me ha sido de mucha utilidad y tambien las modificaciones realizadas por mrlicho.
En resumen, aqui esta el resultado de mi implementacion con un PIC16F628, con salida para 9 canales.
Saludos!
¡Magnífico!, muy chulo.
De genio nada, sólo un poco cabezota. Me alegro que te haya servido.
Se que el codigo puede mejorarse, estas son solo pruebas y tal vez a alguien le pueda servir.
(https://lh6.googleusercontent.com/_jcAN7sZk2-0/TcXC3PDw7hI/AAAAAAAACUw/XgJhDLb22I8/s640/DSC00506.JPG)
(https://lh5.googleusercontent.com/_jcAN7sZk2-0/TcXC5FM3e2I/AAAAAAAACU0/9Coga4C_-Gw/s640/DSC00521.JPG)Código: [Seleccionar]#include <16F628A.h>
#FUSES WDT //Watch Dog Timer
#FUSES HS //High speed Osc (> 4mhz)
#FUSES PUT //Power Up Timer
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOMCLR //Master Clear pin used for I/O
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#use delay(clock=20000000,RESTART_WDT) // Utilizo clock de 20MHz porque me facilita la elección exacta del baudrate a 250k y tenia el cristal
/************************************************************************
* Registros USART *
************************************************************************/
#byte SPBRG= 0x99 // Registros para el pic 16F628
#byte RCSTA= 0x18 // Aqui se han modificado las direcciones correspondientes para el 628
#byte TXSTA= 0x98
#byte RCREG= 0x1A
#byte PIR1= 0x0C
#byte PIE1= 0x8C
#bit SPEN= RCSTA.7
#bit RX9= RCSTA.6
#bit SREN= RCSTA.5
#bit CREN= RCSTA.4
#bit ADDEN= RCSTA.3
#bit FERR= RCSTA.2
#bit OERR= RCSTA.1
#bit RX9D= RCSTA.0
#bit BRGH= TXSTA.2
#bit SYNC= TXSTA.4
#bit RCIF= PIR1.5
#bit RCIE= PIE1.5
/************************************************************************
* Estados protocolo DMX *
************************************************************************/
#define DMX_ESPERA_BYTE 0
#define DMX_ESPERA_BREAK 1
#define DMX_ESPERA_START 2
#define DMX_ESPERA_DATO 3
#define DMX_RECEPCION_DATOS 4
/************************************************************************
* Variables globales y constantes *
************************************************************************/
//--------------------Se han quitado las variables que no utilizo--------------------------------------
int8 DMX_Estado = DMX_ESPERA_BREAK; // Estado de la máquina de estados
int8 DatoRX; // Dato genérico recibido en USART
int8 DMX_Indice = 0; // Apuntador a una posición de la trama DMX
int8 Ticks = 0;
#define TotalCanales 9 // Total canales a almacenar en este caso solo interesan los 3 primeros
int8 TramaDMX[TotalCanales]= {0,0,0,0,0,0,0,0,0}; // Trama completa de valores DMX
int8 r1,g1,b1,r2,g2,b2,r3,g3,b3;
union // Estructura para hacer una copia del registro RCSTA
{
unsigned char registro;
struct {
unsigned char RX9D:1;
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;
} bits ;
}Copia_RCSTA;
/************************************************************************
* Interrupción Timer 0: *
************************************************************************/
#int_Timer0
TIMER0_isr()
{
Ticks++;
if (Ticks==0)
{
r1 = TramaDMX[0];
g1 = TramaDMX[1];
b1 = TramaDMX[2];
r2 = TramaDMX[3];
g2 = TramaDMX[4];
b2 = TramaDMX[5];
r3 = TramaDMX[6];
g3 = TramaDMX[7];
b3 = TramaDMX[8];
output_high(pin_A1);
output_high(pin_A0);
output_high(pin_B7);
output_high(pin_B4);
output_high(pin_B5);
output_high(pin_B6);
output_high(pin_A2);
output_high(pin_A3);
output_high(pin_B3);
}
if(Ticks==r1)
output_low(pin_A2);
if(Ticks==g1)
output_low(pin_A3);
if(Ticks==b1)
output_low(pin_B3);
if(Ticks==r2)
output_low(pin_B4);
if(Ticks==g2)
output_low(pin_B5);
if(Ticks==b2)
output_low(pin_B6);
if(Ticks==r3)
output_low(pin_B7);
if(Ticks==g3)
output_low(pin_A0);
if(Ticks==b3)
output_low(pin_A1);
set_timer0(128);
}
/************************************************************************
* Interrupción RDA: dato recibido por la USART *
* Esta interrupción se activa cada vez que se recibe un dato en la *
* USART. Mediante el control de una máquina de estados se determina *
* la validez y el significado del dato recibido, y se obra en *
* consecuencia. *
************************************************************************/
//--------La interrupción de la USART no se ha modificado, esta tal cual el receptor de Nocturno----------------
//--------solo cambia el hecho de que TotalCanales vale 3 en lugar de 512----------------------------------------
#int_rda
void Dato_Recibido_USART(void)
{
while (RCIF) // ejecutamos mientras haya un dato pendiente de procesar
{
// Hacemos una copia del registro RCSTA porque sus bits cambian de valor
// al leer RCREG y modificar CREN
Copia_RCSTA.registro = RCSTA;
// En RCREG está el dato que acaba de recibir la USART
DatoRX = RCREG;
// Si se reciben más de 3 bytes sin haberlos procesado, se produce un error
// de Overrun. En este caso, se borra el error reiniciando CREN y dejamos
// la interrupción preparada para procesar la siguiente trama DMX
if (Copia_RCSTA.bits.OERR)
{
CREN=0;
CREN=1;
DMX_Estado = DMX_ESPERA_BYTE;
return;
}
// Máquina de estados
switch (DMX_Estado)
{
case DMX_ESPERA_BYTE: // si estamos en este estado y hay error FRAME
// es que nos ha pillado en medio de un Byte. Hay que seguir esperando
// hasta que desaparezca el error.
if (!Copia_RCSTA.bits.FERR)
// Ha llegado un byte. Ahora esperaremos la señal Break
DMX_Estado = DMX_ESPERA_BREAK;
break;
case DMX_ESPERA_BREAK: // estamos esperando la señal Break
// Esta señal se identifica porque aparece el error de Frame
if (Copia_RCSTA.bits.FERR)
// Tras recibir el error de Break, hay que esperar un byte de valor 0
if (!DatoRX)
DMX_Estado = DMX_ESPERA_START;
break;
case DMX_ESPERA_START: // ya hemos recibido el Break y ahora hay que
// esperar un Byte con valor 0, que será la señal de Start
// Mientras tanto, si recibimos un error de Frame, hay que volver a
// empezar para recibir la señal de comienzo de trama.
if (Copia_RCSTA.bits.FERR)
DMX_Estado = DMX_ESPERA_BYTE;
else {
if (!DatoRX)
{
// Llegados a este punto, ya hemos recibido el Byte Start=0
// y comenzamos la trama de valores DMX.
DMX_Indice = 0;
DMX_Estado = DMX_RECEPCION_DATOS;
} else
// Si el dato recibido no es 0, volvemos a empezar
DMX_Estado = DMX_ESPERA_BREAK;
}
break;
case DMX_RECEPCION_DATOS:
// En este estado estamos recibiendo la trama de datos DMX
// Si se detecta un error de Frame es que ha habido un error y estamos
// al principio
if (Copia_RCSTA.bits.FERR)
if (!DatoRX)
DMX_Estado = DMX_ESPERA_START;
else
DMX_Estado = DMX_ESPERA_BYTE;
else
{
// Almacenamos el dato recibido en nuestro array
TramaDMX[DMX_Indice++] = DatoRX;
// Si ha llegado al final de la capacidad, cambiamos al estado de espera
// de nueva trama
if (DMX_Indice >= TotalCanales)
DMX_Estado = DMX_ESPERA_BREAK;
}
break;
}
}
return;
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_wdt(WDT_18MS);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(False);
// Configuración de la USART
SPBRG=4; // A 20Mhz el baudrate es 250.000, sale de la tabla de la hoja de datos del 16F628
BRGH=1; // Seleccionamos high speed
SYNC=0; // Transmisión asíncrona
SPEN=1; // Activamos la USART
RX9=1; // 9 bit para la recepcion
SREN=0; // Desactiva recepción de un byte
CREN=1; // Recepción activada
ADDEN=0; // Desactivada la autodetección de dirección
FERR=0; // No hay error de frame con 1 se activa
OERR=0; // No hay error de overrun con 1 se activa
// Activamos las interrupciones de recepción de la USART y del Timer0
enable_interrupts(INT_RDA);
enable_interrupts(INT_TIMER0);
enable_interrupts(GLOBAL);
//-----------------------------------------------------------
set_timer0(128);
while(1){ delay_ms(5000);}
}
Saludos!
Bueno, finalmente logré hacer funcionar el programa! Mil gracias por el ejemplo Nocturno, la verdad ha sido de una gran utilidad. Paso a comentar que el problema se debía a mi compilador, el código estaba perfecto, reinstalé una versión anterior del ccs y anduvo perfectamente. Recién he recibido la trama DMX, pero aún tengo que terminar el programa para que funcione con pwm, dimmer y flash. Cuando esté terminado lo posteo por si a alguien le sirve.
HOLA QUE TAL AMIGO UNA PREGUNTA SOY NUEVO EN ESO Y QUISIERA VER SI PUEDEN AYUDARME A CONSTRUIR UNO PERO A 12 CANALES CON SU DIRECCIONADOR USANDO switch
ESPERO RESPUESTA O LES DEJO MI CORREO ja_02_da@hotmail.com
gracias..
saludos
Saludos!
Jahir, el código recibe la trama completa en el array TramaDMX[]
Si quieres usar 12 canales, sólo tienes que leer las 12 posiciones del array que te interesen.
Coge el código, modifícalo a tu gusto y si tienes dudas pégalo indicando dónde está el problema.
[/
ya modifique el codigo mi duda es comopuedo poder los dipswich parra dirreccionarlos canales enel codigo esa esmi duda o si tienes un codigo que me ayudet lo agradesco ja_02_da@hotmail.com
saludos...
¿Has modificado el código y te marca errores de compilación?, ¿qué cambios has hecho?
Si no hay cambios sí funciona, yo lo hice. Asegúrate que tienes bien configurado el compilador.
No entiendo qué necesitas, aquí tienes fotos del prototipo terminado y el esquemático de cómo está diseñado.
http://www.micropic.es/mpblog/2007/12/receptor-dmx-dmx512/
¿Has leído el artículo?, ¿has visto el vídeo?
Sólo hay que teclear el canal en el teclado matricial. Se reciben TODOS los canales.
Gracias por vuestras palabras. (Akenafab, esas pilas son las que venden en la cadena de supermercados Mercadona, seguro que muchos de mis compatriotas las conocen. Jesús, el conector no lo venden en Mercadona :D)Hola!
Ya he subido el código fuente y el esquemático, que podéis descargar aquí: Descargas de ReceptorDMX (http://www.micropic.es/index.php?option=com_remository&Itemid=27&func=select&id=48)
(http://img512.imageshack.us/img512/9342/receptordmxqf9.th.jpg) (http://img512.imageshack.us/my.php?image=receptordmxqf9.jpg)
Del código fuente pegaré aquí sólo la rutina de atención a la interrupción de la USART, que es donde está el meollo de la cuestión. El programa completo está disponible para descargar en el link que puse antes. El código está comentado, así que me ahorro explicarlo.
Si necesitáis algo más, no tenéis más que decirlo.Código: C
/************************************************************************ * Interrupción RDA: dato recibido por la USART * * Esta interrupción se activa cada vez que se recibe un dato en la * * USART. Mediante el control de una máquina de estados se determina * * la validez y el significado del dato recibido, y se obra en * * consecuencia. * ************************************************************************/ #int_rda void Dato_Recibido_USART(void) { while (RCIF) // ejecutamos mientras haya un dato pendiente de procesar { // Hacemos una copia del registro RCSTA porque sus bits cambian de valor // al leer RCREG y modificar CREN Copia_RCSTA.registro = RCSTA; // En RCREG está el dato que acaba de recibir la USART DatoRX = RCREG; // Si se reciben más de 3 bytes sin haberlos procesado, se produce un error // de Overrun. En este caso, se borra el error reiniciando CREN y dejamos // la interrupción preparada para procesar la siguiente trama DMX if (Copia_RCSTA.bits.OERR) { CREN=0; CREN=1; DMX_Estado = DMX_ESPERA_BYTE; return; } // Máquina de estados switch (DMX_Estado) { case DMX_ESPERA_BYTE: // si estamos en este estado y hay error FRAME // es que nos ha pillado en medio de un Byte. Hay que seguir esperando // hasta que desaparezca el error. if (!Copia_RCSTA.bits.FERR) // Ha llegado un byte. Ahora esperaremos la señal Break DMX_Estado = DMX_ESPERA_BREAK; break; case DMX_ESPERA_BREAK: // estamos esperando la señal Break // Esta señal se identifica porque aparece el error de Frame if (Copia_RCSTA.bits.FERR) // Tras recibir el error de Break, hay que esperar un byte de valor 0 if (!DatoRX) DMX_Estado = DMX_ESPERA_START; break; case DMX_ESPERA_START: // ya hemos recibido el Break y ahora hay que // esperar un Byte con valor 0, que será la señal de Start // Mientras tanto, si recibimos un error de Frame, hay que volver a // empezar para recibir la señal de comienzo de trama. if (Copia_RCSTA.bits.FERR) DMX_Estado = DMX_ESPERA_BYTE; else { if (!DatoRX) { // Llegados a este punto, ya hemos recibido el Byte Start=0 // y comenzamos la trama de valores DMX. DMX_Indice = 0; DMX_Estado = DMX_RECEPCION_DATOS; } else // Si el dato recibido no es 0, volvemos a empezar DMX_Estado = DMX_ESPERA_BREAK; } break; case DMX_RECEPCION_DATOS: // En este estado estamos recibiendo la trama de datos DMX // Si se detecta un error de Frame es que ha habido un error y estamos // al principio if (Copia_RCSTA.bits.FERR) if (!DatoRX) DMX_Estado = DMX_ESPERA_START; else DMX_Estado = DMX_ESPERA_BYTE; else { // Almacenamos el dato recibido en nuestro array TramaDMX[DMX_Indice++] = DatoRX; // Si ha llegado al final de la capacidad, cambiamos al estado de espera // de nueva trama if (DMX_Indice >= TotalCanales) DMX_Estado = DMX_ESPERA_BREAK; } break; } } return; }
Y como está diseñado el código necesitas almacenar toda la trama. De todas formas ahora no tengo acceso al fuente para ver qué cambios podrían hacerse.
Gracias por los aportes, que hacen que aqui pueda ir el mio, con un pequeño pic, un 12f1840, 3 canales, y dipswitch.
Subo, simulacion en proteus, esquematico, hex, y codigo ccs.
el esquematico es orientativo en cuanto a la etapa de salida, cada uno sabra lo que quiere controlar.
si se quiere se puede dejar sin dipswitch, y el sistema para controlar el 4017, siempre que el pin RA3 este con la resistencia a masa.
No se si al activar las interrupciones por la USART el pin de TX/RA0 se sigue pudiendo usar independientemente como una cuarta salida y canal, sin que esto afecte a la interrupcion y recepcion de datos, asi que por eso subo el codigo por si alguien quiere probar o lo que sea.
En el codigo escrito mas atras para un 16f628, he hecho las modificaciones tipicas para el modelo de PIC, y luego he añadido, dos nuevas variables, contador y canal.
Contador se deja en cero, y canal si se quiere establecer un canal sin poner dipswitch por programa, si no se deja en cero tambien.
el canal 0 es = al 1. Y bueno en la interrupcion de UART al final de ella vereis como hace para seleccionar el canal que interese, sin saturar la ram del micro.
Hola frahg1, primero que nada, no es mio, es de todos..
Segundo, para agregarle direccion, hay una forma muy simple que solo ocupa dos pines. Te paso el esquematico, la rutina la tendras que crear vos, pero mirarando el diagrama lo entenderas.
(ver imagen adjunta)
este esta publicado en este sitio: http://picprojects.org.uk/projects/dmx/dmx688/index.htm, para el que no lo conozca se los recomiendo.
Por ultimo quiero hacer una aclaracion, no tomen este circuito como algo profesional. Yo lo abandone por que no estaba muy contento con su funcionamiento. para ese pic generar 9 pwm por soft y procesar la trama dmx es mucho. Alguien con mas experiencia tal vez pueda corregirme.
Para mi la clave esta en utilizar otros medios para generar los pwm como por ejemplo con TLC5940.
Saludos y suerte!
Yo logré generar 20 salidas pwm por soft comandadas por trama DMX usando interrupciones, en un pic16f877
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.
Esa idea puede funcionar, gracias KillerJC :P, solo me preocuparía entonces que no se perdieran datos de la trama DMX, no sé, todo lo he hecho en la computadora y todavía no he implementado nada porque la computadora de mi casa se me rompió pero espero arreglar eso pronto, gracias...
hasta ahora yo he usado 12 canales Dmx512 Dimmer en 3 Fases y 32Amp, osea cada canales 2000vatios-
a ver si nos explica como lo va querer hacer.