jump to navigation

Control de luces desde pic pinguino 3 febrero, 2010

Posted by ubanov in Electrónica.
Tags: ,
trackback

La primera vez que vi una televisión philips, con lo que ellos llaman ambilight, me gustó bastante. No tanto el hecho de adaptarse a la imagen (que siempre lo quito), sino el hecho de tener una luz posterior reflejada y encima con diferentes colores para no aburrirte.

Como primer proyecto de verdad sobre pinguino (si no sabes lo que es mira el siguiente link: https://ubanov.wordpress.com/2010/01/28/primer-contacto-con-pinguino-microchip-pic/), la semana pasada decidí montar una luces parecidas al ambilight, pero sobre mi tele sony (y además hechas por mi mismo).

Para hacerlo he montado CINCO circuitos:

  • 4 que tienen diodos led tricolores (diodos superflux que compré en ebay por 15€ por 50 diodos)
  • Y una última que contiene un pinguino al que le he añadido dos ULN2003.

El conjunto de las placas sin montar es el que aparece en la siguiente foto:

Cada placa de diodos contiene 8 diodos y puede ser controlada de forma independiente. Cada placa recibe 4 hilos: 5V comunes, y luego los tres colores, que cuando se conectan a masa iluminan. Como cable de conexión he empleado un trozo de cable de red (8 hilos).

Para poner las placas detrás de la tele he empleado dos capas de cinta de doble cara (con una las soldaduras atravesaban la cinta).

Una vez puesta la cinta la pegué en la parte de detrás de la tele. Cuando fui a pegar en uno de los lados me di cuenta que tenía unos conectores que me fastidiaban el ponerlo abajo del todo, con lo que las luces están un poco subidas, pero quedan bien de todas formas.

(La foto está girada)

Un problema que he tenido con la cinta de doble cara es que al cabo de tenerla uno o dos días se acababa despegando por donde estaban juntadas las dos cintas de doble cara… yo lo he solucionado dando una pincelada de loctite entre capa y capa de la cinta de doble cara… si lo volviese hacer igual intentaría comprar una cinta de doble cara mejor.

Para la gestión de encendido apagado de las luces lo que he hecho es enchufar la alimentación de esta placa a una salida de alimentación que tiene mi amplificador 5.1, de esta forma si el ampli está encendido hay luces, y si está apagado no.

Los siguientes pasos que me quedan por hacer: mejorar los juegos de luces, y hacer que las luces puedan ir a ritmo con el sonido (me gustaría poner un filtro que dejase pasar las frecuencias más bajas, y en base al volumen de esas hacer que las luces cambien de color más rápido o más lento).

Aquí os dejo el programa de Pinguino que está controlando mis luces:

———————————————————————

#define PIC18F2550

#define MAXOUTPUTS 12
//MAXDELAYS=MAXOUTPUTS/3
#define MAXDELAYS 4

//we use maxvalue instead of a number in order to be possible to change
// the maximun color, and then recuce the mA needed by the board
#define MAXVALUE 127

unsigned char contadorisr=0;
unsigned int contadorisrhigh=0;

unsigned char outputlevel[MAXOUTPUTS];
unsigned char tempout[MAXOUTPUTS];
unsigned char incout[MAXOUTPUTS];
unsigned char desiredoutputlevel[MAXOUTPUTS];
unsigned int waitcounter[MAXDELAYS];

#define RED 0
#define GREEN 1
#define BLUE 2

// set the value of all the colors, in color goes the number of the color
// (RED,GREEN or BLUE), and in level the color you want to set (0-255)
void SetAllColor(unsigned char color,unsigned char level)
{
if (color>2)
color=2;
for(;color<MAXOUTPUTS;color+=3)
outputlevel[color]=level;
}

// the same that SetAllColor for the desired colors
void SetAllDesiredColor(unsigned char color,unsigned char level)
{
if (color>2)
color=2;
for(;color<MAXOUTPUTS;color+=3)
desiredoutputlevel[color]=level;
}

// this routine will make a fader from current colors to desired colors, it uses one
// temp variable (tempout[x]) and a calculated value of the initial diference between
// the first color and the desired (incout[x]). And each group of 3 colors (RGB) have
// a waitcounter, that it’s the number of cycles it should wait before begining to
// change a color. This routine is called from DoCompleteCycle
void CalculateNextColors(void)
{
unsigned char a,b,c,d;
int t;

for(a=c=0;a<MAXDELAYS;a++,c+=3) {
if(waitcounter[a])
waitcounter[a]–;
else
for(b=0;b<3;b++) {
d=c+b;
t=tempout[d];
t+=incout[d];
if(t>=256) {
if(desiredoutputlevel[d]>outputlevel[d])
outputlevel[d]++;
else if(desiredoutputlevel[d]<outputlevel[d])
outputlevel[d]–;
t-=256;
}
tempout[d]=t;
}
}
}

// This routine test if a cycle has been finished (if all the colors are the desired,
// and waited all the waitcounter[x]). This routine is called from DoCompleteCycle.
// It returns 1 if the cycle is finished, and 0 in any other case.
unsigned char FinishedCycle(void)
{
unsigned char a;

for(a=0;a<MAXDELAYS;a++)
if(waitcounter[a])
return(0);
for(a=0;a<MAXOUTPUTS;a++)
if(outputlevel[a]!=desiredoutputlevel[a])
return(0);
return(1);
}

// this routine is used in order to change the colors from one color to another
// the time that last to go fromone color to another are speed * 256 microseconds
// for example 20, will last a bit more than 5 seconds (5.12)
void DoCompleteCycle(int speed)
{
unsigned char a;

//calculate increments
for(a=0;a<MAXOUTPUTS;a++) {
tempout[a]=0;
if(outputlevel[a]>desiredoutputlevel[a])
incout[a]=outputlevel[a]-desiredoutputlevel[a];
else
incout[a]=desiredoutputlevel[a]-outputlevel[a];
}
//main loop until all the colors are correct
while(!FinishedCycle()) {
delay(speed);
CalculateNextColors();
}
}

//interrupt handler that handles PWM
void UserInterrupt()
{
unsigned char t;

if (PIR1bits.TMR1IF) {
PIR1bits.TMR1IF=0;
TMR1H=0xFF;
//   TMR1L=0x00;
contadorisr++;
// for a better speed bit functions are used rather than digitalWrite
// t is changed in order to variate the cicle where the leds and on and off
// to reduce the peak load of the board
t=contadorisr;
if(outputlevel[0]>=t) PORTBbits.RB5=1; else PORTBbits.RB5=0;
if(outputlevel[1]>=t) PORTBbits.RB4=1; else PORTBbits.RB4=0;
if(outputlevel[2]>=t) PORTBbits.RB3=1; else PORTBbits.RB3=0;
t+=128;
if(outputlevel[3]>=t) PORTBbits.RB2=1; else PORTBbits.RB2=0;
if(outputlevel[4]>=t) PORTBbits.RB1=1; else PORTBbits.RB1=0;
if(outputlevel[5]>=t) PORTBbits.RB0=1; else PORTBbits.RB0=0;
t-=64;
if(outputlevel[6]>=t) PORTAbits.RA2=1; else PORTAbits.RA2=0;
if(outputlevel[7]>=t) PORTAbits.RA1=1; else PORTAbits.RA1=0;
if(outputlevel[8]>=t) PORTAbits.RA0=1; else PORTAbits.RA0=0;
t+=128;
if(outputlevel[9]>=t) PORTAbits.RA5=1; else PORTAbits.RA5=0;
if(outputlevel[10]>=t) PORTAbits.RA4=1; else PORTAbits.RA4=0;
if(outputlevel[11]>=t) PORTAbits.RA3=1; else PORTAbits.RA3=0;
}
}

void EnableTimerInterrupt(void)
{
TMR1H=0xFF;
TMR1L=0x00;
// timer 1 prescaler 1 source is internal oscillator
T1CON=0x01;
// enable interrupt for timer1 in register PIE1
PIE1bits.TMR1IE=1;
// enable peripheral interrupt
INTCONbits.PEIE=1;
// global enable interrupt
INTCONbits.GIE=1;
// now an interrupt will be generated by timer1 every 42,5 microsec (aprox 19500/sec)

}

void setup()
{
unsigned char a;

pinMode(5,OUTPUT);    //RB5
pinMode(4,OUTPUT);    //RB4
pinMode(3,OUTPUT);    //RB3
pinMode(2,OUTPUT);    //RB2
pinMode(1,OUTPUT);    //RB1
pinMode(0,OUTPUT);    //RB0
pinMode(13,OUTPUT);    //RA0
pinMode(14,OUTPUT);    //RA1
pinMode(15,OUTPUT);    //RA2
pinMode(16,OUTPUT);    //RA3
pinMode(17,OUTPUT);    //RA4
pinMode(18,OUTPUT);    //RA5

EnableTimerInterrupt();

SetAllColor(RED,0);
SetAllColor(GREEN,0);
SetAllColor(BLUE,0);

for(a=0;a<MAXDELAYS;a++)
waitcounter[a]=0;

SetAllDesiredColor(RED,0);
SetAllDesiredColor(GREEN,MAXVALUE);
SetAllDesiredColor(BLUE,MAXVALUE);
DoCompleteCycle(2);
}

void CircleClockWise()
{
}

void loop()
{
waitcounter[2]=128;
waitcounter[0]=256;
waitcounter[1]=384;
SetAllDesiredColor(RED,0);
SetAllDesiredColor(GREEN,0);
SetAllDesiredColor(BLUE,MAXVALUE);
DoCompleteCycle(3);

waitcounter[0]=128;
waitcounter[2]=256;
waitcounter[3]=384;
SetAllDesiredColor(RED,MAXVALUE);
SetAllDesiredColor(GREEN,0);
SetAllDesiredColor(BLUE,MAXVALUE);
DoCompleteCycle(2);

waitcounter[2]=128;
waitcounter[0]=256;
waitcounter[1]=384;
SetAllDesiredColor(RED,MAXVALUE);
SetAllDesiredColor(GREEN,0);
SetAllDesiredColor(BLUE,0);
DoCompleteCycle(2);

waitcounter[0]=128;
waitcounter[2]=256;
waitcounter[3]=384;
SetAllDesiredColor(RED,MAXVALUE);
SetAllDesiredColor(GREEN,MAXVALUE);
SetAllDesiredColor(BLUE,0);
DoCompleteCycle(2);

waitcounter[2]=128;
waitcounter[0]=256;
waitcounter[1]=384;
SetAllDesiredColor(RED,0);
SetAllDesiredColor(GREEN,MAXVALUE);
SetAllDesiredColor(BLUE,0);
DoCompleteCycle(2);

waitcounter[0]=128;
waitcounter[2]=256;
waitcounter[3]=384;
SetAllDesiredColor(RED,0);
SetAllDesiredColor(GREEN,MAXVALUE);
SetAllDesiredColor(BLUE,MAXVALUE);
DoCompleteCycle(2);
}
———————————————————————

Si volviese a hacer la placa del pinguino seguramente le pondría un 7805 más cañero, por que la placa hoy en día está consumiendo unos 360mA (y eso que no uso más de dos colores a la vez y además en lugar de ir hasta el valor más alto de brillo, con la variable MAXVALUE lo subo a media potencia).

De todas formas si alguien quiere los fotolitos que me los pida y se los paso (están en TraxMaker 2000, no en eagle, sorry).

Por último aquí va un video de cómo ha quedado más o menos el efecto de cambio de luz:

Quería haber puesto un video de cómo se ven las luces pero no he sido capaz de darme de alta en youtube (me dice que algún día hace mucho tiempo me debí de dar de alta…. y quiero recuperar la password pero parece que tengo que esperar :-))

