TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: ORE en 19 de Junio de 2006, 14:06:01
-
Hola muy buenas,
Después de configurar toda una aplicación, descubro que no puedo, o no hay soluciones, para poder mostrar por un relé la actuación PWM por la patita CCP2 del PIC16F877. Mi aplicación consiste en un regulador PID, que realiza x funciones, y que obtiene mediante el cálculo de la siguiente forma la salida proporcional al error:
// Guardamos error de iteracion anterior
errant=error;
// Calculo del error actual = set_point(consigna)-process_value(variable proceso)
error = set_point - process_value;
// Error acumulativo
serror+=error;
// Señal de control, duty cycle para PWM
salida=Kp*error+Ti*serror+Td*(error-errant);
Esta salida es la que se debe aplicar al rele mediante la instrucción:
//Lo convierto en un valor entero
duty_pwm2=(int) salida;
//Valor de carga para el duty
set_pwm2_duty(duty_pwm2);
Para todo ello realizo los cálculos para ver las frecuencias mínimas y máximas que tiene el periodo T (mi cristal es de 10 MHz):
TPWMminimo=[(PR2+1)]·(4/fosc)·(TMR2 Preescaler)=[(255+1)]·(4/10MHz)·16=1,63 ms
Para saber la frecuencia hago su inversa, y obtengo 610 Hz. A esta frecuencia y periodo, es imposible ver conmutar un relé, ya que como mínimo ese período debería de ser de 1 s por lo menos. Harto de buscar, lo único que se me ocurre es realizar una interrupción (mediante el timer 1) que cada segundo active el pwm según el valor del duty_pwm2. No se si es lo correcto, y en 1 s o 2 s se podrán ver esas conmutaciones con su duty cicle respectivo. Ya no se donde darle más, porque viendo la teoria del pwm, cuando el TMR2=PR2, y posteriormente TMR2=duty cicle, no puedo hacer que ese periodo sea de 1 s. No se si me explico.
Sería de gran ayuda sus aportaciones y/o posibles soluciones, ya que he probado mil y una posibilidades y no se me ocurren más cosas.
Un saludo,
-
Hola ORE, a duras penas un relay puede conmutar a una velocidad de 10 Hz, por lo que los 610 Hz que tu deseas serán imposibles, incluso un led puede generarlos, pero tu vista no lo verá, te recomendaria que controlaras un transistor y este a su ves le envie la señal a un parlante si tu deseas escuchar la variaciones segun el ciclo activo.
Un saludo.
Atte. CARLOS.
-
Hola Chaly29,
Gracias por tu rápida respuesta. Como bién dices debería modificar el hardware, pero a estas alturas ya me es imposible. Pero creo que no me he expresado bién anteriormente. Deseo variar la frecuencia de conmutación del relé en funcion de una salida que es regulada por un PID. Veo que a 610 Hz es imposible ver como conmuta un relé, lo se, pero lo que quiero es hacerlo conmutar a la velocidad más baja que pueda en Hz, por ejemplo lo mínimo que como dices es 10 Hz, la pregunta es ¿Puedo conseguir esos 10 Hz de alguna forma, bien con el pwm o con un timer que me genere una onda cuadrada?
Un saludo,
-
Hola ORE, no creo que con el PWM del PIC consigas los 10Hz, pero con el timer seguro que podras, pero aparte de esto, con un reay no tendras definición para el PWM, pore como no se el uso que le daras no te puedo dar un mejos consejo.
Un saludo.
Atte. CARLOS.
-
A lo mejor podrias cambiar el rele por un LED, y ver las variaciones de brillo según el PWM.
Saludos.
-
Hola,
Gracias a ambos por las respuestas. Creo que la única opción que me queda es probarlo por el timer. Ya veremos como lo hago, no se si ha alguien se le ocurre alguna idea.
En relación al tema del rele por un led, el relé es necesario porque debe actuar sobre una carga, en concreto sobre un soldador, ya que dependiendo del valor de la temperatura que me proporciona un LM35, sobre dos placas de aluminio (simulo una planta con su sensor), actuo sobre el soldador que está insertado en una de las placas de aluminio.
Si consideran alguna idea más sobre este tema que me de una pista para sacar este problema se lo agradecere mucho.
Un saludo,
-
Normalmente la temperatura se hace por un control de todo o nada con un cierto ciclo de histeresis, no se utiliza el PWM ya que la respuesta termica es muy lenta (no es como un motor).
-
Hola ORE, usa el consejo de jfh900 ya que si usas el ralay con una frecuencia de 10Hz, tanto el relay como el soldador te durarán muy poco, como la respuesta de tu equipo en muy lenta, su usas una señal que tenga un periodo de 10 seg te aseguro no notaras la diferencia, y lo mejor seria que tu detectes cuando la temperatura este muy baja y lo enciendas, cuando ya alcansa una mas alta lo apagas.
Un saludo.
Atte. CARLOS.
-
Si el prolema es la frecuencia del relé por que no empleas un relé de estado sólido?? casi seguro que eso te dara mucha mas frecuencia, no mucha mas tb es verdad, ya que estos a la entrada llevan un optoacoplador en esta pagina tienes unos cuantos http://www.eurotherm.es/ con sus datasheet y todo
-
Hola muy buenas,
Gracias por la respuesta qiqe, pero la página que me comentas sobre relés de estado sólido no veo ninguno de ellos que pueda acoplarse a la placa de mi circuito impreso. Había pensado en hacer un TODO-NADA, con el relé y sacar un "cable" de la salida PWM, hacia una placa protoboard, y montar un transistor para con un amplificador para formar un convertidor tensión corriente y actuar sobre el relé como carga. No se me ocurre más. Cierto es que esto debería haber estado en mi aplicación, pero ahora ya es demasiado tarde.
Seguire buscando otras soluciones, no duden en darme otras opciones, seguro que alguna sirve o me encamina hacia el objetivo.
Un saludo,
-
Tambien en vez de un rele puedes usar un TRIAC por ejemplo un BTB600, puedes acoplarlo con un optoacoplador al la salida de PWM, yo he usado algo similar para controlar un horno y funciona correctamente.
-
Bueno si quieres una regulación mas fina y controlar mejor la temperatura, lo que se emplea es una regulación de potencia por triac (la forma de regulación es muy similar al pwm) y asi puedes controlar la potencia entregada a la carga de forma continua. Esta es la opción mas aceptable para este tipo de aplicaciones. Veo que pikman se a adelantado a mi respuesta. :D
Un saludo.
-
Hola,
Bueno al parecer, todo en esta vida de la electrónica tiene solución. Y he encontrado un relé de estado sólido, carito eso si 16,87€, espero que el lunes me traigan alguno más y lo pueda descambiar. Según veo en el data sheet de este puede conmutar a frecuencias muy elevadas, en concreto se trata del RP1B40D5. Ahora bién todo fenomenal, pero antes de "montar" en la placa el relé, lo que he echo es comprobar como cambia la frecuencia, viendo como el led va aumentando su luminosidad. Pero cuando lo aplico al PID, no hay forma de ver como cambia de estado. Y simplemente hago lo siguiente:
Control_PID(){
errant=error;
// Guardamos error de iteracion anterior, usado en parte D.
error = set_point - process_value;
// Calculo del error actual=set_point-process_value=unidad_fisica.
serror+=error; // Error acumulativo.
Ti = (k*periodo)/Ti;
Td = (k*Td)/periodo;
duty_pwm2=k*error+Ti*serror+Td*(error-errant);
// Señal de control, duty cycle para PWM.
setup_timer_2(T2_DIV_BY_16, periodo,1);
// Definiendo el periodo del PWM con la configuracion del timer 2
duty_pwm2=124;
set_pwm2_duty(duty_pwm2);
if (process_value<=BP_max || process_value>=BP_min)
// Si esta dentro de la banda proporcional actuo en función PID
{
duty_pwm2 = (int)duty_pwm2;
//Cambiando de tipo de dato float a 8 bits sin signo.
set_pwm2_duty(duty_pwm2);
// Cargamos en modulo PWM el valor absoluto de la señal de control obtenida.
}
else if (process_value>BP_max)
{
duty_pwm2=0;
set_pwm2_duty(duty_pwm2);
}
else if (process_value<BP_min)
{
duty_pwm2=255;
set_pwm2_duty(duty_pwm2);
}*/
} // Fin control PID.
Y les confirmo que haciendo esto sin interrupciones ni nada por el estilo, configuro los puertos de la misma forma y no hay manera, ¿que puedo estar haciendo mal?
Un saludo,
-
Hola,
He cambiado algunas cosas del programa que postee anteriormente, ahora veo que el regulador PID funciona correctamente, ya que antes había colocado un entero, y debo colocar un long, para poder abarcar el duty cicle del pwm hasta 255, que es el máximo preescaler que puedo conseguir, pero sigo sin ver a frecuencia de salida por la patita CCP2, con lo que no veo iluminarse más o menos el led, sigo intentándolo. Si alguno de ustedes me sugiere alguna idea, la aceptaré encantado. Posteo el nuevo código:
Control_PID(){
errant=error;
// Guardamos error de iteracion anterior, usado en parte D.
error = set_point - process_value;
// Calculo del error actual=set_point-process_value=unidad_fisica.
serror+=error; // Error acumulativo.
ki = (k*periodo)/Ti;
kd = (k*Td)/periodo;
salida_PID=k*error+Ti*serror+Td*(error-errant);
// Señal de control, duty cycle para PWM
if (process_value<BP_max && process_value>BP_min){
// Si esta dentro de la banda proporcional actuo en función PID
setup_timer_2(T2_DIV_BY_16, periodo,1);
// Definiendo el periodo del PWM con la configuracion del timer 2
duty_pwm2 = (long) salida_PID;
//Cambiando de tipo de dato float a 8 bits sin signo.
set_pwm2_duty(duty_pwm2);
// Cargamos en modulo PWM el valor absoluto de la señal de control obtenida.
}
if (process_value>BP_max)
{
setup_timer_2(T2_DIV_BY_16, periodo,1);
duty_pwm2=0;
set_pwm2_duty(duty_pwm2);
}
if (process_value<BP_min)
{
setup_timer_2(T2_DIV_BY_16, periodo,1);
duty_pwm2=255;
set_pwm2_duty(duty_pwm2);
}
} // Fin control PID.
Un saludo,
-
Te voy a realizar una pregunta, solo por curiosidad. Como realizas el termino derivativo y el termino integrativo del PID, por que no lo veo claro (no veo que se integre y se derive le termino).
Un saludo.
-
Hola,
No entiendo tu pregunta. Pero estas acciones de integración y derivación las hago en la fórmula PID, las variables k, periodo, ti y td, las introduzco por teclado.
Sigo sin ver funcionar el PWM, y no se si tendrán algo que ver las interrupciones, porque con un sencillo programa si que va pero con el programa al completo no. Me estoy volviendo loco.
Un saludo,
-
Hola,
Si realizando este programa, veo que el led va cambiando de luminosidad, ¿porque cuando lo coloco en el programa del control PID no funciona?, ¿tiene algo que ver con las interrupciones que uso de los timers 0 y 1? Posteo el código:
#include "C:\15 - Program Files C\Contol_PID.h"
#include <max187.c> // Subrutina de tratamiento conversor A/D MAX187.
#include <hd44780u.c> // Subrutina de tratamiento display 16x2 HD44780U.
#include <max4534.c> // Subrutina de tratamiento multiplexor MAX4534.
#use fast_io (A) // Directiva para el manejo normal de puertos.
#use fast_io (B)
#use fast_io (C)
#use fast_io (D)
#use fast_io (E)
#byte port_a=0X05 // Declarando la direccion de los puertos.
#byte port_b=0X06
#byte port_c=0X07
#byte port_d=0X08
#byte port_e=0X09
int periodo=255; //Variable para el periodo
int duty=0; //Variable para la anchura del pulso
int i=0;
main()
{
output_c(0x00); //Borra las salidas
set_tris_c(0xb1111101); //RC2 salida
//El módulo CCP1 actúa en el modo PWM con salida de señal por RC2/CCP1
//El TMR2 trabaja con un preescaler 1:1 por lo que con una frecuencia de 4MHz evoluciona
//cada 1uS (4*Tosc)
setup_timer_2(T2_DIV_BY_16,periodo-1,1); //Carga el periodo
lcd_init();
lcd_putc("\f");
for(;;)
{
lcd_gotoxy(1,1);
printf(lcd_putc,"%i",i);
lcd_gotoxy(1,2);
printf(lcd_putc,"%i",duty);
CCP_2_LOW=duty; //Carga la anchura del pulso
setup_ccp2(CCP_PWM); //Modo PWM para el CCP
output_high(PIN_B7); // Se activa el rele
delay_ms(50);
output_low(PIN_B7);
if(duty>=124)
{
duty=0;
output_high(PIN_B5); // Se activa el rele
delay_ms(50);
output_low(PIN_B5);
}
if(duty>=124) i=0;
i++;
duty++; //apunta a siguiente frec
}
}
veo que funciona, pero sigo sin entender que hago mal en el otro programa para no ver el PWM
Un saludo,
-
Hola, si estas usando CCS esto
#byte port_a=0X05 // Declarando la direccion de los puertos.
#byte port_b=0X06
#byte port_c=0X07
#byte port_d=0X08
#byte port_e=0X09
No hace falta.
Si estas usando fast_io debes poner primero tris antes de out
output_c(0x00); //Borra las salidas
set_tris_c(0xb1111101); //RC2 salida
Ademas la no se que micro usas pero las salidas de los modulos CCP estan en el portC y en algunos pic18 se puede cambiar una salida por una direccion del portB.
Pero ninguno en B5 ni B7, en tu ejemplo no muestras donde cambias el duty cycle al modulo
solo seteas una variable duty que se va incrementando pero donde se lo cargas al modulo no lo veo
setup
setup_timer_2(T2_DIV_BY_4, 249, 1); // set TMR2 para frecuencia y periodo para PWM
setup_ccp1(CCP_PWM); // set CPP1 como PWM
set_pwm1_duty(512); // indica al modulo 50% de ciclo de trabajo
el ciclo de trabajo, que puede ser hasta 1024, si usas la resolucion de 10 bits.
Esto ultimo no esta en ninguna parte en el ejemplo que muestras, el resultado de tu PID debes cargarlo en set_pwm1_duty(<tu valor>);
Ademas comentas
//El módulo CCP1 actúa en el modo PWM con salida de señal por RC2/CCP1
Y antes ajustastes como salida RC1 y como entrada RC2????
output_c(0x00); //Borra las salidas
set_tris_c(0xb1111101); //RC2 salida???? aca dice RC1 salida!!!, las demas todas input
Aunque una vez que declares usar el CCP1 ya no podras manejar la direccion del los pines
utilizados por cuaquier modulo interno, si estas usando el PIC18F452 deberas seleccionar si el PIN a usar porque como te digo mas arriba lo puedes multiplexar o no pues si no lo haces pude que el CCP este salidendo pro otra parte.
-
Hola Picman,
Si no te importa voy paso a paso y así no tendré problemas para afianzar conceptos:
1. Desconocia que al usar CCS, la declaración de la dirección de los puertos no era necesaria.
2. Ya he cambiado el orden al usar la sentencia fast_io, primero pongo tris y luego out.
3. Uso el PIC16F877, y utilizao la salida RC1, que corresponde al CCP2.
4. Lo cargo de la siguiente forma en el principio del main:
setup_timer_2(T2_DIV_BY_16, periodo,1);
// Definiendo el periodo del PWM con la configuracion del timer 2
setup_ccp2(CCP_PWM);
// Inicializando el modo PWM del modulo CCP2.
y lo siguiente que hago es realizar unos cálculos para que mediante una función me convierta el dato salida_PID que es un float, en un int:
if (process_value<BP_max && process_value>BP_min){
// Si esta dentro de la banda proporcional actuo en función PID
errant=error;
// Guardamos error de iteracion anterior, usado en parte D.
error = set_point - process_value;
// Calculo del error actual=set_point-process_value=unidad_fisica.
serror+=error;
// Error acumulativo.
ki = (k*periodo)/Ti;
// Calculo ganancia intregal
kd = (k*Td)/periodo;
// Calculo Ganancia derivativa
salida_PID=k*error+Ti*serror+Td*(error-errant);
// Señal de control, duty cycle para PWM
duty_pwm2 = (int) salida_PID;
//Cambiando de tipo de dato float a 8 bits sin signo.
setup_timer_2(T2_DIV_BY_16, periodo,1);
//Vuelvo a cargar el timer por si acaso no se si debería incluir también setup_ccp2(CCP_PWM);
set_pwm2_duty(duty_pwm2);
// Cargamos en modulo PWM el valor absoluto de la señal de control obtenida.
periodo, es una variable que puedo modificar por el teclado, y duty_pwm2 es lo que cargo en el preeescaler
5. Lo último que me comentas, ha sido un error mio, como podrás ver configuro el pin RC1 como salida:
set_tris_c(0xb1111101); //RC1 salida
No se ha que se debe el error, y es curioso ver como funciona el incremento y el decremento de la variable duty_pwm2 en función del cálculo de la salida_PID, pero no lo veo en la patita RC1.
Un saludo,
-
Hola muy buenas,
¿Me podrían confirmar, si el uso de interrupciones o del display afecta a la generación del pwm?
Gracias
-
En absoluto, si generas el PWM por hardware no se vera afectado por nada.
-
Hola nocturno,
¿Entonces que estoy haciendo mal? Me estoy volviendo loco.
Un saludo,
-
Intenta buscar una forma de verificar que todo te funciona bien. Como parece, que lo que falla es la función del PID intenta ver que valores te devuelve el PID para distintas situaciones de entrada y de consigna o de entrada y de error haber que te da de PWM.
Un saludo
-
Hola,
Bueno muchas gracias a todos por las respuestas que he obtenido sobre el pwm, y por fin!!!!!! he encontrado cual era el problema. Se trata de la siguiente instrucción:
#use fast_io (C);
la he substituido por esta:
#use standard_io (C)
Ahora mi duda es, ¿Porque cambiando este modo del puerto obtengo lo que quiero?
Solo es para quedarme a gusto, ya que me ha vuelto loco, y mas de un dolor de barriga.
Un saludo,
-
Al usar el modo fast_io el compilador no se preocupa del estado de las entradas y salidas, siendo responsabilidad del programador.
Cuando has cambiado al modo standard_io el compilador se encarga de colocar los TRIS adecuados antes de las operaciones de lectura o escritura si fueran necesarios.
Puesto que al cambiar de modo, has comprobado que funciona, seguro que tu problema era de TRIS mal colocados. Ahora tienes una buena pista para encontrar el error.
-
Leí todo el hilo y quería aclarar varias cositas,
Primero un triac generalmente se controlan por angulo de disparo, un dimmer, es la forma mundialmente conocida, pero también como dijeron por ahi se los puede usar con PWM como rele de estado solido, pero hay que tener una consideración importante
Explico: La red cambia de polarida 100 veces por segundo, si genero un ´pwm con mayor frecuencia es decir 100hz o mas estaría disparando a lo loco en todos los periodos, por lo que de control no estaría haciendo nada, para que esto realmente funcione se tiene que hacer un pwm a una frecuencia mucho menor que la de la red, si no lo ven me dicen y se lo explico con un grafico
Ahora si ya tiene un rele conectado y teniendo en cuenta que activar un triac tiene sus bemoles y además esta el tema de la electrocución, mejor quédate con el rele arma un PWM por soft y con un periodo de al menos 5s (no me quiero imaginar el ruiderio del rele conmutado una vez por segundo y pobre rele no le va a quedar aliento después de unos minutos de trabajo)
PWM: por soft, no hay problema como decía ALF (el que vino de melmac) supongamos queres un PWM con una resolución de 256 , no hay problema , tenes que dividir 5s(periodo) en 256 , te da 19ms , entonces tenes un timer (TMR0 o TMR2) que te interrumpe cada 19ms
Cada vez que te interrumpe el timer contas 1 , entonces vas a ir 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... se entiende y al mismo tiempo comparas esa cuenta de 1 2 3 ... con la variable donde tenes guardado el ciclo útil que queres introducir
entonces con el la cuenta en cero.... prendes el relay .... y cuando llegas al valor del ciclo útil lo apagas y boala(mi francés es muy malo) tenes PWM en un relay
Buenos señores espero no haberlos distraído mucho, aburrido tanto y que esto les haya servido de algo
Saludos Atte Gustavo T
-
No sé mucho , pero tiro una idea .
Porqué en lugar de usar pwm como salida del pid y hacer tanto lío , no haces que la salida del pid entre en forma digital a un dac y luego amplificar la corriente.
Quizá este equivocado pero se me ocurre. Solo trato de aportar algo. :lol: