# Problema de programacion PWM PIC16F877



## Ahona (Feb 28, 2008)

Hola!
Hace poco que he empezado con la programacion de los PIC en C...
C ya lo he visto antes, pero para ordenador, asi que no me resulta muy dificil llegar a entender el codigo...lo que no me acabo de enterar es la configuracion para el PIC, es decir, dependiendo las funciones, no me acabo de aclarar que es lo que hace cada una...
Quiero hacer un programa que mueva un motor por medio del PWM del PIC16F877, ya he empezado hacerlo, pero hay cosas que no entiendo. El compilador que utilizo es el PIC-C Compiler, pero me da error en acda una de las lineas del programa...
Aqui os pongo lo que llevo hasta ahora, seguro que los fallos son por cosas básicas, pero lo estoy aprendiendo por mi cuenta y resulta un poco lioso...


```
#include"pic16f877.h" //incluyo la libreria del PIC que se utilizara
#USE DELAY(clock=40000000) //especifico la frecuencia (Hz) a la que trabajara el //reloj

void main()
{
   while (1)
   {
      SET_TRIS_C(11111011); //pongo RC2 como salida de datos
      SETUP_CCP1(CCP_PWM); //pongo CCP1 como PWM
      SETUP_TIMER_2(T2_DIV_BY_16,255,15); //aqui tengo las dudas
      SET_PWM1_DUTY(11111111); //aqui tb ops: 
   }
}
```

Segun he entendido (seguramente estare equivocado)
La funcion SETUP_TIMER_2() establece el ciclo de trabajo que envia el PWM. Los valores que he puesto no los acabo de entender...(les he puesto mas o menos a voleo para ver si funcionaba o no)
T2_DIV_BY_16 quiere decir que divide la frecuencia del reloj por 16?
El 255 indica el valor al que llegara el timer y reiniciara la cuenta?
El 15, mas o menos lo tengo claro, es el numero de resets antes de una interrupcion, no?

En la funcion SET_PWM1_DUTY() se indica el ciclo de trabajo del PWM? y eso no se hace ya con la funcion anterior?

Se que estas cosas son basicas, pero no acavo de enterarme...me podriais hechar una mano?

Muchas gracias a todos!

Un saludo!


----------



## Paloky (Feb 28, 2008)

Hola.

Creo que te puedo ayudar con tu problema.

Prueba con este ejemplo.


```
#use delay(clock=10000000)           // Usando por ejemplo un cristal de 10MHz


void main()
{
   byte value;                     // Variable para el Convertidor AD

   setup_ccp1(CCP_PWM);   // Configura el CCP1 para trabajar en PWM

        // El ciclo de trabajo es (1/clock) * 4 * t2div * (peridodo+1)
       // En este caso, el clock es de 10MHz con un periodo de 127        
	
       //     (1/10000000) * 4 * 1 * 128 =  51.2 us     o    19.5 khz
       //     (1/10000000) * 4 * 4 * 128 = 204.8 us    o    4.9 khz
       //     (1/10000000) * 4 * 16 * 128= 819.2 us   o    1.2 khz

    // SELECCIONA UNA DE LAS 3
    setup_timer_2(T2_DIV_BY_1, 127, 1);            // Frecuencia de 19'5KHz
    setup_timer_2(T2_DIV_BY_4, 127, 1);            // Frecuencia de 4'9KHz
    setup_timer_2(T2_DIV_BY_16, 127, 1);          // Frecuencia de 1'2KHz


     setup_port_a(ALL_ANALOG);
     setup_adc(adc_clock_internal);
     set_adc_channel( 0 );                      // Select.  el canal 0 del convertidor AD
 

    while( TRUE )
         {
          value=read_adc();            // Leer un potenciómetro de refencia.
     
          set_pwm1_duty(value);    // Determinamos es ciclo de trabajo del PWM
        }   // Fin del While(1);

}  // Fin del Main()
```


Esto te deberia funcionar a la primera.

Saludos.


----------



## Ahona (Feb 28, 2008)

Muchas gracias Paloky!
Solo una cosa...he probado el programa y bueno, el compilador me da este error
"A #DEVICE required before this line"
Y si pongo el "#include<PIC16F877.H>" me da un error por cada linea de codigo...

De todas formas, aun no tengo claro una cosa...

Con la funcion "setup_timer_2" lo que se hace es establecer el ciclo de trabajo del PWM?
Entonces esta funcion "set_pwm1_duty" no hace lo mismo? ahi no le decimos el ciclo de trabajo?

Me he hecho un lio con estas 2 funciones y no logro aclararme...
Alguien me puede hechar una mano?

Gracias y un saludo!


----------



## Elvic (Feb 28, 2008)

Que hay de nuevo, aquí te va un ejemplo, con otro compilador; pues el que utilizan se me dificulta bastante pero bien aquí esta:

#include <system.h>

void main()

{

trisc=0;
CCP1CON=0x0C;
CCP2CON=0x0C;
T2CON=0x04;
PR2=255;//Para el periodo
while(1)
{
CCPR1L=154;
CCPR2L=51;
delay_s(10);
CCPR1L=230;
CCPR2L=128;
delay_s(10);
}
}