Comentarios»

1. Primer contacto con Pinguino (MicroChip PIC) « El Weblog de Ivan Ricondo (Ubanov) - 3 febrero, 2010

[…] Mi primer proyecto serio sobre pinguino es el siguiente: https://ubanov.wordpress.com/2010/02/03/control-de-luces-desde-pic-pinguino/ […]

2. Mi primer Pinguino « Linux Droids Blog - 25 febrero, 2010

[…] Control de luces desde Pinguino – Control de Servos desde […]

3. mrp0t4t0 - 24 marzo, 2010

Muy bueno, estaré atento a tu blog, ya que estoy empezando con pingüino y la verdad que estoy un poco perdido, sobre todo con las instrucciones complejas. Yo vengo de programar PIC’s con CCS en Wxp y ahora estoy intentando programar con pingüino en Mac, y la verdad, tengo más problemas que satisfacciones.
Por favor, me podrías decir donde encontrar un manual sobre la programacion de pingüino??? Que instrucciones son las que hay??
Gracias y enhorabuena por tus aportes, son de gran ayuda para los nuevos.

ubanov - 24 marzo, 2010

La programación es C, y para ver los comandos específicos quizás lo más fácil sea empezar por el tutorial que hay en la siguiente página: http://sites.google.com/site/pinguinotutorial/home

