Wrong Reading Spi M524

I have problems with the values ​​of some of the bits I receive via SPI. I configure a Max31855 with a k-type thermocouple. When reading the internal temperature it is fine, the disconnection errors are read perfectly, but the temperature value in the thermocouple shows erroneous values, sometimes even negative.

This is the code in general terms, I am using an M524 board

void setup() {
                pinMode( (MAXCS, OUTPUT);
               digitalWrite(MAXCS, HIGH);  // Iniciar con el chip deshabilitado

          SPI.beginTransaction(SPISettings(5000000, MSBFIRST, 
           SPI_MODE0));
           SPI.begin();
}


void loop() {
        readThermocouple();
        delay(1000);
}
double readThermocouple() {
       uint32_t v = 0;

    // Activar el MAX31855
    digitalWrite(MAXCS, LOW);
    delayMicroseconds(100);  // Pequeño retardo para asegurar la transmisión

    // Leer 32 bits de datos del MAX31855
    for (int i = 0; i < 4; i++) {
        v <<= 8;
        v |= SPI.transfer(0x00);
    }

    // Desactivar el MAX31855
    digitalWrite(MAXCS, HIGH);

    // Verificar si hay fallos
    if (v & 0x00010000) {  // Verificar el bit D16 (falla)
        Serial.println("Error en la termocupla");
        if (v & 0x00000001) Serial.println("Termocupla abierta (OC Fault)");
        if (v & 0x00000002) Serial.println("Cortocircuito a GND (SCG Fault)");
        if (v & 0x00000004) Serial.println("Cortocircuito a VCC (SCV Fault)");
        return NAN;  // Retornar un valor no numérico si hay un error
    }

    // Extraer la temperatura de la termocupla
    int32_t tempData = (v >> 18) & 0x3FFF;  // Los bits D31:18 contienen la temperatura de la termocupla
   if (v & 0x80000000) {  // Comprobar si es un valor negativo
        tempData |= 0xFFFFC000;  // Extensión de signo para manejar números negativos
    }
    int32_t thermocoupleTemperature = tempData * 0.25;  // Multiplicar por 0.25 para obtener la temperatura en °C

    // Extraer la temperatura de la unión fría (bits D15:4)
    int32_t internalTempData = (v >> 4) & 0x0FFF;  // Los bits D15:4 contienen la temperatura interna
    if (v & 0x00008000) {  // Comprobar si es un valor negativo
        internalTempData |= 0xFFFFF000;  // Extensión de signo para manejar números negativos
    }
    double internalTemperature = internalTempData * 0.0625;  // Multiplicar por 0.0625 para obtener la temperatura en °C

    // Imprimir ambas temperaturas
    Serial.print("Temperatura del termopar: ");
    Serial.println(thermocoupleTemperature);
    Serial.print("Temperatura interna (UnionFria): ");
    Serial.println(internalTemperature);

    return thermocoupleTemperature;
}

What version of Device OS are you using? You should use 5.9.0 on the M-SoM.

beginTransaction() and endTransaction() must surround the actual transaction, not be done in setup. You should put SPI.beginTransaction() right before the digitalWrite() of the CS pin. You should put SPI.endTransaction() right after the CS pin write.

1 Like

I have already updated to 5.9.0 and this is the function with the suggested changes, it presents the same problem.

double readThermocouple() {
uint32_t v = 0;

// Activar el MAX31855
SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE0));
digitalWrite(MAXCS, LOW);
delayMicroseconds(10);  // Pequeño retardo para asegurar la transmisión

// Leer 32 bits de datos del MAX31855
for (int i = 0; i < 4; i++) {
    v <<= 8;
    v |= SPI.transfer(0x00);
}

// Desactivar el MAX31855
digitalWrite(MAXCS, HIGH);
SPI.endTransaction();

// Verificar si hay fallos
if (v & 0x00010000) {  // Verificar el bit D16 (falla)
    Serial.println("Error en la termocupla");
    if (v & 0x00000001) Serial.println("Termocupla abierta (OC Fault)");
    if (v & 0x00000002) Serial.println("Cortocircuito a GND (SCG Fault)");
    if (v & 0x00000004) Serial.println("Cortocircuito a VCC (SCV Fault)");
    return NAN;  // Retornar un valor no numérico si hay un error
}

// Extraer la temperatura de la termocupla
int32_t tempData = (v >> 18) & 0x3FFF;  // Los bits D31:18 contienen la temperatura de la termocupla

