Autor Tema: Libreria para Max6675 en CCS  (Leído 11289 veces)

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

Desconectado marcoscab1166

  • PIC12
  • **
  • Mensajes: 57
Libreria para Max6675 en CCS
« en: 18 de Julio de 2017, 13:29:27 »
Hola, estoy buscando si alguno tiene una libreria para este integrado, que pueda utilizar con el pic 16F873A.

Este integrado se maneja con SPI, y yo mucho no conozco del tema. Lo que necesito es poder extraer la temperatura leida y pasarla a Celsius, para poder utilizarla junto con otros valores que maneja el programa.

Aca les dejo un codigo que encontre en la web, es el mas difundido, pero algunos dicen que no funciona. Ademas segun entiendo extrae la temperatura en caracteres, y yo la necesito en forma numerica. Si alguno me puede dar una pista de como adaptarlo, o si tienen algo similar se los re agradeceria.

Código: [Seleccionar]

/**************************************************************************************
*   max6675.c - communicates with a MAX6675 thermcouple interface chip                *
*   Copyright Jimbob's Ma 2006                                                        *
*                                                                                     *
*   This program is free software; you can redistribute it and/or                     *
*   modify it under the terms of the GNU General Public License                       *
*   as published by the Free Software Foundation version 2                            *
*   of the License.                                                                   *
*                                                                                     *
*   This program is distributed in the hope that it will be useful,                   *
*   but WITHOUT ANY WARRANTY; without even the implied warranty of                    *
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                     *
*   GNU General Public License for more details.                                      *
*                                                                                     *
*   You should have received a copy of the GNU General Public License                 *
*   along with this program; if not, write to the Free Software                       *
*   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.   *
**************************************************************************************/

/*
This is a diver for the MAX6675 K-type thermocouple interface chip. It implements an SPI
bus without the need for dedicated hardware (aka a bit-banged interface). The result from
toFloat_TC() is the temperature in degrees celcius of the thermocouple tip. The rest should
be self-evident. Have a look at the end of the file for example usage.
*/

#ifndef TC_CLK
   #define TC_CLK               PIN_B1            //edit these pins as necessary
#endif

#ifndef TC_CS
   #define TC_CS               PIN_B2
#endif

#ifndef TC_DATA
   #define TC_DATA               PIN_B3
#endif


int1 thermocouple_error;         //a handy dandy global error flag to tell you if a thermocouple is connected or not

void init_TC(void)
{
   output_low(TC_CLK);
   output_low(TC_DATA);
   output_high(TC_CS);            //if we idle high, the chip keeps doing conversions. Change this if you like
}

int16 read_TC(void)               //It takes 200ms (ish) for the MAX6675 to perform a conversion
{
   int8 i;
   int16 data;

   output_low(TC_CS);            //stop any conversion processes
   delay_us(1);               //and give it some time to power up (not very much, admittedly)

   for (i=0;i<16;i++){
      shift_left(&data,2,input(TC_DATA));      //reads in 2 bytes to data from the pin TC_DATA
      output_high(TC_CLK);
      output_low(TC_CLK);
   }

   thermocouple_error=bit_test(data,2);      //this is the thermocouple status bit
       
   output_high(TC_CS);
   return(data);
}

int16 sortout(int16 raw)
{
    return(0x0FFF & (raw>>3));      //returns only the bits converning temperature
}

float toFloat_TC(int16 tmp)
{
   return((float)tmp/4.0);      //adjusts data to floating point format, and accounts for the decimal point
}

float do_everything(void)
{
   init_TC();
   delay_ms(200);               //200ms is a long time to be doing nothing. use a timer interrupt to avoid wasting time here
   return(toFloat_TC(sortout(read_TC())));
}


/*

//example program

#define TC_CLK               PIN_B2
#define TC_CS               PIN_B2
#define TC_DATA               PIN_B1

#include "max6675.c"

void main()
{
   char msg[32];
   delay_ms(50);      //allow oscillator to stabilise

   while(1){
      delay_ms(800);
      sprintf(msg,"%01.2f%cC\r\n",do_everything(),0xB0);
       
      if(thermocouple_error)
         printf("Thermocouple not connected\r\n");   
      else
         printf("%s",msg);
   }
}

*/

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #1 en: 18 de Julio de 2017, 15:07:29 »
La lectura es esta:

Código: C
  1. int16 read_TC(void)               //It takes 200ms (ish) for the MAX6675 to perform a conversion
  2. {
  3.    int8 i;
  4.    int16 data;
  5.  
  6.    output_low(TC_CS);            //stop any conversion processes
  7.    delay_us(1);               //and give it some time to power up (not very much, admittedly)
  8.  
  9.    for (i=0;i<16;i++){
  10.       shift_left(&data,2,input(TC_DATA));      //reads in 2 bytes to data from the pin TC_DATA
  11.       output_high(TC_CLK);
  12.       output_low(TC_CLK);
  13.    }
  14.  
  15.    thermocouple_error=bit_test(data,2);      //this is the thermocouple status bit
  16.        
  17.    output_high(TC_CS);
  18.    return(data);
  19. }

Usa un SPI por software, asi que si lo haces por Hardware mejor.
El codigo es correcto, apenas se baja CS procede a llegar el primer bit, luego en cada pulso del reloj tenes el otro, se repite 16 veces, todo correcto hasta aca.
Devuelve el valor data que es lo leido desde el IC, los cuales son 12bits de temepratura, y  de esos 12, hay 2 que son decimales. los otros bits son de informacion.

la funcion sortout quita esos bits de informacion y deja unicamente la temperatura. Te recuerdo, aca tenes ya la temeperatura sola que son 12bits, que si quisieras tomar solamente el entero y no el decimal deberias rotarlo 2 lugares a la derecha para quitarle la coma. Y tendrias tu valor numerico entero
Y luuego lo pasa a float con la funcion toFloat_TC.

En fin, llamar a la funcion do_everything y te devuelve un valro float con la temeperatura.

Desconectado marcoscab1166

  • PIC12
  • **
  • Mensajes: 57
Re:Libreria para Max6675 en CCS
« Respuesta #2 en: 18 de Julio de 2017, 15:42:34 »
Genial, entonces si quiero leer la temperatura bastaria con esto?

float temp;

temp=do_everything();

Y ya tendria la temperatura en celcius?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #3 en: 18 de Julio de 2017, 16:25:52 »
Exacto

Deberias leer tambien el datasheet para compensar la temperatura.
« Última modificación: 18 de Julio de 2017, 16:38:17 por KILLERJC »

Desconectado marcoscab1166

  • PIC12
  • **
  • Mensajes: 57
Re:Libreria para Max6675 en CCS
« Respuesta #4 en: 19 de Julio de 2017, 14:10:15 »
Bueno estuve intentando pero no logro sacar nada de lectura. Para hacerlo con el hardware SPI del PIC como seria?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #5 en: 19 de Julio de 2017, 14:15:48 »
Una cosa mas, si estas usando un cristal de 10Mhz o mas cambia esto:

Código: C
  1. for (i=0;i<16;i++){
  2.       shift_left(&data,2,input(TC_DATA));      //reads in 2 bytes to data from the pin TC_DATA
  3.       output_high(TC_CLK);
  4.       output_low(TC_CLK);
  5.    }

por

Código: C
  1. for (i=0;i<16;i++){
  2.       shift_left(&data,2,input(TC_DATA));      //reads in 2 bytes to data from the pin TC_DATA
  3.       output_high(TC_CLK);
  4.       delay_us(1);
  5.       output_low(TC_CLK);
  6.    }

Respecto a como hacerlo por hardware, unicamente lo se hacer por XC8, no uso CCS, asi que no te podria ayudar con eso.

Desconectado marcoscab1166

  • PIC12
  • **
  • Mensajes: 57
Re:Libreria para Max6675 en CCS
« Respuesta #6 en: 19 de Julio de 2017, 16:26:03 »
Bueno, cambie esas lineas, pero sigo sin conseguir resultados favorables. El primer problema es que si bien ahora al menos lee algo, el valor no corresponde al de la termocupla. Ademas, en algunas temperaturas tira el error de que no hay termocupla, cuando si hay.
En fin, estuve pensando en cambiar a un amplificador operacional, el LM358. Con ese consigo una lectura aceptable con las termocuplas tipo J. Pero el problema es que yo necesito que reconosca cuando no hay termocupla conectada. Alguna idea para eso?

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #7 en: 19 de Julio de 2017, 16:59:53 »
Que estes leyendo quiere decir que al menos la parte digital esta bien.

Aumentaria un poco el delay, ya que el tiempo de conversion va de 180 a 220ms. Y al bajar el CS simplemente corta la conversion
Los terminales son los correctos? Alumel en T+ y Chromel en T-
T- esta conectado a GND?
¿Capacitor de bypass?
¿Cable largo?
¿Dispositivos cerca que generen reuido ?

