Commit 2430973a authored by Pedro Henrique Kopper's avatar Pedro Henrique Kopper
Browse files

Implement thermocouple

parent 9a5bf9fd
/*!
* @file Adafruit_MAX31856.cpp
*
* @mainpage Adafruit MAX31856 thermocouple reader
*
* @section intro_sec Introduction
*
* This is the documentation for Adafruit's MAX31856 driver for the
* Arduino platform. It is designed specifically to work with the
* Adafruit MAX31856 breakout: https://www.adafruit.com/products/3263
*
* These sensors use SPI to communicate, 4 pins are required to
* interface with the breakout.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* @section dependencies Dependencies
*
* This library depends on <a href="https://github.com/adafruit/Adafruit_Sensor">
* Adafruit_Sensor</a> being present on your system. Please make sure you have
* installed the latest version before using this library.
*
* @section author Author
*
* Written by ladyada for Adafruit Industries.
*
* @section license License
*
* BSD license, all text here must be included in any redistribution.
*
*/
#include "Adafruit_MAX31856.h"
#ifdef __AVR
#include <avr/pgmspace.h>
#elif defined(ESP8266)
#include <pgmspace.h>
#endif
#include <stdlib.h>
#include <SPI.h>
static SPISettings max31856_spisettings = SPISettings(500000, MSBFIRST, SPI_MODE1);
/**************************************************************************/
/*!
@brief Instantiate MAX31856 object and use software SPI pins
@param spi_cs Bitbang SPI Chip Select
@param spi_mosi Bitbang SPI MOSI
@param spi_miso Bitbang SPI MISO
@param spi_clk Bitbang SPI Clock
*/
/**************************************************************************/
Adafruit_MAX31856::Adafruit_MAX31856(int8_t spi_cs, int8_t spi_mosi, int8_t spi_miso, int8_t spi_clk) {
_sclk = spi_clk;
_cs = spi_cs;
_miso = spi_miso;
_mosi = spi_mosi;
}
/**************************************************************************/
/*!
@brief Instantiate MAX31856 object and use hardware SPI
@param spi_cs Any pin for SPI Chip Select
*/
/**************************************************************************/
Adafruit_MAX31856::Adafruit_MAX31856(int8_t spi_cs) {
_cs = spi_cs;
_sclk = _miso = _mosi = -1;
}
/**************************************************************************/
/*!
@brief Initialize MAX31856 attach/set pins or SPI device, default to K thermocouple
@returns Always returns true at this time (no known way of detecting chip ID)
*/
/**************************************************************************/
boolean Adafruit_MAX31856::begin(void) {
pinMode(_cs, OUTPUT);
digitalWrite(_cs, HIGH);
if (_sclk != -1) {
//define pin modes
pinMode(_sclk, OUTPUT);
pinMode(_mosi, OUTPUT);
pinMode(_miso, INPUT);
} else {
//start and configure hardware SPI
SPI.begin();
}
// assert on any fault
writeRegister8(MAX31856_MASK_REG, 0x0);
writeRegister8(MAX31856_CR0_REG, MAX31856_CR0_OCFAULT0 | MAX31856_CR0_AUTOCONVERT);
setThermocoupleType(MAX31856_TCTYPE_K);
return true;
}
/**************************************************************************/
/*!
@brief Set which kind of Thermocouple (K, J, T, etc) to detect & decode
@param type The enumeration type of the thermocouple
*/
/**************************************************************************/
void Adafruit_MAX31856::setThermocoupleType(max31856_thermocoupletype_t type) {
uint8_t t = readRegister8(MAX31856_CR1_REG);
t &= 0xF0; // mask off bottom 4 bits
t |= (uint8_t)type & 0x0F;
writeRegister8(MAX31856_CR1_REG, t);
}
/**************************************************************************/
/*!
@brief Get which kind of Thermocouple (K, J, T, etc) we are using
@returns The enumeration type of the thermocouple
*/
/**************************************************************************/
max31856_thermocoupletype_t Adafruit_MAX31856::getThermocoupleType(void) {
uint8_t t = readRegister8(MAX31856_CR1_REG);
t &= 0x0F;
return (max31856_thermocoupletype_t)(t);
}
/**************************************************************************/
/*!
@brief Read the fault register (8 bits)
@returns 8 bits of fault register data
*/
/**************************************************************************/
uint8_t Adafruit_MAX31856::readFault(void) {
return readRegister8(MAX31856_SR_REG);
}
/**************************************************************************/
/*!
@brief Sets the threshhold for internal chip temperature range
for fault detection. NOT the thermocouple temperature range!
@param low Low (min) temperature, signed 8 bit so -128 to 127 degrees C
@param high High (max) temperature, signed 8 bit so -128 to 127 degrees C
*/
/**************************************************************************/
void Adafruit_MAX31856::setColdJunctionFaultThreshholds(int8_t low, int8_t high) {
writeRegister8(MAX31856_CJLF_REG, low);
writeRegister8(MAX31856_CJHF_REG, high);
}
/**************************************************************************/
/*!
@brief Sets the mains noise filter. Can be set to 50 or 60hz.
Defaults to 60hz. You need to call this if you live in a 50hz country.
@param noiseFilter One of MAX31856_NOISE_FILTER_50HZ or MAX31856_NOISE_FILTER_60HZ
*/
/**************************************************************************/
void Adafruit_MAX31856::setNoiseFilter(max31856_noise_filter_t noiseFilter) {
uint8_t t = readRegister8(MAX31856_CR0_REG);
if(noiseFilter == MAX31856_NOISE_FILTER_50HZ) {
t|=0x01;
} else {
t&=0xfe;
}
writeRegister8(MAX31856_CR0_REG, t);
}
/**************************************************************************/
/*!
@brief Sets the threshhold for thermocouple temperature range
for fault detection. NOT the internal chip temperature range!
@param flow Low (min) temperature, floating point
@param fhigh High (max) temperature, floating point
*/
/**************************************************************************/
void Adafruit_MAX31856::setTempFaultThreshholds(float flow, float fhigh) {
int16_t low, high;
flow *= 16;
low = flow;
fhigh *= 16;
high = fhigh;
writeRegister8(MAX31856_LTHFTH_REG, high >> 8);
writeRegister8(MAX31856_LTHFTL_REG, high);
writeRegister8(MAX31856_LTLFTH_REG, low >> 8);
writeRegister8(MAX31856_LTLFTL_REG, low);
}
/**************************************************************************/
/*!
@brief Begin a one-shot (read temperature only upon request) measurement.
Value must be read later, not returned here!
*/
/**************************************************************************/
void Adafruit_MAX31856::oneShotTemperature(void) {
writeRegister8(MAX31856_CJTO_REG, 0x0);
uint8_t t = readRegister8(MAX31856_CR0_REG);
t &= ~MAX31856_CR0_AUTOCONVERT; // turn off autoconvert!
t |= MAX31856_CR0_1SHOT;
writeRegister8(MAX31856_CR0_REG, t);
delay(250); // MEME FIX autocalculate based on oversampling
}
/**************************************************************************/
/*!
@brief Start a one-shot measurement and return internal chip temperature
@returns Floating point temperature of chip in Celsius
*/
/**************************************************************************/
float Adafruit_MAX31856::readCJTemperature(void) {
//oneShotTemperature();
int16_t temp16 = readRegister16(MAX31856_CJTH_REG);
float tempfloat = temp16;
tempfloat /= 256.0;
return tempfloat;
}
/**************************************************************************/
/*!
@brief Start a one-shot measurement and return thermocouple tip temperature
@returns Floating point temperature at end of thermocouple in Celsius
*/
/**************************************************************************/
float Adafruit_MAX31856::readThermocoupleTemperature(void) {
//oneShotTemperature();
int32_t temp24 = readRegister24(MAX31856_LTCBH_REG);
if (temp24 & 0x800000) {
temp24 |= 0xFF000000; // fix sign
}
temp24 >>= 5; // bottom 5 bits are unused
float tempfloat = temp24;
tempfloat *= 0.0078125;
return tempfloat;
}
/**********************************************/
uint8_t Adafruit_MAX31856::readRegister8(uint8_t addr) {
uint8_t ret = 0;
readRegisterN(addr, &ret, 1);
return ret;
}
uint16_t Adafruit_MAX31856::readRegister16(uint8_t addr) {
uint8_t buffer[2] = {0, 0};
readRegisterN(addr, buffer, 2);
uint16_t ret = buffer[0];
ret <<= 8;
ret |= buffer[1];
return ret;
}
uint32_t Adafruit_MAX31856::readRegister24(uint8_t addr) {
uint8_t buffer[3] = {0, 0, 0};
readRegisterN(addr, buffer, 3);
uint32_t ret = buffer[0];
ret <<= 8;
ret |= buffer[1];
ret <<= 8;
ret |= buffer[2];
return ret;
}
void Adafruit_MAX31856::readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n) {
addr &= 0x7F; // make sure top bit is not set
if (_sclk == -1)
SPI.beginTransaction(max31856_spisettings);
else
digitalWrite(_sclk, HIGH);
digitalWrite(_cs, LOW);
spixfer(addr);
//Serial.print("$"); Serial.print(addr, HEX); Serial.print(": ");
while (n--) {
buffer[0] = spixfer(0xFF);
//Serial.print(" 0x"); Serial.print(buffer[0], HEX);
buffer++;
}
//Serial.println();
if (_sclk == -1)
SPI.endTransaction();
digitalWrite(_cs, HIGH);
}
void Adafruit_MAX31856::writeRegister8(uint8_t addr, uint8_t data) {
addr |= 0x80; // make sure top bit is set
if (_sclk == -1)
SPI.beginTransaction(max31856_spisettings);
else
digitalWrite(_sclk, HIGH);
digitalWrite(_cs, LOW);
spixfer(addr);
spixfer(data);
//Serial.print("$"); Serial.print(addr, HEX); Serial.print(" = 0x"); Serial.println(data, HEX);
if (_sclk == -1)
SPI.endTransaction();
digitalWrite(_cs, HIGH);
}
uint8_t Adafruit_MAX31856::spixfer(uint8_t x) {
if (_sclk == -1)
return SPI.transfer(x);
// software spi
//Serial.println("Software SPI");
uint8_t reply = 0;
for (int i=7; i>=0; i--) {
reply <<= 1;
digitalWrite(_sclk, LOW);
digitalWrite(_mosi, x & (1<<i));
digitalWrite(_sclk, HIGH);
if (digitalRead(_miso))
reply |= 1;
}
return reply;
}
/*!
* @file Adafruit_MAX31856.h
*
* This is the documentation for Adafruit's MAX31856 driver for the
* Arduino platform. It is designed specifically to work with the
* Adafruit MAX31856 breakout: https://www.adafruit.com/products/3263
*
* These sensors use SPI to communicate, 4 pins are required to
* interface with the breakout.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Written by ladyada for Adafruit Industries.
*
* BSD license, all text here must be included in any redistribution.
*
*/
#ifndef ADAFRUIT_MAX31856_H
#define ADAFRUIT_MAX31856_H
#define MAX31856_CR0_REG 0x00 ///< Config 0 register
#define MAX31856_CR0_AUTOCONVERT 0x80 ///< Config 0 Auto convert flag
#define MAX31856_CR0_1SHOT 0x40 ///< Config 0 one shot convert flag
#define MAX31856_CR0_OCFAULT1 0x20 ///< Config 0 open circuit fault 1 flag
#define MAX31856_CR0_OCFAULT0 0x10 ///< Config 0 open circuit fault 0 flag
#define MAX31856_CR0_CJ 0x08 ///< Config 0 cold junction disable flag
#define MAX31856_CR0_FAULT 0x04 ///< Config 0 fault mode flag
#define MAX31856_CR0_FAULTCLR 0x02 ///< Config 0 fault clear flag
#define MAX31856_CR1_REG 0x01 ///< Config 1 register
#define MAX31856_MASK_REG 0x02 ///< Fault Mask register
#define MAX31856_CJHF_REG 0x03 ///< Cold junction High temp fault register
#define MAX31856_CJLF_REG 0x04 ///< Cold junction Low temp fault register
#define MAX31856_LTHFTH_REG 0x05 ///< Linearized Temperature High Fault Threshold Register, MSB
#define MAX31856_LTHFTL_REG 0x06 ///< Linearized Temperature High Fault Threshold Register, LSB
#define MAX31856_LTLFTH_REG 0x07 ///< Linearized Temperature Low Fault Threshold Register, MSB
#define MAX31856_LTLFTL_REG 0x08 ///< Linearized Temperature Low Fault Threshold Register, LSB
#define MAX31856_CJTO_REG 0x09 ///< Cold-Junction Temperature Offset Register
#define MAX31856_CJTH_REG 0x0A ///< Cold-Junction Temperature Register, MSB
#define MAX31856_CJTL_REG 0x0B ///< Cold-Junction Temperature Register, LSB
#define MAX31856_LTCBH_REG 0x0C ///< Linearized TC Temperature, Byte 2
#define MAX31856_LTCBM_REG 0x0D ///< Linearized TC Temperature, Byte 1
#define MAX31856_LTCBL_REG 0x0E ///< Linearized TC Temperature, Byte 0
#define MAX31856_SR_REG 0x0F ///< Fault Status Register
#define MAX31856_FAULT_CJRANGE 0x80 ///< Fault status Cold Junction Out-of-Range flag
#define MAX31856_FAULT_TCRANGE 0x40 ///< Fault status Thermocouple Out-of-Range flag
#define MAX31856_FAULT_CJHIGH 0x20 ///< Fault status Cold-Junction High Fault flag
#define MAX31856_FAULT_CJLOW 0x10 ///< Fault status Cold-Junction Low Fault flag
#define MAX31856_FAULT_TCHIGH 0x08 ///< Fault status Thermocouple Temperature High Fault flag
#define MAX31856_FAULT_TCLOW 0x04 ///< Fault status Thermocouple Temperature Low Fault flag
#define MAX31856_FAULT_OVUV 0x02 ///< Fault status Overvoltage or Undervoltage Input Fault flag
#define MAX31856_FAULT_OPEN 0x01 ///< Fault status Thermocouple Open-Circuit Fault flag
/** Noise filtering options enum. Use with setNoiseFilter() */
typedef enum {
MAX31856_NOISE_FILTER_50HZ,
MAX31856_NOISE_FILTER_60HZ
} max31856_noise_filter_t;
/** Multiple types of thermocouples supported */
typedef enum
{
MAX31856_TCTYPE_B = 0b0000,
MAX31856_TCTYPE_E = 0b0001,
MAX31856_TCTYPE_J = 0b0010,
MAX31856_TCTYPE_K = 0b0011,
MAX31856_TCTYPE_N = 0b0100,
MAX31856_TCTYPE_R = 0b0101,
MAX31856_TCTYPE_S = 0b0110,
MAX31856_TCTYPE_T = 0b0111,
MAX31856_VMODE_G8 = 0b1000,
MAX31856_VMODE_G32 = 0b1100,
} max31856_thermocoupletype_t;
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
/**************************************************************************/
/*!
@brief Class that stores state and functions for interacting with MAX31856
*/
/**************************************************************************/
class Adafruit_MAX31856 {
public:
Adafruit_MAX31856(int8_t spi_cs, int8_t spi_mosi, int8_t spi_miso, int8_t spi_clk);
Adafruit_MAX31856(int8_t spi_cs);
boolean begin(void);
void setThermocoupleType(max31856_thermocoupletype_t type);
max31856_thermocoupletype_t getThermocoupleType(void);
uint8_t readFault(void);
void oneShotTemperature(void);
float readCJTemperature(void);
float readThermocoupleTemperature(void);
void setTempFaultThreshholds(float flow, float fhigh);
void setColdJunctionFaultThreshholds(int8_t low, int8_t high);
void setNoiseFilter(max31856_noise_filter_t noiseFilter);
private:
int8_t _sclk, _miso, _mosi, _cs;
void readRegisterN(uint8_t addr, uint8_t buffer[], uint8_t n);
uint8_t readRegister8(uint8_t addr);
uint16_t readRegister16(uint8_t addr);
uint32_t readRegister24(uint8_t addr);
void writeRegister8(uint8_t addr, uint8_t reg);
uint8_t spixfer(uint8_t addr);
};
#endif
#include <Arduino.h>
#include <Adafruit_MAX31856.h>
#include <InstrumentInterface.hpp>
#include "ADS1115.h"
ADS1115 adc0(ADS1115_DEFAULT_ADDRESS);
Adafruit_MAX31856 thermocouple = Adafruit_MAX31856(10);
InstrumentInterface iface;
void multi_req_cb(bool status, sadapmap_ReqMultiChannelReading *req) {
if(!status)
return; // Pacote inválido
float readings[req->id_count] = {0};
for(uint8_t i = 0; i < req->id_count; i++) {
// 0x04 pra medir single ended
adc0.setMultiplexer(req->id[i] | 0x04);
readings[i] = adc0.getMilliVolts(false);
if(req->id[i] < 2) {
adc0.setMultiplexer(req->id[i] | 0x04);
readings[i] = adc0.getMilliVolts(false);
} else {
readings[i] = thermocouple.readThermocoupleTemperature();
}
}
/*adc0.setMultiplexer(ADS1115_MUX_P0_NG);
readings[0] = adc0.getMilliVolts(false);
adc0.setMultiplexer(ADS1115_MUX_P1_NG);
readings[1] = adc0.getMilliVolts(false);
readings[2] = thermocouple.readThermocoupleTemperature();*/
iface.sendMultiChannel(req->id, readings, req->id_count);
}
......@@ -25,6 +38,9 @@ void setup() {
Serial.begin(115200);
iface.init(Serial, &multi_req_cb);
thermocouple.begin();
thermocouple.setThermocoupleType(MAX31856_TCTYPE_K);
//Serial.println("Testing device connections...");
//Serial.println(adc0.testConnection() ? "ADS1115 connection successful" : "ADS1115 connection failed");
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment