Autor Tema: ayuda con un pwm en pic ccompiler  (Leído 2883 veces)

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

Desconectado CcBeNiTocC

  • PIC10
  • *
  • Mensajes: 14
ayuda con un pwm en pic ccompiler
« en: 16 de Febrero de 2018, 20:04:08 »
buen día, chicos me comunico con ustedes para saber si me pueden asesorar en la creación de un pwm para controlar unos leds rgb para una lampara , que vallan de rojo a morado que cambien muy lentamente y que llegue al blanco, el problema es que ya he visto barios vídeos de youtube y no he podido comprender como hacerlo ya que es para el pic 12f629. y me confunde bastante como activar el pwm en este pic y aun mas como saco la señal según el timer del propio pic.   

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:ayuda con un pwm en pic ccompiler
« Respuesta #1 en: 16 de Febrero de 2018, 20:51:24 »
El PIC12F629 no tiene modulo de PWM por lo tanto no lo vas a poder "activar"

Vas a tener que hacer un PWM por software, trata de crear eso y de alli en adelante es simple.
La idea es que aprendas que es un PWM y como realizarlo, luego le agregas 2 salidas correspondiente a los otros colores.

Desconectado CcBeNiTocC

  • PIC10
  • *
  • Mensajes: 14
Re:ayuda con un pwm en pic ccompiler
« Respuesta #2 en: 17 de Febrero de 2018, 11:50:54 »
ok, mm y yo como creo un pwm desde sofware, jejejejeje :D :D hay si me confundí  :-)

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:ayuda con un pwm en pic ccompiler
« Respuesta #3 en: 17 de Febrero de 2018, 13:11:56 »
Primero buscaria que es un PWM, como es la forma de la señal de la onda, y que es lo que varia en esa onda. Cuando tengas eso visto te vas a dar cuenta que lo unico que tenes que hacer es activar una de las salidas luego de un tiempo determinado y apagarlas todas juntas.

Desconectado CcBeNiTocC

  • PIC10
  • *
  • Mensajes: 14
Re:ayuda con un pwm en pic ccompiler
« Respuesta #4 en: 25 de Febrero de 2018, 00:55:18 »
buen día, asta el momento este es el pwm que tengo el problema es que quiero que la variación de color sea muy lenta de 5 a 10 m mas o menos, me gustaría saber si puedo llegar a esos valores ya que no entiendo muy bien que digamos la ecuación del manejo del pwm y el tiempo de maquina

#include <12f629.h>
#TX,NOWDT,NOMCLR,BROWNOUT
#use delay(clock=4M)
#int_timer0
void pwm_duty(int pwm0, int pwm1, int pwm2){
   int cont;
   if(cont>16)
      cont=0;
   else
      cont++;
   if(cont>0&&cont<pwm0)
      output_high(PIN_A0);
   else
      output_low(PIN_A0);
   if(cont>0&&cont<pwm1)
      output_high(PIN_A1);
   else
      output_low(PIN_A1);
   if(cont>0&&cont<pwm2)
      output_high(PIN_A2);
   else
      output_low(PIN_A2);
   set_timer0(0);     
}
void main(){
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   set_timer0(0);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);
   while(true){
      int r, g, b;
      int time = 50;
      int c = 50;
      for(b=0;b<49;b++){
         pwm_duty(c,0,b);
         delay_ms(time);
      }
      for(r=c;r>1;r--){
         pwm_duty(r,0,c);
         delay_ms(time);
      }
      for(g=0;g<49;g++){
         pwm_duty(0,g,c);
         delay_ms(time);
      }
      for(b=c;b>1;b--){
         pwm_duty(0,c,b);
         delay_ms(time);
      }     
      for(r=0;r<49;r++){
         pwm_duty(r,c,0);
         delay_ms(time);
      }
      for(g=c;g>1;g--){
         pwm_duty(c,g,0);
         delay_ms(time);
      }
   }
}

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:ayuda con un pwm en pic ccompiler
« Respuesta #5 en: 25 de Febrero de 2018, 12:08:31 »
No estas comprendiendo lo que estas haciendo. Voy a hacer una explicacion pero sin entrar en mucho detalles y sin preocuparme por la exactitud de los calculos y/o operaciones.

Cuando uno quiere usar un PWM le quedan varias opciones:

- Usar por Hardware en caso de que tenga 3 salidas independientes
- Crearlo por software, aca hay 2 formas:
           -  Usar un delay dentro del while(1). La ventaja es que es mas simple de realizar, la desventaja es que si haces algo mas en el main, ese tiempo extra afecta.
           -  En ves de usar un delay y poder hacer lo que uno quiera en el main, es usar una interrupcion


Con delay seria algo asi, como vos tenes el main:

Código: C
  1. for(b=0;b<49;b++){
  2.          pwm_duty(c,0,b);
  3.          delay_ms(time);
  4.       }

PERO llegamos a otro punto de tu programa y vemos que:

Código: C
  1. setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
  2.    set_timer0(0);
  3.    enable_interrupts(INT_TIMER0);

Estamos usando Interrupciones!!!

NUNCA NUNCA NUNCA llames desde tu main a una interrupcion

-------------------------------------------------------------------------------------------------------------------------------

Otra parte erronea es la implementacion del PWM, si vos queres hacer un PWM, tenes que definir una frecuencia y la granularidad del duty.
Ejemplo si quisiera una frecuencia de 100Hz mi PWM deberia tener un periodo de 1/100Hz = 10ms
Ahora si quisiera que yo puedo dividir ese tiempo (con mi duty ) en 50 pedazos aproximadamente, deberia tener una interrupcion cada  10ms / 50 = 200us

Definido los parametros del PWM ya ahora tengo los valores para poder configurar mi Timer ( calcular el overflow  y el valor de recarga)

Luego solo debo comparar los valroes que yo le paso con los que va contando el PWM. ¿Como funciona el PWM?
Al principio todas las salidas se encuentran encendidas, luego cuando la cuenta es igual a la definida por nuestra variable PWM procedemos apagarla, asi si definimos un duty de 0 tenemos un minimo.

Como deberias prodecer entonces?

En el main estamos poniendo valores hasta 48 entonces vamos a usar ese valor como maximo. Para eso vamos primero a revisar la funcion de la interrupcion:

Código: C
  1. #int_timer0
  2. void pwm_duty(void){
  3.         set_timer0(0);      
  4.         if(cont>48)
  5.         {
  6.                 cont=0;
  7.                 output_high(PIN_A0);
  8.                 output_high(PIN_A1);
  9.                 output_high(PIN_A2);
  10.         }
  11.  
  12.         if(cont>pwmR)
  13.                 output_low(PIN_A0);
  14.         if(cont>pwmG)
  15.                 output_low(PIN_A1);
  16.         if(cont>pwmB)
  17.                 output_low(PIN_A2);
  18.  
  19.         cont++;
  20.  
  21. }

Luego en tu main, solo te importa actualizar los valroes de pwmR,G y B:
La velocidad de cambio va a estar dada por los delay_ms(time), asi que si queres que sea mas lenta, simplemente cambias el valor de ese delay.

Código: C
  1. while(true)
  2.         {
  3.                 int i;
  4.  
  5.                 pwmR = 50;
  6.                 pwmG = 0;
  7.                 for(i=0;i<49;i++){
  8.                         pwmB = i;
  9.                         delay_ms(time);
  10.                 }
  11.  
  12.                 pwmB = 50;
  13.                 pwmG = 0;
  14.                 for(i=48;i>1;i--){
  15.                         pwmR = i
  16.                         delay_ms(time);
  17.                 }

PD:

Afuera de todas las funciones debes declarar las variables:

Código: C
  1. volatile int pwmR,pwmG,pwmB;
  2. int cont;

Desconectado CcBeNiTocC

  • PIC10
  • *
  • Mensajes: 14
Re:ayuda con un pwm en pic ccompiler
« Respuesta #6 en: 25 de Febrero de 2018, 19:18:51 »
gracias, implementare todo lo que me dijiste y analizare para si comprenderlo todo ya que al parecer me metí un enrredon con el pwm, pero ya he visto como 10 videos de pwm y ya lo entiendo mas, la cosa es entender lo que es el duty cicle. aun así gracias la verdad llevo con esta duda como desde la semana pasada y asta el momento nadie me ah ayudado =)

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:ayuda con un pwm en pic ccompiler
« Respuesta #7 en: 25 de Febrero de 2018, 19:43:18 »
Citar
la cosa es entender lo que es el duty cicle.

En el ejemplo que te di, imaginate que esos 10ms de periodo lo dividis en 50 pedazos,vos fijas hasta que pedazo de tiempo esta encendido, es decir si queres 0 de duty entonces con decirle que desde el 0 apague la salida tendrias eso, y pasarian todos esos "pedacitos" de tiempo la salida en 0. Si quisieras un 50% de duty, tendrias 25 "pedacitos" de tiempo en 1 la salida y otros 25 en 0. Eso es el duty.

Obviamente mientras mas cantidad de pedazos se pueda dividir mas fino es la regulacion de la salida. Pero al hacerlo por software como lo estas haciendo, tiene sus limites.
Imaginate si a 10ms lo quiero dividir en 1024, deberia hacer una interrupcion cada 9us, donde tu micro ejecuta una instruccion de bajo nivel a 1us (a 4Mhz), ya solo el salto a la interrupcion tendrias ocupado el tiempo y ya no cumplirias con actualizar las salidas cada 9us, entonces no tiene sentido ir a este punto haciendolo por software.
« Última modificación: 25 de Febrero de 2018, 19:47:31 por KILLERJC »