TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: septiembre_negro en 21 de Mayo de 2010, 14:29:15

Título: calcular pwm
Publicado por: septiembre_negro en 21 de Mayo de 2010, 14:29:15
Hola  
 Pues resulta que ya me líe al grado de no entender ni m%&%$%&.
Más que nada por que no e encontrado dos ejemplos que resuelvan el cálculo del pmw de la misma forma.
El ejemplo que mejor e entendido es que les pongo a continuación en cual tiene dos defectos el primero que al camarada que puso el ejemplo no le contestaron si su procedimiento  es correcto.
Segundo que en su ejerció sustituyo las literales por los valores por lo cual no termino de entender.
Así que si alguien puede decirme si el ejerció es correcto y cuales serian las formulas que utilizo. Se lo agradezco de antemano



aquí el ejemplo:
Citar
cristal del pic 4MHz, Preescaler 1:1, ciclo de trabajo del PWM 50% y frecuancia del PWM igual a 20KHz

Periodo PWM= 1/20KHz = 50us

Tosc= 1/ 4MHz =250ns

PR2= (50us/(4*250ns*1))-1 = 49

CTPWM 50%= Periodo PWM / 2 = 25us

CCPR1L:CCP1CON = 25us/(250ns*1) = 100

por lo tanto la configuración de esto es:

setup_ccp1(ccp_PWM);
setup_timer_2(t2_div_By_1,49,1);
set_pwm_duty(100);



Ahora suponiendo que el ejercicio es correcto y quisiera cambiar el siclo de trabajo del 50% al 75 por ciento que tendría  que hacer  en esta parte.
Citar

CTPWM 50%= Periodo PWM / 2 = 25us

De verdad que ya le busque y solo me enredo mas


Título: Re: calcular pwm
Publicado por: Mando31 en 23 de Mayo de 2010, 23:09:28
Te recomiendo ver el libro Compilador C CCS y Simulador Proteus Para Microcontroladores PIC, te dejo un MP, suerte.
Título: Re: calcular pwm
Publicado por: Mario en 26 de Mayo de 2010, 12:06:39
Hola septiembre negro,

¿solucionaste tu problema?

No es muy complicado entender el funcionamiento, pero si debes especificar si utilizarás la resolución completa de 10 bits u ocho, el compilador de CCS no distingue, debes forzar a la variable o número para que lo tome de una u otra manera.
Título: Re: calcular pwm
Publicado por: septiembre_negro en 26 de Mayo de 2010, 17:43:21
Hola septiembre negro,

¿solucionaste tu problema?

No es muy complicado entender el funcionamiento, pero si debes especificar si utilizarás la resolución completa de 10 bits u ocho, el compilador de CCS no distingue, debes forzar a la variable o número para que lo tome de una u otra manera.


Hola
Pues  ya me alcance el libro compilador ccs y simulación en proteus , pero sigo empelotado se tiran unas formulas que me marean  :shock: :shock:  agradecería si alguien puede explicarme el ejercicio que colgué.
Básicamente lo que intento es variar la velocidad de un motor   cambiando  el ciclo de trabajo al 20% ,50% ,75%.
Pero ahora si que no doy pie con bola  :? :?mientras unos ejercicios hablan de variar el ciclo de trabajo otros hablan de variar la frecuencia
Título: Re: calcular pwm
Publicado por: Mario en 27 de Mayo de 2010, 07:12:46
Pues vamos viendo......



Supongamos que se desea una frecuencia de 1KHz a un ciclo de trabajo de 50% con una frecuencia del oscilador de 4MHz.


Lo primero es revisar la hoja de datos (en mi caso el 16F887 o cualquiera que tenga CCP).

Establece una fórmula
PWM Period = [(PR2)+ 1]•4•TOSC •(TMR2 Prescale Value)

Pero es menos complicado si se contempla en función de la frecuencia (recordar que f=1/t):
Fpwm=  [(Fosc)/(PR2+1)*(TMR2 Prescale Value)*(4)]

Lo que interesa es el PR2 ya que es el registro del periodo para la frecuencia (revisar fórmula de hoja de datos):
PR2= [(Fosc)/(Fpwm)*(TMR2 Prescale Value)*(4)]-1

PR2 debemos recordar que es de 8 bits, por lo que el valor máximo no debe exceder 255 (muy importante).


Si se desea 1KHz tenemos básicamente dos opciones:


Si tomamos la segunda entonces tenemos tres opciones: 1, 4 y 16.

Con 1:
PR2= [(4MHz)/(1KHz)*(1)*(4)]-1
PR2=1000-1  <---bien importante no olvidarse del -1

PR2=999

Con 1 no sirve, ya que se pasa de los 8 bits.



Con 4:
PR2= [(4MHz)/(1KHz)*(4)*(4)]-1

PR2=249

Con 4 sirve.



Con 16:
PR2= [(4MHz)/(1KHz)*(16)*(4)]-1

PR2=62.5

Con 16 podría servir pero..... el registro no almacena decimales, solo enteros; lo anterior nos proporciona dos posibles caminos:

Si PR2=62, entonces la Fpwm será:
Fpwm=  [(Fosc)/(PR2+1)*(TMR2 Prescale Value)*(4)]
Fpwm=  [(4MHz)/(62+1)*(16)*(4)]
Fpwm=  992.0634 Hz

Lo anterior entrega un error de 0.8% aproximadamente.



Si PR2=63, entonces la Fpwm será:
Fpwm=  [(Fosc)/(PR2+1)*(TMR2 Prescale Value)*(4)]
Fpwm=  [(4MHz)/(63+1)*(16)*(4)]
Fpwm=  976.5625 Hz

Lo anterior entrega un error de 2.4% aproximadamente.



La ideal es PR2=249 con preescalador a 4; cabe señalar que solo estamos en la frecuencia.



Para el PWM es algo similar pero, el CCS utiliza funciones donde el comportamiento no es tan transparente como se desearía.


Recordar que
Pulse Width =(CCPRxL:CCPxCON<5:4>) •TOSC • (TMR2 Prescale Value)



y que

Duty Cycle Ratio= (CCPRxL:CCPxCON<5:4>)
                           --------------------------------
                                       4(PR2 + 1)


El ciclo de trabajo ya se conoce (es el deseado), por lo que interesa es el valor de CCPRxL:CCPxCON<5:4>. En C o en BASIC es relativamente sencillo colocar ese valor, en ensamblador no tanto. Lo anterior debido a que los bits 5 y 4 de CCPxCON son los de menor peso y se debe realizar un corrimiento con todo CCPRxL.


Aquí es donde se torna algo confuso (para la mayoría):

suponiendo un ciclo de trabajo de 50%, significa que el valor donde se repite el periodo (PR2+1) es 250, el valor medio sería 125, por lo que CCPRxL deberá tomar ese valor.
CCPRxL toma el valor ya que es el registro de mayor peso para el ciclo de trabajo, los otros dos bits no afectan.

Lo anterior es si deseas utilizar el PWM en "modo de 8 bits"  (no existe tal modo, pero trabaja asi). Si deseas utilizar los 10 bits de resolución, deberás utilizar esos dos bits de menor peso.

Esos dos bits de menor peso siempre producirán 4 combinaciones adicionales (00,01,10,11) a las 256 del CCPRxL y, como sabemos 10bits=1024. El máximo valor que tendrás será 1023.

Si PR2 es 249, y PR2+1 =250, entonces el valor para el ciclo de trabajo crece de 250 a 1000, dando 4 veces el original (debido a esos dos bits).

Aqui está la situación:
para utilizar los 10 bits de resolución el CCS debe saber que el parámetro de set_pwm_duty() es un entero de 16 bits (INT16 o LONG), de otra manera lo tomará como 8 bits (solo tomará el CCPRxL).

Coloca esto:
setup_ccp1(ccp_PWM);
setup_timer_2(t2_div_By_4,249,1);
set_pwm_duty(125);

Coloca esto:
setup_ccp1(ccp_PWM);
setup_timer_2(t2_div_By_4,249,1);
set_pwm_duty(500L);

Verás que no hay cambio.

Si tu micro cuenta con dos CCP, coloca uno con 125 y otro con 500.

Te mandaría la simulación en registros del MPLAB pero me son las 3:10 AM aquí y ya casi entro a trabajar.


