Autor Tema: Problema con PWM por soft + interrupción con botón (SOLUCIONADO)  (Leído 2726 veces)

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

Desconectado DarkVect

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 302
Hola, estoy terminando una lámapra RGB y el caso es que todo funciona perfectamente cuando el código que le cargo al PIC tiene una sola velocidad de fadding entre colores. Es decir, cada color tarda X segundos en desvancecerse para que empiece a aparecer el siguiente.

El problema lo tengo cuando quiero hacer que se pueda variar la velocidad. El PWM por soft actúa con un periodo de 10ms, con 100 pasos para cada color. El cambio de color lo implemento con un botón y la interrupción externa por rb0.

Las dos situaciones que obtengo son:

1) Si le pongo un antirebote al botón dentro de la interrupción de rb0 (delay_ms(10)) los PWM dejan de actuar y luego ya no se recuperan, quedan como colgados a una frecuencia fija.

2) Si no pongo el antirebote, al pulsar el botón obtengo saltos en las opciones. En lugar de ejecutar la siguiente velocidad, me salta 3 o 4 de golpe, como era de esperar.

Cómo podría solucionarlo? Se me ha ocurrido leer el estado de un switch desde el main, pero claro, eso hace que el cambio de velocidad no sea inmediato, sino que hay que esperar a pases todos los colores para que empiece de nuevo con la nueva velocidad.

Un saludo y gracias a todos!!
« Última modificación: 17 de Julio de 2007, 14:23:48 por DarkVect »

Desconectado DarkVect

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 302
Re: Problema con PWM por soft + interrupción con botón
« Respuesta #1 en: 17 de Julio de 2007, 09:01:29 »
Os doy algunos datos más que podrían ser la calve del problema:

Todos los PWM se inician a la vez y son tres variables (Duty_color1, 2, 3) las que establecen cuando debe bajarse el PWM. Esas varibales Duty_color las modfico en el Main, haciéndolas más o menos grandes para lograr más o menos luminosidad de cada color. Creo que el fallo podría estar en lo siguiente; el tiempo que quiero modificar es el que hay entre cada incremento de esta variable duty_color, para que tarden más o menos en iluminarse o apagarse los leds, pero lo hago mediante un delay_ms(speed), donde speed es la variable a modificar.

¿Podría estar ahí el problema? ¿En encontrarme dentro del delay cuando entra la interrupción que incrementa el valor de speed? Debería utilizar el Timer1 para controlar ese periodo y con la interrupción rb0 modificar el Timer?

Gracias!!

Desconectado Menta

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 607
Re: Problema con PWM por soft + interrupción con botón
« Respuesta #2 en: 17 de Julio de 2007, 09:42:08 »
Habría que ver dónde y cómo modificas esa variable speed. Puedes colgar aunque sea el código de la interrupción rb0?

Si mal no entiendo, según lo que dices puedes cambiar ese retardo delay_ms(speed) por dos o tres retardos fijos dentro de un switch o un if. Por ejemplo

If (!cambiar_vel) delay_ms(5); else delay_ms(20);

En la interrupción cambias el valor de cambiar_vel

Esto me parece que te puede servir para ver si eso que supones es así o no.

Saludos
« Última modificación: 17 de Julio de 2007, 09:44:57 por Menta »
     

Desconectado DarkVect

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 302
Re: Problema con PWM por soft + interrupción con botón
« Respuesta #3 en: 17 de Julio de 2007, 10:50:22 »
El tema va así:

#INT_EXT
void int_boton()
{
    if(speed==40)          //reducir la velocidad a la mitad
    {
        speed=20;
    {
....

Y luego en el main se incrementa el duty_color:

for(i=0;i<=100;i++)
{
    duty_color++;
    delay_ms(speed);
}

¿Queda más claro ahora?

Desconectado DarkVect

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 302
Re: Problema con PWM por soft + interrupción con botón
« Respuesta #4 en: 17 de Julio de 2007, 12:59:14 »
Bueno ya he empezado las pruebas con el Timer2 del PIC (de 8 bits como el Timer0).

El funcionamiento para crear el retardo deseado es contar clocks en el timer hasta alcanzar el retardo deseado y habilitar entonces un flag. Mientras en el main el programa se queda clavado en un while(flag==0) hasta que el timer pone el flag a 1.

Voy a ir provando proque de momento no consigo la temporización exacta.

Desconectado DarkVect

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 302
Re: Problema con PWM por soft + interrupción con botón
« Respuesta #5 en: 17 de Julio de 2007, 14:13:35 »
Ya lo tengo funcionando con el Timer2  :-/ A ver si cuando añada la interrupción del botón no hace nada raro. Por cierto nunca había usado el Timer2 y su configuración me ha parecido bastante particular. Suerte del Datasheet donde está explicado al dedillo.

Desconectado DarkVect

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 302
Re: Problema con PWM por soft + interrupción con botón (SOLUCIONADO)
« Respuesta #6 en: 17 de Julio de 2007, 14:27:08 »
Bueno, puesto ya lo tengo TODO funcionando!!!

He estado haciendo pruebas con los delay_ms y resulta que cada uno duraba como el doble de lo que tenía que durar debido a las interrupciones y de ahí que no funcionara. Ha sido utilizar el Timer2 para controlar los retrasos y todo ir a las mil maravillas.

Ya lo sabéis, cuidado con los delay() cuando se requiere precisión o se usan interrupciones muy a menudo.

Desconectado Menta

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 607
Re: Problema con PWM por soft + interrupción con botón (SOLUCIONADO)
« Respuesta #7 en: 17 de Julio de 2007, 21:56:14 »
Qué bueno que lo solucionaras. Estoy de acuerdo con usar timers (si están disponibles) en lugar de delays

Pero me parece que hay otra solución, no sé si mejor o peor,simplemente otra.
se me ocurrió primero deshabilitar las INT_EXT dentro de su misma rutina de interrupción. Eso se puede, lo he hecho, sirve como antirrebote en lugar de un delay y además usar una variable auxiliar para cambiar speed. Pero en este caso creo que es más simple prescindir de la interrupción mientras se hace el cambio de luz. Algo así:

#INT_EXT
void int_boton()
{
     ***                                 // acá pones el delay antirebotes que quieras
    if(speed==40)   speed=20;    //reducir la velocidad a la mitad
}

Y luego en el main se incrementa el duty_color:

disable_interrupts(INT_EXT);
for(i=0;i<=100;i++)
{
    duty_color++;
    delay_ms(speed);
    if (input(PIN_B0)==x) int_boton();  
}
enable_interrupts(INT_EXT);



Si el delay antirrebotes te afecta la visión de las luces, (que no creo, pues son sólo unos ms y una sola vez por pulso) lo que haces es prescindir por completo de la rutina de interrupción durante el cambio de luces:

disable_interrupts(INT_EXT);
for(i=0;i<=100;i++)
{
    duty_color++;
    delay_ms(speed);
    if (input(PIN_B0)==x)
    {
        if(speed==40)  speed=20;        //reducir la velocidad a la mitad
    }
}
enable_interrupts(INT_EXT);



No sé como se lleva con el resto de tu programa, pero ahí debería funcionar, me parece.

Saludos
« Última modificación: 17 de Julio de 2007, 22:02:28 por Menta »
     

Desconectado DarkVect

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 302
Re: Problema con PWM por soft + interrupción con botón (SOLUCIONADO)
« Respuesta #8 en: 18 de Julio de 2007, 17:20:45 »
Hola te explico el por qué he tenido que hacerlo con el Timer2.

Los PWM los genero por soft, con un periodo de 10ms y con el Timer0 saltando cada 0,1ms para que me de un margen de 100 pasos (0% a 100%) del PWM, con esta frecuencia resulta que los delay_ms(40), por decir alguno, duraban mucho más que los 40ms de rigor. Igual estaba en el delay 60ms. De ahí que cada vez fuese siendo más crítico añadir delays.

Como digo la solución dle otro timer a sido perfecta. Cronometro las duraciones de los delay generados con ñeste y son clavadas, me permite el antirebote en el botón y un código "más limpio" sin tanto delay_ms().

Lo que si voy a probar es el antirebote desactivando la propia interrupción.

Muchas gracias por tus sugerencias.

Desconectado Menta

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 607
Re: Problema con PWM por soft + interrupción con botón (SOLUCIONADO)
« Respuesta #9 en: 18 de Julio de 2007, 20:40:55 »
Qué tonto que soy. Es verdad. El pwm es por soft :!: todos estos post y no lo había asimilado. Ahora sí. Tienes razón...

Lo de desahabilitar interrupciones dentro de interrupciones me había costado un poco, no recuerdo si era necesario la directiva NOCLEAR para tomar control también sobre las banderas de salto de interrupción, pero que funciona, funciona.

Un saludo. Despúes si podés y querés, posteate algún video o foto de esa lámpara!!!

     

Desconectado DarkVect

  • Colaborador
  • PIC18
  • *****
  • Mensajes: 302
Re: Problema con PWM por soft + interrupción con botón (SOLUCIONADO)
« Respuesta #10 en: 19 de Julio de 2007, 06:48:51 »
Tranquilo hombre!!! jajaja!!! He probado lo del disable_interrupts(INT_EXT) a secas en la función de interrupción y no iva del todo bien, supongo que tardaba menos en ejecutar el código de la interrupción que el botón en dejar de rebotar. He tenido que añadir un delay de todas formas.

Igual hago algo mal, pero bueno, así funciona bien.

Cuando la monte del todo os pongo un vídeo, aunque la lámapra es igual a la típica del youtube (moodlamp) comprada en el ikea pero con un código propio.

Un saludo!!


 

anything