Problema con un POV RGB y DAC R2R con PIC18F4550

Buenas tardes, mi nombre es Santiago. Creo haber posteado algo previamente en el foro. Pero en fin, ahora estoy en un proyecto super sencillo. Se trata de manejar 10 LEDs RGB usando la tecnica POV (sin girar!, estaticos), es decir, seleccionando led por led y estableciendole el color y repetiendo esta rutina para que el ojo humano ni se de cuenta. (una especie de PWM casero, pero sin la parte de PWM en si :p).

En fin, vamos al grano. El sistema funciona, ni se nota que estan poveando los leds (imagino que hay mucha velocidad, no la medi aun). Pero tiene un detalle.
Suponiendo que tengo prendios los 10 leds en R, G, B, R, G, B, R, G, B, Violeta (B+R).
En el primer led donde esta prendido el Red, se ven fragmentos de Blue (vienen del ultimo led, que esta en Violeta). En el segundo y tercer led hay fragmentos de Red. Y asi continuamente.

Yo estoy usando BC337 para seleccionar cada led (Vcc -> Transistor -> ComunLED). Pero tambien uso los BC337 para amplificar (e invertir) la señal de cada color que sale de un DAC R2R. (PIC-> R2R-> Transistor).

Segun vi en otros POV, utilizan otros transistores (2N2222, 2N4401), sera por eso?

Dejo adjunto el PDF del esquematico que realice, junto con la parte del codigo que se encarga del POV.
Quiero destacar que hay 2 bits mas en comun para el tema de las "sombras" o "shades" ya que me base exclusivamente en un diseño de LucidScience (hacian una placa VGA con un Atmel y con un R2R de 8 bits hacian 64 colores). Igualmente no los utilizo por ahora.

El codigo (C18):
Código:
void SetRamLED(char r, char g, char b, char shade, char id)
{
    char temp;

    LEDsColors[id-1] = r & 0x3;
    LEDsColors[id-1] |= (g & 0x3) << 2;
    LEDsColors[id-1] |= (b & 0x3) << 4;
    LEDsColors[id-1] |= (shade & 0x3) << 6;
//    LEDsColors[id] = ~LEDsColors[id];
}

void DoPov(void)
{
    char temp;
    char id;

    for (id=1; id<11; id++) {
        LATD = LATB = LATE = 0x0;

        LATD = LEDsColors[id-1];        

        if (id==9) {
            //LATB = 0;
            LATE = 0x1;
        } else if(id==10) {
            //LATB = 0;
            LATE = 0x2;
        } else if(id > 0) {
            LATB = 0x1 << (id-1);
            //LATE = 0;
        } else {
            //LATB = LATE = 0;
        }
    
        
    }
}
Donde LEDsColors es un array: unsigned char LEDsColors[10];. Y para inicializar y llenarle los datos, antes del bucle infinito, le seteo de la siguiente manera:
Código:
    LATA = 0xFF;
    LATB = LATD = LATE = 0x0;
    TRISD = TRISB = 0x0;
    TRISEbits.TRISE0 = 0;
    TRISEbits.TRISE1 = 0;

    SetRamLED(0x3, 0x0, 0x0, 0x0, 0x1);
    SetRamLED(0x0, 0x3, 0x0, 0x0, 0x2);
    SetRamLED(0x0, 0x0, 0x3, 0x0, 0x3);

    SetRamLED(0x3, 0x0, 0x0, 0x0, 0x4);
    SetRamLED(0x0, 0x3, 0x0, 0x0, 0x5);
    SetRamLED(0x0, 0x0, 0x3, 0x0, 0x6);

    SetRamLED(0x3, 0x0, 0x0, 0x0, 0x7);
    SetRamLED(0x0, 0x3, 0x0, 0x0, 0x8);
    SetRamLED(0x0, 0x0, 0x3, 0x0, 0x9);

    SetRamLED(0x3, 0x0, 0x3, 0x0, 0xA);
Esta adjunto el PDF del circuito...

Espero que me puedan dar una mano. Saludos.
 

Adjuntos

  • testrgb.PDF
    94.1 KB · Visitas: 48
Se me ocurre que quizás estés cambiando de un LED a otro demasiado rápido (demasiada frecuencia de refresco)... quizás eso hace que los "glitches" que hace el micro al cambiar el estado de los leds (de un par de microsegundos) se vean...

Probá dejar cada led prendido más tiempo, con delays o timers...

Un saludo,
Gonzalo
 