Lo que esta dentro del while es lo que tienes que cambiar, son los porcentajes de señal, En el primer caso son 60% en una salida y 20% en la otra, luego se espera y cambia a 90% y 50%. sabiendo que 255 son el 100%. Así ya lo puedes cambiar a tu antojo. Sale?

el compilador es este: http://www.sourceboost.com/


----------



## Paloky (Feb 29, 2008)

Ahona dijo:
			
		

> Muchas gracias Paloky!
> Solo una cosa...he probado el programa y bueno, el compilador me da este error
> "A #DEVICE required before this line"
> Y si pongo el "#include<PIC16F877.H>" me da un error por cada linea de codigo...
> ...



Hola Ahona.

el "setup_timer_2" le indicas la frecuencia del PWM, y con el "set_pwm1_duty" la anchura del pulso.

Tendrías una cosa así:


```
set_pwm1_duty
     <--------->
                                             
      ----------                     -----------
     |          |                   |           |
     |          |                   |           |
----            --------------------            ----------

     <----------------------------->
               setup_Timer2
```

Saludos.


----------



## Ahona (Feb 29, 2008)

Coño! ahora si que me ha quedado claro  
Muchas gracias Paloky!
El compilador que tenia, tenia las librerias corruptas, por lo que me daban errores por todos los lados y Elvic, no he conseguido hacer funcionar ese programa...  
Muchas gracias de todas formas!
Haber si luego me pongo con ello y pongo el programilla por aqui...
Un saludo!


----------



## Ahona (Mar 12, 2008)

Bueno, poco a poco va tirando palante el proyecto...perdonad por no contestar antes, pero estado de examenes...

El programa va algo avanzado, es mas, el control de direccion del motor, por lo menos simulado en el proteus, ya lo tengo listo. Ahora tengo otro problemilla: mi intensión es que cuando pulse una tecla del ordenador, el motor gire en un sentido, y cuando pulso otra tecla, que cambie de sentido.
Como digo, lo estoy simulando en el proteus y posiblemente sea porque no se utilizar bien el terminal virtual...y tambien porque no configuro bien la comunicacion rs232
Aqui hos pongo el programa segun lo tengo ahora y como digo, sin poner lo del rs232, si que me funciona.

```
#include <16f877.h>
#use delay (clock=4000000)   //indico la frecuencia del reloj

char direccion;
   
void main (void)
{
   setup_ccp1(CCP_PWM);   // Configura CCP1 en modo PWM
   set_tris_c(11111011);   //rc2 como salida
   setup_timer_2(T2_DIV_BY_16,255,1);  // El periodo de la señal PWM
   set_tris_a(11111100); //RA0 y RA1 como salida de datos
   
   #use rs232 (BAUD=9600,XMIT=PIN_C6,RCV=PIN_C7,bits=1)
   
   while(true)
   {
      direccion=getchar();
      
      while(direccion=='a')
      {
      output_low(pin_A0);//pin A0 a 0
      output_high(pin_A1);//pin A1 a 1
      set_pwm1_duty(200); //indico el ciclo de trabajo del pwm
      direccion=getchar();
      }
      
      while(direccion=='s')
      {
      output_high(pin_A0);//pin A0 a 1
      output_low(pin_A1);//pin A1 a 0
      set_pwm1_duty(200); //indico el ciclo de trabajo del pwm
      direccion=getchar();
      }
   }
}
```

Cuando solo dejo uno de los 2 while, el motor gira en un sentido, si dejo el otro, el motor cambia de giro, pero con el rs232 lo queria hacer al pulsar una tecla...

Sabeis donde puedo tener el error?

Muchas gracias por vuestro tiempo

Un saludo!


----------



## rodriguis (Mar 19, 2008)

hola. yo igual quiero usar el pwm. estoy haciendo un proyecto para la escuela de una silla de ruedas electrica para controlar 2 motores uno para marcha y otro para el sentido de giro. quiero usar un micro 16f873a, pero la verdad no me acuerdo como usar la funcion pwm. estoy usando microcode studio. si alguien tiene un ejemplo para ayudarme se lo agradecere. saludos


----------



## RAUL R. (Jun 14, 2008)

saludos, necesito hacer una programacion para variar el ciclo util del pwm deacuero al valor que obtenga por el puerto A0 (analogico) del PIC 16F877A, necesito decirle al pwm que ese valor en decimal sera el ciclo util. como puedo hacer? yo intenet 



pwm portb.7,dec ao,500

donde ao var porta.0

pero da error al compilar


gracias


----------



## dragondgold (Ago 11, 2009)

hola yo necesito generar una frecuancia de 38Khz con el PWM del pic pero cuando lo simulo en proteus no me da los 38Khz de salida alguein sabe por que aca les dejo el programa (soy algo nuevo en C):

#include<16f877a.h>
#fuses NOWDT,NOPROTECT
#use delay(clock=4000000)
#byte TRISB=0x86
#byte PORTB=0x06
#byte TRISC=0x87
#byte PORTC=0x07
#byte T2CON=0x12

