PWM a 10 Bits con PIC18F2550

#1
Hola.
Tengo una duda con el PWM del PIC18F2550 y tiene un ADC de hasta 10 bits y salida PWM de hasta 10 bits también.

El problema es que quiero tener una entrada de 10 bits de resolución y una salida de 10 bits de resolución.
Utilizo un LED como visualizador del PWM y un potenciómetro, obviamente.
El código me funciona bien con 8 bits de entrada y 8 de salida por cada 0-255
El LED enciende y apaga con PWM sin problema.

Con 10 bits de entrada y 10 de salida, debería ser igual que con 8-8, pero pasa que el LED pasa por 4 ciclos por cada 1 del potenciómetro.
Según yo, sólo tengo que cambiar el ciclo en el setup del timer 2, pero no me funciona.

Les dejo el código:
PHP:
#include <18f2550.h>
#device adc=10
#use delay(clock=4M)
#fuses NOWDT,INTRC,CPUDIV1
int8 value;

   VOID main()
   {
   setup_adc_ports(an0);
   setup_adc(adc_clock_internal);
   set_adc_channel(0);             
   
   setup_timer_2(t2_div_by_16,1023,1);  //si cambio 1023 a 255 y el #device adc=8, funciona bien, pero lo quiero 10-10 <.>
   setup_ccp1(ccp_pwm);             
      for(;;)
      {
      value=read_adc();
      set_pwm1_duty(value);
      delay_ms(10);
      }
   }
 
Última edición por un moderador:
#2
Me parece que estás mal con tus cálculos y sobre el funcionamiento de generación PWM en el PIC.

Mira cómo funciona:
El PWM a 10 bits es controlado por el Timer 2.
El Timer 2 se incrementa a través de un prescaler 1:1, a partir del reloj que es la salida del oscilador a través de un sistema de gestión con un postscaler 1:4 (Fosc / 4 )
El Timer 2 es en realidad un temporizador de 8 bits para conseguir 10 bits de resolución.
El Timer 2 se combina con los dos bits menos significativos de Fosc / 4 para el postscaler.

El tiempo alto de la señal PWM está controlado por un valor de 10 bits que se almacena en dos registros de 8 bits.
PWM:LOL:CH y PWM:LOL:CL para generar el PWM y CCPRxL o CCPxCON sobre los periféricos del PCCh y del PECC.
El registro PWM:LOL:CH o CCPRxL contiene los 8 bits superiores y PWM:LOL:CL y el registro CCPxCON contiene los dos bits menos significativos.

Cuando el valor de 10 bits en estos dos registros coincide con el valor del Timer 2 en la concatenación de 10 bits, la salida PWM pasará de un nivel alto a un nivel bajo.
Esto crea la anchura del pulso de la señal y determina el ciclo de trabajo.

El Timer2 continúa funcionando después de que el estado de los interruptores de salida llegue al valor superior de los 8 bits y coincida con un segundo valor de 8 bits almacenado en el registro del período (PR2)
Cuando estos valores coinciden, la salida PWM cambia de estado bajo a estado alto y el Timer 2 se pone en cero.

El valor almacenado en PR2 determina el período de la señal PWM y por defecto la frecuencia de la señal.


Ahora un ejemplo para generar una señal PWM de 1 KHz @ 4 MHz.
Supongamos que queremos el 100 % del ciclo activo: (Ver fórmulas en la hoja de datos)

El valor para PR2 = 249
Para CCPRxL = 249
El prescaler para el Timer 2 en 1:4
El postescaler en 1:1

La configuración en PIC C Compiler:
PHP:
    setup_ccp1(CCP_PWM);
    setup_timer_2(T2_DIV_BY_4,249,1);
    set_pwm1_duty(249);
Como puedes ver, el valor máximo para CCPRxL es de 249
Entonces no puedes superar éste valor porque es el parámetro máximo para 1 KHz @ 4 MHz.

Ahora con el 50 % del ciclo activo:
El valor para PR2 = 249
Para CCPRxL = 124
El prescaler para el Timer 2 en 1:4
El postescaler en 1:1

Y la configuración en PIC C Compiler:
PHP:
    setup_ccp1(CCP_PWM);
    setup_timer_2(T2_DIV_BY_4,249,1);
    set_pwm1_duty(124);
Lo que puedes hacer, es generar un sencillo algoritmo para que el valor leído del ADC no sobrepase el valor máximo requerido por el registro CCPR1L y ese valor colocarlo en; set_pwm1_duty(ciclo_activo);

Suerte.
 
Última edición:
#3
Veo que es algo dificil de digerir, ciertamente logre que funcione con un servo a 8-8, pero no estoy satisfecho :LOL:, ya vi en el datasheet lo que dices pero no logro entenderlo del todo. pero seguire intentando hasta conseguirlo. gracias :D



Otra pregunta... solo los pines ccp pueden usarse como salida pwm? veo que tanto el 2550 como el 4550 solo cuenta con 3 de estos, no lo hace muy ideal para robots :s
 
Última edición:
#4
No entendí bien esa explicación.

Bueno, creo que solo 2 pines pueden ser PWM por hardware (nota que CPP2 tiene dos pines, pero es el mismo modulo), la solución muchas veces es hacerlo por software usando interrupciones del timmer, o buscar otro chip.
 
#5
No se si esto te aclara o te liará más; que el modulo ccp tenga una resolución de 10bit no implica que el fondo de escala siempre sea de 10bit, y más, que el modulo ccp tenga una resolución de 10bit no quiere decir que siempre pueda darla.

Te dejo un enlace donde insertas la frecuencia de reloj, el ducty cycle y frecuencia deseada y te devuelve una tabla con los valores que tienes que cargar en registros para múltiples frecuencias, mostrándote la resolución y fondo de escala. Se supone que para fondo de escala el ducty cycle tendrá que ser del 100%.

http://www.micro-examples.com/public/microex-navig/doc/097-pwm-calculator.html
 
Arriba