Contador descendente con PIC16F877A

Que no... que tienes que fijarte bien... que la condición no es

hor+min+seg > 0

sino

hor >= 0

Lo que hace la condición es salir cuando hor se convierte a negativo.
 
Última edición por un moderador:
Te agradezco tu ayuda, hor+min+seg>0 lo habia puesto para que lo vieses, si lo pongo como tu dices hor>=0 el contador sigue contando hacia atras y no se para en 00:00:00 entra en horas -, no se el por que pero es asi.
 
No puede ser que "hor" entre en la parte de los números negativos, porque precisamente la condición es justamente que se realice el bucle mientras que las "hor" sean positivas. Si "hor" es negativo, debe terminar inmediatamente.

¿No te habrás equivocado y lo has escrito con '<'? Eso explicaría lo de los horas negativas.

He tomado el código que has publicado en #20, y he cambiado la condición a hor >= 0, y sale el resultado perfecto: de 02:00:00 a 00:00:00, así que no acabo de entender lo que te pasa.

En fin... algún gremlin.
 
Joaquin podria ser que el proteus que tengo tubiese algun error o bug, como se quiera llamar, y por eso continua contando hacia atras,aunque por otro lado tengo otros programas con las funciones >= o <= y van bien.
 
Cambia
PHP:
if (seg == 0) {
por
PHP:
if (seg <= 0) {
y
PHP:
if (min == 0) {
por
PHP:
if (min <= 0) {
y sigue manteniendo la condición
PHP:
} while (hor >= 0 );
 
PHP:
tiempo_segs--;                   // Decrementar variable tiempo
      tmp_tiempo = tiempo_segs;        // Guardar tiempo en tmp_tiempo
      horas = tmp_tiempo /3600;        // Obtener las horas.
      tmp_tiempo %= 3600;              // Obtener el residuo en la misma variable.
      minutos = tmp_tiempo /60;        // Dividir tmp_tiempo /60 para obtener los minutos.
      tmp_tiempo %= 60;                // Obtener nuevamente el residuo que serán los segundos.
      segundos = tmp_tiempo;           // Guardar los segundos del resultado final.
D@rkbytes quiero comentar lo siguente y tu me dices si lo explico bien, lo que has hecho es crear un prototipo al que le has dado 7200 segundos y le llamas "iniciar_timer(7200);", luego lo que has hecho es empezar a reducir tiempo desde los 7200 segundos trasladando primero los 7200 a horas, de hay la division de 3600, con lo que nos da 2 horas, creo que es asi no?, entonces la variable con el residuo que creas "tmp_tiempo %=3600 es por que al comenzar a disminuir el tiempo quedaria 1 hora y todo lo otro aunque sean minutos y segundos o mejor dicho, minutos convertidos a segundos + segundos, se entiende, todo, como residuo de lo que falta para completar 1 hora, asi mismo esto traslado a los minutos.(y)
 
Última edición:
D@rkbytes, quiero comentar lo siguiente y tu me dices si lo explico bien.
Lo que has hecho es crear un prototipo al que le has dado 7200 segundos y le llamas "iniciar_timer(7200);", luego lo que has hecho es empezar a reducir tiempo desde los 7200 segundos trasladando primero los 7200 a horas, de hay la división de 3600, con lo que nos da 2 horas, creo que es así, ¿no?
Entonces la variable con el residuo que creas "tmp_tiempo %=3600 es porque al comenzar a disminuir el tiempo quedaría 1 hora y todo lo otro aunque sean minutos y segundos o mejor dicho, minutos convertidos a segundos + segundos, se entiende, todo, como residuo de lo que falta para completar 1 hora, asi mismo esto traslado a los minutos.(y)
Pues si, lo que se hace es ir desglosando la cantidad dada en segundos para obtener "Horas, Minutos y Segundos"
La variable tmp_tiempo la usé para el desglose y poderla ir dividiendo para de ahí obtener el valor de las otras variables.

Fue así cómo se me ocurrió, y pues funciona. :D

Saludos.
 
Última edición:
Bueno pues, siguiendo con el tema, estoy intentando hacer, con la ayuda prestada por D@rkbytes, con el contador regresivo, un calentador para un trabajo especifico, en el cual cuando llega la temperatura a un nivel se active el contador y un motor.
Pues en estas estamos ya que no se si es el sistema operativo, el proteus que uso, el ccs que tengo o que yo se lo que se, que no es mucho, la cosa es que tal y como echo el programa cuando lo pruebo en proteus unas veces me dice muchos mensajes, tambien el tiempo cuando corre hace cosas raras, aveces incluso sin pasar la temperatura se activa el temporizador y cuando lo reseteo entonces parece que va pero el tiempo en pantalla va raro, en fin queria ver que cosas echo mal y el por que.
Una cosa, no se si es correcto o no, pero para que no me haga cosas raras he puesto la variable de leer el ds18b20 en dos sitios si no se me vuelve loco, y eso es todo.
El ejemplo lo he reducido a 4 minutos.
Adjuntos los archivos:
posdata: creo que va aqui pero como tambien hay tema de temperatura igual no
 

Adjuntos

  • calentador.rar
    41 KB · Visitas: 25
La cosa es qué tal y como he hecho el programa cuando lo pruebo en proteus unas veces me dice muchos mensajes, también el tiempo cuando corre hace cosas raras, a veces incluso sin pasar la temperatura se activa el temporizador y cuando lo reseteo entonces parece que va pero el tiempo en pantalla va raro, en fin quería ver que cosas he hecho mal y el por qué.
Una cosa, no se si es correcto o no, pero para que no me haga cosas raras he puesto la variable de leer el ds18b20 en dos sitios si no se me vuelve loco, y eso es todo.
El tiempo mostrado incorrectamente, es porque incluiste la llamada para leer el sensor dentro de la rutina de conteo del tiempo.
Al hacer eso, no se tiene un periodo estable al realizar las operaciones.

Cuando la lectura del sensor a veces funciona y otras no, puede ser debido a la librería, trata de usar otra para comprobar esto, o realiza una prueba físicamente y ve si funciona correctamente, porque también puede ser un error durante la simulación.

Realicé algunos cambios al programa que subiste y al parecer funciona mejor, pero tampoco estoy muy convencido de un buen funcionamiento.

Suerte.
 

Adjuntos

  • calentador.rar
    41.8 KB · Visitas: 21
Cuando la lectura del sensor a veces funciona y otras no, puede ser debido a la librería, trata de usar otra para comprobar esto, o realiza una prueba físicamente y ve si funciona correctamente, porque también puede ser un error durante la simulación.

Realicé algunos cambios al programa que subiste y al parecer funciona mejor, pero tampoco estoy muy convencido de un buen funcionamiento.

Suerte.

Gracias D@rbytes, he cambiado las librerias ya que visto que hay algunas diferencias, probare como dices a montarlo fisicamente haber como responde, aunque he probado el que has modificado y no se si sera a mi o no te has dado cuenta pero cuando lo activo en proteus al llegar a los 48 grados el tiempo empieza a contar bien, que es lo que pretendo, pero si modifico la temperatura hacia arriba o para abajo en la pantalla no cambia la temperatura, como si no respondiese, y si que sigue contando bien el tiempo.
Quiero decirte que este era uno de los problemas que ya habia visto y no veia como resolverlo, no se si a ti te sucede lo mismo con el tiempo y la temperatura cuando lo has probado.
 
he probado el que has modificado y no se si será a mi o no te has dado cuenta, pero cuando lo activo en proteus al llegar a los 48 grados el tiempo empieza a contar bien, que es lo que pretendo, pero si modifico la temperatura hacia arriba o para abajo en la pantalla no cambia la temperatura, como si no respondiese, y si que sigue contando bien el tiempo.
Quiero decirte que este era uno de los problemas que ya había visto y no veía como resolverlo.
No sé si a ti te sucede lo mismo con el tiempo y la temperatura cuando lo has probado.
Sip, eso es normal, porque cuando se entra a la rutina de conteo del tiempo, se genera un bucle y es por eso que el programa ya no responde hasta que se sale de esa rutina.
Y el problema de agregar ahí la llamada de lectura del sensor, es que se pierde sincronía.

Posiblemente lo puedas resolver usando los Timers del PIC, esto puede ser la solución.
 
Posiblemente lo puedas resolver usando los Timers del PIC, esto puede ser la solución.

Si no es mucho pedir dame alguna idea, con los comentarios añadidos, que yo pueda entenderlo, ya que en el tema de los timer estoy vastante flojo, voy poco a poco, con decirte que gracias a ti ahora me voy defendiendo con los famosos "void" (rutinas) y aun hay cosa que no hago bien ¡¡pero bueno!!, de todas maneras estoy leyendo sobre timers. :oops::oops::D:D
 
Si no es mucho pedir, dame alguna idea, con los comentarios añadidos, que yo pueda entenderlo, ya que en el tema de los timer estoy bastante flojo, voy poco a poco, con decirte que gracias a ti ahora me voy defendiendo con los famosos "void" (rutinas) y aún hay cosas que no hago bien ¡¡pero bueno!!, de todas maneras estoy leyendo sobre timers. :oops::oops::D:D
OK. Mira el ejemplo adjunto, se hace uso del Timer1 para conseguir 1 segundo y se colocó la rutina de conteo dentro del servicio de interrupción del Timer1.
No es complicado hacer estas cosas con los Timers y se consiguen beneficios en el programa.

Como se hace uso de otro cristal de 32768Hz, tendrás que conseguirlo, o realizar cambios al programa para usar la sincronía interna, establecer que el Timer1 desborde cada 500Ms, y usar un contador.
Con el uso del cristal es más sencillo, aunque se utilizan dos pines mas, pero es más preciso.

Si el ejemplo te sirve, ya sólo tienes que realizar las modificaciones que necesites.

Suerte.
 

Adjuntos

  • 16F877A Contador regresivo con Timer1 y DS18B20.rar
    37.4 KB · Visitas: 18
Última edición:
Muchas gracias, el ejmplo me sirve pero quiero hacerte varias preguntas de esa manera procuro tener mas claros los conceptos.
1º para colocar, en este caso, el cristal de 32768 has tenido que hacer calculos, supongo, dime donde devo leer para aprender este concepto ya que leo el tema de los timer y me cuesta entenderlo vastante.
2º T1_ON = 0x10.0 se refiere, segun el 16f877a, #define T1_DISABLED 0?.
3º Pones (#define pin_relay pin_d3) pero en el "main" colocas (output_low(pin_relay); y output_low(pin_d3);), no son lo mismo los dos conceptos?.
Y 4º Como se usa el TIMER1 se indica con (enable_interrupts(INT_TIMER1);) y luego con (setup_timer_1(T1_EXTERNAL_SYNC | T1_DIV_BY_1);) decimos que estamos usando un oscilador exterior, en este caso el cristal de 32768, y en los dos pines que el micro tiene marcados para tal fin, en este caso pin_15 y pin_16, y ademas que trabaje a esa frecuencia ya que la division es por 1, es eso?. Da igual que vaya delante o detras (enable_interrupts(GLOBAL);)?.
Posdata: como haceis para poner los famosos "me gusta", jejeje.
 
Muchas gracias, el ejemplo me sirve pero quiero hacerte varias preguntas, de esa manera procuro tener más claros los conceptos.
1º ¿Para colocar, en este caso, el cristal de 32768 has tenido que hacer cálculos, supongo?
¿Dime dónde debo leer para aprender este concepto? Ya que leo el tema de los timer y me cuesta entenderlo bastante.
Uno sencillo. Si el cristal es de 32768Hz, y la máxima división para el Timer es de 65535 (16 Bits),
Entonces con el prescaler 1:1 tan sólo cargamos con 32768 el Timer para obtener un segundo (1Hz.)
32768 / 32768 = 1
2º ¿T1_ON = 0x10.0 se refiere, segun el 16f877a, #define T1_DISABLED 0?
Nop, es la referencia al bit 0 (TMR1ON) del registro T1CON
Cuando defines algo le puedes poner cualquier nombre, uno más corto en este caso.
Y como este bit es de lectura o escritura, lo puedes tanto leer, como escribir.
En el programa se usa para detener o iniciar el Timer1.
PIC C Compiler no tiene muchos registros definidos para poder usarse directamente, así que hay que crear las referencias.
Se puede usar GETENV, pero de esa forma es más sencillo.
Por ejemplo, así:
#bit T1_ON = GETENV("BIT:TMR1ON")
3º Pones (#define pin_relay pin_d3) pero en el "main" colocas (output_low(pin_relay); y output_low(pin_d3); ¿No son lo mismo los dos conceptos?
Sip. Es un error del programador. :D Pero si es lo mismo.
Y 4º Como se usa el TIMER1 se indica con (enable_interrupts(INT_TIMER1); y luego con (setup_timer_1(T1_EXTERNAL_SYNC | T1_DIV_BY_1); decimos que estamos usando un oscilador exterior, en este caso el cristal de 32768, y en los dos pines que el micro tiene marcados para tal fin, en este caso pin_15 y pin_16, y además que trabaje a esa frecuencia ya que la división es por 1, es eso?
Para que entiendas más esta parte y no me extienda explicando esto, es mejor que leas la hoja de datos.
Ahí encontrarás todo lo referente a la configuración del Timer1.
¿Da igual que vaya delante o detrás (enable_interrupts(GLOBAL);?
Para esas instrucciones, sip, no importa el orden. (Son configuraciones de registros)
Posdata: ¿Cómo haceis para poner los famosos "me gusta"?
Hay una etiqueta sobre la parte de abajo a la derecha del mensaje, que dice; Me Gusta
vbseo_like.png
 
Muchas gracias D@rkbytes por tus explicaciones, a seguir leyendo me toca, la ventaja de que hayais gente como vosotros es que es facil entender las cosas. Venga un saludote
 
Atrás
Arriba