Desconectado jorge luis

  • PIC10
  • *
  • Mensajes: 13
Re:Libreria para Max6675 en CCS
« Respuesta #8 en: 06 de Diciembre de 2017, 17:32:26 »
Hola, necesito su ayuda, estoy intentado leer la temperatura de un termopar con un MAX6675 y un PIC16F877A a 10MHz, en la simulación logro capturar datos, en la programación realice una condición de que si el cable del termopar esta abierto en el LCD debe salir el mensaje "TERMOPAR ABIERTO"(cuando el bit 2 del registro leído esta en 1) pero me encuentro con 3 problemas:

1)  Al momento de variar la temperatura en el termopar a pesar de estar conectado, el mensaje se sobreescribe sobre la temperatura leída y esto continua mientras voy haciendo la variación.
2) Entre el MAX y el PIC puse un switch para hacer pruebas de abrir el circuito, al abrir el switch debería mostrarse el mensaje "TERMOPAR ABIERTO" pero ésto no sucede y se sigue mostrando el valor de temperatura y si vario el valor en el termopar en el lcd se observa tambien la variación cuando deberia estar mostrandose el mensaje.
3) El valor de temperatura que indica en el termopar no coincide con el valor calculado por el pic, el calculo en el pic lo estoy haciendo multiplicando el valor de los 12bits*0.25 (ésto lo saque del calculo de la libreria que se usa en arduino para el MAX6675).

Ojala puedan ayudarme, les agradezco por su tiempo. Adjunto el programa en CCS v5.070, circuito en proteus 8.6 y el datasheet del MAX6675.

Desconectado M16A14

  • PIC10
  • *
  • Mensajes: 2
Re:Libreria para Max6675 en CCS
« Respuesta #9 en: 07 de Marzo de 2020, 02:01:58 »
Hola,

Tengo un inconveniente, estoy utilizando el max6675  con el pic16f877a. Cuando simulo el programa no tengo ningun inconveniente, pero cuando lo pongo en mi montaje, en la lcd me sale el mensaje de error. Agradeceria indicar como puedo solucionar esto.

este es el programa que estoy utilizando

#INCLUDE <16f877a.h>
#fuses HS,NOWDT, NOLVP, XT, NOPROTECT ,NOBROWNOUT ,NOPUT ,NOLVP//hs,noput
#USE DELAY(CLOCK=4000000)

#define TC_CLK     PIN_C3 
#define TC_CS      PIN_C0
#define TC_DATA    PIN_C4
#INCLUDE <LCD.C>
#include "MAX.c"

void main()
{
 LCD_INIT();       //Inicializa el LCD
 LCD_PUTC("\f");   //Borrar el contenido del LCD
 char msg[32];
 delay_ms(50);      //allow oscillator to stabilise 
 
 while(1){
    delay_ms(800);
    LCD_PUTC("\f");
    sprintf(msg,"%1.1f%cC\r\n",do_everything(),0xB0);
    printf(LCD_PUTC,"Temp = %s",msg);
    delay_ms(1000);
   

}
}

esta es la libreria que utilizo


#ifndef TC_CLK
    #define TC_CLK     PIN_C3            //edit these pins as necessary
#endif

#ifndef TC_CS
    #define TC_CS      PIN_C0
#endif

#ifndef TC_DATA
    #define TC_DATA    PIN_C4
#endif

int1 thermocouple_error;         //a handy dandy global error flag to tell you if a thermocouple is connected or not
void init_TC(void)
{
   output_low(TC_CLK);
   output_low(TC_DATA);
   output_high(TC_CS);            //if we idle high, the chip keeps doing conversions. Change this if you like
   //setup_spi (SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_16);
}

int16 read_TC(void)               //It takes 200ms (ish) for the MAX6675 to perform a conversion
{
   int8 i;
   int16 data;
   output_low(TC_CS);            //stop any conversion processes
   delay_ms(1);               //and give it some time to power up (not very much, admittedly)
   
   for (i=0;i<16;i++){
      shift_left(&data,2,input(TC_DATA));      //reads in 2 bytes to data from the pin TC_DATA
      output_high(TC_CLK);
      delay_us(100); //Descomentar si usa crystal mayor a 10MHz
      output_low(TC_CLK);
      delay_us(100);
   }
   
   thermocouple_error=bit_test(data,2);      //this is the thermocouple status bit 
   output_high(TC_CS);
   delay_ms(1);
   return(data);
}

int16 sortout(int16 raw)
{
   return(0x0FFF & (raw>>3));      //returns only the bits converning temperature
}
float toFloat_TC(int16 tmp)
{

   return((((float)tmp)-48.725)/1.9835);


}
float do_everything(void)
{
   init_TC();
   delay_ms(200);               //200ms is a long time to be doing nothing. use a timer interrupt to avoid wasting time here
   return(toFloat_TC(sortout(read_TC())));
}

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #10 en: 07 de Marzo de 2020, 14:45:16 »
Citar
en la lcd me sale el mensaje de error.

Si vos no estas enviando la palabra ERROR al LCD en tu programa, entonces es un problema con el LCD y no con el MAX6675.

Deberias revisar el datasheet del LCD para ver cuando es que da ese mensaje y porque, tal ves la libreria del LCD no este respetando algun tiempo. O enviandole algun caracter raro para el LCD.

Desconectado M16A14

  • PIC10
  • *
  • Mensajes: 2
Re:Libreria para Max6675 en CCS
« Respuesta #11 en: 07 de Marzo de 2020, 16:47:09 »
No, la LCD esta bien, me apare el mensaje cuando el max6675 esta desconectado.

Desconectado Ruco

  • PIC12
  • **
  • Mensajes: 62
Re:Libreria para Max6675 en CCS
« Respuesta #12 en: 15 de Enero de 2021, 06:12:00 »
Recién estoy implementando el MAX6675 con los post de este foro. Y me esta lidiando un comentario en particular que ponen dentro de la función:

Código: C++
  1. float do_everything(void)
  2. {
  3.    init_TC();
  4.    delay_ms(200);               //200ms is a long time to be doing nothing. use a timer interrupt to avoid wasting time here
  5.    return(toFloat_TC(sortout(read_TC())));
  6. }

El comentario es //200ms is a long time to be doing nothing. use a timer interrupt to avoid wasting time here o sea que 200ms es mucho tiempo sin hacer nada. Use una interrupción del temporizador para evitar perder el tiempo aquí. En realidad me gustaria implementarlo y evitar este atasco de tiempo.

Como se podría implementar el timer1?. para que en el tiempo de los 200ms el pic este realizando algunas otras tareas en lugar de estar demorando tiempo solo aquí.


« Última modificación: 15 de Enero de 2021, 06:25:11 por Ruco »

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:Libreria para Max6675 en CCS
« Respuesta #13 en: 15 de Enero de 2021, 11:49:25 »
En realidad eso significa modificar la forma en como programas. Ya que vos necesitas que siga haciendo todo lo demás y cuando llegue nuevamente a esta parte que se fije si paso el tiempo..

Dependiendo de cuanto duren las funciones read_TC, sortout y toFloat_TC vas a poder ponerlo en la interrupcion o no. Si duran muy poco, pero MUY poco. entonces en la interrupcion del timer podes hacer:

