Skip to content

readTemperature() returns garbage (1073741824.00) (=2^32/4) for negative values #26

@drf5n

Description

@drf5n

See the discussion here:

https://forum.arduino.cc/t/arduino-mkr-therm-shield-not-measuring-temperatures-below-0-c/1313825/1

Output:

The cooling mixture is ice + sodium chloride

Reference temperature 26.94 °C
Temperature 3.50 °C

Reference temperature 27.00 °C
Temperature 1073741824.00 °C

Reference temperature 27.00 °C
Temperature 1073741824.00 °C

Reference temperature 27.00 °C
Temperature 1073741824.00 °C

Reference temperature 27.06 °C
Temperature 1073741824.00 °C

Reference temperature 27.00 °C
Temperature 1073741824.00 °C

Fix suggested in:

https://forum.arduino.cc/t/arduino-mkr-therm-shield-not-measuring-temperatures-below-0-c/1313825/6?u=davex

and

https://forum.arduino.cc/t/arduino-mkr-therm-shield-not-measuring-temperatures-below-0-c/1313825/7

and

/*
  This file is part of the Arduino_MKRTHERM library.
  Copyright (c) 2019 Arduino SA. All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library 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
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#include "MKRTHERM.h"

THERMClass::THERMClass(int cs, SPIClass& spi) :
  _cs(cs),
  _spi(&spi),
  _spiSettings(4000000, MSBFIRST, SPI_MODE0)
{
}

int THERMClass::begin()
{
  int32_t rawword;  // Change uint32_t to int32_t

  pinMode(_cs, OUTPUT);
  digitalWrite(_cs, HIGH);
  _spi->begin();

  rawword = readSensor();
  if (rawword == 0xFFFFFF) {
    end();
    return 0;
  }

  return 1;
}

void THERMClass::end()
{
  pinMode(_cs, INPUT);
  digitalWrite(_cs, LOW);
  _spi->end();
}

uint32_t THERMClass::readSensor()
{
  uint32_t read = 0x00;

  digitalWrite(_cs, LOW);
  delayMicroseconds(1);

  _spi->beginTransaction(_spiSettings);

  for (int i = 0; i < 4; i++) {
    read <<= 8;
    read |= _spi->transfer(0);
  }

  _spi->endTransaction();
  digitalWrite(_cs, HIGH);

  return read;
}

float THERMClass::readTemperature()
{
  int32_t rawword;  // Change uint32_t to int32_t
  float celsius;

  rawword = readSensor();

  // Check for reading error
  if (rawword & 0x7) {
    return NAN; 
  }

  // The temperature is stored in the last 14 bits 
  // sent by the Thermocouple-to-Digital Converter
  rawword >>= 18; // Drop the lower 18 bits

  // No need for manual sign extension, int32_t handles it
  celsius = rawword * 0.25f;

  return celsius;
}

float THERMClass::readReferenceTemperature()
{
  uint32_t rawword;
  float ref;

  rawword = readSensor();

  // Ignore the first 4 FAULT bits
  rawword >>= 4;

  // The cold junction reference temperature is stored in the first 11 bits
  // sent by the Thermocouple-to-Digital Converter
  rawword = rawword & 0x7FF;

  // Check the sign bit and convert to negative value if needed.
  if (rawword & 0x800) {
    ref = (0xF800 | (rawword & 0x7FF)) * 0.0625;
  } else {
    // Multiply by the LSB value
    ref = rawword * 0.0625f;
  }

  return ref;
}

THERMClass THERM;

Metadata

Metadata

Assignees

No one assigned

    Labels

    topic: codeRelated to content of the project itselftype: imperfectionPerceived defect in any part of project

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions