Generar señal pwm en pic18f4550

hola a todos
tengo que crear una señal pwm que salga del micro para controlar un puente h. si me pueden ayudar es que no tengo idea de como hacerlo
gracias :cry:
 
Primero que nada hay que saber en que lenguaje lo necesitas? en ensamblador o en c

en C lo hago asi

setup_ccp1(CCP_PWM); ///esto al principio del programa

al modificar x modifico la frecuencia
al modificar time ajusto el tiempo de encendido
duty lo utilizo para modificar el ancho de pulso

void pulso(int x, long time,int duty)
{
setup_timer_2(T2_DIV_BY_16, x, 1);
set_pwm1_duty(duty);
delay_ms(time);
set_pwm1_duty(0);
}

la formula para obtener el valor que va en x es

x=[1/(frecuencia*4*Tosc*16)] -1 el numero 16 es el valor que se le da al timer 2 puede ser 16, 4 o 1.

Tosc es igual a 1/ (valor del oscilador)
 
Es algo mas complicado en ensamblador.
Primero que nada ten en mente que frecuencias vas a utilizar,
y el tiempo de encendido (duty cycle), de cuanto es tu oscilador
y ve por cuanto mas o menos tendrias que dividir el timer 2(tabla en la hoja de datos)
luego con la formula de PR2 sacas el valor y ya lo que queda es seguir los pasos


Esto lo saque de la hoja de datos. Busca en la seccion PWM.

15.4.4 SETUP FOR PWM OPERATION

The following steps should be taken when configuring
the CCP module for PWM operation:
1. Para ajustar el periodo de PWM tienes que cargarle un valor al registro PR2 del pic
2. Luego para ajustar el ciclo de encendido escribes en los registros
CCPRxL y CCPxCON<5:4>
3. Tienes que poner algun pin de CCPx como salida, borrando algun TRIS bit(ponerlo a 0) yo he usado RC2

4. Le asignas un valor para iniciar el TMR2
Luego un valor de preescale(division + o -) a los bits (T2CKPS1:T2CKPS0)
00 = Prescaler is 1
01 = Prescaler is 4
1x = Prescaler is 16

TMR2ON: Timer2 On bit
1 = Timer2 is on
0 = Timer2 is off

5. Configura el registro CCPx para operar como PWM.
Registro :
CCPxCON
Bits:
CCPxM3:CCPxM0: CCPx Module Mode Select bits
11xx = PWM mode




Frecuencia = 1/periodo

PWM Period = [(PR2) + 1] • 4 • TOSC • F
(TMR2 Prescale Value)

O si quieres Sacar el valor de PR2

PR2=[1/(frecuencia*4*Tosc*16)] -1


Vere si puedo conseguir un ejemplo luego, mientras intenta con esto.
 
hola soy nuevo en los pics,,, me interesaria saber como puedo generar tres señales senoidales,,, de distitntas frecuencia,,, utilizando el pic 18f4550,, epsero me puedan ayudar,,, la amplitud debe ser mayor a un volt me inteesa manejar distintas frecuencias,,, hablamos de 12kh,, 80kh.,, y una superior a los 120kh,, espero me ayuden gracias
 
Es algo mas complicado en ensamblador.
Primero que nada ten en mente que frecuencias vas a utilizar,
y el tiempo de encendido (duty cycle), de cuanto es tu oscilador
y ve por cuanto mas o menos tendrias que dividir el timer 2(tabla en la hoja de datos)
luego con la formula de PR2 sacas el valor y ya lo que queda es seguir los pasos


Esto lo saque de la hoja de datos. Busca en la seccion PWM.

15.4.4 SETUP FOR PWM OPERATION

The following steps should be taken when configuring
the CCP module for PWM operation:
1. Para ajustar el periodo de PWM tienes que cargarle un valor al registro PR2 del pic
2. Luego para ajustar el ciclo de encendido escribes en los registros
CCPRxL y CCPxCON<5:4>
3. Tienes que poner algun pin de CCPx como salida, borrando algun TRIS bit(ponerlo a 0) yo he usado RC2

4. Le asignas un valor para iniciar el TMR2
Luego un valor de preescale(division + o -) a los bits (T2CKPS1:T2CKPS0)
00 = Prescaler is 1
01 = Prescaler is 4
1x = Prescaler is 16

TMR2ON: Timer2 On bit
1 = Timer2 is on
0 = Timer2 is off

5. Configura el registro CCPx para operar como PWM.
Registro :
CCPxCON
Bits:
CCPxM3:CCPxM0: CCPx Module Mode Select bits
11xx = PWM mode




Frecuencia = 1/periodo

PWM Period = [(PR2) + 1] • 4 • TOSC • F
(TMR2 Prescale Value)

O si quieres Sacar el valor de PR2

PR2=[1/(frecuencia*4*Tosc*16)] -1


Vere si puedo conseguir un ejemplo luego, mientras intenta con esto.
hola Airoa Airon...me interasa mucho esa respuesta que dejaste en lenguaje c, estaria muy agradacido si pudieras explicar un poco mas lo de variar el duty y la frecuencia... pues exactamente es lo que tengo que hacer con un teclado matricial.....de antemno muchas gracias....
 
Hola a todos he visto este trozo de programa y si podéis ayudarme estaría muy agradecido, necesito hacer un programa en mplab en c para generar PWM con el dsPIC30F4013, si me podeis ayudar os lo agradecería.
Un saludo GRACIAS
 
que tal, como seria la configuracion inicial, si uso un pic18f4550 y en donde dice (duty) no te entiendo que va ahi?


Primero que nada hay que saber en que lenguaje lo necesitas? en ensamblador o en c

en C lo hago asi

setup_ccp1(CCP_PWM); ///esto al principio del programa

al modificar x modifico la frecuencia
al modificar time ajusto el tiempo de encendido
duty lo utilizo para modificar el ancho de pulso

void pulso(int x, long time,int duty)
{
setup_timer_2(T2_DIV_BY_16, x, 1);
set_pwm1_duty(duty);
delay_ms(time);
set_pwm1_duty(0);
}

la formula para obtener el valor que va en x es

x=[1/(frecuencia*4*Tosc*16)] -1 el numero 16 es el valor que se le da al timer 2 puede ser 16, 4 o 1.

Tosc es igual a 1/ (valor del oscilador)
 
Haber si alguien me puede ayudar. Tengo que generar una señal cuadrada de 7 Khz con el 18f4620, pero tengo que hacer 10 mediciones en 1 segundo cuando la señal este en la metad del ciclo positivo y desacupando lo maximo el micro. Lo intente solucionar simplemente con un timer, que divide cada ciclo en 4 partes y con un contador hago la conversión en un determinado instante. Pero la cresta de la señal tiene una pendiente y me acupa muchos ciclos maquina. ¿Hay alguna manera mas efectiva de hacerlo?
 
Duty es la carga, osease el valor del pwm ya sean 8 o 10 bits (255 o 1024 en decimal) es lo que le puedes poner al pwm, digamos que el 1024( si se maneja por bits y no por % ) seria un 100%,
512 un 50%, 0 un 0%.
 
Saludos!!

Quisiera preguntar si alguien sabe como puedo generar pwm digital automático con el pic.

Explico:

Tengo que controlar la velocidad de un motor desde 0% hasta el 100%., pero no debo de controlarlo yo con un potenciometro externo, sino que cuando presione un solo botón que estará conectado al pic, se active el pwm hacia el motor, y que a intervalos de tiempo determinados, el pic incremente el ciclo util automáticamente digamos de 5% en 5% hasta llegar al 100%.

El punto clave es que necesito que el motor inicie detenido, y que cuando oprima el boton comience a incrementar su giro hasta llegar al 100%, de esta manera, el pwm esta restringido a terminar en un periodo de tiempo especifico.

Y bueno tambien referente a esto, pues quisiera saber si se pueden controlar dos motores conectados al pic, utilizando la tecnica que describi anteriormente.

Gracias
 
Hola
Estoy tratando de controlar un motor DC con el modulo PWM (librerias). Y no se por que no se detiene cuando pongo la intruccion ClosePWM1(); trato tambien de contarlo con el encoder que en dos vueltas se detenga y tampoco AYUDA!!
Gracias de Antemano
 

Adjuntos

  • PWM_Motor.rar
    92.5 KB · Visitas: 493
Hola, como puedo controlar la velocidad de un motor CD con el pwm. en lenguaje C.
Tengo este programa pero aun no logro hacerlo funcionar

Código:
#include <18F4550.h>
#device adc=8                    
#fuses hs,nowdt,noprotect,nolvp  
#use delay(clock=20000000)       
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)

byte velocidad;


void inicializar()
{
setup_ccp2(CCP_PWM);                   
setup_timer_2(T2_DIV_BY_4, 127, 1);    
                                      
                                       
set_tris_b(0x00);
set_tris_a(0x01);                 
setup_adc(ADC_clock_internal); 
setup_adc_ports(AN0);         
set_adc_channel(0);           
velocidad=0;                 
}

void main(){
inicializar();
while(1){

velocidad=read_adc();    

set_pwm2_duty(velocidad);  
}
}
 
Última edición por un moderador:
Saludos.

Prueba ahora así...
Código:
#include <18F4550.h>
#device adc=8
#fuses hs,nowdt,noprotect,nolvp
#use delay(clock=20000000)
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)

unsigned int8 velocidad;


void inicializar()
{
   setup_ccp2(CCP_PWM);
   setup_timer_2(T2_DIV_BY_4, 127, 1);

   set_tris_c(0xFD);
   set_tris_a(0x01);
   setup_adc(adc_clock_internal);
   delay_us(12);
   setup_adc_ports(AN0);
   set_adc_channel(0);

   velocidad=0;
}

void main(){
   inicializar();
   
   while(true){

   velocidad=read_adc();
   delay_us(12);

   set_pwm2_duty(velocidad/2);
   }
}
Suerte.
 
Hola, como puedo controlar la velocidad de un motor CD con el pwm. en lenguaje C.



proba con esto
Código:
void main()
{

   setup_adc_ports(AN0_TO_AN1|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_1,99,1);
   setup_ccp1(CCP_PWM_FULL_BRIDGE|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L);
   setup_ccp2(CCP_PWM);
   set_pwm1_duty(0);
   set_pwm2_duty(0);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(OSC_4MHZ|OSC_TIMER1|OSC_31250|OSC_PLL_OFF);
{
   long duty=0;
  
   set_adc_channel(0);  //selecciona el canal del adc
   
   while (1)
            {
      duty=read_adc()/3; //leemos el valor el adc y lo dividimos en 2
      delay_us(20);  //esperamos 20us para el adc
      set_pwm1_duty(duty);  // ajustamos el pwm con el ciclo de trabajo q nos da el adc/2
     
      }
   }


también depende con que programa lo compiles...yo uso CCS
 
Última edición por un moderador:
proba con esto
Código:
void main()
{

   setup_adc_ports(AN0_TO_AN1|VSS_VDD);
   setup_adc(ADC_CLOCK_INTERNAL);
   setup_psp(PSP_DISABLED);
   setup_spi(SPI_SS_DISABLED);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DIV_BY_1,99,1);
   setup_ccp1(CCP_PWM_FULL_BRIDGE|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L);
   setup_ccp2(CCP_PWM);
   set_pwm1_duty(0);
   set_pwm2_duty(0);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   setup_oscillator(OSC_4MHZ|OSC_TIMER1|OSC_31250|OSC_PLL_OFF);
{
   long duty=0;
  
   set_adc_channel(0);  //selecciona el canal del adc
   
   while (1)
            {
      duty=read_adc()/3; //leemos el valor el adc y lo dividimos en 2
      delay_us(20);  //esperamos 20us para el adc
      set_pwm1_duty(duty);  // ajustamos el pwm con el ciclo de trabajo q nos da el adc/2
     
      }
   }


también depende con que programa lo compiles...yo uso CCS
-------------------

Hola gracias, la verdad no probé tu modificación pero tenias razón acerca de que podría ser el compilador que utilizo. probé con el Dev-C y si me fundió el original.
 
Bueno gente, después de dos días de buscar información y poder generar dos pwm,
pude generar los dos pwm y resolviendo el problema que tenia.
Este ejemplo genero dos pwm, donde el ciclo de trabajo (duty) lo vario con dos potenciómetros conectados a las puertas del conversor.
Cada pwm es diferente uno del otro, solo que estan a la misma frecuencia.
Código:
#include <18F4550.h>
#device adc=10


#FUSES NOWDT                    //No Watch Dog Timer
#FUSES WDT128                   //Watch Dog Timer uses 1:128 Postscale
#FUSES INTHS                    //Internal Oscillator, HS used by USB
#FUSES NOPROTECT                //Code not protected from reading
#FUSES BROWNOUT                 //Reset when brownout detected
#FUSES BORV43                   //Brownout reset at 4.3V
#FUSES PUT                      //Power Up Timer
#FUSES NOCPD                    //No EE protection
#FUSES STVREN                   //Stack full/underflow will cause reset
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOWRT                    //Program memory not write protected
#FUSES NOWRTD                   //Data EEPROM not write protected
#FUSES IESO                     //Internal External Switch Over mode enabled
#FUSES FCMEN                    //Fail-safe clock monitor enabled
#FUSES NOPBADEN                 //PORTB pins are configured as digital I/O on RESET
#FUSES NOWRTC                   //configuration not registers write protected
#FUSES NOWRTB                   //Boot block not write protected
#FUSES NOEBTR                   //Memory not protected from table reads
#FUSES NOEBTRB                  //Boot block not protected from table reads
#FUSES NOCPB                    //No Boot Block code protection
#FUSES MCLR                     //Master Clear pin enabled
#FUSES LPT1OSC                  //Timer1 configured for low-power operation
#FUSES NOXINST                  //Extended set extension and Indexed Addressing mode disabled (Legacy mode)
#FUSES PLL1                     //No PLL PreScaler

#use delay(internal=8000000)
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)
void main(){ 
       
   setup_adc_ports(AN0_TO_AN1|VSS_VDD);
   setup_adc(ADC_CLOCK_DIV_8);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_32);
   setup_timer_1(T1_EXTERNAL|T1_DIV_BY_1);
   setup_timer_2(T2_DIV_BY_1,99,1);
   setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   //setup_ccp1(CCP_PWM_FULL_BRIDGE|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L); aca era el problema que tenia;
   setup_ccp1(ccp_pwm);
   setup_ccp2(ccp_pwm);
   setup_comparator(NC_NC_NC_NC);
   setup_vref(FALSE);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(INT_EXT);
   enable_interrupts(INT_EXT1);
   enable_interrupts(INT_EXT2);
   enable_interrupts(GLOBAL);
   setup_oscillator(OSC_8MHZ|OSC_INTRC|OSC_31250|OSC_PLL_OFF);
 
   // TODO: USER CODE!!
   {
      long duty=0;
      long duty1=0;
                 
   while (TRUE) {
            set_adc_channel(0);  //selecciona el canal 1 del adc
            delay_us(10);
            duty=read_adc()/3; //leemos el valor el adc y lo dividimos en 3
            delay_us(20);  //esperamos 20us para el adc
            set_pwm1_duty(duty);  // ajustamos el pwm con el ciclo de trabajo q nos da el adc/3
      set_adc_channel(1);//selecciona el canal 2 del adc
            delay_us(10); //esperamos
            duty1=read_adc()/3;//leemos el valor el adc y lo dividimos en 3
            delay_us(20); //esperamos
            set_pwm2_duty(duty1);//salida del pwm2
                           
            }
   }  
         
}
 
Última edición por un moderador:
soy nuevo en el tema de los micro y muy poco se sobre el tema... estoy buscando información de como genera un señal pwm con el pic 16f877a con dos pulsadores uno que incremente la señal y otro que disminuya.
 
Haber si alguien me puede ayudar. Tengo que generar una señal cuadrada de 7 Khz con el 18f4620, pero tengo que hacer 10 mediciones en 1 segundo cuando la señal este en la metad del ciclo positivo y desacupando lo maximo el micro. Lo intente solucionar simplemente con un timer, que divide cada ciclo en 4 partes y con un contador hago la conversión en un determinado instante. Pero la cresta de la señal tiene una pendiente y me acupa muchos ciclos maquina. ¿Hay alguna manera mas efectiva de hacerlo?

Tal vez tu problema se deba a que estas generando la senal PWM por software, si ocupas el modulo CCP integrado, el microcontrolador estará entero para realizar otras acciones... saludos!
 
Atrás
Arriba