Si tienes alguna duda concreta si quieres pregúntame (uso MAC y Linux con mis pinguinos 🙂

4. mrp0t4t0 - 25 marzo, 2010

Gracias Ivan, pero que es DoCompleteCycle(2)??
A esto me refiero cuando digo lo de las instrucciones. O por ejemplo como se llama el bit nº x del registro de control del timer y. Ya sabes lo que digo?? yo vengo de CCS y es mu diferente, tenía que definir los registros antes de usarlos con un nombre, sin embargo C18 se pueden utilizar porque en otro archivo ya los definía, como _ADGODONE por ejemplo (no se si se llama así)

De todas manera en el foro de ARDE me han dicho que el lenguaje es SDCC así que me miraré algún manual, a ver que saco en claro.
Gracias.

mrp0t4t0 - 25 marzo, 2010

Perdón ivan, ya he visto lo del DoCompleteCycle, es que es un poco dificil leer codigo sin «colorines» jejeje

5. mrp0t4t0 - 2 abril, 2010

Ivan, estos son los fallos que me salen cuando compilo tu programa:

/Applications/Pinguino beta7 OSX /source/user.c:67: warning 110: conditional flow changed by optimizer: so said EVELYN the modified DOG

/Applications/Pinguino beta7 OSX /source/user.c:139: syntax error: token -> ’00’ ; column 11

/Applications/Pinguino beta7 OSX /source/user.c:140: syntax error: token -> ’01’ ; column 11
error while compiling file /Applications/Pinguino beta7 OSX /NoName0

6. jose - 3 septiembre, 2011

oye excelente aplicación, te felicito.

7. Sarra - 15 octubre, 2012

Muy bueno Ivan eres un crack ,-)

8. Sonia - 17 abril, 2013

Admiring the dedication you put into your site and detailed information you offer.
It’s good to come across a blog every once in a while that isn’t the same unwanted rehashed material.

Great read! I’ve bookmarked your site and I’m including your RSS feeds to my Google account.


Deja un comentario