Cualquier cosa estamos siguiendo el hilo.
Título: Re: calcular pwm
Publicado por: septiembre_negro en 28 de Mayo de 2010, 11:30:43
Mas claro imposible   :-/ :-/ :-/ ;  de verdad te agradezco mucho, sobre todo por el tiempo que te as tomado en dar una explicación tan completa de seguro a alguien mas le servirá  ;-)
Título: Re: calcular pwm
Publicado por: septiembre_negro en 30 de Mayo de 2010, 18:03:18
Hola
Después de haber solucionado el problema de configurar el pwm, pues resulta que el motor pierde torque al conectar el motor directamente a vcc opera  de  forma correcta al aplicar el pwm la perdida de torque es tal que incluso el motor se puede detener con la mano .
No entiendo  cual pudiera ser el problema se entiende que a un pwm del 100% el motor debería estar a su máximo.
Un amigo me dice que a menor pwm mayor torque pero esto tampoco se cumple,
Estoy seguro que esta configurado correctamente ya que en el osciloscopio la señal que se observa  corresponde al duty_cicle que configuro 25% ,50%,100%.
Así que  lo único que se me ocurre es que estoy aplicando  mal el pwm al cto.
Estoy utilizando un l2724 como puente h y  para inyectar el pwm lo que ago es  aplicar el pwm a  la base de un  transistor de potencia que conecta y desconecta   12vcc que llegan  al l2724.
Cualquier sugerencia es bienvenida
 
Título: Re: calcular pwm
Publicado por: japifer_22 en 30 de Mayo de 2010, 19:17:45
hola septiembre_negro, bueno te comento, lo que puede pasarte son varias cosas;

primero alomejor tu motor no es del voltaje del cual le estas aplicando, en ocaciones suele suseder esto, por ejemplo si tienes un motor de 9V y le inyectas 12V en este caso te aumenta las RPM pero no el torque, por que este te desminuira.

segundo alomejor tu driver no tiene la corriente que requiere el motor.

alomejor estas aplicando un driver dañado.

lo otro que puede ser, es que la frecuencia del PWM no es la correcta para tu motor, y como saver cual es la mas indicada para esto??, bueno lo que yo hice en un momento dado y por la sujerencia de varios en este foro fue que a mas bajo empiesa a funcionar el motor del PWM va a ser mejor el decempeño del motor. por ejemplo le aplico 5 PWM de distintas frec, por ejemplo de 8KHz, 13KHz, 15KHz, 18KHz o 20KHz y los pruebo de a 1 con un duty cicle del 10% por ejmplo y veo si el motor me parte con alguna de estas frecuencias al 10% del duty y si es así, es la recomendada para tu motor.

de todas formas, te dejo una simulacion y el codigo, el cual hice para probar los PWM para unos motores que estoy usando. el programa que hice le puse 9 PWM diferentes con un rango de trabajo del 0 a 100%.
en la simulacion tambien te dejo un driver que uso yo para la parte de potencia del pic, en donde se conecta directo el motor.

bueno espero que te sirva de algo.

el codigo es este:

Código: [Seleccionar]
#include <16F873a.h>
#device adc=10
#FUSES NOWDT, HS, NOPUT, NOPROTECT, BROWNOUT, NOLVP, NOCPD, NOWRT
#use delay (clock=4000000) //Fosc=20Mhz
#define use_portb_lcd TRUE //definir portb lcd
#include<lcd420.c> //libreria manejo lcd de 20x4 modificada por suky para el puerto D
#use standard_io(A)
#use standard_io(C)

void frecuencia_20KHz(void);

void frecuencia_18KHz(void);

void frecuencia_16KHz(void);

void frecuencia_14KHz(void);

void frecuencia_12KHz(void);

void frecuencia_10KHz(void);

void frecuencia_8KHz(void);

void frecuencia_6KHz(void);

void frecuencia_5KHz(void);


int16 a;//variables para el PWM
int frecuencia,frec,b=20;
float c,e;


void main(){//programa principal
lcd_init();         //inicializa lcd

  while(true){
      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A0));            //...rebotes del boton
     if(frecuencia<=9){
     frecuencia++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A1));            //...rebotes del boton
     if(frecuencia>=2){
     frecuencia--;
     }}
     lcd_gotoxy(1,1);
     printf(lcd_putc,"Escoja una frec ");
     lcd_gotoxy(1,2);
     printf(lcd_putc,"de PWM. opt 1-10");
     lcd_gotoxy(1,3);
     printf(lcd_putc,"Frec %i ",frecuencia);
     lcd_gotoxy(1,4);
     printf(lcd_putc,"                ");     
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A2));            //...rebotes del boton     
   frec=frecuencia;
      }
      else{
      frec=0;
      }
     
switch( frec )
   {
   case 1:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 20KHz");
         frecuencia_20KHz();
           break;
   case 2:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 18KHz");   
         frecuencia_18KHz();
           break;
   case 3:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 16KHz");   
         frecuencia_16KHz();
           break;
   case 4:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 14KHz");   
         frecuencia_14KHz();
           break;
   case 5:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 12KHz");   
         frecuencia_12KHz();
           break;
   case 7:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 10KHz");   
         frecuencia_10KHz();
           break;

   case 8:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 8KHz ");   
         frecuencia_8KHz();
           break;
   case 9:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 6KHz ");   
         frecuencia_6KHz();
           break;
   case 10:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 5KHz ");   
         frecuencia_5KHz();
           break;           

   } }
}

void frecuencia_20KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 49, 1);
   
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
   
   while(TRUE){
   
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=198){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
   
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM  ");
      e=b;
      c=(e*100)/200;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f ",c);   
     
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A2));            //...rebotes del boton
       
        break;
        }
   }
   
}


void frecuencia_18KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 54, 1);
   
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
   
   while(TRUE){
   
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=220){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM2  ");
      e=b;
      c=(e*100)/222;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);     
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A2));            //...rebotes del boton
       
        break;
        }
}}

void frecuencia_16KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 61, 1);
   
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
   
   while(TRUE){
   
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=248){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM3  ");
      e=b;
      c=(e*100)/250;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A2));            //...rebotes del boton
       
        break;
        }
}}

void frecuencia_14KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 70, 1);
   
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
   
   while(TRUE){
   
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=283){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM4  ");
      e=b;
      c=(e*100)/285;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);     
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A2));            //...rebotes del boton
       
        break;
        }
}}

void frecuencia_12KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 82, 1);
   
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
   
   while(TRUE){
   
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=331){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM5  ");
      e=b;
      c=(e*100)/333;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A2));            //...rebotes del boton
       
        break;
        }
}}

void frecuencia_10KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 99, 1);
   
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
   
   while(TRUE){
   
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=398){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM7  ");
      e=b;
      c=(e*100)/400;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);     
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A2));            //...rebotes del boton
       
        break;
        }
}}

void frecuencia_8KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 124, 1);
   
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
   
   while(TRUE){
   
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=498){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM8  ");
      e=b;
      c=(e*100)/500;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);     
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A2));            //...rebotes del boton
       
        break;
        }
}}

void frecuencia_6KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 165, 1);
   
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
   
   while(TRUE){
   
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=664){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM9  ");
      e=b;
      c=(e*100)/666;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);     
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A2));            //...rebotes del boton
       
        break;
        }
}}
void frecuencia_5KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 199, 1);
   
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
   
   while(TRUE){
   
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=798){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM10  ");
      e=b;
      c=(e*100)/800;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...           
         }while(!input(PIN_A2));            //...rebotes del boton
       
        break;
        }
}}

