Despues de haber dejado este proyecto un rato apartado por motivos de trabajo, vuelvo con algunos cambios y grandes avances, y como no, con ganas de mas mejoras, pero de momento la idea propuesta en el 1 mensaje ya esta lista. De momento aqui os dejo unas fotos de lo que viene siendo el esquema para la simulacion y el programa hecho en VB6 para el control:
El codigo en CCS para el Pic (tambien adjunto en la descarga)
#include <16F88.h>
#device adc=8
#FUSES NOWDT //No Watch Dog Timer
#FUSES INTRC //Internal RC Osc
#FUSES NOPUT //No Power Up Timer
#FUSES MCLR //Master Clear pin enabled
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOWRT //Program memory not write protected
#FUSES NODEBUG //No Debug mode for ICD
#FUSES NOPROTECT //Code not protected from reading
#FUSES FCMEN //Fail-safe clock monitor enabled
#FUSES IESO //Internal External Switch Over mode enabled
#FUSES RESERVED //Used to set the reserved FUSE bits
#use delay(clock=8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_B5,rcv=PIN_B2,bits=8)
#use fast_io(a)
#use fast_io(b)
#byte PORTA=0x05
#byte PORTB=0x06
#bit LedRojo = PORTA.0
#bit LedVerde = PORTA.1
#bit LedAzul = PORTA.2
#define Retardo 1
char buffer[20];
int8 Rojo,Verde,Azul, Ticks, MiID, MiGD;
int8 CaracteresRecibidos = 0;
int1 ComandoRecibido;
#int_Timer0
void ActivaLed() {
Ticks++;
if (Ticks == 0) {
if(Rojo >= 1) LedRojo = 1;
if(Verde >= 1) LedVerde = 1;
if(Azul >= 1) LedAzul = 1;
}
if (Ticks == Rojo) LedRojo = 0;
if (Ticks == Verde) LedVerde = 0;
if (Ticks == Azul) LedAzul = 0;
set_timer0(140);
}
#INT_RDA
void serial_isr()
{
char c;
c=getc();
putchar(c);
buffer[CaracteresRecibidos] = c;
if (c == 13) // el numero 13 hacer referencia en el codigo ascii al final de carrera.
ComandoRecibido = true;
else
CaracteresRecibidos = (CaracteresRecibidos + 1) % sizeof(buffer);
}
void ProcesaRGB() {
int8 i = 0, ID = 0, GD = 0, TD;
int1 CambiandoRojo, CambiandoVerde, CambiandoAzul, CambiaMiGD, MiraID, MiraGD;
CambiandoRojo = false;
CambiandoVerde = false;
CambiandoAzul = false;
CambiaMiGD = false;
while (i<CaracteresRecibidos) {
if ((Buffer[i] == 'D') && (Buffer[i-1] == 'T')){
TD = 1;
}
if ((Buffer[i] == 'D') && (Buffer[i-1] == 'I')){
MiraID = true;
MiraGD = false;
CambiaMiGD = false;
CambiandoRojo = false;
CambiandoVerde = false;
CambiandoAzul = false;
ID = 0;
}
if ((Buffer[i] == 'D') && (Buffer[i-1] == 'G')){
MiraID = false;
MiraGD = true;
CambiaMiGD = false;
CambiandoRojo = false;
CambiandoVerde = false;
CambiandoAzul = false;
GD = 0;
}
if ((ID == MiID) || (GD == MiGD ) || (TD == 1)) {
if ((ID == MiID) && (Buffer[i] == 'C')){
MiraID = false;
MiraGD = false;
CambiaMiGD = true;
CambiandoRojo = false;
CambiandoVerde = false;
CambiandoAzul = false;
MiGD = 0;
printf("Direccion de Grupo cambiada \n\r\n\r");
}
if (Buffer[i] == 'R'){
MiraID = false;
MiraGD = false;
CambiaMiGD = false;
CambiandoRojo = true;
CambiandoVerde = false;
CambiandoAzul = false;
Rojo = 0;
}
if (Buffer[i] == 'G'){
MiraID = false;
MiraGD = false;
CambiaMiGD = false;
CambiandoRojo = false;
CambiandoVerde = true;
CambiandoAzul = false;
Verde = 0;
}
if (Buffer[i] == 'B'){
MiraID = false;
MiraGD = false;
CambiaMiGD = false;
CambiandoRojo = false;
CambiandoVerde = false;
CambiandoAzul = true;
Azul = 0;
}
}
if ((Buffer[i] >= '0') && (Buffer[i] <= '9')) {
if (MiraID) ID = ID * 10 + Buffer[i] - 48;
if (MiraGD) GD = GD * 10 + Buffer[i] -48;
if (CambiaMiGD) MiGD = MiGD * 10 + Buffer[i] -48;
if (CambiandoRojo) Rojo = Rojo * 10 + Buffer[i] - 48;
if (CambiandoVerde) Verde = Verde * 10 + Buffer[i] - 48;
if (CambiandoAzul) Azul = Azul * 10 + Buffer[i] - 48;
}
i++;
}
printf ("Color establecido: Rojo = %u, Verde = %u, Azul = %u \n\r\n\r",Rojo,Verde,Azul);
CaracteresRecibidos = 0;
ComandoRecibido = false;
TD = 0;
}
void main()
{
setup_adc_ports(NO_ANALOGS|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_2);
setup_spi(SPI_SS_DISABLED);
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_oscillator(OSC_8MHZ|OSC_INTRC);
set_tris_A(0);
Rojo = 0;
Verde = 0;
Azul = 0;
Ticks = 0;
MiID = 1; // ID del dispositivo
MiGD = 2; // GD del dispositivo
ComandoRecibido = false;
printf ("Jugando con LEDS RGB \n\r\n\r");
enable_interrupts(INT_RDA);
enable_interrupts(INT_TIMER0);
enable_interrupts (GLOBAL);
while (1) {
if (ComandoRecibido)
ProcesaRGB();
}
}
Funcionamiento
(Sacado del control de leds RGB de nocturno):
El comando a escribir se compone de 2 partes. Por un lado la direccion y por otro lado el comando de colores:
- Para la direccion tenemos 3 opciones: ID (individual direction), GD (group direction) y TD (todas diecciones). Despues de una de estas 3 opciones solo tendremos que indicar la direccion del receptor sobre el que queremos actuar.
- Para los colores tenemos otras 3 opciones: R (Red, rojo), G (Green, verde) y B (Blue, azul). Al igual que con la direccion, despues de la letra indicamos un valor de 0 a 255 (min - max).
Ejemplos:
- ID1R100G100B100: Pone los colores rojo, verde y azul del dispositivo con direccion individual 1 a un valor de 100.
- GD5R100G200: Pone el color rojo en un valor de 100 y el verde en un valor de 200 a los dispositivos con la direccion de grupo 5.
- TDR0B255: Pone el color rojo a 0 y el azul a 255 de todos los dispositivos.
Aclarar que tanto el soft del pic como el del VB no son definitivos, esa es la razon de no estar comentado. Por otra parte para la simulacion, al ser un unico esclavo, no he añadido el MAX485 ni sus controles en el programa, pero es algo que tendre que añadir para una comunicacion bidireccional sin problemas.
Posibles mejoras que tengo intencion de hacer:
- En vez de cada esclavo controlar un unico led RGB, controlar un TLC5940
- En vez de usar comunicacio RS485, cambiar el protocolo a DMX
- Un modulo externo con el que poder asignar las direcciones individuales de cada dispositivo en vez de hacerlo en el programa
- ¿Se os ocurre algo mas?
La simulacion se puede hacer tanto por virtual terminal como con el programa en VB. En este segundo caso habra que usar el VSPE y cambiar los puertos a los que simule el programa.
Espero que os guste. Un saludo!