Skip to content

Commit

Permalink
Merge pull request #10 from RobTillaart/develop
Browse files Browse the repository at this point in the history
0.2.1 release
  • Loading branch information
RobTillaart authored Aug 26, 2020
2 parents 8a6131e + 6596a05 commit 2e6c80e
Show file tree
Hide file tree
Showing 8 changed files with 227 additions and 102 deletions.
19 changes: 12 additions & 7 deletions MAX31855.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
//
// FILE: MAX31855.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.2.0
// VERSION: 0.2.1
// PURPOSE: Arduino library for MAX31855 chip for K type thermocouple
// DATE: 2014-01-01
// URL: https://github.com/RobTillaart/MAX31855_RT
//
// HISTORY:
//
// 0.2.1 2020-08-26 read rawData and STATUS_NO_COMMUNICATION recognition (thanks to FabioBrondo)
// 0.2.0 2020-06-20 #pragma once; major refactor; removed pre 1.0 support; fix offset
// 0.1.10 2019-07-31 add 3 inline functions to test errors + demo sketch
// 0.1.9 2017-07-27 reverted double -> float (issue33)
Expand All @@ -22,8 +23,10 @@
// 0.1.00 2014-01-02 initial version.
//


#include "MAX31855.h"


MAX31855::MAX31855(const uint8_t sclk, const uint8_t cs, const uint8_t miso)
{
_sclk = sclk;
Expand Down Expand Up @@ -60,7 +63,7 @@ uint8_t MAX31855::read()
// 31 SIGN
uint32_t value = _read();

if (value == 0xFFFFFFFF)
if (value == 0xFFFFFFFF) // needs a pull up on miso pin to work properly!
{
// bit 3 and bit 17 should always be 0 - P10 datasheet
_status = STATUS_NO_COMMUNICATION;
Expand All @@ -71,10 +74,11 @@ uint8_t MAX31855::read()

// process status bit 0-2
_status = value & 0x0007;
// if (_status) return _status;

value >>= 3;

// reserved bit 3
// reserved bit 3, allways 0
value >>= 1;

// process internal bit 4-15
Expand All @@ -89,19 +93,19 @@ uint8_t MAX31855::read()
// _fault = value & 0x01;
value >>= 1;

// reserved bit 17
// reserved bit 17, allways 0
value >>= 1;

// process temperature bit 18-30 + sign bit = 31
_temperature = (value & 0x1FFF) * 0.25;
if (value & 0x2000) // negative flag
{
_temperature = -2048 + _temperature; // fix neg temp
_temperature = -2048 + _temperature; // calculate neg temp
}
return _status;
}

// TODO optimize, how.

uint32_t MAX31855::_read(void)
{
_rawData = 0;
Expand Down Expand Up @@ -134,7 +138,8 @@ float MAX31855::getTemperature()
// in practice this works also for K_TC but is way slower..
// 1: reverse calculate the Voltage measured
float Vout = K_TC * (_temperature - _internal); // PAGE 8 datasheet
// 2: from Voltage to corrected temperature usinfg the Seebeck Coefficient

// 2: from Voltage to corrected temperature using the Seebeck Coefficient
float _temp = Vout / _SC + _internal;
return _temp;
}
Expand Down
27 changes: 17 additions & 10 deletions MAX31855.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//
// FILE: MAX31855.h
// AUTHOR: Rob Tillaart
// VERSION: 0.2.0
// VERSION: 0.2.1
// PURPOSE: Arduino library for MAX31855 chip for K type thermocouple
// DATE: 2014-01-01
// URL: https://github.com/RobTillaart/MAX31855_RT
Expand All @@ -11,7 +11,8 @@

#include "Arduino.h"

#define MAX31855_VERSION "0.2.0"
#define MAX31855_VERSION "0.2.1"


// STATE constants returnd by read()
#define STATUS_OK 0x00
Expand All @@ -22,16 +23,18 @@
#define STATUS_NOREAD 0x80
#define STATUS_NO_COMMUNICATION 0x81


// Thermocouples working is based upon Seebeck effect.
// Different TC have a different Seebeck Coefficient (µV/°C)
// See http://www.analog.com/library/analogDialogue/archives/44-10/thermocouple.html
//
// As the MAX31855 is designed for K type sensors, one can calculate
// the factor needed to convert other sensors measurements.
// NOTE: this is only a linear approximation.

//
// Seebeck Coefficients (sensitivity) from the MAX31855 datasheet page 8
// to be used in setSeebeckCoefficient()
//
// TYPE COEFFICIENT
#define E_TC 76.373
#define J_TC 57.953
Expand All @@ -41,9 +44,11 @@
#define S_TC 9.587
#define T_TC 52.18


class MAX31855
{
public:

MAX31855(uint8_t SCLK, uint8_t CS, uint8_t MISO);
void begin();

Expand All @@ -53,11 +58,13 @@ class MAX31855
float getInternal(void) const { return _internal; }
float getTemperature(void);

uint8_t getStatus(void) const { return _status; };
// next 3 applies to last read
inline bool shortToGND() { return (_status & STATUS_SHORT_TO_GND) != 0; };
inline bool shortToVCC() { return (_status & STATUS_SHORT_TO_VCC) != 0; };
inline bool openCircuit() { return (_status & STATUS_OPEN_CIRCUIT) != 0; };
uint8_t getStatus(void) const { return _status; };
inline bool openCircuit() { return _status == STATUS_OPEN_CIRCUIT; };
inline bool shortToGND() { return _status == STATUS_SHORT_TO_GND; };
inline bool shortToVCC() { return _status == STATUS_SHORT_TO_VCC; };
inline bool genericError() { return _status == STATUS_ERROR; };
inline bool noRead() { return _status == STATUS_NOREAD; };
inline bool noCommunication() { return _status == STATUS_NO_COMMUNICATION; };

// use offset to callibrate the TC.
void setOffset(const float t) { _offset = t; };
Expand All @@ -68,8 +75,8 @@ class MAX31855
void setSeebeckCoefficient(const float SC) { _SC = SC; };
float getSeebeckCoefficient() const { return _SC; };

uint32_t lastRead() { return _lastRead; };
uint32_t getRawData() { return _rawData;};
uint32_t lastRead() { return _lastRead; };
uint32_t getRawData() { return _rawData;};

private:
uint32_t _read();
Expand Down
151 changes: 102 additions & 49 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

Arduino library for MAX31855 chip for K type thermocouple


## Description

The MAX38155 is a chip to convert the reading of a K-type thermocouple to a temperature.
Expand All @@ -13,10 +14,13 @@ For every type of TC there exist an MAX31855 variant, this library is primary
developed for the K-type sensor. However it has experimental support for all
other types of TC's. See details below.

## Interface

To make a temperature reading call **tc.read()**.
It returns the status of the read which is a value between 0..7
The function **getStatus()** returns the same status value.

Status from **read()**
Table: values returned from **read()** and **getStatus()**

| value | Description | Action |
|:----:|:----|:----|
Expand All @@ -28,46 +32,120 @@ Status from **read()**
| 128 | No read done yet | check wiring |
| 129 | No communication | check wiring |

The function **getStatus()** returns the same status value. There are three functions
to check individual error conditions.
There are six functions to check the individual error conditions mentioned above.
These make it easier to check them.

- **openCircuit()**
- **shortToGND()**
- **shortToVCC()**
- **genericError()**
- **noRead()**
- **noCommunication()**

After a **tc.read()** you can get the temperature with **tc.getTemperature()**
and **tc.getInternal()** for the temperature of the chip / board itself.
and **tc.getInternal()** for the interrnal temperature of the chip / board itself.

Repeated calls to **getTemperature()** will give the same value until a new **tc.read()**.
The latter fetches a new value from the sensor, and does the most work.
Repeated calls to **tc.getTemperature()** will give the same value until a new **tc.read()**.
The latter fetches a new value from the sensor. Note that if the **tc.read()** fails
the value of **tc.getTemperature()** can become incorrect.

The library supports a fixed offset to callibrate the thermocouple.
For this the functions **getOffset()** and **setOffset(offset)** are available.
This offset is included in the **getTemperature()** function.
For this the functions **tc.getOffset()** and **tc.setOffset(offset)** are available.
This offset is included in the **tc.getTemperature()** function.

As the **tc** object holds its last known temperature it is easy to determine the delta
with the last known temperature, e.g. for trend analysis.

```cpp
float last = tc.getTemperature();
int state = tc.read();
float new = tc.getTemperature();
float delta = new - last;
float last = tc.getTemperature();
int state = tc.read();
if (state == STATUS_OK)
{
float new = tc.getTemperature();
float delta = new - last;
// process data
}
```
The **tc** object keeps track of the last time **read()** is called in the function **lastRead()**.
The **tc** object keeps track of the last time **tc.read()** is called in the function **tc.lastRead()**.
The time is tracked in **millis()**. This makes it easy to read the sensor at certain intervals.
```cpp
if (millis() - lastRead() >= interval)
if (millis() - tc.lastRead() >= interval)
{
tc.read();
float new = tc.getTemperature();
// process read value.
int state = tc.read();
if (state == STATUS_OK)
{
float new = tc.getTemperature();
// process read value.
}
else
{
// handle error
}
}
```


## GetRawData

The function **tc.getRawData()** allows you to get all the 32 bits raw data from the board,
after the standard **tc.read()** call.

Example code can be found in the examples folder.

```cpp
int state = thermocouple.read();
uint32_t value = thermocouple.getRawData(); // Read the raw Data value from the module
```


## Pull Up Resistor

To have proper working of the MAX31855 board, you need to add a pull-up resistor
(e.g. 4K7 - 1K depending on wirelength) between the MISO pin (from constructor call) and the
VCC (5Volt). This improves the signal quality and will allow you to detect if there is
proper communication with the board. WIthout pull-up one might get random noise that could
look like real data.

**Note:** the MISO pin can be different from each board, please refer to your board datasheet.

If the MAX31855 board is not connected **tc.read()** will return **STATUS_NO_COMMUNICATION**.

You can verify this by **tc.getRawData()** which will give 32 HIGH bits or 0xFFFFFFFF).

You can use a simple code to detect connection error board:

```cpp
uint8_t status = thermocouple.read();
if (status == STATUS_NO_COMMUNICATION)
{
Serial.println("NO COMMUNICATION");
}
```
or
```cpp
uint8_t status = thermocouple.read();
if (thermocouple.getRawData() == 0xFFFFFFFF)
{
Serial.println("NO COMMUNICATION");
}
```


## Operation

See examples


## Experimental part (to be tested)

**NOTE:**
The support for other thermocouples is experimental **use at your own risk**.


The MAX31855 is designed for K type sensors. It essentially measures a
voltage difference and converts this voltage using the Seebeck Coefficient (SC)
to the temperature. As the SC is lineair in its nature it is possible
Expand All @@ -76,7 +154,7 @@ to replace the K-type TC with one of the other types of TC.
Datasheet Table 1, page 8

| Sensor type | Seebeck Coefficient (µV/°C) | Temp Range (°C) | Material |
|:----|:----|:----|:----|
|:----:|:----|:----|:----|
| E_TC | 76.373 | -270 to +1000 | Constantan Chromel |
| J_TC | 57.953 | -210 to +1200 | Constantan Iron |
| K_TC | 41.276 | -270 to +1372 | Alumel Chromel |
Expand All @@ -90,41 +168,16 @@ The core formula to calculate the temperature is (Datasheet page 8)
Vout = (41.276µV/°C) x (Temp_R - Temp_internal)
```
As we know the internal temperature and the returned temperature from the sensor
the library can calculate the Vout measured(as the chip assumes that a K-type
the library can calculate the Vout measured (as the chip assumes that a K-type
thermocouple is connected.
Having that Vout we can redo the math for the actual thermocouple type and
calculate the real temperature.
The library has two functions **setSeebeckCoefficient(factor)** and
**getSeebeckCoefficient()**

The library has two functions **tc.setSeebeckCoefficient(factor)** and
**tc.getSeebeckCoefficient()**
to get/set the Seebeck Coefficient (== thermocouple) to be used.
One can adjust the values to improve the accuracy of the temperature read.

The **getTemperature()** has implemented this algorithm, however as long
as one does not set the SC it will use the K_TC as default.

## GetRawData
This function allows you to get all the 32 bits raw data from the board, after the standard reading.
Example code could be found in the examples folder.

```cpp
thermocouple.read();
value=thermocouple.getRawData(); // Read the raw Data value from the module
```
## Pull Up Resistor
This conversation was marked as resolved by FabioBrondo
To check if the board is connected or not, you can add a 1k pull-up resistor over the MISO pin (MISO pin can be different from each board, please refer to your board datasheet).
To check if the board is connected or not, you can add a 1k pull-up resistor over the MISO pin (MISO pin can be different from each board, please refer to your board datasheet, to find out wich pin is the MISO pin).

If no board is connected you can find 31 HIGH bit, so you can discriminate the error.
You can use a simple code to detect connection error board:

```cpp
uint8_t status = thermocouple.read();
if (status == STATUS_NO_COMMUNICATION)
{
Serial.println("NO COMMUNICATION");
}
```
**NOTE:**
The support for other thermocouples is experimental **use at your own risk**.
The **tc.getTemperature()** has implemented this algorithm, however as long
as one does not set the Seebeck Coefficient it will use the K_TC as default.

Loading

0 comments on commit 2e6c80e

Please sign in to comment.