Autor Tema: programar un PWM  (Leído 21954 veces)

0 Usuarios y 4 Visitantes están viendo este tema.

Desconectado deray8

  • PIC10
  • *
  • Mensajes: 9
programar un PWM
« en: 12 de Mayo de 2009, 12:44:05 »
Estimados amigos

Quiciera saber si alguien ha programado, por sus propios medios, un PWM.
Me explico mejor: El modelo del pic que utilizo es el 16F877, el cual posee 2 PWM internos, pero yo necesito 3 o mas.
En mis años de estudiante, mi profesor de Microcontroladores Aplicados, mencionó que cualquier salida podria comportarse como PWM, programandola previamente.
Al parecer, y por lo que estuve cachureando antes de hacer esta pregunta, varios tienen la misma inquietud, aunque aplicada a otros proyectos, como controlar un servomotor. La verdad es que yo niciquiera he intentado la programacion, y haciendo la del flojo, preferí en primer lugar, ver si alguien mas, se habia dado esa paja... "al parecer me equiboque". bueno, tengo alguna idea de como se podria hacer...
si alguien mas sabe como... o tiene algun programa relacionado... se agradeceria que colaborara y asi, poder resolver esta inquietud de varios hobbistas y proyectistas.

en cuanto logre poder crear o encontrar algun programa... posteare.


manos a la obra!!!

Desconectado Suky

  • Moderador Local
  • DsPIC33
  • *****
  • Mensajes: 6758
Re: programar un PWM
« Respuesta #1 en: 12 de Mayo de 2009, 12:59:38 »
No se cual lenguaje utilizaras, pero aquí hay un ejemplo para el PIC16F628A en asm. La base es la misma...
No contesto mensajes privados, las consultas en el foro

Desconectado deray8

  • PIC10
  • *
  • Mensajes: 9
Re: programar un PWM
« Respuesta #2 en: 12 de Mayo de 2009, 13:55:03 »
No se cual lenguaje utilizaras, pero aquí hay un ejemplo para el PIC16F628A en asm. La base es la misma...

la verdad que de assembler no recuerdo nada, me desidí por el lenguaje "C".

por lo que pude ver, esa es la configuracion de la salida PWM que trae incorporado el PIC. en eso no tengo problema. puedo configurar las dos salidas PWM que trae el modelo 16F877 a voluntad (luego de horas de prueba y error y de varios intentos fallidos, lo reconosco).

el asunto es poder tener 3, 4, 5 o más pines con salidas PWM, ¿¿¿ me entiendes??? o sea, ser capas de generar un programa para convertir cualquier salida normal del pic, en una salida PWM.

por mi parte, hoy en la noche, tratare de generar ese programa.

saludos cordiales

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: programar un PWM
« Respuesta #3 en: 12 de Mayo de 2009, 14:48:52 »
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: C
  1. char step, pwm1,pwm2,pwm3;
  2. step=1;
  3. pwm1=128;
  4. pwm2=64;
  5. pwm3=250;
  6.  
  7. while(1){
  8. if(pwm1>=step) output_high(pin_b0) else output_low(pin_b0);
  9. if(pwm2>=step) output_highpin_b1) else output_low(pin_b1);
  10. if(pwm3>=step) output_high(pin_b2) else output_low(pin_b2);
  11. //delay_us(xxx);
  12. step++;                    //incrementar paso
  13. if(!step) step++;        //si step==0, step=1
  14. }
Eso sería muy básico. Se puede hacer más rápido(o lento) si se necesita.

Saludos.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado deray8

  • PIC10
  • *
  • Mensajes: 9
Re: programar un PWM
« Respuesta #4 en: 14 de Mayo de 2009, 18:54:58 »
Bien amigos... les cuento que logré programar un PWM, pero, es un weveo mas grande que la xuxa!!!  :shock:

Como 4 variables, muchas cuentas, otros pocos delay's... pfffff el pic solo se dedicaria a esto y a nada mas... asi que como buen chileno... busque una alternativa mas "economica" y mas realizable.

Basta con interconectar una salida PWM a un CI CMOS 4066 (que posee 4 switch controlados). ¿que gano con esto? tener 4 salidas PWM, y poder habilitar las que quiera en cualquier instante.

El punto en contra es que todas las salidas serían idénticas, o sea, tendrían el mismo largo eficás en su periodo (PWM1).  :x
Esto se puede solucionar en parte, agregando la otra salida PWM2.

En todo caso... si alguien quiere la programacion del PWM que realice, la pondre aki cuando tenga un tiempecillo.
Es completamente configurable en periodo y largo eficas de periodo. Por defecto lo deje para 50 Hz (ideal para servomotores, 20mseg).     

Bueno, eso... ojala a alguien le sea un aporte este comentario.

PD: Eso si, yo programo en C. :mrgreen:

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: programar un PWM
« Respuesta #5 en: 14 de Mayo de 2009, 18:57:04 »
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... :? :? :?
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado deray8

  • PIC10
  • *
  • Mensajes: 9
Re: programar un PWM
« Respuesta #6 en: 15 de Mayo de 2009, 23:46:25 »
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.

para los que no cachan que es un PWM, voy a tratar de explicar (si me equivoco en algo me corrigen, y lo discutimos):

el largo eficas de esta señal, es el porcentaje del periodo en que la señal es alta (un 1 logico). por ejemplo:
               
                  0%             50%          100% 
                    __________                 __________
       _______!                 !_________!                 !______  = señal cuadrada (por ejemplo de un clock) con periodo T=[1/F] (donde F es la frecuencia de la señal)
                   !<------------T---------->!

En este ejemplo, el ciclo eficas es de 50% (para un servomotor, significaria que se pocicionaria en el centro, o sea su pococion natural; para un diodo led, su brillo seria del 50%).

                  0%      33%                100% 
                    ______                        _______
       _______!          !_____________!           !__________  = la misma señal cuadrada con el mismo periodo T, pero con un 33% de su ciclo efectivo.
                   !<------------T---------->!

(para el servomotor, significaria que se pocicionaria hacia la izquierda; para un diodo led, se estaria casi apagando).


                  0%                 66%     100% 
                    _____________            _______
       _______!                      !______!            !__________  = la misma señal cuadrada con el mismo periodo T, pero con un 66% de su ciclo efectivo.
                   !<------------T---------->!

(para el servomotor, significaria que se pocicionaria hacia la derecha; para un diodo led, estaria serca de su maximo brillo).



si pudieramos controlar el largo de el ciclo efecaz al alimentar un diodo led, hariamos un dimmer. si el didodo es un RGB, con 2 salidas de estas, podriamos hacer una mescla de 2 colores.... y asi sucesivamente. 

PD: ojala no sea muy latoso esto que postee. :shock:
 

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: programar un PWM
« Respuesta #7 en: 16 de Mayo de 2009, 00:38:56 »
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.

NO. Mi rutina tiene 255 posiciones efectivas(8 bits de resolución) para cada PWM. La frecuencia es la que está fija y la variarías sencillamente des-comentando la línea //delay_us(XXX) y reemplazando las XXX por un valor acorde para obtener la frecuencia deseada.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado rasec_1984

  • PIC10
  • *
  • Mensajes: 29
Re: programar un PWM
« Respuesta #8 en: 23 de Junio de 2009, 05:04:46 »
Tienes razón Bruno, tiene 25 posiciones, yo tampoco le habia prestado atención en un principio, ahora veo bien el código y está buenisimo, lo traducire a basic para un programita que estoy haciendo. Saludos ;)
........Los grandes espíritus siempre han encontrado una violenta oposición de parte de mentes mediocres.....

Desconectado granados

  • PIC10
  • *
  • Mensajes: 1
Re: programar un PWM
« Respuesta #9 en: 09 de Julio de 2013, 19:25:23 »
Hola Amigosss
Buenasss
Amigos Quiciera saber si el programa de BrumoF sirve para toda clase de pic como el 16f628a 16f84a o 18f2550 u otros mas
y si se podria hacer con todos los pines

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
}
 


osea si lo puedo modificar

char step, pwm1,pwm2,pwm3,pwm4,pwm5.......pwm12; ///////// omas pines
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
}
 


es que es para un proyecto de leds RGB y son 4 leds cada leds tiene 3 pines 3*4= 12 pines y pues e estado haciendo programaciones y programaciones
pero no estoy seguro si me funcionaria o no
y e buscado muchas formas y programaciones
nose si
el ADC funciona o no PWM y Delay_ms

pues voy a ver si me funciona y enviare otra publicacion para ver si me an funcionado subire unos documentos de proteus y archivos de MikroC
Chaooo Graciasss Amigoooosss

Desconectado ppyote

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 929
Re: programar un PWM
« Respuesta #10 en: 09 de Julio de 2013, 20:17:00 »
funcionar funciona, pero la frequencia disminuye a cada pwm por sothware que añadas, a demas de que el pic tiene que estar al 100% en la gestion de los pwm....
osea que no podras atender ninguna interrupcion o funcion que sean relativamente altas en cuanto a tiempo consumido por estas....
PPyote... siempre estareis en mi corazon.... Te quiero Hermano...

Desconectado jeremylf

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1341
Re: programar un PWM
« Respuesta #11 en: 10 de Septiembre de 2014, 22:49:27 »
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: C
  1. char step, pwm1,pwm2,pwm3;
  2. step=1;
  3. pwm1=128;
  4. pwm2=64;
  5. pwm3=250;
  6.  
  7. while(1){
  8. if(pwm1>=step) output_high(pin_b0) else output_low(pin_b0);
  9. if(pwm2>=step) output_highpin_b1) else output_low(pin_b1);
  10. if(pwm3>=step) output_high(pin_b2) else output_low(pin_b2);
  11. //delay_us(xxx);
  12. step++;                    //incrementar paso
  13. if(!step) step++;        //si step==0, step=1
  14. }
Eso sería muy básico. Se puede hacer más rápido(o lento) si se necesita.

Saludos.

Bruno, porque el:
Código: [Seleccionar]
if(!step) step++;        //si step==0, step=1
Porque no dejar que el step fluya de 0 a 255, en ese caso tendria 256 posciciones efectivas o ya debo ir a dormir? xD

Desconectado BrunoF

  • Administrador
  • DsPIC30
  • *******
  • Mensajes: 3865
Re: programar un PWM
« Respuesta #12 en: 14 de Septiembre de 2014, 13:08:58 »
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.
"All of the books in the world contain no more information than is broadcast as video in a single large American city in a single year. Not all bits have equal value."  -- Carl Sagan

Sólo responderé a mensajes personales, por asuntos personales. El resto de las consultas DEBEN ser escritas en el foro público. Gracias.

Desconectado jeremylf

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1341
Re: programar un PWM
« Respuesta #13 en: 24 de Octubre de 2014, 02:35:55 »
Efectivamente es como dices; luego de analizarlo más pude interpretarlo como era y tu mensaje me lo ha reforzado. Llego hasta aquí pues estuve haciendo lo mismo de otra forma y al parecer la que propones consume menos tiempo de ejecución porque consume menos rom (ideal, pues trabajo con más de 10 pwm dentro de un timer). Gracias Bruno.

Desconectado Eigenbrotler555

  • PIC10
  • *
  • Mensajes: 1
Re: programar un PWM
« Respuesta #14 en: 24 de Noviembre de 2015, 03:37:18 »
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
  1. #include <18f4550.h>
  2. #fuses hs,nowdt,nolvp,noprotect
  3. #use delay(clock=20000000)
  4. #use standard_io(C)
  5. #use standard_io(B)
  6. #define use_portB_lcd true
  7. #include <lcd.c>
  8.  
  9.  
  10. int res0, res1, res2;
  11. char step, pwm0,pwm1,pwm2;
  12.  
  13.  
  14.  
  15. void main()
  16. {
  17.      
  18.       setup_port_A(all_analog);
  19.       setup_adc(adc_clock_internal);
  20.       lcd_init();
  21.      
  22.       delay_ms(100);
  23.       printf(lcd_putc,"\fBienvenido");
  24.       delay_ms(500);
  25.       printf(lcd_putc,"\nRGBControl");
  26.       delay_ms(500);
  27.       printf(lcd_putc,"\fColor code");
  28.      
  29.       do{
  30.      
  31.          delay_ms(50);
  32.          set_adc_channel(0);
  33.          res0=read_adc();
  34.          delay_ms(50);
  35.          lcd_gotoxy(1,2);
  36.          printf(lcd_putc,"%uR ",res0);
  37.              
  38.          delay_ms(60);
  39.          set_adc_channel(1);
  40.          res1=read_adc();
  41.          delay_ms(60);
  42.          lcd_gotoxy(6,2);
  43.          printf(lcd_putc,"%uG ",res1);
  44.  
  45.          delay_ms(70);
  46.          set_adc_channel(2);
  47.          res2=read_adc();
  48.          delay_ms(70);
  49.          lcd_gotoxy(11,2);
  50.          printf(lcd_putc,"%uB ",res2);
  51.          
  52.        
  53.          step=1;
  54.          pwm0=res0;
  55.          pwm1=res1;
  56.          pwm2=res2;
  57.  
  58.             do{
  59.             if(pwm0>=step) output_high(pin_c0); else output_low(pin_c0);
  60.             if(pwm1>=step) output_high(pin_c1); else output_low(pin_c1);
  61.             if(pwm2>=step) output_high(pin_c2); else output_low(pin_c2);
  62.             //delay_us(xxx);
  63.             step++;                    //incrementar paso
  64.             if(!step) step++;        //si step==0, step=1
  65.             }while(true);
  66.          
  67.  
  68.      }while(true);
  69.      
  70.      
  71.      
  72.      
  73. }



De antemano Gracias! :)


 

anything