Podrias usar un convertidor de Corriente a Voltaje, en base al consumo de este lo mandas al ADC del Micro y con el puedes incrementar o decrementar la velocidad mediante el PWM o lo que se te ocurra utilizar como tecnica para esta variacion, pudes usar cualquier tipo de control, PI PD PID Fuzzy etc.
Hay dos métodos que funcionan bastante bien:
A - Método por compensación de corriente:
1º Mides la corriente del motor
2º Aumentas la tensión de alimentación del motor dV = I · Rmotor
La Rmotor tienes que conocerla antes(se puede medir con un polímetro, midiendo Ohmios con el motor parado)
B - Método por medición de la tensión generada (back-emf)
1º Apagas la tensión de alimentación del motor
2º Esperas a que la corriente de las bobinas llegue a cero
3º Mides la tensión que está generando el motor
4º Vuelves a alimentar el motor
(todo el ciclo debe durar poco tiempo, p.ejemplo 10ms)
La tensión que genera el motor es proporcional a la velocidad de giro
Error de los métodos: <1% si los ajustas bien
Saludos.
Gracias mil una vez mas " picuino ", bueno pues entonces a googlear se a dicho 8) 8) 8) 8)Si tienes dudas concretas no dudes en preguntar.
buscare informacion este fin de semana y publicare los avances de este proyecto...
Pero claro si alguien mas quiere aportar con sus conocimientos bienvenido seran chauu chauu amigos foreros :-/ :-/ :-/ :-/ :-/ :-/
Si hay más foreros interesados, se podría hacer un proyecto colaborando para hacer una placa que regule la velocidad de un motor DC pequeño (serviría para controlar la velocidad de un taladro tipo dremel).
Saludos.
Saludos sander,
Gracias por sumarte. Creo que podemos apuntarnos en este mismo hilo y de paso resolveremos dudas a amyver, que lo inició.
Por ahora podemos ir pensando si el regulador debería ser de un sólo sentido o de dos sentidos, es decir con marcha atrás (el doble de dificil).
Saludos.
He abierto otra entrada sin querer, porque no veía la anterior (estaba en la página siguiente)
Saludos.
P.D.:
Aprovecho para comentar que el circuito anterior tiene una 'zona muerta' en la que no mide tensión del motor.
Las tensiones de motor por debajo de 0.6v (tensión en directo del diodo) no se pueden medir.
Esto hace que en este rango el motor se mueva sin control.
Saludos.
Bueno luego de analizar el circuito que muestras picuino, se me quedan algunas dudas...
- La primera: Entiendo que los diodos que salen de los terminales del motor son para aterrarlo y asi tener una lectura confiable
de la Back-emf cuando se pare el motor por un instante de tiempo verdad???.
- La segunda: Cual es la funcionalidad del Diodo D5, pues si no me equivoco es por el catodo de este diodo por donde se haran las lecturas
de la Back-Back-emf....
- La Tercera: Las lecturas de la Back-emf deberan ser pasadas al modulo CAD del micro que se usa, pero para esta lectura no hara falta limitar
el voltaje de entrada a dicho conversor???, bueno normalmente yo uso los micros de Microchip y su conversor analogico digital tiene
un voltaje max analog de In de 5V.
- Y la Ultima: Segun entiendo la funcionalidad del transistor BC337 es para habilitar las lecturas de la Back-emf cuando se necesite..
Bueno son algunas dudas que tube y confiando en la amabilidad y tolerancia si es necesario de los amigos foreros en especial de picuino seguiremos adelante... :-/ :-/ :-/ :-/ :-/ :-/ :-/ :-/
No se ve el esquema, picuinoGracias Nocturno, creo que google sites da problemas a veces mientras lo edito. (sólo lo veo yo)
muy interesante picuino :-/ sigo atento al hilo, termino un proyecto pendiente y hago pruebas... suerte a todos :mrgreen:
El código en el que me baso está unos mensajes más arriba y ya funciona (sin módulo PWM)
Sólo hay que mejorarle.
Saludos.
El problema está en llevar el terminal negativo del motor a masa (dependiendo del sentido de giro el terminal negativo es distinto)
En los circuitos que hemos publicado hasta ahora, una resistencia lleva a masa un terminal, pero eso no es suficiente con dos sentidos de giro.
Saludos
yo me animo :-/ , lo que pasa es que no encontre el L6203 por mi ciudad, asi que pense en armar un puente H con MOSFETs discretos, pero luego me di cuenta que iba a necesitar algun driver para los MOSFETS para poder manejarlos de forma mas eficiente, y tampoco consegui esos drivers, asi que para probarlo voy a usar el L293, que es parecido al L6203 pero para motores mas pequeños.
Voy a tratar de probarlo con el mismo micro, o talvez pruebe otro sin USB
Saludos
Ya he terminado de modelar el motor de corriente continua y he publicado el manual en mi web y en el foro:
Modelo equivalente del motor eléctrico:
https://sites.google.com/site/picuino/motor_equivalent_model
GUIA: Motores de corriente continua
http://www.todopic.com.ar/foros/index.php?topic=37484.0
Ahora vamos a por la regulación de corriente del motor.
Saludos,
Estoy probando un método para medir la velocidad del motor y 'obsevar' como varía la velocidad.
Añadiendo un led al PIC que se encienda durante 1ms cada 10ms se consigue una luz estroboscópica.
Iluminando el eje del motor con la luz se observa el eje del motor "quieto" cuando gira a 6000rpm
Si añadimos al eje motor 3 marcas negras (por ejemplo las 3 pinzas en un motor de taladro), podemos dejarlas "quietas" a 2000rpm
El código es sencillo. He modificado la rutina de interrupción para que encienda un led en el puerto RB5:
[code = c]
if (sys_clk==0) {
sys_clk = TMR0_COUNT;
LATBbits.LATB5 = 1; // Luz estroboscópica off
if (++milli_second == 10) {
LATBbits.LATB5 = 0; // Luz estroboscópica on
milli_second = 0;
}
}
Yo también tengo problemas de ruido a la hora de medir corrientes porque la tensión en la resistencia de sensado es pequeña y el ruido se nota mucho.
En mi caso noto ruido en torno a 20mV. Como estoy utilizando placa de prototipos de inserción rápida (protoboard) esto es normal con las corrientes de hasta 1 amperio con las que trabajo.
En mi caso ya he conseguido que funcione bien el sensado de corriente con un operacional cmos y la parte de potencia trabajando con medio puente (un sólo sentido de giro).
Sólo me falta conseguirlo con un puente en H completo.
Creo que va siendo hora de hacer una placa PCB para que el ruido afecte menos.
Si en tu caso el ruido es mucho mayor que 20mV y el microcontrolador llega a resetearse, el problema es otro.
¿Has colocado un condensador entre Vdd y Gnd?
¿Has unido bien las masas de los dos circuitos? PIC_____Puente H
¿Has colocado resistencias de 100 ohm en los cables de señal para asegurarte de que no conducen grandes corrientes?
Si envías una foto podemos opinar otros posibles problemas.
Saludos.
Si, las resistencias deben estar entre el microcontrolador y el puente en H.
Estas resistencias NO SON NECESARIAS, pero te pueden dar una pista de dónde está el problema.
Si se producen sobretensiones o cortocircuitos en los cables de señal, con las resistencias no se debería resetear el micro.
Con un polímetro puedes comprobar la tensión en las resistencias, que debería ser cero o muy cercano a cero. En caso contrario ahí está el problema.
Saludos.
/****************************************************************************
By: Amyver - Foro TODOPIC
*****VERSION 1B*****
Funciones:
*Modulo controlado atravez del interface USART
****************************************************************************/
#include <16F877A.h>
#device adc=10 //Definimos un Conversor Analogo/Digital con resolucion de 10 bits
#Fuses XT, NOWDT, NOPROTECT, NOLVP, PUT, BROWNOUT, NOCPD, NOWRT//palabra de configuracion
#Use delay(clock=4000000) //usando un oscilador de 4MHz
#Use RS232(Baud=9600, Xmit=Pin_C6, Rcv= Pin_C7, Parity=N, Bits=8)
#Use Fast_io(B)
#Use Fast_io(C)
#Byte PortB=0x06
#Byte PortC=0x07
//declaracion de variables globales que seran usados en el programa
char var;
signed int16 senialError=0;
signed int16 lecturaBackEmf=0,fijarVelocidad=0,valorPWM=0;
////////////////////////////////////////////////////////////////////////////////
void incrementarVelocidad()
{
OutPut_High(Pin_C5); //Habilitamos el driver L6203
fijarVelocidad+=25; //incrementamos la velocidad en 25
if(fijarVelocidad>=1000) //pregutamos si se llego a la velocidad tope hacia adelante
{
fijarVelocidad=1000; //se fija una velocidad tope
}
if(fijarVelocidad>=0) //Preguntamos si la velocidad es positiva (motor con giro hacia adelante)
{
OutPut_Low(Pin_C4); //Habilitamos driver L6203 para el giro a la derecha
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
else
{
OutPut_High(Pin_C4); //Habilitamos driver L6203 para el giro a la izquierda
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
}
void decrementarVelocidad()
{
OutPut_High(Pin_C5); //Habilitamos el driver L6203
fijarVelocidad-=25; //decrementamos la velocidad en 25
if(fijarVelocidad<-1000) //pregutamos si se llego a la velocidad tope hacia atras
{
fijarVelocidad=-1000; //se fija una velocidad tope
}
if(fijarVelocidad>=0) //Preguntamos si la velocidad es positiva (motor con giro hacia adelante)
{
OutPut_Low(Pin_C4); //Habilitamos driver L6203 para el giro a la derecha
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
else
{
OutPut_High(Pin_C4); //Habilitamos driver L6203 para el giro a la izquierda
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
}
void pararMotor() //paramos el motor
{
fijarVelocidad=0; //Establecemos la velocidad en cero
OutPut_Low(Pin_C5); //Deshabilitamos el driver L6203
set_pwm1_duty((int16)0); //se establece el PWM1 en Cero
printf("\r\n\r\nPARAR MOTOR=%Ld\r\n ",fijarVelocidad);
}
////////////////////////////////////////////////////////////////////////////////
void verificarRS232() //Funcion encargada de verificar si existen datos en buffer
{ //del USART
if(kbhit()) //Preguntamos si existen datos pendientes a ser procesados
{ //Si, hay algo pendiente de recibir ...
var=getc(); //tomamos el dato ingresado por el usuario y lo almacenamos en
//una variable
if(var==0x0D) //preguntamos si se presiono Enter
{
incrementarVelocidad();//llamamos a la funcion incrementar velocidad
}
if(var==0x08) //preguntamos si se presiono retroceso
{
decrementarVelocidad();//llamamos a la funcion decrementar velocidad
}
if(var==0x20) //preguntamos si se presiono la barra espaciadora
{
pararMotor(); //funcion que para los motores
}
}
}
void testearBackEmf() //Funcion que tomara el valor de la Back-emf
{
delay_ms(10); //tiempo que se enviara la señal PWM
OutPut_Low(Pin_C5); //Enable Motor OFF
delay_ms(1); //tiempo de espera para que la señal Back-emf se estabilice
Set_adc_channel(1); //selecion de canal 1 del modulo ADC
delay_us(50); //Retardo para que se carge la senal analogica
lecturaBackEmf=read_adc();//Se toma el resultado de la convercion y se guarda en nuestra variable de 16bits
printf("\r\nLectura BACK-EMF=%Ld",lecturaBackEmf); //imprimimos un dato por pantalla
OutPut_High(Pin_C5); //Enable Motor ON
}
void ajustarVelocidad() //funcion encargada de realizar el control de velocidad(ES LA QUE PRETENDO MEJORAR)
{
signed int16 auxiliar=0; //Definimos una variable de tipo entero con signo de 16 bits
if(fijarVelocidad>=0) //preguntamos si la velocidad es positiva (Giro Derecho)
{
senialError= fijarVelocidad-lecturaBackEmf; //sacamos el error
}
else //si la velocidad es negativa (Giro Izquierdo)
{
auxiliar=(int16)ABS(fijarVelocidad); //tomamos el valor absoluto de la variable
senialError= auxiliar-lecturaBackEmf; //la almacenamos en una variable para despues usarla
}
printf("\r\nSenial de Error=%Ld",senialError); //Imprimimos por pantalla el valor de la señal de error
if(senialError>5) //Establecemos un desplazamiento maximo de 5 unidades
{
valorPWM+=senialError; //ajustamos el valor del PWM
if(valorPWM>=1000) //preguntamos si se llego al limite maximo del PWM1
valorPWM=1000;
set_pwm1_duty((int16)valorPWM); //establecemos el nuevo valor del PWM1
printf("\r\n\r\nValor del PWM=%Ld\r\n ",valorPWM); //imprimimos el valor del PWM1
}
if(senialError<-5) //Establecemos un desplazamiento maximo de -5 unidades
{
valorPWM+=senialError; //ajustamos el valor del PWM
if(valorPWM<25) //si el valor del PWM1 es menor que 25, apagamos el CCP1
valorPWM=0;
set_pwm1_duty((int16)valorPWM); //establecemos el nuevo valor del PWM1
printf("\r\n\r\nValor del PWM=%Ld\r\n ",valorPWM); //imprimimos el valor del PWM1
}
}
void main()
{
Set_Tris_B(0b11111110); //Configuramos el pin RB0 como salida, los restantes como entradas
Set_Tris_C(0b10001011); //Configuramos los pines RC0,RC1,RC3 y RC7 como entradas, los restantes como salidas
PortB=0x00; //limpiamos el puertoB
PortC=0x00; //limpiamos el puertoC
OutPut_High(Pin_B0); //senializacion de pic ON
////////////////////////////////////Configuracion de CCPx(PWM)/////////////////////////////////////////////////
setup_timer_2(T2_DIV_BY_1,249,1); //configuramos el timer2, Prescaler=1,Periodo=249,Postcaler=1
//con lo que se conseguira: T=250us o f=4Khz
//"setup_timer_2(Prescaler,Periodo,Postcaler)"
setup_CCP1(CCP_PWM); //Escogemos el modo de trabajo de CCP1, lo escojemos como modulacion por ancho de pulso
//NOTA.- Tanto para PWM1 y PWM2 el periodo es establecido por el timer2
//NOTA2.-la resolucion maxima esta dada por: Tpwm=2exp(n) * 1/Fosc
// 250us=2exp(n) * 1/(4exp(6))
// 2exp(n)= 1000
//Entonces el maximo valor que podemos cargar al "value" es de 1000 con lo que se
//conseguira un ciclo de trabajo de 100% "set_pwm1_duty(value)"
////////////////////////////////////Configuracion de CAD////////////////////////////////////////////////////
setup_adc(ADC_CLOCK_INTERNAL); //Se usara un reloj interno
Setup_adc_Ports(AN0_AN1_AN3); //se configuran lo pines: RA0,RA1,RA2 como entradas analogicas
////////////////////////////////////////////////////////////////////////////////////////////////////////////
set_pwm1_duty((int16)0); //se inicializa el PWM en cero
OutPut_High(Pin_C5); //Enable Motor ON
printf("\r\nSystem OK.\r\n"); //Sistema en linea y listo para transmitir
while(true) //ciclo infinito
{
verificarRS232(); //llamamos a la funcion que se encargara de verificar la tecla que se pulso
testearBackEmf(); //funcion que determinara el valor de la Back-emf
ajustarVelocidad(); //FUNCION QUE REALIZA EL CONTROL DE VELOCIDAD (es la que pretendo mejorar)!!!!
}
}
1. Entrada de señal Back-Emf:
El rango de entrada es de 0 a 1023 puntos del ADC
El rango de lectura es de 0 a 23.4 voltios con el divisor de tensión que has puesto
Por lo tanto la señal BackEmf está multiplicada por 1023/23.4 = 43.7 puntos/voltio
Así cuando haya un voltio en el motor se leerá como: 1v · 43.7 = 43 puntos
Pero luego de algunas pruebas pude evidenciar que con el divisor de tension tenia una entrada de señal por el CAD de aprox. 1000 "puntos" lo que es equivalente a una entrada de tension de aprox 5 V cuando insertaba un PWM señal con un ciclo de trabajo de 100% o 1000"puntos"
Por lo tanto la señal BackEmf está multiplicada por 1023/23.4 = 43.7 puntos/voltio--> Entonces si no me equivoco la correccion seria de la siguiente manera:
Por lo tanto la señal BackEmf está multiplicada por 1023/5 = 204 puntos/voltio
/****************************************************************************
By: Amyver - Foro TODOPIC
*****VERSION 2B*****
Funciones:
*Modulo controlado atravez del interface USART
*Modulo usado CCP1
*El programa controla velocidad de un motor DC
en dos sentido de giro, con la particularidad
de mantener la velocidad constante ante cambios bruscos de carga
*Se soluciono el problema del reseteo del Micro usando
amplificadores operacionales configurados como seguidores de voltaje
dichos amplificadores fueron conectados a las salidas de los pines
de -CCP1- -Control de Giro- y -Enable-
****************************************************************************/
#include <16F877A.h>
#device adc=10 //Definimos un Conversor Analogo/Digital con resolucion de 10 bits
#Fuses XT, NOWDT, NOPROTECT, NOLVP, PUT, BROWNOUT, NOCPD, NOWRT//palabra de configuracion
#Use delay(clock=4000000) //usando un oscilador de 4MHz
#Use RS232(Baud=9600, Xmit=Pin_C6, Rcv= Pin_C7, Parity=N, Bits=8)
#Use Fast_io(B)
#Use Fast_io(C)
#Byte PortB=0x06
#Byte PortC=0x07
char var;
signed int16 senialError=0;
signed int16 lecturaBackEmf=0,fijarVelocidad=0,valorPWM=0;
void incrementarVelocidad()
{
OutPut_High(Pin_C5); //Habilitamos el driver L6203
fijarVelocidad+=20; //incrementamos la velocidad en 300
if(fijarVelocidad>=1000) //pregutamos si se llego a la velocidad tope hacia adelante
{
fijarVelocidad=1000; //se fija una velocidad tope
}
if(fijarVelocidad>=0) //Preguntamos si la velocidad es positiva (motor con giro hacia adelante)
{
OutPut_Low(Pin_C4); //Habilitamos driver L6203 para el giro a la derecha
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
else
{
OutPut_High(Pin_C4); //Habilitamos driver L6203 para el giro a la izquierda
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
}
void decrementarVelocidad()
{
OutPut_High(Pin_C5); //Habilitamos el driver L6203
fijarVelocidad-=20; //decrementamos la velocidad en 300
if(fijarVelocidad<-1000) //pregutamos si se llego a la velocidad tope hacia atras
{
fijarVelocidad=-1000; //se fija una velocidad tope
}
if(fijarVelocidad>=0) //Preguntamos si la velocidad es positiva (motor con giro hacia adelante)
{
OutPut_Low(Pin_C4); //Habilitamos driver L6203 para el giro a la derecha
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
else
{
OutPut_High(Pin_C4); //Habilitamos driver L6203 para el giro a la izquierda
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
}
void pararMotor() //paramos el motor
{
fijarVelocidad=0; //Establecemos la velocidad en cero
OutPut_Low(Pin_C5); //Deshabilitamos el driver L6203
set_pwm1_duty((int16)0); //se inicializa el PWM en Cero
printf("\r\n\r\nPARAR MOTOR=%Ld\r\n ",fijarVelocidad);
}
void verificarRS232() //Funcion encargada de verificar si existen datos en buffer
{ //del USART
if(kbhit()) //Preguntamos si existen datos pendientes a ser procesados
{ //Si, hay algo pendiente de recibir ...
var=getc(); //tomamos el dato ingresado por el usuario y lo almacenamos en
//una variable
if(var==0x0D) //preguntamos si se presiono Enter
{
incrementarVelocidad();//llamamos a la funcion incrementar velocidad
}
if(var==0x08) //preguntamos si se presiono retroceso
{
decrementarVelocidad();//llamamos a la funcion decrementar velocidad
}
if(var==0x20) //preguntamos si se presiono la barra espaciadora
{
pararMotor(); //funcion que para los motores
}
}
}
void testearBackEmf()
{
delay_ms(7); //tiempo que se enviara la señal PWM
OutPut_Low(Pin_C5); //Enable Motor OFF
delay_ms(1); //tiempo de espera para que la señal Back-emf se estabilice
Set_adc_channel(1); //selecion de canal 1
delay_us(50); //Retardo para que se carge la senal analogica
lecturaBackEmf=read_adc(); //lee el resultado de la convercion y se guarda en nuestra variable de 16bits
printf("\r\nLectura BACK-EMF=%Ld",lecturaBackEmf);
OutPut_High(Pin_C5); //Enable Motor ON
}
void ajustarVelocidad()
{
signed int16 Control_I, KI; //Definimos variables enteras con signo
signed int16 auxiliar=0,fijarVelocidadAux=0;//de 16 bits..
if(fijarVelocidad>=0) //Preguntamos si se tiene una velocidad
{ //positiva (Giro del motor en derecha)
senialError= fijarVelocidad-lecturaBackEmf;//Tomamos la señal de error
fijarVelocidadAux=fijarVelocidad; //Guardamos el valor de la velocidad programada
} //puesto que sera usada despues
else //si la velocidad es Negativa(Giro del motor en Izquierda)
{
auxiliar=(int16)ABS(fijarVelocidad); //Tomamos el valor ABSOLUTO de la variable "fijarVelocidad"
senialError= auxiliar-lecturaBackEmf; //la combertimos en una variable de 16 bits y la almacenamos.
fijarVelocidadAux=auxiliar; //Guardamos el valor de la velocidad programada
}
printf("\r\nSenial de Error=%Ld",senialError);
//////////////CONTROL INTEGRAL (propuesto por PICUINO)//////////////////////////
if((fijarVelocidadAux>=0)&&(fijarVelocidadAux<=200)) //nos aseguramos de que la velocidad se
{ //encuentre entre estos dos rangos.
KI =10; // Ganancia integral
}
else //Si la velocidad programada es mayor a (PWM1->200)
{ //le daremos otra ganancia para que responda lento
KI = 2; // Ganancia integral //con lo cual se lograra que el motor Oscile menos
} //a altas velocidades.
Control_I = (senialError * KI) / 8; //ecuaciones para el CONTROL INTEGRAL
valorPWM += Control_I; //se almacena el la variable "valorPWM" el resultado del
//resultado arrojado por el control Integral
if(valorPWM>=1000) //fijamos limites para la velocidad
valorPWM=1000;
if((valorPWM<20))
valorPWM=0;
set_pwm1_duty((int16)valorPWM); //se da el nuevo valor al PWM
printf("\r\n\r\nValor del PWM=%Ld\r\n ",valorPWM);
}
void main()
{
Set_Tris_B(0b11111110); //Configuramos el pin RB0 como salida, los restantes como entradas
Set_Tris_C(0b10001011); //Configuramos los pines RC0,RC1,RC3 y RC7 como entradas, los restantes como salidas
PortB=0x00; //limpiamos el puertoB
PortC=0x00; //limpiamos el puertoC
OutPut_High(Pin_B0); //senializacion de pic ON
setup_timer_2(T2_DIV_BY_1,249,1); //configuramos el timer2, Prescaler=1,Periodo=249,Postcaler=1
//con lo que se conseguira: T=250us o f=4Khz
//"setup_timer_2(Prescaler,Periodo,Postcaler)"
setup_CCP1(CCP_PWM); //Escogemos el modo de trabajo de CCP1, lo escojemos como modulacion por ancho de pulso
//NOTA.- Tanto para PWM1 y PWM2 el periodo es establecido por el timer2
//NOTA2.-la resolucion maxima esta dada por: Tpwm=2exp(n) * 1/Fosc
// 250us=2exp(n) * 1/(4exp(6))
// 2exp(n)= 1000
//Entonces el maximo valor que podemos cargar al "value" es de 1000 con lo que se
//conseguira un ciclo de trabajo de 100% "set_pwm1_duty(value)"
////////////////////////////////////Configuracion de CAD////////////////////////////////////////////////////
setup_adc(ADC_CLOCK_INTERNAL); //Se usara un reloj interno
Setup_adc_Ports(AN0_AN1_AN3); //se configuran lo pines: RA0,RA1,RA2 como entradas analogicas
////////////////////////////////////////////////////////////////////////////////////////////////////////////
set_pwm1_duty((int16)0); //se inicializa el PWM en cero
OutPut_High(Pin_C5); //Enable Motor ON
printf("\r\nSystem OK.\r\n"); //Sistema en linea y listo para transmitir
while(true)
{
verificarRS232();
testearBackEmf();
ajustarVelocidad();
}
}
Hola amyver,
Parece que el archivo RAR tiene un error porque no puedo abrirlo.
Saludos
/****************************************************************************
By: Amyver - Foro TODOPIC
*****VERSION 2_1B*****
Funciones:
*Modulo controlado atravez del interface USART
*Modulo usado CCP1
*El programa controla velocidad de un motor DC
en dos sentido de giro, con la particularidad
de mantener la velocidad constante ante cambios bruscos de carga
*Se soluciono el problema del reseteo del Micro usando
amplificadores operacionales configurados como seguidores de voltaje
dichos amplificadores fueron conectados a las salidas de los pines
de -CCP1- -Control de Giro- y -Enable-
****************************************************************************/
#include <16F877A.h>
#device adc=10 //Definimos un Conversor Analogo/Digital con resolucion de 10 bits
#Fuses XT, NOWDT, NOPROTECT, NOLVP, PUT, BROWNOUT, NOCPD, NOWRT//palabra de configuracion
#Use delay(clock=4000000) //usando un oscilador de 4MHz
#Use RS232(Baud=9600, Xmit=Pin_C6, Rcv= Pin_C7, Parity=N, Bits=8)
#Use Fast_io(B)
#Use Fast_io(C)
#Byte PortB=0x06
#Byte PortC=0x07
char var;
signed int16 senialError=0;
signed int16 lecturaBackEmf=0,fijarVelocidad=0,valorPWM=0;
int1 flagReversa=0,flagMicroMotor=0;
////////////////////////////////////////////////////////////////////////////////
void incrementarVelocidad()
{
flagMicroMotor=1; //bandera de señalizacion de motor ON
OutPut_High(Pin_C5); //Habilitamos el driver L6203
fijarVelocidad+=20; //incrementamos la velocidad en 300
if(fijarVelocidad>=1000) //pregutamos si se llego a la velocidad tope hacia adelante
{
fijarVelocidad=1000; //se fija una velocidad tope
}
printf("\r\n\r\nVelocidad Programada=%Ld\r\n ",fijarVelocidad);
}
void cambiarGiroMotor() //preguntamos si se pulsa el boton reversa en PANEL o PEDAL
{
flagReversa++;
if(flagReversa) //si hay Reversa
{
printf("\r\n\r\nGIRO IZQUIERDO MOTOR\r\n ");
if(flagMicroMotor==1) //preguntamos si el MicroMotor esta en funcionamiento
{
OutPut_Low(Pin_C5); //Deshabilitamos el motor (PARADA)
delay_ms(2000); //tiempo prudente para el frenado del motor
OutPut_High(Pin_C5); //Habilitamos el motor (GIRO)
set_pwm1_duty((int16)0); //se inicializa el PWM en Cero
}
OutPut_High(Pin_C4); //Cambiamos el sentido de giro del Micro Motor
}
else
{
printf("\r\n\r\nGIRO DERECHA MOTOR\r\n ");
if(flagMicroMotor==1) //preguntamos si el MicroMotor esta en funcionamiento
{
OutPut_Low(Pin_C5); //Deshabilitamos el motor (PARADA)
delay_ms(2000); //tiempo prudente para el frenado del motor
OutPut_High(Pin_C5); //Habilitamos el motor (GIRO)
set_pwm1_duty((int16)0); //se inicializa el PWM en Cero
}
OutPut_Low(Pin_C4); //Cambiamos el sentido de giro del Micro Motor
}
}
void pararMotor() //Funcion que recudira a cero la velocidad del Auto IR
{
flagMicroMotor=0; //señalizamos motor Apagado
OutPut_Low(Pin_C5); //Deshabilitamos el motor (PARADA)
delay_ms(2500);
valorPWM=0; //actualizamos la variable
set_pwm1_duty(valorPWM); //se inicializa el PWM en Cero
fijarVelocidad=0; //Establecemos la velocidad en cero
printf("\r\n\r\nPARAR MOTOR=%Ld\r\n ",fijarVelocidad);
}
////////////////////////////////////////////////////////////////////////////////
void verificarRS232()
{
if(kbhit())
{ // Si hay algo pendiente de recibir ...
var=getc();
if(var==0x0D) //preguntamos si se presiono Enter
{
incrementarVelocidad();
}
if(var==0x08) //preguntamos si se presiono retroceso
{
cambiarGiroMotor();
}
if(var==0x20) //preguntamos si se presiono retroceso
{
pararMotor();
}
}
}
void testearBackEmf()
{
delay_ms(7); //tiempo que se enviara la señal PWM
OutPut_Low(Pin_C5); //Enable Motor OFF
delay_ms(1); //tiempo de espera para que la señal Back-emf se estabilice
Set_adc_channel(1); //selecion de canal 0
delay_us(50); //Retardo para que se carge la senal analogica
lecturaBackEmf=read_adc(); //lee el resultado de la convercion y se guarda en nuestra variable de 16bits
printf("\r\nLectura BACK-EMF=%Ld",lecturaBackEmf);
OutPut_High(Pin_C5); //Enable Motor ON
}
void ajustarVelocidad()
{
signed int16 Control_I, KI;
signed int16 fijarVelocidadAux=0;
senialError= fijarVelocidad-lecturaBackEmf;
fijarVelocidadAux=fijarVelocidad;
printf("\r\nSenial de Error=%Ld",senialError);
if((fijarVelocidadAux>=0)&&(fijarVelocidadAux<=100))//Estabelecemos una Ganancia alta para bajas velocidades
{ //para lograr una respuesta Rapida
KI =10; // Ganancia integral
}
else if((fijarVelocidadAux>100)&&(fijarVelocidadAux<=600))
{ //para lograr una respuesta Lenta
KI = 2; // Ganancia integral
}
else
{
KI = 1; // Ganancia integral
}
Control_I = (senialError * KI) / 8;
valorPWM += Control_I;
if(valorPWM>=1000)
valorPWM=1000;
if((valorPWM<20))
valorPWM=0;
set_pwm1_duty((int16)valorPWM); //se inicializa el PWM en Cero
printf("\r\n\r\nValor del PWM=%Ld\r\n ",valorPWM);
}
void main()
{
Set_Tris_B(0b11111110);
Set_Tris_C(0b10001011);
PortB=0x00; //limpiamos el puertoB
PortC=0x00; //limpiamos el puertoC
OutPut_High(Pin_B0); //senializacion de pic ON
////////////////////////////////////Configuracion de CCPx(PWM)/////////////////////////////////////////////////
setup_timer_2(T2_DIV_BY_1,249,1); //configuramos el timer2, Prescaler=1,Periodo=249,Postcaler=1
//con lo que se conseguira: T=50us o f=20Khz
//"setup_timer_2(Prescaler,Periodo,Postcaler)"
setup_CCP1(CCP_PWM); //Escogemos el modo de trabajo de CCP1, lo escojemos como modulacion por ancho de pulso
//setup_CCP2(CCP_PWM); //Escogemos el modo de trabajo de CCP2, lo escojemos como modulacion por ancho de pulso
//NOTA.- Tanto para PWM1 y PWM2 el periodo es establecido por el timer2
// set_pwm2_duty((int16)value); //NOTA2.-la resolucion maxima esta dada por: Tpwm=2´(n) * 1/Fosc
// 50us=2´(n) * 1/4´(6)
// 2´(n)= 200
//Entonces el maximo valor que podemos cargar a "value" es de 200, con lo que se
//conseguira un ciclo de trabajo de 100%
////////////////////////////////////Configuracion de CAD////////////////////////////////////////////////////
setup_adc(ADC_CLOCK_INTERNAL); //Se usara un reloj interno
Setup_adc_Ports(AN0_AN1_AN3); //A0
////////////////////////////////////////////////////////////////////////////////////////////////////////////
set_pwm1_duty((int16)0); //se inicializa el PWM en
OutPut_High(Pin_C5); //Enable Motor ON
printf("\r\nSystem OK.\r\n"); //Sistema en linea y listo para transmitir
while(true)
{
verificarRS232();
testearBackEmf();
ajustarVelocidad();
}
}
Rmotor = 156; // (Rmotor + Rtransistores) · 10 = (15 + 0.6) · 10 = 156
Vdd = 950; // Vdd = 950 · 32v / 1023ptos = 29.7 voltios. Cuando ADC=1023 el puente está a 32 voltios.
D = 325; // Ciclo de trabajo de 0 a 1000
Vmotor = (Vdd/4) * (D/4); // Vmotor = 19197 = 9.65 voltios
Eg = 150; // Eg = 150 · 32v / 1023ptos = 4.69 voltios.
Vrm = Vmot - Eg*62; // Vrm = 19197 - 9300 = 9897 = 4.96 voltios. (caída de tensión en la resistencia del motor)
Imotor = (Vrm / Rmotor)*81/16; // Imotor = (9897 / 156)*81/16 = 318 = 0.318 Amperios
Bien puedes empezar midiendo la tensión del puente con el PIC.
¿Cuantos puntos mide tu ADC cuando mides tensión mientras el puente está conectado?
void testearBackEmf()
{
delay_ms(10); //tiempo que se enviara la señal PWM
OutPut_Low(Pin_C3); //Enable Motor OFF
delay_ms(1); //tiempo de espera para que la señal Back-emf se estabilice
Set_adc_channel(0); //selecion de canal 0
delay_us(50); //Retardo para que se carge la senal analogica
lecturaBackEmf=read_adc(); //lee el resultado de la convercion y se guarda en nuestra variable de 16bits
OutPut_High(Pin_C3); //Enable Motor ON
}Puedes conectar el puente durante 20us (Enable = 1)
comenzar la conversión ADC
Desconectar el puente (Enable = 0)
Leer la conversión ADC cuando termine.
signed int16 Analog;
void ADC_Analog_read(void)
{
// Conectar el puente
Set_adc_channel(0); // selecion de canal 0
set_pwm1_duty((int16)1001); // PWM siempre a uno
OutPut_High(Pin_C3); // Enable Motor ON
// Medir el valor de tensión
delay_us(5); // Retardo para que se carge la senial analogica
Analog = read_adc(); // Lee el resultado de la conversion y se guarda en nuestra variable de 16bits
// Dejar el puente en los valores originales
OutPut_LowHigh(Pin_C3); // Enable Motor OFF
set_pwm1_duty((int16)valorPWM);
}
Me alegro de que estés contento con los resultados.
Recuerdo que querías limitar la corriente del motor. Yo estoy detras de ello y ya he conseguido resultados. Cuando lo pula un poco (el problema está en el ruido que ya he comentado) lo publicaré para que lo puedas utilizar.
Si con master te refieres a que has aprendido de mis aportes, me alegro mucho que para eso estamos en el foro.
Un saludo.
for (i=0; i<100; i++); // Esperar un tiempo a que la tensión se estabilice
Vmax = 0;
for (i=0; i<10; i++) { // Realizar diez mediciones de back-emf
V = medir_back_emf():
if (V>Vmax) Vmax = V; // memorizar la medición mayor
}
return Vmax;