(http://img706.imageshack.us/img706/466/ctodepotenciaasta5amp.jpg)
saludos!



Título: Re: calcular pwm
Publicado por: septiembre_negro en 31 de Mayo de 2010, 23:22:10
hola septiembre_negro, bueno te comento, lo que puede pasarte son varias cosas;

primero alomejor tu motor no es del voltaje del cual le estas aplicando, en ocaciones suele suseder esto, por ejemplo si tienes un motor de 9V y le inyectas 12V en este caso te aumenta las RPM pero no el torque, por que este te desminuira.

segundo alomejor tu driver no tiene la corriente que requiere el motor.

alomejor estas aplicando un driver dañado.

lo otro que puede ser, es que la frecuencia del PWM no es la correcta para tu motor, y como saver cual es la mas indicada para esto??, bueno lo que yo hice en un momento dado y por la sujerencia de varios en este foro fue que a mas bajo empiesa a funcionar el motor del PWM va a ser mejor el decempeño del motor. por ejemplo le aplico 5 PWM de distintas frec, por ejemplo de 8KHz, 13KHz, 15KHz, 18KHz o 20KHz y los pruebo de a 1 con un duty cicle del 10% por ejmplo y veo si el motor me parte con alguna de estas frecuencias al 10% del duty y si es así, es la recomendada para tu motor.

de todas formas, te dejo una simulacion y el codigo, el cual hice para probar los PWM para unos motores que estoy usando. el programa que hice le puse 9 PWM diferentes con un rango de trabajo del 0 a 100%.
en la simulacion tambien te dejo un driver que uso yo para la parte de potencia del pic, en donde se conecta directo el motor.

bueno espero que te sirva de algo.

el codigo es este:

Código: [Seleccionar]
#include <16F873a.h>
#device adc=10
#FUSES NOWDT, HS, NOPUT, NOPROTECT, BROWNOUT, NOLVP, NOCPD, NOWRT
#use delay (clock=4000000) //Fosc=20Mhz
#define use_portb_lcd TRUE //definir portb lcd
#include<lcd420.c> //libreria manejo lcd de 20x4 modificada por suky para el puerto D
#use standard_io(A)
#use standard_io(C)

void frecuencia_20KHz(void);

void frecuencia_18KHz(void);

void frecuencia_16KHz(void);

void frecuencia_14KHz(void);

void frecuencia_12KHz(void);

void frecuencia_10KHz(void);

void frecuencia_8KHz(void);

void frecuencia_6KHz(void);

void frecuencia_5KHz(void);


int16 a;//variables para el PWM
int frecuencia,frec,b=20;
float c,e;


void main(){//programa principal
lcd_init();         //inicializa lcd

  while(true){
      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A0));            //...rebotes del boton
     if(frecuencia<=9){
     frecuencia++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A1));            //...rebotes del boton
     if(frecuencia>=2){
     frecuencia--;
     }}
     lcd_gotoxy(1,1);
     printf(lcd_putc,"Escoja una frec ");
     lcd_gotoxy(1,2);
     printf(lcd_putc,"de PWM. opt 1-10");
     lcd_gotoxy(1,3);
     printf(lcd_putc,"Frec %i ",frecuencia);
     lcd_gotoxy(1,4);
     printf(lcd_putc,"                ");    
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A2));            //...rebotes del boton    
   frec=frecuencia;
      }
      else{
      frec=0;
      }
      
switch( frec )
   {
   case 1:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 20KHz");
         frecuencia_20KHz();
           break;
   case 2:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 18KHz");  
         frecuencia_18KHz();
           break;
   case 3:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 16KHz");  
         frecuencia_16KHz();
           break;
   case 4:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 14KHz");  
         frecuencia_14KHz();
           break;
   case 5:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 12KHz");  
         frecuencia_12KHz();
           break;
   case 7:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 10KHz");  
         frecuencia_10KHz();
           break;

   case 8:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 8KHz ");  
         frecuencia_8KHz();
           break;
   case 9:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 6KHz ");  
         frecuencia_6KHz();
           break;
   case 10:
         lcd_gotoxy(1,1);
         printf(lcd_putc,"Frec de 5KHz ");  
         frecuencia_5KHz();
           break;          

   } }
}

void frecuencia_20KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 49, 1);
  
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
  
   while(TRUE){
  
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=198){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
    
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM  ");
      e=b;
      c=(e*100)/200;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f ",c);    
      
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A2));            //...rebotes del boton
        
        break;
        }
   }
    
}


void frecuencia_18KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 54, 1);
  
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
  
   while(TRUE){
  
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=220){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM2  ");
      e=b;
      c=(e*100)/222;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);      
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A2));            //...rebotes del boton
        
        break;
        }
}}

void frecuencia_16KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 61, 1);
  
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
  
   while(TRUE){
  
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=248){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM3  ");
      e=b;
      c=(e*100)/250;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A2));            //...rebotes del boton
        
        break;
        }
}}

void frecuencia_14KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 70, 1);
  
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
  
   while(TRUE){
  
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=283){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM4  ");
      e=b;
      c=(e*100)/285;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);      
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A2));            //...rebotes del boton
        
        break;
        }
}}

void frecuencia_12KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 82, 1);
  
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
  
   while(TRUE){
  
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=331){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM5  ");
      e=b;
      c=(e*100)/333;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A2));            //...rebotes del boton
        
        break;
        }
}}

void frecuencia_10KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 99, 1);
  
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
  
   while(TRUE){
  
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=398){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM7  ");
      e=b;
      c=(e*100)/400;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);      
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A2));            //...rebotes del boton
        
        break;
        }
}}

void frecuencia_8KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 124, 1);
  
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
  
   while(TRUE){
  
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=498){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM8  ");
      e=b;
      c=(e*100)/500;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);      
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A2));            //...rebotes del boton
        
        break;
        }
}}

void frecuencia_6KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 165, 1);
  
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
  
   while(TRUE){
  
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=664){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM9  ");
      e=b;
      c=(e*100)/666;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);      
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A2));            //...rebotes del boton
        
        break;
        }
}}
void frecuencia_5KHz(void){

   setup_ccp1(CCP_PWM); //ccp1 modo PWM
   setup_timer_2(T2_DIV_BY_1, 199, 1);
  
   a=20;   // punto medio del duty de 10 bits
   set_pwm1_duty(a);//duty cycle con una variable para variar el PWM
  
   while(TRUE){
  
      set_pwm1_duty(a);//duty cycle con una variable para variar el PWM

      if(!input(PIN_A0)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A0));            //...rebotes del boton
     if(a<=798){
     a++;
     b++;
     }}
      if(!input(PIN_A1)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A1));            //...rebotes del boton
     if(a>=2){
     a--;
     b--;
     }}
      lcd_gotoxy(1,2);
      printf(lcd_putc,"PWM10  ");
      e=b;
      c=(e*100)/800;
      lcd_gotoxy(1,4);
      printf(lcd_putc,"PWM= %f",c);
      if(!input(PIN_A2)){                  //¿se ha pulsado el boton?
         do{                           //SI -> eliminar...            
         }while(!input(PIN_A2));            //...rebotes del boton
        
        break;
        }
}}

(http://img706.imageshack.us/img706/466/ctodepotenciaasta5amp.jpg)
saludos!








Hola
Te agradezco, los archivos de proteus están excelentes bastante didácticos     :-/ :-/ :-/ .
Ahora me queda claro mi error, es  producto de mi ignorancia; resulta que el motor que tengo bajo tortura es de 5.6 v y al  puente h le aplico 12vcc  :mrgreen: , esto es debido  a que el driver que utilizo el voltaje del motor debe ser superior al voltaje de la parte lógica 5vcc.  así que no teniendo otro motor a  mano  se me hizo fácil conectarlo  :oops: .


Título: Re: calcular pwm
Publicado por: japifer_22 en 01 de Junio de 2010, 20:14:32
que bueno que te allas dado cuenta del error. saludos! :lol:
Título: Re: calcular pwm
Publicado por: yeremayo en 01 de Diciembre de 2010, 04:53:33
Hola japifer_22 espero que no sea demaciado tarde para comentarte esto, antes que nada un saludo te comento que lleve a cabo el circuito que propones para el pwm en mi proto board y lamentablemente no logre nada voy a seguirle intentando pero me gustaria que me guiaras sobre que voltajes debo tener en los transistores, si la frecuencia se altera al pasar por la primera resistencia y a cuanto se altera, no cuento con un osciloscopio pero tengo un frecuenciometro y al medir a la salida del pic tengo los 20khz que quiero pero al pasar de la primera resistencia la frecuencia medida por mi frecuenciometro sube a mas de 100khz eso es normal? ya revise la resistencia y esta correcta (4.7k) pero el motor nunka se mueve.

un saludo
Título: Re: calcular pwm
Publicado por: ilcapo_cba en 29 de Diciembre de 2013, 11:11:01
hola expertos!

al circuito de la figura mostrada para conectar los moteres,,se puede conectar a 24V ? porque tengo motorcitos de esa tension, gracias
Título: Re: calcular pwm
Publicado por: estalli2 en 29 de Octubre de 2014, 09:31:12
 :-/ :-/ GRACIAS japifer_22! TAMBIEN VENIA BUSCANDO UNA BUENA EXPLICACION HACE TIEMPO!  ((:-)) ((:-)) ((:-))
Título: Re: calcular pwm
Publicado por: gabrielnbr89 en 14 de Julio de 2015, 19:13:22
Hola gente! Estuve estudiando este tema con la hoja de datos a mano com es costumbre... Se trata del PIC18F4550. En la sección
"CAPTURE/COMPARE/PWM MODE->PWM Mode" (pag. 148) hay un diagrama simplificado del módulo CCP2 cuando se trabaja en modo PWM. y Luego aparecen las ecuaciones que dan el período de la señal y el ciclo de trabajo.
Viendo dicho diagrama y el diagrama del temporizador 2 es fácil entender de donde sale la ecuación que nos da el período de la señal. Pero no logro entender como sale la ecuación para el ciclo de trabajo.
No entiendo por que desaparece el factor "4" de la ecuación?!!! A caso para el ciclo de trabajo [CCPR"L:CCP2CON<5:4>] no se compara con el timer 2?
Alguien lo entiende? O es que al simplificarse el diagrama se pierde información explicita de lo qu epregunto?

Ademas andando por ahi encontre esta ecuación:
DC=( [CCPR"L:CCP2CON<5:4>]*(Pre-escalar del timer2) ) / (FOSC*Tpwm)
Que da un valor entre 1 y 0. Aparentemente nos da digamos el porcentaje del ciclo de trabajo con respecto al período de la señal. Pero como se deduce ésta ecuación? es corecta?

Espero sus respuestas... saludos!!
Título: Re: calcular pwm
Publicado por: KILLERJC en 14 de Julio de 2015, 21:08:06
Estoy mas que seguro que es por que el timer2 es de 8 bits, entonces como haces para compararlo con un valor de 10 bits ?

Al timer2 se le anexa o concatena 2 bits mas ( o un reloj interno (imagino que Fosc) o el preescaler segun el datasheet), quedando:

TMR2:2bits

Pero hacer eso es lo mismo que si al TMR2 lo multiplicas por 4, ya que estas rotando su posicion, por eso desaparece el 4.

Lo que dependa que sea el reloj interno o el preescaler esos ultimos bits , es segun el preescaler del TMR2,
Si es 1/16 y sabiendo que ya tenes 1/4 desde la entrada(del Fosc), esos 2 bits sera un reloj de Fosc/4
Si es 1/4 , entonces o puede usar el reloj del cristal con un 1/2 si no me equivoco.
Y si es 1/1, ya ahi deberia usar el reloj del cristal directo para esos ultimos 2 bits.

Al menos es lo que yo haria :).

Citar
Pero como se deduce ésta ecuación? es corecta?

DC=( [CCPR"L:CCP2CON<5:4>]*(Pre-escalar del timer2) ) / (FOSC*Tpwm)

Acomodemosla un poco diferente

DC=( [CCPR"L:CCP2CON<5:4>]*(Pre-escalar del timer2) ) * Tosc/ (Tpwm)

DC = Ton / (Toff + Ton)

Ton + Toff = Tpwm  En eso no hay duda

ton = [CCPR"L:CCP2CON<5:4>]*(Pre-escalar del timer2) ) * Tosc

Acordate que de aca al comparar se multiplico por 4 el TMR2, o para si queres hacerlo equivalente seria dividir los CCPR por 4, y que luego multiplicado por el 4*Tosc se va.
Título: Re: calcular pwm
Publicado por: gabrielnbr89 en 15 de Julio de 2015, 00:53:41
Claro! entiendo... En algun lugar de mi gran cabeza habia algo que me decía que tenia que ver con eso mismo, la comparación entre un valor de 8 bits contra uno de 10 bits. De principio intuía la misma relación que haces vos con el pre-escalar en 1:1. Pero lo impresionante es que hiciste las otras deducciones en la dirección correcta! Mientras que yo las intentaba hacer en la dirección opuesta y no entendía por que esos dos ultimos bits me cambiaban de valor tan rápidamente!! :z) . en otras palabras, mientras que vos dividís la frecuencia FOSC yo intentaba multiplicarla, se entiende?. Pero claro haciendo lo que vos, ese factor "4" desaparece siempre... Mil gracias!
Lo mismo con la fórmula, intentaba ir al reves pero claro, nunca iba a llegar a la tésis partiendo desde algo equivocado ya que no tenía claro que pasaba con ese maldito 4!
Clarísimo...
Ahora, una última duda, entiendo que FOSC no es directamente la frecuencia del cristal conectado a OSC1 y OSC2 ¿no es asi?. Si no que FOSC es la frecuencia que llega finalmente al CPU despues de pasar por algunos PLL y pre-escalares. Es decir, en mi caso tengo un cristal de 20MHz. pero como uso el PIC con Bootloader, éste configura los preescalares para obtener una frecuencia de 48MHz en el módulo USB y viendo el código del Bootloader, hace llegar esa misma frecuencia al CPU. Finalmente FOSC en el timer2 es en mi caso 48MHz?
Además intuyo que ese "4" en FOSC/4 se debe a que cada cuatro ciclos de reloj se da una ejecución. Por eso insisto en que FOSC es 48MHz en mi caso.

Mil Gracias! SALUDOS!
Título: Re: calcular pwm
Publicado por: KILLERJC en 15 de Julio de 2015, 03:36:08
Si pensalo de esta forma... Fosc siempre se le llamo a la frecuencia que ingresa al core y luego se divide por 4 (O sea la frecuencia antes de la ultima etapa que se divide por 4 para lso modulos). Puede ser un cristal, un reloj externo o puede ser como es en el caso de este PIC, en el que posee un PLL interno y luego preescaler, entonces lo que entra al PIC vendria a ser justo esos 48Mhz que estas nombrando, eso es Fosc, luego cuando se divide por 4, la nomeclatura de Microchip fue siempre Fcy (Fosc/4) y el inverso Tcy (4/Fosc)

Y si el 4 se debe al pipeline y algo mas de la arquitectura. ya que si fueramos rigurosos, solo bastaria 1 ciclos ( suponiendo que utiliza 1/2 ciclo para cada etapa, busqueda y ejecucion), por eso la gran pelea de algunos otros usuarios de otros micros en el que sus instrucciones o modulos se terminan ejecutando en Fosc y no Fosc/4. Por ejemplo en los Atmega sus instrucciones se realizan en 1 ciclo de reloj ( es decir en Tosc ), pero bueno, tambien tienen otro "formato" de memoria respecto a los PIC16, y es mas parecido a un PIC24 o dspic, y luego tenes otra forma de operar con los datos, lo cual para algunas cosas se hacen mejores en uno que otro. ( PD: eso me recuerda algun dia ponerme con los atmega en ASM :) )

Ejemplo para sumar 2 valores en PIC seria algo asi:

1er valor en registro VALOR1
2do valor literal VALOR2

PIC (suponiendo PIC16 y que estoy en el banco ese de RAM):

MOVF VALOR2         ; W = Valor2
ADDWF VALOR1,F    ; Valor1 = Valor2 + Valor1

ATmega ( recien me puse a ver su set y puede que le este errando feo)

valor1 = direccion 0x0060
valor2 = direccion 0x0061

;Carga del valor en un registro de trabajo, esto puede ser directo o indirecto, expongo caso de indirecto y que esten seguidos valor1 y 2 ( cosa que no importa en el PIC )
ldi r27,$00                              (1) ciclo
ldi r26,$60   ;apunto direccion 0x0060     (1) ciclo
ld  r0,X+      ; Pongo el valor en r0 e incremento X, quedando en 0x0061, (2) ciclo
ld  r1,X        ; en R1 pongo lo de 0x0061 (1) ciclo
add r0,r1     ; r0 = r0 + r1 (1) ciclo
st -X,r0        ; Procede a decrementar ( X = 0x0060 ) y guardar en la RAM, (2) ciclo

Y tuvimos justamente 8 ciclos de reloj o que es igual que el PIC. Y si digamos que queremos un equivalente podemos usar el PIC18

LFSR 2,0060          ; direccion (2) ciclos
MOVF POSTINC2,W  ; W= Valor2 y FSR2 +1 (1) ciclos
ADDWF INDF2,F      ; Valor1 = Valor2 + Valor1 (1) ciclos
(Este llevo mucho mas usando indirecto)

Pero obviamente esto no es para todos los casos, si estaba a mano de un acceso directo entonces era distinto, otras operaciones tambien hubieran resultado distinto Por ejemplo el PIC18 tiene resta con literales en su set extendido de instrucciones. Es decir depende de lo que sea necesario hacer, alguno va a tener una ventaja o no respecto al otro. Por otro lado, el PIC16 tiene creo que 23 instrucciones, mientras que el atmega tiene Muchisimas mas.
Título: Re: calcular pwm
Publicado por: gabrielnbr89 en 15 de Julio de 2015, 15:23:06
Clarísimo! muchas gracias! ((:-))