Hola, gracias por contestar. Mira, probe eso, pero pasa que pierden luminosidad porque seria como bajarle el Duty a un PWM. Ademas que el "glitch" apenas desaparecia. La frecuencia puede ser, pero suponiendo que en el datasheet del bc337 dice 100MHz, y dudo que el PIC trabaje a eso.

Alguna otra opcion?

Saludos
 
Hola, gracias por contestar. Mira, probe eso, pero pasa que pierden luminosidad porque seria como bajarle el Duty a un PWM. Ademas que el "glitch" apenas desaparecia. La frecuencia puede ser, pero suponiendo que en el datasheet del bc337 dice 100MHz, y dudo que el PIC trabaje a eso.

No, cambiar el delay entre LEDs sería como bajar la frecuencia del PWM, no el duty... El duty va a ser siempre el mismo: 1/10 en tu caso que tenés 10 LEDs...

Fijate de bajar la frecuencia MUCHO, por ejemplo 2 segundo en cada led... Ahí podés ver si sigue pasando eso... Si sigue pasando, claramente es un problema de software.

Un saludo,
Gonzalo
 
Hola de nuevo, recien probe de poner un delay de 500mS (prende de a 1 led) y aparentemente no hay problemas. Pero me suena ilogico, porque en mi codigo yo hago lo siguiente:

BusData = 0
BusDireccion = 0 (inclusive los 2 bits en LATE)
BusData = datos
BusDireccion = direccion

Y eso se repite constantemente.

Por otro lado, yo estaba pensando en utilizar otros metodos para prender los leds que no involucren al POV; osea usar buffers (latchs) o SRAMs, pero sea cual sea la opcion, tengo que utilizar 10 integrados mas y compartir la misma linea de datos entre todos, lo cual se hace un poco grande al cuete.
Igualmente he visto que existen integrados de 16 canales PWM, pero aca en Rosario (Sta. Fe, Arg.) no esta en venta el modelo. Es un Texas Instruments TLC5940. (DS: http://focus.ti.com/lit/ds/symlink/tlc5940.pdf).

Si tenes alguna otra idea, comentame!

Saludos!
 
Me contesto a mi mismo, puse un delay de Delay10KTCYx(1); que aparentemente elimina el error de los colores, pero el brillo baja mucho. Tecnicamente no estoy bajando el Duty, sino la F del PWM, pero magicamente baja el brillo.
Ademas lo del delay no me gusta mucho, ya que voy a usar USB con interrupciones, y realmente va a tardar una eternidad hasta poder responder a la interrupcion. Inclusive cambiando el for que use por otros metodos no tan invasivos del % de cpu.

Saludos.
 
La solución es usar interrupciones de timer en vez de hacerlo manualmente con polling...

Igualmente, las interrupciones se responden en el instante... Lo peor que puede pasar es que un led esté un poco más de tiempo (algunos millisegundos) prendido algún led...

Respecto a lo del brillo, si pudieses encontrar el datasheet de tus leds RGBs, verías que es posible hacerles circular una corriente mucho más alta en el modo pulsante, por lo que quizás puedas bajar el valor de las resistencias limitadoras...

Un saludo,
Gonzalo
 
Hola, si el tema de las Interrupciones puede ser, pero por ahora quiero ver esto de la luminosidad del led. Actualmente hay resistencias de 220ohms a 5v.
Tengo el DS de mis leds (es el que esta en http://dled.com.ar/product/index/LED-RGB--5mm--4-Patas/?id_product=44, ahi lo compre). Segun vi, 100mA es el de 1/10 de Duty a 0,1ms (10khz).

Por lo que yo vi, con el delay que estoy usando, no llega a ser 1khz. Puedo subir aun mas, pero ahi ya se nota el glitch (estuve probando con muchas variantes de delays).

Igualmente voy a usar este metodo. Tengo que comprar resistencias mas grandes para el R2R de los Shades, ya que al activar cualquier bit, los leds quedan prendidos en blanco (logicamente por la R que use.)

Ah, y mande 5 samples del integrado de PWM de TI (para usar en un futuro).

Voy a ver si implemento el tema de los Timers en vez del bucle, aunque yo tenia una teoria sencilla para no ocupar nada del CPU y no retrasar la respuesta de la interrupcion.

Cuando me refiero a respuesta de interrupcion, es para leer lo que yo mande por usb, no para contestar a la interrupcion de hardware en si.

Saludos
 
Atrás
Arriba