Modulo PWM y transmicion RS232 con PIC18F4550

Este circuito es una practica que nos dejaron en una ocasion en la materia de Microprocesadores y microcontroladores en sexto semestre de la carrera ing. electronica en el ITLM 2010, se las voy a compartir para que armen sus propios proyectos.
Esta practica consta de utilizar el modulo de PWM del PIC18F4550 para variar la velocidad de giro de un motor.
Esto funciona asi: El circuito consta de 3 botones, inicio-paro, incremento y decremento, al activar el boton inicio el ancho del pulso se ira incrementando de tal forma que al llegar los 15 segundos alcanze una velocidad del 50% del giro del motor (los botones incremento y decremento son inutiles hasta que se alcanza esta velocidad), una vez que se alcanzo el 50% de la velocidad podemos incrementar o decrementar la velocidad del motor en un 5%, con velocidad minima del motor del 30% (lo limite con el sofware) y velocidad maxima del 90%, al precionar el boton inicio-paro la velocidad del motor se ira decrementando en saltos (el salto depende del porcentaje de la velocidad en la que se encuentre el motor al momento de precionar inicio-paro) de tal forma que alcanze una velocidad de 0% en 15 segundos, esto que acabo de explicar lo hice con 3 interrupciones externas para los 3 botones y una interrupcion interna configurada como timer a 1 segundo. Tambien necesitabamos medir las revoluciones por minuto del motor esto lo hicimos con un optoacoplador ranurado por donde pasaban las aspas de motor (de ahi conectado al pin b7 del PIC).
La practica tambien necesitaba que estubiesemos sensando la temperatura y que prendieramos un extractor a los 40°C y se apagara al regresar a los 30°C (Histeresis), para la lectura utilizamos el sensor LM35 y el ADC a 10 bits del PIC .
Lo siguiente que hicimos fue mostrar la temperatura las rpm's y el ciclo de trabajo del PWM en respectivo orden en una pantalla LCD 16x2, y de la misma forma transmitirlo a la PC por medio de RS-232(con el circuito integrado MAX232), para leerlo en la PC hice un pragrama en visual basic 6 acoplado con measurement studio para los indicadores (este programa es para que en visual basic puedas tener indicadores como tacometros, termometros, velocimetros, led's, etc).
Para la programacion del pic utilize el programa de CCS: PIC C Compiler (utiliza programacion en C :E ), y utilize el programa Isis de Proteus 7 para la simulacion.
Todo va incluido en el archivo en RAR que esta adjunto en esta pagina.

Nota:
Es mi primer aporte, dejen comentarios, si ahi algun problema para abrir los programas, simulacion y/o cualquier duda pregunten, me gustaria un tema nuevo sobre comunicacion PIC a PIC I2C pues no lo enseñaron y me gustaria aprender.
El programa tiene comentarios "paso a paso".
 

Adjuntos

  • Practica PWM - comentarios.rar
    1.4 MB · Visitas: 2,138
Este circuito es una practica que nos dejaron en una ocasion en la materia de Microprocesadores y microcontroladores en sexto semestre de la carrera ing. electronica en el ITLM 2010, se las voy a compartir para que armen sus propios proyectos.
Esta practica consta de utilizar el modulo de PWM del PIC18F4550 para variar la velocidad de giro de un motor.
Esto funciona asi: El circuito consta de 3 botones, inicio-paro, incremento y decremento, al activar el boton inicio el ancho del pulso se ira incrementando de tal forma que al llegar los 15 segundos alcanze una velocidad del 50% del giro del motor (los botones incremento y decremento son inutiles hasta que se alcanza esta velocidad), una vez que se alcanzo el 50% de la velocidad podemos incrementar o decrementar la velocidad del motor en un 5%, con velocidad minima del motor del 30% (lo limite con el sofware) y velocidad maxima del 90%, al precionar el boton inicio-paro la velocidad del motor se ira decrementando en saltos (el salto depende del porcentaje de la velocidad en la que se encuentre el motor al momento de precionar inicio-paro) de tal forma que alcanze una velocidad de 0% en 15 segundos, esto que acabo de explicar lo hice con 3 interrupciones externas para los 3 botones y una interrupcion interna configurada como timer a 1 segundo. Tambien necesitabamos medir las revoluciones por minuto del motor esto lo hicimos con un optoacoplador ranurado por donde pasaban las aspas de motor (de ahi conectado al pin b7 del PIC).
La practica tambien necesitaba que estubiesemos sensando la temperatura y que prendieramos un extractor a los 40°C y se apagara al regresar a los 30°C (Histeresis), para la lectura utilizamos el sensor LM35 y el ADC a 10 bits del PIC .
Lo siguiente que hicimos fue mostrar la temperatura las rpm's y el ciclo de trabajo del PWM en respectivo orden en una pantalla LCD 16x2, y de la misma forma transmitirlo a la PC por medio de RS-232(con el circuito integrado MAX232), para leerlo en la PC hice un pragrama en visual basic 6 acoplado con measurement studio para los indicadores (este programa es para que en visual basic puedas tener indicadores como tacometros, termometros, velocimetros, led's, etc).
Para la programacion del pic utilize el programa de CCS: PIC C Compiler (utiliza programacion en C :E ), y utilize el programa Isis de Proteus 7 para la simulacion.
Todo va incluido en el archivo en RAR que esta adjunto en esta pagina.

Nota:
Es mi primer aporte, dejen comentarios, si ahi algun problema para abrir los programas, simulacion y/o cualquier duda pregunten, me gustaria un tema nuevo sobre comunicacion PIC a PIC I2C pues no lo enseñaron y me gustaria aprender.
El programa tiene comentarios "paso a paso".

hola mui interesante tu proyecto tengo que hacer uno parecido al que tienes solo que con 16f877a
podras acerme el favor de convertirlo al pic 16f877
 
hola hasta el momento elogrado hacer que funcione con el pic 16f877 pero faltan detalles lo puedes chequear un punto es que cuando decremento baja al 10% y retorna al 30% quisiera que no retornara a 30% al menos que pulsara el boton de in cremento

el otro punto es para cambiar cuando inicia al 50% a uno de acuerdo ala nececidad del proyecto
el codigo

PHP:
#include <16F877A.h>
#device adc=10
#use delay(clock=8000000)
#FUSES NOWDT                    //No Watch Dog Timer
#FUSES XT                       //Crystal osc <= 4mhz for PCM/PCH , 3mhz to 10 mhz for PCD
#FUSES NOPUT                    //No Power Up Timer
#FUSES NOPROTECT                //Code not protected from reading
#FUSES NODEBUG                  //No Debug mode for ICD
#FUSES NOBROWNOUT               //No brownout reset
#FUSES NOLVP                    //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD                    //No EE protection
#FUSES NOWRT                    //Program memory not write protected
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8)

int x=0, y=0,z=0,h=0,a1=0,a2=0,ciclo2=0,vent=0;
float read1=0,temp=0,ciclo=0,porc=0,dc2=0;
long dc=0,rev=0,vel=0,pulso=0,pulso2=0;
int1 a=0,b=0,c=0,n=0,cambio=0;
#int_TIMER0
TIMER0_isr()   //timer en cada segundo
{

set_adc_channel(0);  //lectura del convertidor analogo digital
read1=read_adc();



pulso2=pulso*60;   //esto es para sacar las revoluciones por minuto,cada segundo
pulso=0;           //se reinicia para tener una lectura correcta
a=1;           //esta variable es para que en el while infinito mande los datos por    
               //tx cada segundo solamente
if(y==1&&b==0) //este if sirve para el encendido, b es para limitarlo a 15seg y 
{              //si es 1 es encendido
x+=1;          //cada segundo se incrementa en 1

if(x<15)       //al llegar a los 15 segundos el ciclo de trabajo es igual al 50%
{
dc+=34.1;      //dc y dc2 son del mismo valor siempre pero son de diferente tipo de
dc2+=34.1;     //variable, una long y otra float
               //este incremento es para que en el encendido de 15seg se valla incrementando   
               //la velocidad en forma de rampa
}
else
{
dc=511.5;     //en caso de que pasen los 15seg el ciclo de trabajo es igual al 50%  
dc2=511.5;

b=1;          //b es la variable que nos permite salir del ciclo de encendido
}
}

if(c==1)      //esta parte es para el apagado     
{
if(n==0)      
{
porc=dc/15;   //esto es para saber que porcentaje se decrementa cada segundo durante el  
n=1;          //apagado del motor
} 

z+=1;          //z es para contar los 15seg de apagado
dc-=porc;      //es el decremento que hace 
dc2-=porc;

if(z>=15)      //ya que pasaron los 15seg del apagado se reinician todas las variables 
{              //para asi poder volverla a prender en forma de rampa
y=0;
b=0;
z=0;
dc=0;
dc2=0;
ciclo=0;
c=0;
x=0;
porc=0;
n=0;
}
}
}



#int_TIMER1
TIMER1_isr() 
{


}

#int_EXT //interrupcion externa para encendido y apagado
EXT_isr() 
{

y=1;

if(b==1)
y+=1;

if(b==1&&y==2)
{
c=1;
}


}


#define LCD_TYPE 2
#include <lcd.c>
void main()
{
   lcd_init();
   setup_adc_ports(RA0_RA1_RA3_ANALOG);
  setup_adc(ADC_CLOCK_DIV_8);
   //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_16,255,1);
   //setup_timer_3(T3_DISABLED|T3_DIV_BY_1);
   //setup_ccp1(CCP_PWM_FULL_BRIDGE|CCP_SHUTDOWN_AC_L|CCP_SHUTDOWN_BD_L);
   setup_ccp1(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!!
set_tris_b(0xff);
#use fixed_io(a_outputs=PIN_A2, PIN_A3)    /*para utilizar solo unos pines del 
puerto a como salidas*/

while(1)
{
if(input(pin_b6)&&cambio==0)  //contador de cambios de estados para contar las rpm
{
ciclo2=ciclo;
if(b==1&&y==1)  //solo si ya alcanzo el 50%
{
delay_ms(120);
if(ciclo>10)     //decrementa en 5%
{
dc-=51.15;
dc2-=51.15;
}

if(ciclo2<=10&&b==1&&y==1)  //limite menor del 30%
{
ciclo=10;
dc=306.9;
dc2=306.9;
}

}
}


if(input(pin_b7)&&cambio==0)  //contador de cambios de estados para contar las rpm
{
ciclo2=ciclo;
if(b==1&&y==1) //solo si ya alcanzo el 50% del ciclo de trabajo
 {
delay_ms(120);
if(ciclo<100)
{
dc+=51.15;     //aumenta en 5%  
dc2+=51.15;

}

if(ciclo2>=100&&b==1&&y==1) //limite maximo del ciclo de trabajo
ciclo=100;


 }


}

 if(!input(pin_b7)&&cambio==1)//con la variable cambio se detecta el cambio de estado 
 //y asi sacamos las rpm
{
cambio=0;
}


ciclo=dc2/10.23;    //para saber a cuanto equivale cada 1%
a1=temp;
a2=ciclo;

if(a==1)        //se hace 1 en el timer interno
{
printf("$%i|%lu/%i",a1,pulso2,a2); //manda datos por tx
a=0;                               //la iguala a cero para esperar a que pase un segundo mas
}
vent=temp;        //esto es para encender el ventilador si la temperatura pasa de 40 grados 
if(vent>=40)
output_high(pin_a2);

if(vent<=10)       //histeresis
output_low(pin_a2);


//TEMPERATURA
lcd_gotoxy(1,1);
lcd_putc("T:");

temp=((read1*0.0048875855327468))*100;  //lectura del adc de la temperatura

lcd_gotoxy(3,1);
printf(lcd_putc,"%i \xdfC %lu rpm        \n %i%%    ",a1,pulso2,a2);/*impresion
de temperatura, rpm y ciclo de trabajo*/
//PWM


set_pwm1_duty(dc);  //porciento del ciclo de trabajo



}

}
 
Última edición por un moderador:
Magnifico simplmente. soy de Ing. en Sistemas Computacionales y tengo rato tratando de hacer esto con el pic4550 para controlar luces con el puerto usb y con una salida PWM me parece que es posible. Gracias!!!!
 
Esta muy bueno, lo estoy mirando, existe la posibilidad de que subas el mismo proyecto pero con comunicacion usb??, y manejado desde labview? es para guiarme, Gracias.
 
Muy muy interesante proyecto, excelente material. Yo estoy intentando hacer un PWM con un 16F887, mi idea era hacerlo con una resistencia variable y el modulo ADC y así manejar el ancho de pulso... Cualquier cosa buna que salga la voy a publicar. Muchas gracias, tu material aporta mucho
 
hola soy estudiante de mecatronica y me intereza la programacion de un motor ac por (pwm) para un proyecto de porton automatico!!! agradezco a quien pueda aportar una pagina o manual que me pueda guiar, ah con pic 16f877
 
Muy buenas a todos. Tengo una duda. El programa que gentilmente comparte rodalt anda de mil maravillas. Ahora yo quiero hacer andar algo muy similar, pero con un 16F887 como ya puse. Llevo varias pruebas, pero lo que me pases es, primero arreglo los fuses para el 887, genial. Pero si dejo el programa tal cual está, sin modificar nada más que los fuses, el compilardor ccs me tira un error en las interrupciones de incremento y decremento del ancho de pulso.... Repito solo tocando los fuses... al no poder hacer andar esto, todavía ni me he puesto a ver si en vez de con dos botones lo hago con una resistencia variable a la modificación del ancho....Cualquier ayuda la agradezco. Saludos

Tengo una pregunta para @underwol8443, lo probaste a tu programa? Porque como el 877 está mucho más cerca del 887, intenté probarlo, pero me tira varios errores al compilarlo, y no me deja hacerlo, yo estoy usando PCWHD ccs para compilar.... Gracias Saludos

Tengo una duda más general: Hago andar el pwm sin problemas poniendole valores de entre 0 y 1023... Pero cuando quiero hacer que lo gobierne al módulo adc, me hace cualquier cosa.... Yo he visto que nadie hace ninguna conversión matemática sobre el tema.... o viendo los ejemplos no me doy cuenta donde está.... he visto ejemplos de otros post y la verdad no la caso, simplemente leen el canal del adc correspondiente y eso lo ponen en el duty cicle del pwm.... alguien me puede ilustrar un poco sobre el tema. Muchas gracias

Pude hacer lo que quería en breve lo subo, tengo que optimizar unas cosas, pero anda lindo.... Saludos
 
Última edición por un moderador:
Hola pues muy buen post, pero tengo unas dudas y ojala y puedas responder

El Max232 como es que lo conectas para poderte comunicar y que tipo de motores ocupaste para tu practica ya que por lo que yo sé, se ocupan drivers para asi poder entregar toda la corriente al motor y asi evitar que se te queme el pic
 
Por que no aprovechan mejor los micros? un 18F4550 y usando puerto serie?
Este micro ya es de la gama alta y soporta USB, porque no lo usan asi?
Acá comparto un video de lo que yo hice:
 
Atrás
Arriba