fbpx

Expresate

Si además quieres enviarnos un Artículo para el Blog y redes sociales, pulsa el siguiente botón:

Avisos
Vaciar todo

ayuda cronometro en pic c compiler

12 Respuestas
6 Usuarios
0 Reactions
10.1 K Visitas
lorenzorenzzo
Respuestas: 8
Topic starter
(@lorenzorenzzo)
Active Member
Registrado: hace 11 años

E estado intentando hacer un codigo el cual funcione como un cronometro real, el cual al presionar un boton comience la cuenta del tiempo y al presionar de nuevo ese boton lo detenga mostrando el ultimo tiempo registrado, e intentado de distintas formas pero no e logrado que el tiempo se detenga
aqui el codigo del cronometro:

#include <16f887.h>
#fuses INTRC,NOPROTECT,NOLVP,NOWDT
#use delay (clock=8000000)
#include <stdlib.h>
#use rs232(baud=9600, xmit=PIN_c6, rcv=PIN_c7)

void main()
{
int16 minutos=0 ;
int16 segundos=0;
int16 milisegundos=0;
int1 boton;

while(true)
{
boton=input_state(pin_b7);
milisegundos=milisegundos+1;
delay_ms(1);

if(milisegundos>=999)
{
milisegundos=0;
segundos=segundos+1;
}

if(segundos==59)
{
segundos=0;
minutos=minutos+1;
}
if(boton==1)
{
printf("%li : %li : %linr",minutos,segundos,milisegundos);

}
}
}

Responder
11 respuestas
ranganok
Respuestas: 3875
(@ranganok)
Ardero
Registrado: hace 19 años

En primer lugar cuida la ortografía, ese E me ha matado mucho... (casi ni contesto)

Respecto al tema ¿cómo tienes conectado el botón a tierra o a Vcc?
- Si es a tierra el if deberá ser con if(boton == 0){ ... } si es a Vcc ya está bien.

¿tienes puesta la resistencia de pull-up o pull-down?
- Si tienes el botón a tierra tendrá que que tener una resistencia de pull-up (interna del micro o externa en la PCB), si es a Vcc la resistencia deberá ser externa a tierra (pull-down).

Mejoras:
- El cronómetro no va a ser exacto -> ten en cuenta que en cada instrucción el micro se lleva unos cuantos us, por lo que cada vuelta tendrás un error acumulado --> ¿has probado a usar interrupciones?

- El inicio de la cuenta la haces con el reset (supongo) por lo que aquí tendrás más error acumulado (el tiempo que el micro tarda en empezar a funcionar desde el reset + la puesta a 0 de las variables).

S2

Ranganok Schahzaman

Responder
sphinx
Respuestas: 651
(@sphinx)
Ardero
Registrado: hace 17 años

Hola lorenzorenzzo,
bienvenido a los foros de ARDE.

Varios consejillos sobre tu programa:

1) Efectivamente, aunque hagas el delay de 1 milisegundo, la ejecución del resto de instrucciones va a ir acumulando un exceso de tiempo sobre el milisegundo que deseas que pase. Aunque sea poco al cabo de 10 milisegundos, al cabo de un minuto puede ser demasiado. Y la deriva del cronómetro puede hacerlo extremadamente impreciso.
Tienes varias maneras de ajustar el tiempo que tarda tu código en ejecutar el bucle para hacer que la precisión sea mayor. Dinos qué precisión deseas que tenga y te podemos comentar algún truco para hacerlo.

2) Creo que tu programa sí podría funcionar, siempre y cuando ocurra lo siguiente:
a - la variable "boton" esté conectada a (o lea el valor de...) el pin donde tienes el botón físico.
b - para conectar el botón físico a tu pin, puedes hacerlo de 2 maneras...Te añado una imagen para que veas como va esto de conectar un pulsador a un pin del PIC con una resistencia de pull-up o pull-down.

Puedes elegir conectarlo de cualquiera de los dos modos. Pero recuerda:
- con resistencia de pull-up, sabrás que el botón está pulsado cuando el pin del PIC esté a 0.
- con resistencia de pull-down, sabrás que el botón está pulsado cuando el pin del PIC esté a 1.

