mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 00:29:46 +01:00
drivers: add max31855
This commit is contained in:
parent
350fbf6ba4
commit
ebf64133d7
135
drivers/include/max31855.h
Normal file
135
drivers/include/max31855.h
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (C) 2024 HAW Hamburg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup drivers_max31855 MAX31855 Thermocouple-to-Digital Converter driver
|
||||
* @ingroup drivers_sensors
|
||||
* @brief Driver for the SPI Thermocouple-to-Digital Converter MAX31855.
|
||||
*
|
||||
* The MAX31855 performs cold-junction compensation and digitizes
|
||||
* the signal from a K-, J-, N-, T-, S-, R-, or E-type
|
||||
* thermocouple. The data is output in a signed 14-bit,
|
||||
* SPI-compatible, read-only format. This converter resolves
|
||||
* temperatures to 0.25°C, allows readings as high as +1800°C and
|
||||
* as low as -270°C, and exhibits thermocouple accuracy of ±2°C
|
||||
* for temperatures ranging from -200°C to +700°C for K-type
|
||||
* thermocouples.
|
||||
*
|
||||
* @note See the datasheet for more information:
|
||||
* https://www.analog.com/media/en/technical-documentation/data-sheets/MAX31855.pdf
|
||||
*
|
||||
* @note This driver doesn't require a MOSI line, as the MAX31855 is a read-only.
|
||||
*
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
*
|
||||
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
|
||||
*/
|
||||
|
||||
#ifndef MAX31855_H
|
||||
#define MAX31855_H
|
||||
|
||||
/* Add header includes here */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "periph/spi.h"
|
||||
|
||||
/* Declare the API of the driver */
|
||||
|
||||
/**
|
||||
* @brief Device initialization parameters
|
||||
*/
|
||||
typedef struct {
|
||||
spi_t spi; /**< SPI device */
|
||||
spi_cs_t cs_pin; /**< Chip select pin */
|
||||
} max31855_params_t;
|
||||
|
||||
/**
|
||||
* @brief Device descriptor for the driver
|
||||
*/
|
||||
typedef struct {
|
||||
const max31855_params_t *params; /**< device configuration */
|
||||
} max31855_t;
|
||||
|
||||
/**
|
||||
* @brief Fault status of the MAX31855
|
||||
*/
|
||||
typedef enum {
|
||||
MAX31855_FAULT_VCC_SHORT = 0, /**< VCC short-circuit */
|
||||
MAX31855_FAULT_GND_SHORT = 1, /**< GND short-circuit */
|
||||
MAX31855_FAULT_OPEN_CIRCUIT = 2, /**< Open circuit */
|
||||
MAX31855_FAULT_NO_FAULT = 3 /**< No fault */
|
||||
} max31855_fault_t;
|
||||
|
||||
/**
|
||||
* @brief Data structure for the MAX31855
|
||||
*/
|
||||
typedef struct {
|
||||
int32_t thermocouple_temperature; /**< Thermocouple temperature in centi degrees C */
|
||||
int32_t internal_temperature; /**< Internal temperature in centi degrees C */
|
||||
max31855_fault_t fault; /**< Fault status */
|
||||
} max31855_data_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize the given device
|
||||
*
|
||||
* @param[inout] dev Device descriptor of the driver
|
||||
* @param[in] params Initialization parameters
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -ENXIO invalid SPI device
|
||||
* @retval -EINVAL invalid SPI CS pin/line
|
||||
*/
|
||||
int max31855_init(max31855_t *dev, const max31855_params_t *params);
|
||||
|
||||
/**
|
||||
* @brief Parse the raw data from the MAX31855 to the data structure
|
||||
*
|
||||
* @param[in] raw_data Raw data from the MAX31855
|
||||
* @param[out] data Pointer to the data structure.
|
||||
*
|
||||
* @pre @p data must not be NULL
|
||||
*/
|
||||
void max31855_raw_to_data(uint32_t raw_data, max31855_data_t *data);
|
||||
|
||||
/**
|
||||
* @brief Read data from the MAX31855. This is a shortcut to read raw data
|
||||
* and parse it to the data structure.
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
* @param[out] data Pointer to the data structure.
|
||||
*
|
||||
* @pre @p dev and @p data must not be NULL
|
||||
*
|
||||
* @retval 0 on success
|
||||
* @retval -EIO if there is an error detected by the MAX31855. For a detailed
|
||||
* error description, check the fault field of the data structure. On this
|
||||
* case, temperature fields are not valid.
|
||||
*/
|
||||
int max31855_read(max31855_t *dev, max31855_data_t *data);
|
||||
|
||||
/**
|
||||
* @brief Read raw data from the MAX31855
|
||||
*
|
||||
* @param[in] dev Device descriptor of the driver
|
||||
* @param[out] data Pointer where to store the raw data.
|
||||
*
|
||||
* @pre @p dev and @p data must not be NULL
|
||||
*/
|
||||
void max31855_read_raw(max31855_t *dev, uint32_t *data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MAX31855_H */
|
||||
/** @} */
|
1
drivers/max31855/Makefile
Normal file
1
drivers/max31855/Makefile
Normal file
@ -0,0 +1 @@
|
||||
include $(RIOTBASE)/Makefile.base
|
1
drivers/max31855/Makefile.dep
Normal file
1
drivers/max31855/Makefile.dep
Normal file
@ -0,0 +1 @@
|
||||
FEATURES_REQUIRED += periph_spi
|
2
drivers/max31855/Makefile.include
Normal file
2
drivers/max31855/Makefile.include
Normal file
@ -0,0 +1,2 @@
|
||||
USEMODULE_INCLUDES_max31855 := $(LAST_MAKEFILEDIR)/include
|
||||
USEMODULE_INCLUDES += $(USEMODULE_INCLUDES_max31855)
|
173
drivers/max31855/include/max31855_constants.h
Normal file
173
drivers/max31855/include/max31855_constants.h
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (C) 2024 HAW Hamburg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_max31855
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Internal addresses, registers and constants
|
||||
*
|
||||
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
|
||||
*/
|
||||
|
||||
#ifndef MAX31855_CONSTANTS_H
|
||||
#define MAX31855_CONSTANTS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Size of the data read from the MAX31855 in bytes.
|
||||
*/
|
||||
#define MAX31855_DATA_SIZE (4)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the thermocouple sign bit.
|
||||
*/
|
||||
#define MAX31855_THERMOCOUPLE_SIGN_SHIFT (31)
|
||||
|
||||
/**
|
||||
@brief Mask value for the thermocouple sign bit.
|
||||
*/
|
||||
#define MAX31855_THERMOCOUPLE_SIGN_MASK (1UL << MAX31855_THERMOCOUPLE_SIGN_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the thermocouple integer bits.
|
||||
*/
|
||||
#define MAX31855_THERMOCOUPLE_INTEGER_SHIFT (20)
|
||||
|
||||
/**
|
||||
* @brief Mask value for the thermocouple integer bits.
|
||||
*/
|
||||
#define MAX31855_THERMOCOUPLE_INTEGER_MASK (0x7FFUL << MAX31855_THERMOCOUPLE_INTEGER_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the thermocouple fractional half degree bit.
|
||||
*/
|
||||
#define MAX31855_THERMOCOUPLE_FRACTIONAL_HALF_SHIFT (19)
|
||||
|
||||
/**
|
||||
* @brief Mask value for the thermocouple fractional half degree bit.
|
||||
*/
|
||||
#define MAX31855_THERMOCOUPLE_FRACTIONAL_HALF_MASK (1UL << MAX31855_THERMOCOUPLE_FRACTIONAL_HALF_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the thermocouple fractional quarter degree bit.
|
||||
*/
|
||||
#define MAX31855_THERMOCOUPLE_FRACTIONAL_QUARTER_SHIFT (18)
|
||||
|
||||
/**
|
||||
* @brief Mask value for the thermocouple fractional quarter degree bit.
|
||||
*/
|
||||
#define MAX31855_THERMOCOUPLE_FRACTIONAL_QUARTER_MASK (1UL << MAX31855_THERMOCOUPLE_FRACTIONAL_QUARTER_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the internal sign bit.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_SIGN_SHIFT (15)
|
||||
|
||||
/**
|
||||
@brief Mask value for the internal sign bit.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_SIGN_MASK (1UL << MAX31855_INTERNAL_SIGN_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the internal integer bits.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_INTEGER_SHIFT (8)
|
||||
|
||||
/**
|
||||
* @brief Mask value for the internal integer bits.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_INTEGER_MASK (0x7FUL << MAX31855_INTERNAL_INTEGER_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the internal fractional half degree bit.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_FRACTIONAL_HALF_SHIFT (7)
|
||||
|
||||
/**
|
||||
* @brief Mask value for the internal fractional half degree bit.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_FRACTIONAL_HALF_MASK (1UL << MAX31855_INTERNAL_FRACTIONAL_HALF_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the internal fractional quarter degree bit.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_FRACTIONAL_QUARTER_SHIFT (6)
|
||||
|
||||
/**
|
||||
* @brief Mask value for the internal fractional quarter degree bit.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_FRACTIONAL_QUARTER_MASK (1UL << MAX31855_INTERNAL_FRACTIONAL_QUARTER_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the internal fractional eighth degree bit.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_FRACTIONAL_EIGHTH_SHIFT (5)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the internal fractional eighth degree bit.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_FRACTIONAL_EIGHTH_MASK (1UL << MAX31855_INTERNAL_FRACTIONAL_EIGHTH_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the internal fractional sixteenth degree bit.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_FRACTIONAL_SIXTEENTH_SHIFT (4)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the internal fractional sixteenth degree bit.
|
||||
*/
|
||||
#define MAX31855_INTERNAL_FRACTIONAL_SIXTEENTH_MASK (1UL << MAX31855_INTERNAL_FRACTIONAL_SIXTEENTH_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the fault bit indicating a VCC short.
|
||||
*/
|
||||
#define MAX31855_FAULT_VCC_SHORT_SHIFT (2)
|
||||
|
||||
/**
|
||||
* @brief Mask value for the fault bit indicating a VCC short.
|
||||
*/
|
||||
#define MAX31855_FAULT_VCC_SHORT_MASK (1UL << MAX31855_FAULT_VCC_SHORT_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the fault bit indicating a GND short.
|
||||
*/
|
||||
#define MAX31855_FAULT_GND_SHORT_SHIFT (1)
|
||||
|
||||
/**
|
||||
* @brief Mask value for the fault bit indicating a GND short.
|
||||
*/
|
||||
#define MAX31855_FAULT_GND_SHORT_MASK (1UL << MAX31855_FAULT_GND_SHORT_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Shift value for the fault bit indicating an open circuit.
|
||||
*/
|
||||
#define MAX31855_FAULT_OPEN_CIRCUIT_SHIFT (0)
|
||||
|
||||
/**
|
||||
* @brief Mask value for the fault bit indicating an open circuit.
|
||||
*/
|
||||
#define MAX31855_FAULT_OPEN_CIRCUIT_MASK (1UL << MAX31855_FAULT_OPEN_CIRCUIT_SHIFT)
|
||||
|
||||
/**
|
||||
* @brief Mask value for the fault bits.
|
||||
*/
|
||||
#define MAX31855_FAULT_MASK (MAX31855_FAULT_VCC_SHORT_MASK | \
|
||||
MAX31855_FAULT_GND_SHORT_MASK | \
|
||||
MAX31855_FAULT_OPEN_CIRCUIT_MASK)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MAX31855_CONSTANTS_H */
|
||||
/** @} */
|
86
drivers/max31855/include/max31855_params.h
Normal file
86
drivers/max31855/include/max31855_params.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (C) 2024 HAW Hamburg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_max31855
|
||||
*
|
||||
* @{
|
||||
* @file
|
||||
* @brief Default configuration for the MAX31855 driver
|
||||
*
|
||||
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
|
||||
*/
|
||||
|
||||
#ifndef MAX31855_PARAMS_H
|
||||
#define MAX31855_PARAMS_H
|
||||
|
||||
#include "board.h"
|
||||
#include "saul_reg.h"
|
||||
|
||||
#include "max31855.h"
|
||||
#include "max31855_constants.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @name Default configuration for the MAX31855 driver
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Default SPI bus for the MAX31855 driver
|
||||
*/
|
||||
#ifndef MAX31855_PARAM_PARAM_SPI
|
||||
#define MAX31855_PARAM_PARAM_SPI (SPI_DEV(0))
|
||||
#endif
|
||||
/**
|
||||
* @brief Default CS pin for the MAX31855 driver
|
||||
*/
|
||||
#ifndef MAX31855_PARAM_PARAM_CS_PIN
|
||||
#define MAX31855_PARAM_PARAM_CS_PIN (GPIO_PIN(0, 4))
|
||||
#endif
|
||||
/**
|
||||
* @brief Default parameters for the MAX31855 driver
|
||||
*/
|
||||
#ifndef MAX31855_PARAMS
|
||||
#define MAX31855_PARAMS { \
|
||||
.spi = MAX31855_PARAM_PARAM_SPI, \
|
||||
.cs_pin = MAX31855_PARAM_PARAM_CS_PIN, \
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @brief Default SAUL info for the MAX31855 driver
|
||||
*/
|
||||
#ifndef MAX31855_SAULINFO
|
||||
#define MAX31855_SAULINFO { .name = "max31855_thermo" },{ .name = "max31855_internal" }
|
||||
#endif
|
||||
/**@}*/
|
||||
|
||||
/**
|
||||
* @brief Configuration structs for the MAX31855 driver
|
||||
*/
|
||||
static const max31855_params_t max31855_params[] =
|
||||
{
|
||||
MAX31855_PARAMS
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Allocate and configure entries to the SAUL registry
|
||||
*/
|
||||
static const saul_reg_info_t max31855_saul_info[] =
|
||||
{
|
||||
MAX31855_SAULINFO
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MAX31855_PARAMS_H */
|
||||
/** @} */
|
156
drivers/max31855/max31855.c
Normal file
156
drivers/max31855/max31855.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (C) 2024 HAW Hamburg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_max31855
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Device driver implementation for the drivers_sensors
|
||||
*
|
||||
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "byteorder.h"
|
||||
#include "log.h"
|
||||
|
||||
#include "max31855.h"
|
||||
#include "max31855_constants.h"
|
||||
#include "max31855_params.h"
|
||||
|
||||
|
||||
void _raw_data_to_thermocouple_temperature(uint32_t raw_data, int32_t *temperature)
|
||||
{
|
||||
assert(temperature);
|
||||
|
||||
int32_t is_negative = raw_data & MAX31855_THERMOCOUPLE_SIGN_MASK;
|
||||
|
||||
if (is_negative) {
|
||||
raw_data = ~raw_data + 1;
|
||||
}
|
||||
|
||||
*temperature = (raw_data & MAX31855_THERMOCOUPLE_INTEGER_MASK) >>
|
||||
MAX31855_THERMOCOUPLE_INTEGER_SHIFT;
|
||||
|
||||
/* convert to centi degC */
|
||||
*temperature = *temperature * 100;
|
||||
|
||||
/* add fractional parts */
|
||||
*temperature += (raw_data & MAX31855_THERMOCOUPLE_FRACTIONAL_HALF_MASK) ? 50 : 0;
|
||||
*temperature += (raw_data & MAX31855_THERMOCOUPLE_FRACTIONAL_QUARTER_MASK) ? 25 : 0;
|
||||
|
||||
if (is_negative) {
|
||||
*temperature *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
void _raw_data_to_internal_temperature(uint32_t raw_data, int32_t *temperature)
|
||||
{
|
||||
assert(temperature);
|
||||
|
||||
int32_t is_negative = raw_data & MAX31855_INTERNAL_SIGN_MASK;
|
||||
|
||||
if (is_negative) {
|
||||
raw_data = ~raw_data + 1;
|
||||
}
|
||||
|
||||
*temperature = (raw_data & MAX31855_INTERNAL_INTEGER_MASK) >> MAX31855_INTERNAL_INTEGER_SHIFT;
|
||||
|
||||
/* convert to centi degC */
|
||||
*temperature = *temperature * 100;
|
||||
|
||||
/* add fractional parts */
|
||||
*temperature += (raw_data & MAX31855_INTERNAL_FRACTIONAL_HALF_MASK) ? 50 : 0;
|
||||
*temperature += (raw_data & MAX31855_INTERNAL_FRACTIONAL_QUARTER_MASK) ? 25 : 0;
|
||||
*temperature += (raw_data & MAX31855_INTERNAL_FRACTIONAL_EIGHTH_MASK) ? 12 : 0;
|
||||
*temperature += (raw_data & MAX31855_INTERNAL_FRACTIONAL_SIXTEENTH_MASK) ? 6 : 0;
|
||||
|
||||
if (is_negative) {
|
||||
*temperature *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
void _raw_data_to_fault(uint32_t raw_data, max31855_fault_t *fault)
|
||||
{
|
||||
assert(fault);
|
||||
|
||||
switch (raw_data & MAX31855_FAULT_MASK) {
|
||||
case MAX31855_FAULT_VCC_SHORT_MASK:
|
||||
*fault = MAX31855_FAULT_VCC_SHORT;
|
||||
break;
|
||||
case MAX31855_FAULT_GND_SHORT_MASK:
|
||||
*fault = MAX31855_FAULT_GND_SHORT;
|
||||
break;
|
||||
case MAX31855_FAULT_OPEN_CIRCUIT_MASK:
|
||||
*fault = MAX31855_FAULT_OPEN_CIRCUIT;
|
||||
break;
|
||||
default:
|
||||
*fault = MAX31855_FAULT_NO_FAULT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int max31855_init(max31855_t *dev, const max31855_params_t *params)
|
||||
{
|
||||
assert(dev);
|
||||
assert(params);
|
||||
dev->params = params;
|
||||
|
||||
int ret = spi_init_cs(dev->params->spi, dev->params->cs_pin);
|
||||
|
||||
if (ret < 0) {
|
||||
LOG_ERROR("Failed to initialize MAX31855\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void max31855_read_raw(max31855_t *dev, uint32_t *data)
|
||||
{
|
||||
assert(dev);
|
||||
assert(data);
|
||||
|
||||
uint8_t buffer[MAX31855_DATA_SIZE] = { 0 };
|
||||
spi_acquire(dev->params->spi, dev->params->cs_pin, SPI_MODE_0, SPI_CLK_5MHZ);
|
||||
spi_transfer_bytes(dev->params->spi, dev->params->cs_pin, false, NULL, buffer, sizeof(buffer));
|
||||
spi_release(dev->params->spi);
|
||||
|
||||
*data = byteorder_bebuftohl(buffer);
|
||||
}
|
||||
|
||||
void max31855_raw_to_data(uint32_t raw_data, max31855_data_t *data)
|
||||
{
|
||||
assert(data);
|
||||
|
||||
_raw_data_to_thermocouple_temperature(raw_data, &data->thermocouple_temperature);
|
||||
_raw_data_to_internal_temperature(raw_data, &data->internal_temperature);
|
||||
_raw_data_to_fault(raw_data, &data->fault);
|
||||
}
|
||||
|
||||
int max31855_read(max31855_t *dev, max31855_data_t *data)
|
||||
{
|
||||
assert(dev && data);
|
||||
|
||||
uint32_t raw_data;
|
||||
max31855_read_raw(dev, &raw_data);
|
||||
max31855_raw_to_data(raw_data, data);
|
||||
|
||||
if (data->fault != MAX31855_FAULT_NO_FAULT) {
|
||||
LOG_ERROR("MAX31855 fault: %d\n", data->fault);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
69
drivers/max31855/max31855_saul.c
Normal file
69
drivers/max31855/max31855_saul.c
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2024 HAW Hamburg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup drivers_max31855
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief SAUL adaption for MAX31855 devices
|
||||
*
|
||||
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "saul.h"
|
||||
#include "phydat.h"
|
||||
#include "max31855.h"
|
||||
|
||||
static int read_temp(const void *dev, phydat_t *res, bool thermocouple)
|
||||
{
|
||||
max31855_data_t data;
|
||||
max31855_read((max31855_t *)dev, &data);
|
||||
|
||||
if (data.fault != MAX31855_FAULT_NO_FAULT) {
|
||||
return -ECANCELED;
|
||||
}
|
||||
|
||||
res->unit = UNIT_TEMP_C;
|
||||
res->scale = -2;
|
||||
|
||||
if (thermocouple) {
|
||||
phydat_fit(res, &data.thermocouple_temperature, 1);
|
||||
}
|
||||
else {
|
||||
phydat_fit(res, &data.internal_temperature, 1);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int read_thermo_temp(const void *dev, phydat_t *res)
|
||||
{
|
||||
return read_temp(dev, res, true);
|
||||
}
|
||||
|
||||
static int read_internal_temp(const void *dev, phydat_t *res)
|
||||
{
|
||||
return read_temp(dev, res, false);
|
||||
}
|
||||
|
||||
const saul_driver_t max31855_thermo_temp_saul_driver = {
|
||||
.read = read_thermo_temp,
|
||||
.write = saul_write_notsup,
|
||||
.type = SAUL_SENSE_TEMP
|
||||
};
|
||||
|
||||
const saul_driver_t max31855_internal_temp_saul_driver = {
|
||||
.read = read_internal_temp,
|
||||
.write = saul_write_notsup,
|
||||
.type = SAUL_SENSE_TEMP
|
||||
};
|
80
drivers/saul/init_devs/auto_init_max31855.c
Normal file
80
drivers/saul/init_devs/auto_init_max31855.c
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2024 HAW Hamburg
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
* directory for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* @ingroup sys_auto_init_saul
|
||||
* @{
|
||||
*
|
||||
* @file
|
||||
* @brief Auto initialization for MAX31855 thermocouple-to-digital converters
|
||||
*
|
||||
* @author Leandro Lanzieri <leandro.lanzieri@haw-hamburg.de>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
|
||||
#include "assert.h"
|
||||
#include "log.h"
|
||||
#include "saul_reg.h"
|
||||
#include "max31855_params.h"
|
||||
#include "max31855.h"
|
||||
|
||||
/**
|
||||
* @brief Define the number of configured devices
|
||||
*/
|
||||
#define MAX31855_NUM ARRAY_SIZE(max31855_params)
|
||||
|
||||
/**
|
||||
* @brief Allocate memory for the device descriptors
|
||||
*/
|
||||
static max31855_t max31855_devs[MAX31855_NUM];
|
||||
|
||||
/**
|
||||
* @brief Memory for the SAUL registry entries
|
||||
*/
|
||||
static saul_reg_t saul_entries[MAX31855_NUM * 2];
|
||||
|
||||
/**
|
||||
* @brief Define the number of saul info
|
||||
*/
|
||||
#define MAX31855_INFO_NUM ARRAY_SIZE(max31855_saul_info)
|
||||
|
||||
/**
|
||||
* @name Import SAUL endpoints
|
||||
* @{
|
||||
*/
|
||||
extern const saul_driver_t max31855_thermo_temp_saul_driver;
|
||||
extern const saul_driver_t max31855_internal_temp_saul_driver;
|
||||
/** @} */
|
||||
|
||||
void auto_init_max31855(void)
|
||||
{
|
||||
/* each device has thermocouple and internal temperature, needs 2 infos */
|
||||
assert(MAX31855_INFO_NUM == 2 * MAX31855_NUM);
|
||||
|
||||
for (unsigned int i = 0; i < MAX31855_NUM; i++) {
|
||||
LOG_DEBUG("[auto_init_saul] initializing MAX31855 #%u\n", i);
|
||||
|
||||
if (max31855_init(&max31855_devs[i], &max31855_params[i]) != 0) {
|
||||
LOG_ERROR("[auto_init_saul] error initializing MAX31855 #%u\n", i);
|
||||
continue;
|
||||
}
|
||||
|
||||
saul_entries[(i * 2)].dev = &(max31855_devs[i]);
|
||||
saul_entries[(i * 2)].name = max31855_saul_info[(i * 2)].name;
|
||||
saul_entries[(i * 2)].driver = &max31855_thermo_temp_saul_driver;
|
||||
|
||||
saul_entries[(i * 2) + 1].dev = &(max31855_devs[i]);
|
||||
saul_entries[(i * 2) + 1].name = max31855_saul_info[(i * 2) + 1].name;
|
||||
saul_entries[(i * 2) + 1].driver = &max31855_internal_temp_saul_driver;
|
||||
|
||||
saul_reg_add(&(saul_entries[(i * 2)]));
|
||||
saul_reg_add(&(saul_entries[(i * 2) + 1]));
|
||||
}
|
||||
}
|
@ -207,6 +207,10 @@ void saul_init_devs(void)
|
||||
extern void auto_init_mag3110(void);
|
||||
auto_init_mag3110();
|
||||
}
|
||||
if (IS_USED(MODULE_MAX31855)) {
|
||||
extern void auto_init_max31855(void);
|
||||
auto_init_max31855();
|
||||
}
|
||||
if (IS_USED(MODULE_MCP47XX)) {
|
||||
extern void auto_init_mcp47xx(void);
|
||||
auto_init_mcp47xx();
|
||||
|
Loading…
Reference in New Issue
Block a user