if (v & 0x80000000) { // Comprobar si es un valor negativo
tempData |= 0xFFFFC000; // Extensión de signo para manejar números negativos
}
int32_t thermocoupleTemperature = tempData * 0.25; // Multiplicar por 0.25 para obtener la temperatura en °C

// Extraer la temperatura de la unión fría (bits D15:4)
int32_t internalTempData = (v >> 4) & 0x0FFF;  // Los bits D15:4 contienen la temperatura interna
if (v & 0x00008000) {  // Comprobar si es un valor negativo
    internalTempData |= 0xFFFFF000;  // Extensión de signo para manejar números negativos
}
double internalTemperature = internalTempData * 0.0625;  // Multiplicar por 0.0625 para obtener la temperatura en °C

// Imprimir ambas temperaturas
Serial.print("Temperatura del termopar: ");
Serial.println(thermocoupleTemperature);
Serial.print("Temperatura interna (UnionFria): ");
Serial.println(internalTemperature);

return thermocoupleTemperature;

}

@camiloB91, you do know that there is an Adafruit_MAX31855 library available on the WebIDE, which you can also "install" if you are using Workbench. This library should work for you.

I already tried it, the library has the same problem

/***************************************************
This is an example for the Adafruit Thermocouple Sensor w/MAX31855K

Designed specifically to work with the Adafruit Thermocouple Sensor
----> Thermocouple Amplifier MAX31855 breakout board (MAX6675 upgrade) : ID 269 : Adafruit Industries, Unique & fun DIY electronics and kits

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
****************************************************/

#include <SPI.h>
#include "Adafruit_MAX31855.h"

// Default connection is using software SPI, but comment and uncomment one of
// the two examples below to switch between software SPI and hardware SPI:

// Example creating a thermocouple instance with software SPI on any three
// digital IO pins.
#define MAXDO D11
#define MAXCS D8
#define MAXCLK D13

// initialize the Thermocouple
//Adafruit_MAX31855 thermocouple(MAXCLK, MAXCS, MAXDO);

// Example creating a thermocouple instance with hardware SPI
// on a given CS pin.
//#define MAXCS 10
Adafruit_MAX31855 thermocouple(MAXCS);

// Example creating a thermocouple instance with hardware SPI
// on SPI1 using specified CS pin.
//#define MAXCS 10
//Adafruit_MAX31855 thermocouple(MAXCS, SPI1);

void setup() {
Serial.begin(9600);

while (!Serial) delay(1); // wait for Serial on Leonardo/Zero, etc

Serial.println("MAX31855 test");
// wait for MAX chip to stabilize
delay(500);
Serial.print("Initializing sensor...");
if (!thermocouple.begin()) {
Serial.println("ERROR.");
while (1) delay(10);
}

// OPTIONAL: Can configure fault checks as desired (default is ALL)
// Multiple checks can be logically OR'd together.
// thermocouple.setFaultChecks(MAX31855_FAULT_OPEN | MAX31855_FAULT_SHORT_VCC); // short to GND fault is ignored

Serial.println("DONE.");
}

void loop() {
// basic readout test, just print the current temp
Serial.print("Internal Temp = ");
Serial.println(thermocouple.readInternal());

double c = thermocouple.readCelsius();
if (isnan(c)) {
Serial.println("Thermocouple fault(s) detected!");
uint8_t e = thermocouple.readError();
if (e & MAX31855_FAULT_OPEN) Serial.println("FAULT: Thermocouple is open - no connections.");
if (e & MAX31855_FAULT_SHORT_GND) Serial.println("FAULT: Thermocouple is short-circuited to GND.");
if (e & MAX31855_FAULT_SHORT_VCC) Serial.println("FAULT: Thermocouple is short-circuited to VCC.");
} else {
Serial.print("C = ");
Serial.println(c);
}
//Serial.print("F = ");
//Serial.println(thermocouple.readFahrenheit());

delay(1000);
}

You need to speficy the use of hardware SPI. Let me take a look and post here how it should be done.

UPDATE: There is a second "Adafruit_max31855" (note the lower case "max") library which can use the hardware SPI. Is this the one you used?

AdafruitMAX31855 thermocouple(CSpin);
1 Like

A small interference in the thermocouple signal was responsible for the negative values, although it does not appear in the typical connection, the problem can be solved with a 0.01uf capacitor between the thermocouple terminals.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.