3) (mejora) Ahorrate el if para chequear el botón dentro del bucle. Ya que utilizas un while hazlo así:
while (boton) {
....
<tareas de cronómetro>
...
}
... y en este caso el botón, cuando se pulse, lleva el pin a 0(configuración física con resistencia de pull-up) y se sale del bucle.
o
while (!boton) {
....
<tareas de cronómetro>
...
}
... y en este caso sale del bucle cuando estando pulsado genere un 1 en el pin (configuración física del botón con resistencia de pull-down).

4) (Mejora) Efectivamente, si en lugar de chequear en tu bucle si el botón está o no pulsado utilizas interrupciones, harás tu rutina más eficaz. Una interrupción que "vigila" el pin donde tienes conectado el botón, interrumpe el programa independientemente de donde esté, y salta a ejecutar una rutina de interrupción que tú hayas creado para gestionar el evento de pulsación del botón. Es mucho mejor.

Saludos,
Sphinx.

PD: Para la edición de código aquí, puedes hacer que te salga como he hecho yo en este post simplemente marcando el trozo de texto de tu código y pulsando el botón "Code" que aparecerá arriba de tu ventana de edición de post. O puedes utilizar el la palabra clave "code" entre corchetes [ ] para marcar el inicio del texto de código, y poner "/code" entre corchetes [ ] para marcar el final de tu código.

Responder
lorenzorenzzo
Respuestas: 8
Topic starter
(@lorenzorenzzo)
Active Member
Registrado: hace 11 años

Muchas gracias por responder fuiste de mucha ayuda
La verdad me gustaría que el cronometro fuese muy preciso ¿cómo se podría lograr eso?

Responder
jmn
Respuestas: 376
 JMN
(@jmn)
Ardero
Registrado: hace 13 años

Para hacer un cronómetro exacto lo primero que tienes que hacer como te han dicho más arriba es usar un timer del microcontrolador, un timer es un módulo del microcontrolador que va contando los ticks del reloj del sistema y cuando esta cuenta alcanza el valor que estableces genera una interrupción. Esa interrupción interrumpe el flujo del programa ejecutando el codigo que le indiques en la rutina de atención de la interrupción, en este caso ese código de esa rutina de la interrupción incrementaría un contador de milisegundos, así podrías llevar una cuenta exacta.

Como el timer funciona con el reloj del sistema u otro reloj del micro, por reloj entiendase la señal cuadrada que se genera con el cristal que pones, pues lo que va a determinar la exactitud de la cuenta va a ser la frecuencia que selecciones de ese reloj. Esa frecuencia del cristal externo tiene que ser la adecuada para poder generar la cuenta de 1 ms, 1 s, etc.. sin generar un error que se vaya acumulando.

Si tienes un reloj de 8 MHz, pues tendrás un pulso de reloj cada 1/(8*10^6) segundos, (por lo general esa frecuencia la puedes dividir usando un prescaler para tener un pulso de reloj en incrementos mayores de tiempo). Si quieres generar una interrupción cada 1 ms, pues el timer contará X incrementos de 1/(la señal del reloj que le entra al timer), y ese número de incrementos por la división anterior tiene que dar 1 ms exacto, si en lugar de 1 ms da 1.0003 ms pues ahí ya estás teniendo un error acumulativo. Esto se soluciona eligiendo un reloj de la frecuencia exacta, por ejemplo si quieres contar incrementos de 1 segundo, o llevar la cuenta con una precisión de segundos, lo normal es colocar un cristal de 32768 KHz en los relojes de tiempo real atendiendo al bajo consumo. Por lo general uno de los timers del microcontrolador tendrá dos pines para colocar un cristal externo si no quieres usar el mismo que el del sistema.

Si no te suena mucho de lo que te hablo pues mirate información sobre los timers del microcontrolador, como funcionan, en el datasheet del microcontrolador que uses suele venir detallado.

Si quieres que sea muy preciso, lo siguiente que puede afectar a la precisión de la cuenta es la elección de los condensadores que se suelen colocar con los cristales externos que ponemos en el microcontrolador. Por lo general y en la mayoría de los diseños para generar la señal de reloj se pone un cristal y dos condensadores entre las patillas del cristal y tierra, estos condensadores son del orden de picofaradios, el cristal indica la capacitancia que necesita para oscilar a la frecuencia que indica en su cuerpo. Por ejemplo puedes comprar un cristal de 8 MHz y te indicará 20 pF, el valor de los dos condensadores que colocas con el cristal (van en serie) pues deben proporcionar esa capacidad de 20 pF, por lo que tendrías que colocar dos condensadores de 40 pF que en serie tendrían los 20 pF que te indica el cristal. Pero no es tan sencillo ya que también tienes que incluir la capacitancia de los pines del microcontrolador a donde se conecta el cristal, que también suele ser del orden de picofaradios, por lo que al final tendrás que calcular los condensadores externos que colocas entre el cristal y tierra atendiendo a la indicación de la capacitancia indicada por el cristal y a los condensadores parásitos de los pines del microcontrolador. Es un cálculo simple que haces mirando las capacitnacias parásitas que te indica el datasheet que hay en esos pines.

Si no pones la capacitancia adecuada pues el cirstal en lugar de oscilar a 8 MHz pues a lo mejor ocila a 8.001 MHz.

La frecuencia a la que oscila el cristal es también función de la temperatura y de la tensión (ruido que puedas tener en la alimentación). La frecuencia del cristal oscilará un poco sobre la que te marca en su cuerpo con la temperatura ambiente, para corregirlo pues debes añadir un circuito que sintonice el cristal con la temperatura ambiente o comprar algún cristal especial para esots casos, TCXOs, DTCXO donde su variación con la temperatura ambiente va a ser mucho menor que la del cristal tradicional que solemos poner en los microcontroladores.

En cuanto a tener una tensión de alimentación sin ruidos pues añade los condensadores de desacoplo que indica el microcontrolador, si tienes mucho ruido pues también puede afectar en la frecuencia del cristal y no oscilar a la frecuencia exacta que te indica en su cuerpo.

El cristal es piezoeléctrico por lo que si hay vibraciones también le puede afectar a la frecuencia de oscilación.

Resumiendo, como mínimo y para no hacer una chapuza de cronómetro usa un timer del microcontrolador para generar una interrupción que lleve la cuenta del tiempo. Si puedes cambiar el cristal por un cristal de la frecuencia adecuada para que la cuenta del timer sea exacta y no genere un error acumulativo. Y si quieres que sea muy preciso pues atiende a los condensadores, a la variación de la frecuencia del cristal con la temperatura y a no tener una alimentación con mucho ruido. No sé si me dejo algo.

En cuanto al tema del botón añado un poco más a lo anterior, cuando pulsas un botón por lo general no vas a tener una sola pulsación sino que vas a tener rebotes: http://webdelcire.com/wordpress/archives/2973 " onclick="window.open(this.href);return false;

Tendrías algo como esto al pulsar el botón, canal negro de la imagen "pulsador":

analizador1p

El micro no ve una pulsación, sino 4 pulsaciones debido a los rebotes cuando tú has pulsado el botón solo una vez. Puedes montar el circuito como dice Sphinx y quitar esos rebotes por software, pero yo montaría este:

botones

Añadiendo una resistencia más y un condensador con los valores adecuados (en función del tiempo de rebotes del botón) pues evitas los rebotes del pulsador, canal marrón de la imagen "pin", y así no tienes que quitarlos por código, una resistencia y un condensador no cuestan prácticamente nada y facilitan la programación.

Edito: añado el enlace donde explica bien el circuito antirrebotes (a partir de la página 12): http://www.eng.utah.edu/~cs5780/debouncing.pdf " onclick="window.open(this.href);return false; en el caso de los AVR hay un Schmitt trigger en cada pin de entrada por lo que no es necesario añadirlo externamente y con ese circuito sería suficiente, si no se tiene en el pin es adecuado ponerlo. Los pic creo recordar que solo llevan el trigger schmitt en unos pocos puertos, por lo que en este caso habría que añadir también este integrado para formar el antirrebotes sino se usa uno de los pines con ST.

Saludos.

Responder
Página 1 / 3
Compartir: