No se cual lenguaje utilizaras, pero aquí (http://www.todopic.com.ar/foros/index.php?topic=24720.msg207737#msg207737) hay un ejemplo para el PIC16F628A en asm. La base es la misma...
Ehh...Te dejé la rutina para hacer un PWM fácil hace dos días....la tenés un poco más arriba de esto que estás leyendo... :? :? :?
Ehh...Te dejé la rutina para hacer un PWM fácil hace dos días....la tenés un poco más arriba de esto que estás leyendo... :? :? :?
Te agradesco mucho el aporte bruno...
pero, si bien, con tu rutina, puedes modificar el periodo (cambiar la velocidad) solo tienes 3 posiciones para "el largo del ciclo eficaz" (no esta mal para controlar un servomotor), pero es insuficiente para crear un mesclador de colores, por ejemplo (como lo que estoy haciendo yo)
el codigo que yo realice, puedes modificar la velocidad a gusto (igual al programa tuyo), pero ademas, puedes programar el largo del ciclo eficas a gusto.
El programa que necesitás hacer no es de gran complejidad, siempre y cuando puedas atender debidamente a tus PWMs y no satures al uC con otras tareas que puedan perjudicar la precisión de los PWMs.
Un PWM por soft muy sencillo podría ser:Código: CEso sería muy básico. Se puede hacer más rápido(o lento) si se necesita.
char step, pwm1,pwm2,pwm3; step=1; pwm1=128; pwm2=64; pwm3=250; while(1){ if(pwm1>=step) output_high(pin_b0) else output_low(pin_b0); if(pwm2>=step) output_highpin_b1) else output_low(pin_b1); if(pwm3>=step) output_high(pin_b2) else output_low(pin_b2); //delay_us(xxx); step++; //incrementar paso if(!step) step++; //si step==0, step=1 }
Saludos.
if(!step) step++; //si step==0, step=1Hola jeremy,
es un pequeño error común en mucha gente que implementa el PWM por software, e incluso lo he visto en algunos PWM hardware también al fallo.
La idea es que cuando el PWM es 0%, el pin tendría realmente estar siempre en bajo. Lo opuesto para un duty del 100% (siempre activo). Si no salteas el cero, en realidad cuando pones el PWM al 0% ocurre un muy breve duty, debido a que el IF se cumple si pwm = 0 y step = 0.
Esto ocurre inicialmente, porque cuando uno elige hacer un pwm de n bits de resolución, la cantidad de pasadas (iteraciones) que se necesitan hacer para generar un ciclo de PWM no son 2^n, sino 2^n - 1. Tal vez sea dificil verlo al principio, pero esa pasada de menos que aparece, es porque cuando tu tomas una decisión binaria, estás obteniendo dos resultados posibles (SI o NO).
Si lo hacemos con un PWM de 2 bits de resolución, se ve fácilmente que sólo necesitamos 3 (2^n-1) iteraciones para generarlo perfectamente:
la primera iteración decide mediante el IF si el duty es del 0% o mayor;
la segunda iteración decide mediante el IF si el duty es del 33% o mayor;
la tercera iteración decide mediante el IF si el duty es del 67%, caso contrario es del 100%;
Fijate que con 3 iteraciones, hemos logrado 4 resultados de duty distintos, que son los que necesitamos.
Visto en código:
step = 1;
while(1){
if(pwm1>=step) output_high(pin_b0) else output_low(pin_b0);
//delay_us(xxx);
step++; //incrementar paso
if(step == 0x04) step = 1; //si no hay más iteraciones, step=1
}
De manera idéntica ocurre cuando hacemos un PWM de 8 bits de resolución (256 posiciones efectivas), sólo necesitamos 255 iteraciones. Si lo quieres ver más básico aún. para hacer un PWM de 1 bit de resolución (2 valores posibles), sólo necesitas un sólo if (una sola iteración), que nuevamente resulta ser 2^n - 1.
Saludos.
El programa que necesitás hacer no es de gran complejidad, siempre y cuando puedas atender debidamente a tus PWMs y no satures al uC con otras tareas que puedan perjudicar la precisión de los PWMs.
Hola jeremy,
es un pequeño error común en mucha gente que implementa el PWM por software, e incluso lo he visto en algunos PWM hardware también al fallo.
La idea es que cuando el PWM es 0%, el pin tendría realmente estar siempre en bajo. Lo opuesto para un duty del 100% (siempre activo). Si no salteas el cero, en realidad cuando pones el PWM al 0% ocurre un muy breve duty, debido a que el IF se cumple si pwm = 0 y step = 0.
Esto ocurre inicialmente, porque cuando uno elige hacer un pwm de n bits de resolución, la cantidad de pasadas (iteraciones) que se necesitan hacer para generar un ciclo de PWM no son 2^n, sino 2^n - 1. Tal vez sea dificil verlo al principio, pero esa pasada de menos que aparece, es porque cuando tu tomas una decisión binaria, estás obteniendo dos resultados posibles (SI o NO).
Si lo hacemos con un PWM de 2 bits de resolución, se ve fácilmente que sólo necesitamos 3 (2^n-1) iteraciones para generarlo perfectamente:
la primera iteración decide mediante el IF si el duty es del 0% o mayor;
la segunda iteración decide mediante el IF si el duty es del 33% o mayor;
la tercera iteración decide mediante el IF si el duty es del 67%, caso contrario es del 100%;
Fijate que con 3 iteraciones, hemos logrado 4 resultados de duty distintos, que son los que necesitamos.
Visto en código:
step = 1;
while(1){
if(pwm1>=step) output_high(pin_b0) else output_low(pin_b0);
//delay_us(xxx);
step++; //incrementar paso
if(step == 0x04) step = 1; //si no hay más iteraciones, step=1
}
De manera idéntica ocurre cuando hacemos un PWM de 8 bits de resolución (256 posiciones efectivas), sólo necesitamos 255 iteraciones. Si lo quieres ver más básico aún. para hacer un PWM de 1 bit de resolución (2 valores posibles), sólo necesitas un sólo if (una sola iteración), que nuevamente resulta ser 2^n - 1.
Saludos.
Que tal, haciendo uso de tu programa intente hacer el mio para un sistema de control para una tira de leds RGB, el problema que tengo es con los ciclos, ya que se queda en la parte del PWM y no vuelve a verificar el estado de las variables de entrada en este caso el ADC, espero me puedan ayudar u orientar para resolver mi problema, adjunto mi codigo en C:Código: C
#include <18f4550.h> #fuses hs,nowdt,nolvp,noprotect #use delay(clock=20000000) #use standard_io(C) #use standard_io(B) #define use_portB_lcd true #include <lcd.c> int res0, res1, res2; char step, pwm0,pwm1,pwm2; void main() { setup_port_A(all_analog); setup_adc(adc_clock_internal); lcd_init(); delay_ms(100); delay_ms(500); delay_ms(500); do{ delay_ms(50); set_adc_channel(0); res0=read_adc(); delay_ms(50); lcd_gotoxy(1,2); delay_ms(60); set_adc_channel(1); res1=read_adc(); delay_ms(60); lcd_gotoxy(6,2); delay_ms(70); set_adc_channel(2); res2=read_adc(); delay_ms(70); lcd_gotoxy(11,2); step=1; pwm0=res0; pwm1=res1; pwm2=res2; do{ if(pwm0>=step) output_high(pin_c0); else output_low(pin_c0); if(pwm1>=step) output_high(pin_c1); else output_low(pin_c1); if(pwm2>=step) output_high(pin_c2); else output_low(pin_c2); //delay_us(xxx); step++; //incrementar paso if(!step) step++; //si step==0, step=1 }while(true); }while(true); }
De antemano Gracias! :)