TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: pablete en 06 de Febrero de 2014, 01:22:50
-
Hola Amigos,
Estoy en un proyecto con un pic 16f628a. El mismo consiste en, mediante una interrupcion externa por RB0, medir el tiempo de un tren de pulsos, y generar una salida con otro pulso, que tenga un retraso menor, igual o mayor a los pulsos de entrada. No se si me explico bien. O sea, por cada pulso, hacer un retraso y largar el pulso justo antes que entre otro pulso por rb0.
No logro generar ese retraso. No tengo mucha experiencia con pic, por eso es que estoy confundido. Ya lei varios ejemplos pero cada vez me confundo mas.
Estoy programando en CCS.
Cualquier idea y ejemplos serán bienvenidos.
Muchas gracias
-
El principal es saber ... Que duración tiene el pulso más pequeño que puedas tener?
-
El principal es saber ... Que duración tiene el pulso más pequeño que puedas tener?
El rango de frecuencia de pulsos va desde los 10 Hz hasta los 300 Hz.
Los pulsos duran entre aprox 5 uS
-
podrias poner tu código para ayudarte sobre ese mismo
-
podrias poner tu código para ayudarte sobre ese mismo
La verdad no tengo mucho codigo. Ando buscando ideas o sugerencias. Lo que he estado probando fue guardar el valor del timer1 cuando se produce la interrupcion externa, hacer un delay en base a ese tiempo y generar el pulso. El tema es que
necesito un delay igual o mayor al tiempo entre los pulsos de entrada.
#INT_ext
void IntRB0(VOID)
{
t=get_timer1();
set_timer1(0);
delay_us(t);
output_high (PIN_A0);
delay_us(200);
output_low (PIN_A0);
}
void main(VOID)
{
set_tris_b (0b00000001); //portb como salida menos RB0
set_tris_a (0b00000101); //RA0, RA1 y RA2 como salida, el resto entradas
disable_interrupts (global); // Inicializo el Micro y ...
disable_interrupts (INT_timer1); // deshabilitando todo lo no necesario ...
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_INTERNAL|T1_DIV_BY_8);
setup_timer_2(T2_DISABLED,0,1);
// setup_comparator (NC_NC_NC_NC);
enable_interrupts (INT_ext); // Habilito las interrupciones necesarias
ext_INT_edge (0, L_TO_H); //configuracion:interrupcion cuando señal baja
enable_interrupts (global);
set_timer1 (0);
WHILE (TRUE)
{
un codigo especifico
}
}
-
por lo que entiendo quieres generar un pulso que sea de el mismo periodo o mayor que tu pulso de entrada
para esto podrías detectar el flanco de subida con tu interrupción externa y en ese momento encender tu salida, y configurar tu interrupción para que ahora interrumpa en flanco de bajada.
cuando tu interrupción vuelva a ocurrir en ese momento sabes que tu pulso de entrada termino y en ese momento pones un delay para apagar tu salida, si tu delay es 0 entonces tus periodos serán iguales, si incrementas tu delay tendras una salida de mayor tiempo que la entrada
espero haberme explicado
-
Si, es una buena idea. Tambien el pulso deberia hacerse antes del pulso de entrada. O sea que deberia producirse antes, durante y despues del pulso de entrada. Debe "fluctuar" un pulso sobre el pulso de entrada.
-
haa, ya entiendo tambien necesitas un defase.
algo similar, en cuanto recibas el flanco de subida inicias un timer para dar el tiempo de defasamiento, cuando el contador se cumpla, entonces inicias tu señal de salida, en cuanto recibas el flanco de bajada entonces el tiempo para apagar tu señal de salida será el tiempo de tu defase mas el tiempo que quieras agregar para agrandar el pulso
espero sea lo que necesitas y haberme explicado, si necesitas ayuda con el código lo puedes ir posteando y lo vamos revisando para que haga lo que deseas
Saludos
-
Porque no explicas mejor lo que quieres obtener en la salida, a ver si podemos ayudar mas ??
-
entre pulso y pulso, el tiempo de la salida debe ser el mismo pero desfasado?
Tienes que pensar una cosa, sí el tren de pulsos saliente lo desfasas mucho tendrás problemas, de igual forma sí los pulsos salientes los alargas mucho
puedes poner uno de los timer para obtener tiempos de duración, y otro de los timer para reproducirlo haciendo una cuenta, cuando empieza el pulso, leer el valor del timer, cuando acabe el pulso, obtener la diferencia de ticks y guardarlo en un array... Cuando vuelva a llegar otro pulso, obtener la diferencia de nuevo... Así continuamente... Ahora es cuando viene el problema, y no es otra cosa que sí alargas mucho el desfase enseguida se te acabara el array...
Sería continuo el tren de pulsos?
-
es para un encendido electronico de moto. Recibe los pulsos del sensor y retrasa la salida para darle avance la chispa.
Ya lo tengo funcionando pero encuentro un problema. A medida que suben las rpm, el motor se atrasa, y deberia adelantarse o mantenerse fijo.
He probado haciendo que cuando se produzca la interrupcion, haga la señal de la chispa y el resultado es que me lo da casi 25 grados despues de la entrada de señal del sensor, cuando deberia hacerlo instantaneamente. si acelero un poco, se retrasa un poco mas. Llegue a la conclusion que se debe al tiempo que usa el pic en los calculos. Deberia usar una ecuacion para contrarestar ese tiempo que emplea el pic. Alguien me puede decir si estoy en lo cierto?
Saludos y gracias
-
Cuantos pulsos por segundo recibes ??
Que cristal utilizas en el PIC ??
-
Cuantos pulsos por segundo recibes ??
Que cristal utilizas en el PIC ??
trabaja entre 10 y 300 hz (entre 10 y 300 pulsos por segundo)
Usa el cristal interno, 4 mhz
-
Cual es la máxima frecuencia de oscilación de ese PIC ??
Deberías llevarlo al máximo de velocidad, así los cálculos se harán en menos tiempo aun, y seras mucho mas preciso con los tiempos... ;-) ;-)
-
Debes hacerlo de otra forma, la forma que estas diseñando el codigo no es la correcta. Piensa que a 1000RPM un grado son 160us, sin embargo a 5000RPM tienes 33us por grado, asi que con que falles en unos pocos us ya estas teniendo mucho error de avance.
Lo primero es saber que posicion te indica la señal del sensor, normalmente suele ser PMS o bien alguna otra posicion APMS, sabiendo esto tienes que calcular cuando quieres que sea efectivo la chispa, tiene que ser un calculo con la mayor precision posible para tener poco margen de error, una vez tienes esto para calcular el DWELL simplemente le restas a el calculo los mS necesarios para que la bobina se cargue, lo importante es la descarga puesto que si fallas unos pocos uS en el DWELL no tienes problema alguno, pero en el momento de la chispa debes ser lo mas preciso posible, alrededor de 1º +-.
Para ello utiliza mas timers, por ejemplo cada vez que recibes el pulso haces ambos calculos (chispa y dwell) y pones un timer para ON y otro para OFF (olvidate de poner delays y cosas asi...). Para hacer el avance lo mismo, tienes que poner una tabla (array) que segun que RPMs haga mas avance/retraso incluso tambien se utiliza la carga (acelerador) para hacer el calculo tanto como asi:
(http://www.hdforums.com/forum/attachments/touring-models/223292d1325048778-ignition-timing-advance-curves-ignition-stock-2.jpg)
-
Hola Merlinz, gracias por la sugerencia.
Te comento que este es un cdi, el cual no necesita Dwel para cargar la bobina. Yo estoy trabajando con el tiempo para hacer los retrasos, asi que el retraso es proporcional al tiempo.
Si revisare el tema del disparo, usando como dices los timers para no usar delays. Tal vez sea eso lo que me esta generando ese retraso indeseado.
Sigo con las pruebas.
Saludos
-
Piensa que sí haces un delay_us(t), son microsegundos no ticks, en todo caso usa delay_cycles(t)
-
pues mas facil aun, solo necesitas un timer para el disparo te ahorras todo el tema del dwell.
-
Hola amigos,
Sigo teniendo problemas. No encuentro donde esta el error. Voy a ser lo mas explicito posible:
El motor tiene el sensor de disparo unos 20º antes del pms. Yo quiero lograr que el avance sea antes de 20º, por ejemplo, 30º.
Para ello, lo que hago es: Cuando se produce la interrupcion externa, miro el tiempo del timer1. Con eso, saco la frecuencia para usarla en el calculo del retraso de la chispa. Ese calculo es: esperar casi una vuelta completa y disparar la chispa unos 10 grados antes que se produzca la nueva interrupcion, que en ese caso seria 30º antes del pms.
Por ejemplo: a 6000 rpm, el tiempo en en dar una vuelta es 10000 us. Entonces la ecuacion de retraso calcula 9150 us: 9150/10000*360= aprox 30 grados. Tiene que esperar 9150 us para producir la chispa a 30 grados
EN la teoria, todo bien.
En la practica, no se mantiene a 30º, sino que al acelerar el motor atrasa. Dentro de la interrupcion, hago el calculo del valor "retaso". Ese valor lo uso en el main para generar la chispa:
WHILE (TRUE)
{
output_high(PIN_A0);
delay_us(100);
output_low (PIN_A0);
while(get_timer1()>retraso);
}
Yo creo que mi problema esta en el momento de esperar ese retraso.
Espero que me ayuden a encontrar el problema porque yo se poco de programacion, y el que me ayuda sabe programar C pero no tiene mucha experiencia en PIC. Practicamente estamos aprendiendo con este proyecto.
Saludos y gracias
-
Para medir frecuencia necesitás medir el intervalo de tiempo entre dos instantes. Me parece que en tu caso sería entre dos interrupciones del RB0. Por otro lado necesitás generar el retraso. Se te va a complicar realizar la medición de la frecuencia y generar el retraso del disparo utilizando el mísmo Timer.
Tampoco veo el código que realiza el cálculo de la variable "retraso".
Saludos
-
Por un lado necesitas medir cuanto mide cada grado, para ello si solo tiene un sensor que te indica 20º pues debes capturar el tiempo en 2 vueltas, entonces tienes el tiempo de 360º, lo divides entre 360 y tienes cuanto vale cada grado, como quieres llegar al 30BTDC pues tendrias que hacer el disparo a 350º despues de cada interrupcion, para ello multiplicas el nº por 350 y activas el timer para que dure esa secuencia.
Otra forma mas sencilla es si puedes poner el sensor de alguna forma en 30BTDC o 40BTDC tienes la ventaja de no tener que activar la chispa en la siguiente vuelta.
-
gracias merlinz,
Basicamente mido asi, como tu dices:
IF (f > 133){
x=46;
}
ELSE {
x=35+((f-33)/10);
}
}
aux1=((f-33)/5)+x;
}
else{
aux1=20;
}
retraso = (t/360)*(380-aux1);
}
donde aux es una variable que depende de la frecuencia, ya que el avance es variable.
Lo de mover el sensor, seria lo ideal, pero en estas motos es imposible moverlo.
"endrias que hacer el disparo a 350º despues de cada interrupcion, para ello multiplicas el nº por 350 y activas el timer para que dure esa secuencia."
Ahi es donde creo que tengo el problema. No se bien como hacer para que el disparo sea a 350 despues de cada interrupcion, o como activar el timer. Me puedes dar una pista?
-
un timer de 16 bits se desborda (produce interrupcion) al llegar a 0xFFFF (65535 al pasar al 0).
Ahora por un lado necesitas configurar el timer de tal forma que a las RPM que sea (tanto en bajas como en altas) te sirva, con su preescaler correspondiente. Si haciendo calculos decimos que por ejemplo 350º equivalen a 34000 ciclos del timer entonces tendrias que restar simplemente 65535-34000 y con el resultado hacer un set_timer(). Esperas a la interrupcion del timer, y dentro de ella activas el disparo de la chispa.
-
Estuve probando hacer lo siguiente:
Con la interrupcion externa, habilito el timer0 con prescaler 1 y el timer cargado en 156 (que me da un desborde cada 1us)
Entonces, por ejemplo, si se que la vuelta dura 30000us, coloco un contador dentro de la interrupcion del timer0 para que cuando llegue a 28000 haga el disparo
#int_RTCC
void retraso()
{
flag++;
if(flag>=(28000)){
output_high(PIN_A0);
delay_us(100);
output_low(PIN_A0);
flag=0;
disable_interrupts(INT_RTCC);
}
}
Y desactivo el timer para que no haga pulsos demas
Eso haria que la chispa se produzca antes. Eso en la teoria. En la practica, no va.
Donde esta el error?
gracias
-
Lo primero que debes hacer es habilitar la interrupción externa
cuando llega el pulso, empezar a contar con el timer una vuelva entera
adapta el preescaler para no tener que contar los desbordes en exceso ya que saturaras el pic con tanto desborde
Después de dar la vuelva, lee el valor del timer...
con el primer timer sólo te encargaras de leer el tiempo de una vuelta así te asegurarás la relación tiempo con las rpm, a más rpm menor el tiempo entre pulso y pulso
con un cristal de 20mhz, preescaler a 2, y timer a 8 bits tendrás un desborde de 204.8us
30000/204,8=146,5 desbordes, ósea 146 acumulado en tú variable flag y 127en el valor del timer
pues bien, dentro de la función del timer, poner una condición íf, cuando la variable llegué al 85% del máximo, que active una bandera y en la función principal incluir el encendido,retardo y apagado del pulso de salida
recuerda que anteriormente debes de leer el tiempo que duró con otro de los timer
se me olvido comentarte que nunca metas delays dentro de ninguna interrupción
-
Estaba pensando que sí usas está metodología a la hora de trabajar, casi que sería mejor que al preescaler lo pusieras en 1
así tendrías
30000us/104,4us=292,96 desbordes, ósea más precisión
también podrías aumentar la frecuencia, por ejemplo, 24,27,32,48mhz
yo he trabajado con un 16F628a a 24mhz sin problemas
-
gracias ppyote.
Estuve probando la metodologia de merlinz. Cargar el timer0 para que desborde segun el retraso que quiero hacer.
Ya las primeras pruebas fueron buenas. Ahora tengo que afinar la ecuacion que me carga el timer0 para que sea precisa.
Si no lo logro con esto, intentaré usar una tabla de valores segun las rpm. He visto que muchos hacen asi. Por algo será
Saludos y a seguir probando!