void main(void){
TRISB=0x00;
PORTB=0x00;
TRISC=0x00;
T2CON=0b00000111; //TMR2 habilitado y predivisor de 16
while(TRUE){
SETUP_CCP1(CCP_PWM);
SET_PWM1_DUTY(594);
}
} 

para caluclar los 38Khz use esta formula es correcta?

valor/(1/clock)*predivisor tmr2

0.000594/(1/4000000)*16


----------



## lostxcoco (Nov 8, 2009)

Holaa!!

Yo intento hacer algo similar, pero tengo muchas dudas u_u, soy nueva en esto de los pics de la familia 16f87x y aún más en la programación de pics en C u_u, alguien me puede ayudar con mi programa?, se trata de un programa que mueve un motor en una dirección a un nivel bajo de velocidad, incrementa poco a poco la misma y cuando llega al límite de velocidad, cambia de dirección, aqui les dejo una mejor explicación del algoritmo :3 :



1.- Arrancar el motor suavemente en el sentido "horario" hasta llegar a la velocidad máxima
2.- Girar en sentido "horario" tantos pasos como determine la constante "HORARIO"
3.- Parar un segundo
4.- girar en sentido "antihorario" tantos pasos como indique la constante "ANTIHORARIO" a la velocidad que determinen los interruptores (RA4-RA0)*8
5.- Decrecer la velocidad hasta llegar a detener al motor
6.- Parar un segundo
7.- Vuelve al paso 1

Los valores de las variables son los siguientes:

HORARIO: 1500 (Núm de pasos en sentido horario)
ANTIHORARIO: 100 (Núm de pasos en sentido antihorario)
PERIODO: 255 (periodo de 255 predivisor de 16 (4ms))
delay_cont: 0x21 (variable de temporización)

Espero que esta informacion sea suficiente x_x y que ojalá me puedan ayudar u_u, estoy desesperada y ya no sé que hacer u_u
para más información, el problema viene en el libro "MICROCONTROLADORES <<PIC>> Diseño y aplicaciónes segunda parte: PIC 16f87x" de José María Angulo Usategui, Susanaa Romero Yesa e Ignacio Angulo Martinez, editorial MC Graw Hill


Si alguien me puede ayudar favor de contactarme aqui o mandar un correo a ebbj_240787@hotmail.com, les agradeceria su ayuda x3


----------



## havat (May 6, 2010)

hola esta muy bien tu repuesta...pero me gustaria saber como seria al algoritmo para controlar el duty con un teclado matricial,,,,debe ser simple pero no lo logro implementar....por ejemplo si pulso 1 de estar el duty al 10% de la frecuencia y si pulso el 2 estara a 20% de la frecuencia y asi hasta el 90%.....espero alguien me pueda ayudar......gracias a todos--!!


----------



## oriel arriagada (Oct 27, 2010)

Saludos!!!!
Muchas gracias por este topico ya que es el que mas me ha mostrado cosas del PWM. 
tengo un consulta basica.....alguien sabe que significa en el setup_timer2 el MODO y porque toma valores 1,4 y 16? o el PERIODO con valores 0-255? y el POSESCALE 1-16.
Si ven, son preguntas basicas como las que respondio Paloky (muchas gracias)
Espero que me puedan ayudar o darme un link o cita de libro para entender.......
Muchas gracias
Oriel


----------



## magnetosiug (Oct 27, 2010)

hola expertos en la electronica, soy nuevo en este foro todavia no se como desembolverme en el asi que si les pareco fuera de lugar tenganme paciencia.
nesesito su ayuda , quiero simular circuitos de elceronica tanto analogica como digital ya que estoy estudiando y me recomendaron el multisim 8 pero no se donde conseguirlo ni como instalarlo


----------



## Rijiru (Dic 16, 2010)

oriel arriagada dijo:


> Saludos!!!!
> Muchas gracias por este topico ya que es el que mas me ha mostrado cosas del PWM.
> tengo un consulta basica.....alguien sabe que significa en el setup_timer2 el MODO y porque toma valores 1,4 y 16? o el PERIODO con valores 0-255? y el POSESCALE 1-16.
> Si ven, son preguntas basicas como las que respondio Paloky (muchas gracias)
> ...


 

Te recomiendo que entres al Foro de los creadores de CCS, ahi vienen ayudas muy buenas acerca del compilador =)

Saludos


----------



## edwardzinho29 (May 22, 2012)

havat dijo:


> hola esta muy bien tu repuesta...pero me gustaria saber como seria al algoritmo para controlar el duty con un teclado matricial,,,,debe ser simple pero no lo logro implementar....por ejemplo si pulso 1 de estar el duty al 10% de la frecuencia y si pulso el 2 estara a 20% de la frecuencia y asi hasta el 90%.....espero alguien me pueda ayudar......gracias a todos--!!



amigo pudiste conseguir eso???
Yo necesito algo muy parecido ...si pudiste conseguirlo ..colaborame


----------