Código: C
  1. #INT_TM0  //Ojo que asi no se llama, pero no uso CCS demasiado
  2. void intetTm0(void) {
  3.    valor = toFloat_TC(sortout(read_TC());
  4.    valorNuevo=1;
  5.    disable_interrupt(INT_TM0);
  6. }
  7.  
  8. float do_everything(void)
  9. {
  10.    if(valorNuevo) {
  11.        valorNuevo = 0;
  12.        return valor;  
  13.   } else {
  14.       init_TC();
  15.       set_timer0(xxx); //Valor al timer
  16.       clear_interrupt(INT_TM0);
  17.       enable_interrupt(INT_TM0);
  18.       return 0; //Todavia no listo
  19.   }
  20. }

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

En el caso de que NO duren poco, por que como veo tenes varios funciones con flotantes,etc, entoces conviene que este en el main:

Código: C
  1. #INT_TM0  //Ojo que asi no se llama, pero no uso CCS demasiado
  2. void intetTm0(void) {
  3.    TiempoCumplido=1;
  4.    disable_interrupt(INT_TM0);
  5. }
  6.  
  7. float do_everything(void)
  8. {
  9.    if(TiempoCumplido) {
  10.         //Listo, valor obtenido.
  11.        TiempoCumplido = 0;
  12.        return(toFloat_TC(sortout(read_TC())));  
  13.   } else {
  14.       init_TC();
  15.       set_timer0(xxx); //Valor al timer
  16.       clear_interrupt(INT_TM0);
  17.       enable_interrupt(INT_TM0);
  18.       return 0; //Todavia no listo
  19.   }
  20. }

Obviamente TODAS las demas funciones deberian funcionar de la misma manera.. Es decir sin delays, o que sea dependiente de un solo delay y muy pequeño.
Lo cual deberias remover esos delays de 800ms, y de 1000ms, deberias cambiar a una forma que sea mas desatendida en la transmision de caracteres, y en la recepción también.
Sino por 200ms no tienen ningun sentido, cuando estas esperando 1.8s en tu while.

Por eso mismo dije que deberias cambiar toda la forma de programar.
« Última modificación: 15 de Enero de 2021, 12:06:42 por KILLERJC »

Desconectado Ruco

  • PIC12
  • **
  • Mensajes: 62
Re:Libreria para Max6675 en CCS
« Respuesta #14 en: 15 de Enero de 2021, 15:37:40 »
Estoy probando el codigo y no muestra la temperatura.. El valor para el desborde del timer es 3036 por que lo trabajo a 20Mhz y con 3036 alcanzo 200ms del timer.

Asi es como decis Killer JC
Código: C++
  1. short TiempoCumplido=0;
  2.          
  3.          #INT_TIMER0                                                                        //Ojo que asi no se llama, pero no uso CCS demasiado
  4.          void intetTm0(void) {
  5.          set_timer1(3036);
  6.          TiempoCumplido=1;
  7.          disable_interrupts(INT_TIMER0);
  8.          }
  9.          
  10.          float do_everything(void)
  11.          {
  12.          if(TiempoCumplido) {
  13.         //Listo, valor obtenido.
  14.          TiempoCumplido = 0;
  15.          return(toFloat_TC(sortout(read_TC())));  
  16.          } else {
  17.          init_TC();
  18.          set_timer0(3036); //Valor al timer
  19.          //clear_interrupt(INT_TIMER0);
  20.          enable_interrupts(INT_TIMER0);
  21.          return 0; //Todavia no listo
  22.          }
  23.          }


En el Main

Código: C++
  1. void main()
  2.          {
  3.          lcd_init();      
  4.          setup_timer_0(RTCC_INTERNAL|RTCC_DIV_16);                
  5.          set_timer0(3036);
  6.          enable_interrupts(INT_TIMER0);  
  7.          enable_interrupts(global);                                                       //Activamos las interrupciones globales
  8.          
  9.          while(true){
  10.          lcd_gotoxy(1,2); printf(lcd_putc,"Todopic %3.2f%cC ",do_everything(),0xDF);  
  11.          
  12.          }
  13.          }

pero no muestra nada.

Este es el resto del codigo...

Código: C++
  1. #define TC_CLK     PIN_E1
  2.          #define TC_CS      PIN_E2
  3.          #define TC_DATA    PIN_E0
  4.  
  5.          short thermocouple_error;                                              // bandera de error global para indicarle si un termopar está conectado o no
  6.  
  7.          void init_TC(void)
  8.          {
  9.          output_low(TC_CLK);
  10.          output_low(TC_DATA);
  11.          output_high(TC_CS);            //if we idle high, the chip keeps doing conversions. Change this if you like
  12.          }
  13.  
  14.          int16 read_TC(void)               //It takes 200ms (ish) for the MAX6675 to perform a conversion
  15.          {
  16.          int8 i;
  17.          int16 data;
  18.          output_low(TC_CS);            //stop any conversion processes
  19.          delay_ms(1);               //and give it some time to power up (not very much, admittedly)
  20.            
  21.          for (i=0;i<16;i++){
  22.          shift_left(&data,2,input(TC_DATA));      //reads in 2 bytes to data from the pin TC_DATA
  23.          output_high(TC_CLK);
  24.          delay_us(100); //Descomentar si usa crystal mayor a 10MHz
  25.          output_low(TC_CLK);
  26.          delay_us(100);
  27.          }
  28.            
  29.          thermocouple_error=bit_test(data,2);      //this is the thermocouple status bit
  30.          output_high(TC_CS);
  31.          return(data);
  32.          }
  33.  
  34.          int16 sortout(int16 raw)
  35.          {
  36.          return(0x0FFF & (raw>>3));      //returns only the bits converning temperature
  37.          }
  38.  
  39.          float toFloat_TC(int16 tmp)
  40.          {
  41.          return((((float)tmp)-48.725)/1.9835);
  42.          }
« Última modificación: 15 de Enero de 2021, 15:40:23 por Ruco »