/**
* @file MAX31865_ATY.c
*
* @param Project DEVICE_GENERAL_ATY_LIB
*
* @author ATY
*
* @copyright
* - Copyright 2017 - 2026 MZ-ATY
* - This code follows:
* - MZ-ATY Various Contents Joint Statement -
*
* https://mengze.top/MZ-ATY_VCJS
* - CC 4.0 BY-NC-SA -
*
* https://creativecommons.org/licenses/by-nc-sa/4.0/
* - Your use will be deemed to have accepted the terms of this statement.
*
* @brief functions of MAX31865 platinum resistance temperature detector for C platform
*
* @version
* - 1_01_251216 > ATY
* -# Preliminary version, first Release
*
* @todo MAX31865_CONFIG_FAULTCTR and MAX31865_REG_H/LFAULT_M/LSB
*
* @note SPI_POLARITY_HIGH + SPI_PHASE_2EDGE = CPOL=1, CPHA=1 = SPI Mode 3
********************************************************************************
*/
#ifndef __MAX31865_ATY_C
#define __MAX31865_ATY_C
#include "MAX31865_ATY.h"
#define MAX31865_ATY_TAG "\r\n[MAX31865_ATY] "
/******************************* For user *************************************/
/******************************************************************************/
uint8_t wrData[2] = {0x00, 0x00};
/**
* @brief Initialize MAX31865 device
*
* @param dev Device structure pointer
* @return uint8_t Execution result
*/
uint8_t MAX31865_Init(struct MAX31865_ATY_Dev* dev){
__ATY_LOCK(dev);
if(dev->initFlag == 0){
// Set default parameters for PT100 sensor
if(dev->rtdNominal == 0)
dev->rtdNominal = 100.0;
if(dev->refResistor == 0)
dev->refResistor = 430.0;
// Configuration register settings
wrData[0] = MAX31865_REG_CONFIG | 0x80;
wrData[1] = 0;
if(dev->filter50Hz == 1){
wrData[1] |= MAX31865_CONFIG_FILT50HZ;
}
if(dev->rtdWires == 3){
wrData[1] |= MAX31865_CONFIG_3WIRE;
}
if(dev->autoConvert == 1){
wrData[1] |= MAX31865_CONFIG_MODEAUTO;
}
if(dev->bias == 1){
wrData[1] |= MAX31865_CONFIG_BIAS;
}
// Write to configuration register
dev->nssSet(__ATY_HL_L);
dev->spiProcess(wrData, 2, __ATY_RW_W);
dev->nssSet(__ATY_HL_H);
dev->initFlag = 1;
__ATY_UNLOCK(dev);
printf_ATY_D("%sInit config: 0x%02X",
MAX31865_ATY_TAG, wrData[1]);
MAX31865_ReadConfig(dev);
__ATY_LOCK(dev);
}
__ATY_UNLOCK(dev);
return 0;
}
/**
* @brief Read configuration register
*
* @param dev Device structure pointer
* @return uint8_t Configuration register value
*/
uint8_t MAX31865_ReadConfig(struct MAX31865_ATY_Dev* dev){
__ATY_LOCK(dev);
wrData[0] = MAX31865_REG_CONFIG;
dev->nssSet(__ATY_HL_L);
dev->spiProcess(wrData, 1, __ATY_RW_W);
dev->spiProcess(wrData, 2, __ATY_RW_R);
dev->nssSet(__ATY_HL_H);
printf_ATY_D("%sRead config: 0x%02X",
MAX31865_ATY_TAG, wrData[0]);
__ATY_UNLOCK(dev);
return wrData[0];
}
/**
* @brief Read raw RTD value
*
* @param dev Device structure pointer
* @param rtd Pointer to store RTD value
* @return uint8_t Execution result
*/
uint8_t MAX31865_ReadRTD(struct MAX31865_ATY_Dev* dev){
__ATY_LOCK(dev);
wrData[0] = MAX31865_REG_RTD_MSB;
wrData[1] = 0;
dev->nssSet(__ATY_HL_L);
dev->spiProcess(wrData, 1, __ATY_RW_W);
dev->spiProcess(wrData, 2, __ATY_RW_R);
dev->nssSet(__ATY_HL_H);
// remove last fault bit
dev->rtdValue = ((wrData[0] << 8) | wrData[1]) >> 1;
__ATY_UNLOCK(dev);
return 0;
}
/**
* @brief Read fault status
*
* @param dev Device structure pointer
* @return uint8_t Fault status register value
*/
uint8_t MAX31865_ReadFault(struct MAX31865_ATY_Dev* dev){
__ATY_LOCK(dev);
dev->faultStatus = 0;
wrData[0] = MAX31865_REG_FAULT_STATUS;
dev->nssSet(__ATY_HL_L);
dev->spiProcess(wrData, 1, __ATY_RW_W);
dev->spiProcess(wrData, 1, __ATY_RW_R);
dev->nssSet(__ATY_HL_H);
dev->faultStatus = wrData[0];
if(dev->faultStatus != 0){
printf_ATY_D("%sFault: 0x%02X", MAX31865_ATY_TAG, dev->faultStatus);
if(dev->faultStatus & MAX31865_FAULT_HIGH_THRESH){
printf_ATY_D(" HIGH_THRESHOLD");
}
if(dev->faultStatus & MAX31865_FAULT_LOW_THRESH){
printf_ATY_D(" LOW_THRESHOLD");
}
if(dev->faultStatus & MAX31865_FAULT_REFIN_LOW){
printf_ATY_D(" REFIN_LOW");
}
if(dev->faultStatus & MAX31865_FAULT_REFIN_HIGH){
printf_ATY_D(" REFIN_HIGH");
}
if(dev->faultStatus & MAX31865_FAULT_RTDIN_LOW){
printf_ATY_D(" RTDIN_LOW");
}
if(dev->faultStatus & MAX31865_FAULT_OVUV){
printf_ATY_D(" OVER_UNDER_VOLTAGE");
}
}
__ATY_UNLOCK(dev);
return wrData[0];
}
/**
* @brief Clear fault status
*
* @param dev Device structure pointer
* @return uint8_t Execution result
*/
uint8_t MAX31865_ClearFaults(struct MAX31865_ATY_Dev* dev){
__ATY_LOCK(dev);
dev->faultStatus = 0;
wrData[0] = MAX31865_REG_CONFIG;
// Read current configuration
dev->nssSet(__ATY_HL_L);
dev->spiProcess(wrData, 1, __ATY_RW_W);
dev->spiProcess(wrData, 1, __ATY_RW_R);
dev->nssSet(__ATY_HL_H);
// Set fault clear bit
wrData[1] = wrData[0];
wrData[1] |= MAX31865_CONFIG_FAULTSTAT;
// printf_ATY_D("\r\n0x%02X", wrData[0]);
// printf_ATY_D("\r\n0x%02X", wrData[1]);
wrData[0] = MAX31865_REG_CONFIG | 0x80;
// Write back to configuration register
dev->nssSet(__ATY_HL_L);
dev->spiProcess(wrData, 1, __ATY_RW_W);
dev->spiProcess(wrData + 1, 1, __ATY_RW_R);
dev->nssSet(__ATY_HL_H);
__ATY_UNLOCK(dev);
return 0;
}
/**
* @brief Trigger one-shot conversion
*
* @param dev Device structure pointer
* @return uint8_t Execution result
*/
uint8_t MAX31865_OneShot(struct MAX31865_ATY_Dev* dev){
__ATY_LOCK(dev);
wrData[0] = MAX31865_REG_CONFIG;
// Read current configuration
dev->nssSet(__ATY_HL_L);
dev->spiProcess(wrData, 1, __ATY_RW_W);
dev->spiProcess(wrData, 1, __ATY_RW_R);
dev->nssSet(__ATY_HL_H);
wrData[1] = wrData[0];
wrData[1] |= MAX31865_CONFIG_1SHOT;
wrData[0] = MAX31865_REG_CONFIG | 0x80;
// Write back to configuration register
dev->nssSet(__ATY_HL_L);
dev->spiProcess(wrData, 1, __ATY_RW_W);
dev->spiProcess(wrData + 1, 1, __ATY_RW_R);
dev->nssSet(__ATY_HL_H);
__ATY_UNLOCK(dev);
return 0;
}
/**
* @brief Calculate resistance from RTD value
*
* @param dev Device structure pointer
* @param rtd RTD value, if 0, use internal RTD value
* @return float Resistance
*/
float MAX31865_CalculateResistance(struct MAX31865_ATY_Dev* dev, uint16_t rtd){
if(rtd == 0)
return (float)dev->rtdValue * dev->refResistor / ((uint16_t)1 << 15);
return (float)rtd * dev->refResistor / ((uint16_t)1 << 15);
}
/**
* @brief Calculate temperature from RTD value
*
* @param dev Device structure pointer
* @param rtd RTD value, if 0, use internal RTD value
* @return float Temperature
*/
float MAX31865_CalculateTemperature(struct MAX31865_ATY_Dev* dev, uint16_t rtd){
return (MAX31865_CalculateResistance(dev, rtd) - dev->rtdNominal) / 0.385;
}
#endif /* __MAX31865_ATY_C */
/************************************ etc *************************************/
/* init */
// MAX31865 --------------------------------------------------------------------
// #include "MAX31865_ATY.h"
// void MAX31865_1_NSS_SET(uint8_t level){
// if(level == __ATY_HL_L)
// HAL_GPIO_WritePin(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin, GPIO_PIN_RESET);
// else if(level == __ATY_HL_H)
// HAL_GPIO_WritePin(SPI2_NSS_GPIO_Port, SPI2_NSS_Pin, GPIO_PIN_SET);
// }
// uint8_t MAX31865_1_SPI(uint8_t* data_t, uint16_t len, uint8_t rw){
// if(rw == __ATY_RW_R){
// return HAL_SPI_Receive(&hspi2, (uint8_t*)data_t, len, 1000);
// }
// else{
// return HAL_SPI_Transmit(&hspi2, (uint8_t*)data_t, len, 1000);
// }
// }
// struct MAX31865_ATY_Dev MAX31865_ATY_Dev_1 = {
// .nssSet = MAX31865_1_NSS_SET,
// .spiProcess = MAX31865_1_SPI,
// .rtdWires = 3,
// .filter50Hz = 1,
// .autoConvert = 1,
// .bias = 1,
// .faultControl = 0,
// .rtdNominal = 100.0,
// .refResistor = 424.0,
// .lock = __ATY_UNLOCKED
// };
/* use */
// uint8_t Max31865_errCount = 0;
// void MAX31865_Test(void){
// MAX31865_Init(&MAX31865_ATY_Dev_1);
// MAX31865_ReadRTD(&MAX31865_ATY_Dev_1);
// MAX31865_ReadFault(&MAX31865_ATY_Dev_1);
// // (9584640.0 / MAX31865_ATY_Dev_1.refResistor) -> 500C
// // (2015232.0 / MAX31865_ATY_Dev_1.refResistor) -> -100C
// if(MAX31865_ATY_Dev_1.faultStatus != 0
// || MAX31865_ATY_Dev_1.rtdValue == 32767
// || MAX31865_ATY_Dev_1.rtdValue == 0
// || MAX31865_ATY_Dev_1.rtdValue > (9584640.0 / MAX31865_ATY_Dev_1.refResistor)
// || MAX31865_ATY_Dev_1.rtdValue < (2015232.0 / MAX31865_ATY_Dev_1.refResistor)){
// Max31865_errCount++;
// // if cycle is long like 1s, this errCount can be lower
// if(Max31865_errCount > 6){
// Max31865_errCount = 0;
// MAX31865_ATY_Dev_1.initFlag = 0;
// // Notice: ClearFaults might make next rtd value wrong,
// // so wait a cycle to read value after clear fault
// if(MAX31865_ATY_Dev_1.faultStatus != 0) MAX31865_ClearFaults(&MAX31865_ATY_Dev_1);
// printf_ATY("\r\nRTD Value Abnormal - Reinitializing...");
// }
// }
// // else
// {
// printf_ATY("\r\nRTD: 0x%04X, Resistance: %.2f ohm, Temperature: %.2f C",
// MAX31865_ATY_Dev_1.rtdValue,
// MAX31865_CalculateResistance(&MAX31865_ATY_Dev_1, 0),
// MAX31865_CalculateTemperature(&MAX31865_ATY_Dev_1, 0));
// // MAX31865_ReadConfig(&MAX31865_ATY_Dev_1);
// }
// }
/******************************************************************************/
/******************************** End Of File *********************************/