Code does not return correct value for negative internal temperature values -- here's a fix:
/***************************************************
This is a library for the Adafruit Thermocouple Sensor w/MAX31855K
Designed specifically to work with the Adafruit Thermocouple Sensor
----> https://www.adafruit.com/products/269
These displays use SPI to communicate, 3 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
modified 03/21/2013 by cmay -- there was an error in the output
when the internal temperature was negative -- see Maxim's datasheet
tables 4 and 5 for sample data values
****************************************************/
include "Adafruit_MAX31855.h"
include <avr/pgmspace.h>
include <util/delay.h>
include <stdlib.h>
Adafruit_MAX31855::Adafruit_MAX31855(int8_t SCLK, int8_t CS, int8_t MISO) {
sclk = SCLK;
cs = CS;
miso = MISO;
//define pin modes
pinMode(cs, OUTPUT);
pinMode(sclk, OUTPUT);
pinMode(miso, INPUT);
digitalWrite(cs, HIGH);
}
double Adafruit_MAX31855::readInternal(void) {
uint32_t v;
v = spiread32();
// ignore bottom 4 bits - they're just thermocouple data
v >>= 4;
// pull the bottom 11 bits off
float internal = v & 0x7FF;
// internal = 0.0625; // LSB = 0.0625 degrees -- cmay 03/21/2013 MOVED below if statement
// check sign bit!
if (v & 0x800)
{
///////////////////////////////////////////////
//internal *= -1; //not quite cmay 03/21/2013
//try this instead:
int16_t tmp;
tmp = ~(v&0x7FF)+1; //2's complement
tmp= tmp & 0x07FF; //only using 11 bits
internal = tmp-1;
///////////////////////////////////////////////
}
internal *= 0.0625;
//Serial.print("\tInternal Temp: "); Serial.println(internal);
return internal;
}
double Adafruit_MAX31855::readCelsius(void) {
int32_t v;
v = spiread32();
//Serial.print("0x"); Serial.println(v, HEX);
/*
float internal = (v >> 4) & 0x7FF;
internal *= 0.0625;
if ((v >> 4) & 0x800)
internal *= -1;
Serial.print("\tInternal Temp: "); Serial.println(internal);
*/
if (v & 0x7) {
// uh oh, a serious problem!
return NAN;
}
// get rid of internal temp data, and any fault bits
v >>= 18;
//Serial.println(v, HEX);
////////////////////////////////////////////////////////
/* the following lines DO NOTHING ... cmay 03/21/2013
// pull the bottom 13 bits off
int16_t temp = v & 0x3FFF;
// check sign bit
if (v & 0x2000)
temp |= 0xC000;
//Serial.println(temp);
*/
////////////////////////////////////////////////////////
double centigrade = v;
// LSB = 0.25 degrees C
centigrade *= 0.25;
return centigrade;
}
uint8_t Adafruit_MAX31855::readError() {
return spiread32() & 0x7;
}
double Adafruit_MAX31855::readFarenheit(void) {
float f = readCelsius();
f *= 9.0;
f /= 5.0;
f += 32;
return f;
}
uint32_t Adafruit_MAX31855::spiread32(void) {
int i;
uint32_t d = 0;
digitalWrite(sclk, LOW);
_delay_ms(1);
digitalWrite(cs, LOW);
_delay_ms(1);
for (i=31; i>=0; i--)
{
digitalWrite(sclk, LOW);
_delay_ms(1);
d <<= 1;
if (digitalRead(miso))
{
d |= 1;
}
digitalWrite(sclk, HIGH);
_delay_ms(1);
}
digitalWrite(cs, HIGH);
//Serial.println(d, HEX);
////////////////////////////////////////////////////////////////////
//cmay -- for test cases return values like
// tc AND internal
//0x3E806490 -- should be 1000 AND 100.5625 no Tcouple Errors
//0xf060ec00 -- should be -250 AND -20 with no Tcouple Errors
//0xFFFCFFF0 -- should be -0.25 AND -0.0625 with no Tcouple Errors
//0xF060C900 -- should be -250 AND -50 with no Tcouple Errors
////////////////////////////////////////////////////////////////////
//d = 0xF060C900; //0xfffcfff0; //0xf060ec00;
return d;
}