Midiendo Temperatura con max6675 y pic16f887 pulsos desincronizados

Buenas estoy realizando un medidor de temperatura con max6675 la lectura es correcta en cuanto a medicion se refiere el tema es la sincronizacion de los datos en la simulacion no se nota ya que subo cada 0.25grados

pero no logro sincronizar los valores en pantalla probe con el timer1 para aumentarle la velocidad.
Noté que cuando aumento la temperatura en la termocupla de manera brusca los valores llegan no sincronizados habra alguna manera de detectar cambios
de temperatura y de manera automatica, aumente la velocidad de timer quedando sincronizadas

este es el codigo
Código:
#INCLUDE <16F887.H>  //PIC utilizado
#DEVICE ADC = 10
#INCLUDE <MATH.H>    //Libreria con funciones matematicas
#FUSES   NOWDT       //No Watch Dog Timer
#FUSES   XT          //
#FUSES   NOPUT       //No Power Up Timer
#FUSES   PROTECT   //Code not protected from reading
#FUSES   NOBROWNOUT  //No brownout reset
#FUSES   NOLVP       //No low voltage prgming, B3(PIC16) or B5(PIC18) used FOR I/O
#FUSES   CPD       //No EE protection
#use  delay(clock=4000000)

#use rs232(baud=9600, xmit=pin_c6, rcv=pin_c7, parity=n, bits=8, stop=1)

#bit Chip_Select=0x07.0                //RC0=Chip_Select
//#bit Chip_Select_Direccion=0x87.0      //TRISA.0=Chip_Select_Direccion

int16 Data;
short EstadoTKP;                       //estado de la Termocuple, abierto o cerrado
float temp;
int t[9]=0,0,0,0,0,0,0,0,0;


#define t1 t[0]
#define t2 t[1]
#define t3 t[2]

#define t_seg t[3]
#define t_sog t[4]
#define t_log t[5]

#define t_deseado1 t[6]
#define t_deseado2 t[7]
#define t_deseado3 t[8]

#INT_TIMER1

void  TIMER1_isr(void)
{
   t1++;                         // Contador para funcion pulsadores
   t2++;                         // Contador para lectura de termocupla 
   t3++;

   if(t1==1){                  // Si la interrupcion se activo 154 veces
      t_seg++;                   // paso 1 segundo
      t1=0;                      // Reinicio el contador
   }
   if(t2==1){                  // Si la interrupcion se activo 154 veces
      t_sog++;                  // paso 1 segundo
      t2=0;                      // Reinicio el contador
   } 
      if(t3==1){                  // Si la interrupcion se activo 154 veces
      t_log++;                  // paso 1 segundo
      t3=0;                      // Reinicio el contador
   }
}

void InitMain()
{

   setup_adc_ports(sAN0 | sAN1 | sAN2);
   setup_adc(ADC_CLOCK_DIV_8);

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_INTERNAL | T1_DIV_BY_1); // modo de trabajo
   setup_timer_2(T2_DISABLED,0,1);

   enable_interrupts(int_TIMER1);
   enable_interrupts(GLOBAL); //Habilita interrupciones
   t_deseado1=3; // Establezco el timer en 3. 
   Chip_Select=1;                   //Deshabilito el SPI en el DAC mediante RC0, Pulso de seleccion de esclavo en alto
   //Chip_Select_Direccion=0;         //Pin RC0 como salida
   set_tris_c(0x10);
   setup_spi(SPI_MASTER|SPI_L_TO_H | SPI_XMIT_L_TO_H|SPI_CLK_DIV_4);    //th>=100ns,tl>=100ns, Tp=10MHz/4=0.4us=200ns

}

void ADC_Input()
{
if(t_seg>=t_deseado1){
   char DataHigh, DataLow;

   Chip_Select=0;
   delay_us(20);
   //Recibe el byte mas significativo y menos significativo
   DataHigh=spi_read(0);
   DataLow=spi_read(0);

   Chip_Select=1;

   Data=make16(DataHigh,DataLow);
   Data=Data>>2;
   EstadoTKP=Data & 0x01;
   Data=Data>>1;
   temp=Data*0.25;           //12bits, resolucion 0.25°C

       printf("Temp: %f \r\n",temp);  //muestro la temperatura actual por uart

  t1=0;    //Contadores de timer timer1_t1 a 0.
  t_seg=0;
}

}

void main()
{
   InitMain();

   while(TRUE)
   {



      ADC_Input();
   }

}

adjunto los archivos simulacion en proteus y codigo con pic c compiler
 

Adjuntos

  • CCS MAX6675.zip
    21.8 KB · Visitas: 20
  • pruebas en uart tool pickit2.jpg
    pruebas en uart tool pickit2.jpg
    81.3 KB · Visitas: 10
Última edición:
Ya lo he solucionado, me he buscado por todo internet durante varios dias y no pude encontrar absolutamente ningun ejemplo ni tampoco que nadie requiera " medir temperatura PERfectamente" y los valores escalonados sin "saltear numeros" como burro arrepentido
Porque hasta muy buenos programadores en videos de youtube con un codigo magistral se les piantan las unidades en lecturas extremadamente rapidas.

Tambien el tema de ruidos hasta cuando permanecia en temperatura ambiente oscilaba 0.5 a 0.75 y eso hacia que la lectura se lea en oscilacion 1°c.

La solucion es NO utilizar la variable que toma la temperatura para mostrar en display o lcd, sino otra variable aparte e igualarla solo que con retraso. Leer la temperatura cada 200ms o un poco más por medio del timer0. Y el hadware Filtrar correctamente segun hoja de datos. Tambien ver el tema de tierra analogica y digital

Utilizar una variable llamemosle buffer y actualizarla unicamente si la lectura da un valor mayor (puede ser a 2 minimo).

Bueno sin más publico el "rebuscado codigo todo desordenado descomentado en prueba empírica" hay que pasarlo en limpio, mejorarlo y demas hierbas. que probando aqui con una maquina con resistencias termicas conectadas a un rele de estado solido controlado por el pic. en total las resistencias dan 16 Amp en 220v. Probado en temperatura ambiente como asi tambien hasta los 300.

da exactamente muy buena lectura Consisa, sin oscilaciones.

No es un medidor de la farsa digo de la Nasa.. pero camina.....
Esto tambien se puede aplicar a las apestosas lecturas oscilantes analogicas

espero que alguien más le sirva.
Agradezco enormeente a Thulsa Doom el cual me ayudó muchisimo gracias!!

Código:
//Aqui va el main correspondiente
do{

if(i==1){  //Aqui se toma la variable i del conteo del timer1 seteado en 200ms aprox

leer_temperatura(); //Procedemos a ejecutar la instruccion lectura de temp del max6675

}

if(temp2<temp_final){ // si la nueva lectura es menor que la vieja.. entonces DISMINUYE:: Cuanto?

  temp_temporal=temp_final-temp2;


    if(temp_final!=temp2){

   

        temp_final--; //Disminuimos la variable buffer final segun haya aumentado anteriormente la variable original


        }

        //delay_ms(1);

     

}else if(temp2>temp_final){ // si la nueva lectura es mayor que la vieja.. entonces AUMENTA:: Cuanto?

temp_temporal=temp2-temp_final;


        //if(temp_final!=temp2){

        if(temp_temporal>=3){

   
        temp_final++; //Aumentamos la variable buffer...

      delay_ms(1); //Realizamos un pequeño delay

         }
}

if(item==0){ //Menu = 0

//Imprimimos la variable de temperatura ya procesada en el display tm1637
   int firstdig = temp_final / 100;

   int seconddig = (temp_final - (firstdig * 100))/ 10;

   int thirddig =  temp_final - (firstdig * 100) - (seconddig*10);


   TM1637_display_digit(TM1637_SET_ADR_00H, (firstdig) % 0x10);

   TM1637_display_digit(TM1637_SET_ADR_01H, (seconddig) % 0x10);

   TM1637_display_digit(TM1637_SET_ADR_02H, (thirddig) % 0x10);

}

  if(temp_final<=Temperatura_deseada-2){ //Si Alcanzo la temperatura deseada Apago Rele_temperatura de lo cotnario Lo enciendo.

  if(temp_final!=0){

   Encend(Rele_temperatura);  // Enciendo el Relay de calentamiento

   }

if(item==0){ //Si menu==0.


     lcd_gotoxy(1,3);

   printf(lcd_putc,"     Calentando..   ");               // Escribo la temperatura actual de la termocupla

}
    }else{

  Apag(Rele_temperatura); //Apago el rele de calentamiento.

   if(item==0){ //Si menu==0

  lcd_gotoxy(1,3);

  printf(lcd_putc,"    Calor deseado.  ");               // Escribo la temperatura actual de la termocupla

   }

}

#include <menu_item.c>//Más menu.

       }
      while(TRUE); //Bucle infin.
}

//Guido Batan Maquinarias


y en el void de temperatura:

Código:
void leer_temperatura(){ //Aqui tomamos las muestras de temp del max6675

  int16 temp; //Variable temporal

  int cadena1,cadena2;  //declaramos las variables donde se guardaran el dato que viene del max6675

        output_low(CS_max6675);               //Se activa la señal de bit_select(CS) a 0 para que el max se active

        cadena1 = spi_read(0);  //Lee el primer byte que viene del max6675

        cadena2 = spi_read(0);  //Lee el segundo byte, con eso ya tenemos los 16bits de la lectura del max7765

        output_high(CS_max6675);              //Se pone a 1 la señal de bit_select(CS) para que el max tome otra lectura
     

      // buffer = ((cadena1 * 256) + cadena2);  //Se unen las dos cadenas de 1 byte que viene del max6675 y se

                                                    //guardan en una variable int16 llamada buffer de 16 bits

           buffer = cadena2; // Cargo Byte LB

*((char *)&buffer+1)=cadena1; // Cargo Byte HB.  y los uno los dos en una palabra de 16 bits que se llama buffer    


                      temp = (buffer & 0b0111111111111000)>>3;    //Seleccionamos los bits que nos interesan haciéndole lo que se llama

                                                           //Una máscara, se le hace un AND al dato con un número en binario, los unos significan los bits que queremos utilizar y los 0 los que desechamos

                                                           //Luego le hacemos un >>3 que significa que rodamos los 1 a la derecha 3 posiciones para eliminar los 0 del final

                                                       

   

          temp2 = (temp * 0.25);  //12 bits en decimal equivalen a 4095, para que de los 1023,75 ºC se tiene que multiplicar por 0.25 que es la resolución de cada bit del MAX6675

     

  if(temp2!=0 && temp_test==0){     //Si la variable temp2 (lectura del max) no es igual a 0 y a su vez es la primera vez que tomamos la muestra entonces ->  )

temp_final=temp2;  //Variable final de temperatura ya procesada es igual a temp2 (lectura del max)  

temp_test=1; //Asigno esta variable a 1 para que no vuelva a actualizar las mensionadas variables de nuevo aquí.    

         }





:mad::mad::mad::mad::ROFLMAO::ROFLMAO::ROFLMAO::ROFLMAO::cafe::cafe:
 
Última edición:
De que cosa estas midiendo la temperatura???
Por que la temperatura siempre varia MUY lentamente, y muestrearla cada 200 ms es una exageracion....hasta 1 vez por segundo es mucho.
Claro...siempre en aplicaciones "normales".
 
hola Zoidberg como estas, estoy midiendo temperatura en maquinas sublimadoras que si bien tal cual dijiste es bastante lento en llegar por ejemplo de temp ambiente hasta los 250 grados tarda 45minutos o mas depente de la linea de alimentacion.

Lo que deseaba era de que no me oscilara el valor de temp mostrado en pantalla Tambien si requeria controlar otro artefacto más rapido pudiera hacerlo. Siempre probé dandole calor con una antorcha y los valores subian tan rapidos que "salteaban numeros" es decir se perdian las unidades y eso era horrible. Un pirometro bueno cuando se le acerca la llama debe empezar a subir "en escalera" no todo salteado los numeros de medicion bueno esa era mi intencion. En internet está lleno de ejemplos pero cuando medis con un encendedor mide cualquier cosa parece un medidor de amperaje con ruido
 
Última edición:
Ok, pero siempre tenes que simular en las mismas condiciones que va a trabajar tu proyecto.
Si sube 200° en 40' eso son 5° por minuto o 0.083° por segundo o 0.017° por cada 200 ms, que son medidas que estan hundidas en el piso de ruido del sensor.
Para tener lecturas de 0.5°, por ejemplo, deberias muestrear, como minimo, cada 7 segundos y dificilmente tengas que complicar el soft...
 
Zoidberg, gracias por la respuesta si, es mi utopia lo que mencionaste. Eso seria "automatico". Si detecta en determinado tiempo que la temperatura asciende determinados grados entonces "ajusta la frecuencia". Como las computadoras cuando se transfieren archivos de disco a disco.. en fin, si finalmente hay que pasarlo en limpio y "reducir la velocidad de lectura del pobre max" para que tan rapido :)? el datsheet dice minimo 200ms asique no es nada ilegal probar asi
 
Última edición:
Atrás
Arriba