Autor Tema: pregunta termostato  (Leído 1000 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado BORIScristian

  • PIC10
  • *
  • Mensajes: 13
pregunta termostato
« en: 18 de Abril de 2016, 22:53:51 »
Hola, estoy haciendo un termostato en el compilador CCS para un pic16f88, siempre programe en assembler pero me anime a programar en c ya  que hace un tiempo programaba en turbo c++ y c++ builder asi que pense que no iba a ser complicado. El programa muestra bien la temperatura (lo que me interesa es de 0º a 10º pero al momento de cambiar la temperatura de corte (mediante dos pulsadores) deja de cambiar de estados el corte del termostato pero sigue mostrando la temperatura lo mas bien, supongo que el problema esta en la estructura del programa ya que no me acuerdo bien como usar algunas instrucciones, espero puedan ayudarme, muchas gracias. (el termostato es para una heladera y muestra la temperatura por display 7 segmentos)
codigo:
« Última modificación: 30 de Junio de 2016, 23:52:39 por BORIScristian »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:pregunta termostato
« Respuesta #1 en: 19 de Abril de 2016, 05:13:27 »
Una par de cosas:

Código: C
  1. voltios=5.0*lectura/1000.0;// no divido 1024 para evitar error 1º entre 0º y 5º
  2.          grados=voltios*100;

Por:

Código: C
  1. grados=lectura / 2;
o
Código: C
  1. grados=lectura >> 1;

Si dividis por 1000 y multiplicas por 100 es lo mismo que dividir por 10, luego si tenes 5 / 10, es lo mismo que 1 / 2, Esto por 2 cosas mas que nada. Hacelo en la calculadora (5 / 1000 ) * 100 y te va a dar 0.5 que es 1/2

La primera y principal es menor tiempo de procesamiento.
La segunda es que al dividir por 1000 y la representacion de float vas a perder algunos bits de interes.
Como luego al final lo terminas asignando si o si a un entero, no tiene ni sentido tener las comas en la division ( para pasarlo a float ) ya que todos los decimales se perderian. Entonces mejor una operacion de enteros.

Solo destacar una cosa... si lectura es de 10 bits, un division por 2 ( que es identica a un shift a la derecha ) va a ser de 9 bits, es decir que necesitas un int16 en grados.

-----------------------------------------------------------------------
Código: C
  1. decena=grados/10;
  2.     unidad=grados-decena*10;
  3.     output_b(display[decena]);
  4.     output_b(display[unidad]);

Tenes que tener cuidado con estas cosas.. grados es maximo de 8 bits en este caso (aunque deberia ser de 16 como dije ) y por lo tanto puede llegar a tener hasta un valor de 255, lo cual te dejaria a decena con un valor de 25, unidades no correria riesgo aca. El problema esta en que el array display[] posee solo 10 lugares, si vos haces display[25] vas a tener un problema, asi que seria bueno que limitaras los valores

Código: C
  1. decena=grados/10;
  2.     if( decena > 9 ) { decena = 9; unidad = 9; }
  3.     else { unidad=grados-decena*10; }
  4.     output_b(display[decena]);
  5.     output_b(display[unidad]);

-----------------------------------------------------------------


Código: C
  1. while(input(PIN_A1)==1)
  2.            {temp=temp+1;
  3.            }

Si pensas como trabaja el micro, el mismo va a hacer todo el while principal cada 200us aproximadamente, pero vos al presionar ese boton encerras al micro en ese while, ese while no son mas que 3/4 instrucciones para el micro, los cuales serian unos 2us, un pulso "rapido" de un ser humano puede estar en el orden de los milisegundos, yo siempre tomo como 100ms un pulso rapido. En 100ms eso se incremento 50.000 veces!.

Código: C
  1. if(input(PIN_A1)==1)
  2.            {
  3.                    delay_ms(5);
  4.                    while(input(PIN_A1)==1);
  5.                    temp++;
  6.            }

Como en el otro iba a quedar encerrado en un while por igual, en este caso lo que hago es preguntar por si el pin esta en 1, si lo esta espero un rato y pregunto de nuevo, mientras no lo suelte se va a quedar encerrado en el while, cuando lo suelte va a continuar y va a sumar 1 a temp.

Esto posee una desventaja... que si estas mostrando con los displays en la rutina principal va a pararse de mostrar mientras se tenga presionado los botones.
La solucion es usar el timer para que cuando se produzca la interrupcion sea el que muestre los valores de unidades y decenas. Ojo nada de delays dentro de la interrupcion!, 1 entrada a la interrupcion y pones lo de las decenas, otra entrada y pones lo de las unidades y volves a repetir.
« Última modificación: 19 de Abril de 2016, 05:17:19 por KILLERJC »


 

anything