Files
OpenBK7231T_App/src/driver/drv_mcp9808.c
MaxineMuster ff0941016b Pinalias as arg (#1948)
* Add int HAL_PIN_Find(const char *name) for all platforms
add simple selftest (and added some alias strings to windows pins)

* fix ESP

* fix second occurence of isdigit for ESP by casting to unsigned char

* Moved code for HAL_PIN_Find to "src/hal/generic/hal_pins_generic.c" and removed it from the (few) platforms aleady implemented it.
Added some "complex" pin alias descriptions for windows to test

made function case insensitive - introducing "char *wal_stristr(const char *haystack, const char *needle);" as a case insensitiver version of "strstr" in new_common.c

* Try fix windows (by including src\hal\generic\hal_pins_generic.c)
Enable ENABLE_TEST_COMMANDS for all platforms to do some testing

* comment out weak functions for Windows

* including "../hal/hal_pins.h" in cmd_test.c to clear warning about HAL_PIN_Find()

* comment out StackOverflow test for ESP - it won't compile

* fix

* Moved code from hal_pins_generic.c to new_pins.c
reverted usage of hal_pins_generic.c in Windows build
changed Tokenizer_GetPin()

* Changed driver commands to use Tokenizer_GetPin() instead of Tokenizer_GetArgIntegerDefault() to get drivers pins

* Fix typo in drv_pinMutex.c

* Fix cmd_test.c and ds1820_full.c
Added debug output to Tokenizer_GetPin()

* Removed tesing and debugging code

* Also allow pin alias in SetPinRole command

* Fix typo
2026-01-20 14:38:40 +01:00

300 lines
8.6 KiB
C

// based on MCP9808_RT by RobTillaart
// See also: https://www.elektroda.pl/rtvforum/topic3988466.html
#include "../new_common.h"
#include "../new_pins.h"
#include "../new_cfg.h"
// Commands register, execution API and cmd tokenizer
#include "../cmnds/cmd_public.h"
#include "../mqtt/new_mqtt.h"
#include "../logging/logging.h"
#include "drv_local.h"
#include "drv_uart.h"
#include "../httpserver/new_http.h"
#include "../hal/hal_pins.h"
#define MCP9808_RFU 0x00
#define MCP9808_CONFIG 0x01
#define MCP9808_TUPPER 0x02
#define MCP9808_TLOWER 0x03
#define MCP9808_TCRIT 0x04
#define MCP9808_TA 0x05
#define MCP9808_MID 0x06
#define MCP9808_DID 0x07
#define MCP9808_RES 0x08
static int g_targetChannel = -1;
static softI2C_t g_softI2C;
static byte g_addr = 30;
static float g_temp = 0.0f;
static int g_mcp_secondsBetweenMeasurements = 10;
static int g_mcp_secondsUntilNextMeasurement = 0;
static float g_mcp_userCalibrationDelta = 0.0f;
void MCP9808_WriteReg16(uint8_t reg, uint16_t value)
{
if (reg > MCP9808_RES)
return; // see p.16
Soft_I2C_Start(&g_softI2C, g_addr);
Soft_I2C_WriteByte(&g_softI2C, reg);
Soft_I2C_WriteByte(&g_softI2C, value >> 8);
Soft_I2C_WriteByte(&g_softI2C, value & 0xFF);
Soft_I2C_Stop(&g_softI2C);
}
uint16_t MCP9808_ReadReg16(uint8_t reg)
{
byte reply[2];
Soft_I2C_Start(&g_softI2C, g_addr);
Soft_I2C_WriteByte(&g_softI2C, reg);
Soft_I2C_Stop(&g_softI2C);
rtos_delay_milliseconds(20); //give the sensor time to do the conversion
Soft_I2C_Start(&g_softI2C, g_addr | 1);
Soft_I2C_ReadBytes(&g_softI2C, reply, 2);
Soft_I2C_Stop(&g_softI2C);
uint16_t val = reply[0] << 8;
val += reply[1];
return val;
}
float MCP9808_ReadFloat(uint8_t reg)
{
uint16_t val = MCP9808_ReadReg16(reg);
if (val & 0x1000) // negative value
{
return ((val & 0x0FFF) * 0.0625) - 256.0;
}
return (val & 0x0FFF) * 0.0625;
}
void MCP9808_WriteFloat(uint8_t reg, float f)
{
bool neg = (f < 0.0);
if (neg)
f = -f;
uint16_t val = ((uint16_t)(f * 4 + 0.5)) * 4;
if (neg)
val |= 0x1000;
MCP9808_WriteReg16(reg, val);
}
void MCP9808_SetConfigRegister(uint16_t configuration)
{
MCP9808_WriteReg16(MCP9808_CONFIG, configuration);
}
uint16_t MCP9808_GetConfigRegister()
{
return MCP9808_ReadReg16(MCP9808_CONFIG);
}
void MCP9808_SetTupper(float temperature)
{
MCP9808_WriteFloat(MCP9808_TUPPER, temperature);
}
float MCP9808_GetTupper()
{
return MCP9808_ReadFloat(MCP9808_TUPPER);
}
void MCP9808_SetTlower(float temperature)
{
MCP9808_WriteFloat(MCP9808_TLOWER, temperature);
}
float MCP9808_GetTlower()
{
return MCP9808_ReadFloat(MCP9808_TLOWER);
}
void MCP9808_SetTcritical(float temperature)
{
MCP9808_WriteFloat(MCP9808_TCRIT, temperature);
}
float MCP9808_GetTcritical()
{
return MCP9808_ReadFloat(MCP9808_TCRIT);
}
void MCP9808_Measure() {
g_temp = MCP9808_ReadFloat(MCP9808_TA) + g_mcp_userCalibrationDelta;
if (g_targetChannel >= 0) {
int type = CHANNEL_GetType(g_targetChannel);
if (type == ChType_Temperature_div10) {
CHANNEL_Set(g_targetChannel, g_temp * 10, 0);
}
else {
CHANNEL_Set(g_targetChannel, g_temp, 0);
}
}
}
commandResult_t MCP9808_Adr(const void* context, const char* cmd, const char* args, int cmdFlags) {
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
g_addr = Tokenizer_GetArgInteger(0);
return CMD_RES_OK;
}
commandResult_t MCP9808_Calibrate(const void* context, const char* cmd, const char* args, int cmdFlags) {
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
g_mcp_userCalibrationDelta = Tokenizer_GetArgFloat(0);
return CMD_RES_OK;
}
commandResult_t MCP9808_cycle(const void* context, const char* cmd, const char* args, int cmdFlags) {
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
g_mcp_secondsBetweenMeasurements = Tokenizer_GetArgInteger(0);
return CMD_RES_OK;
}
// MCP9808_AlertRange [MinT] [MaxT] [OptionalBActiveHigh]
// MCP9808_AlertRange 20 26 1
commandResult_t MCP9808_AlertRange(const void* context, const char* cmd, const char* args, int cmdFlags) {
float min, max;
int bActiveHigh;
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 2)) {
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
min = Tokenizer_GetArgFloat(0);
max = Tokenizer_GetArgFloat(1);
bActiveHigh = Tokenizer_GetArgIntegerDefault(2, 0);
MCP9808_SetTlower(min);
MCP9808_SetTupper(max);
MCP9808_SetTcritical(max);
// SET ALERT PARAMETERS
uint16_t cfg = MCP9808_GetConfigRegister();
cfg &= ~0x0001; // set comparator mode
if (bActiveHigh) {
cfg &= ~0x0002; // set polarity HIGH
}
else {
cfg |= 0x0002; // set polarity LOW
}
cfg &= ~0x0004; // use upper lower and critical
cfg |= 0x0008; // enable alert
MCP9808_SetConfigRegister(cfg);
return CMD_RES_OK;
}
// MCP9808_AlertMin [MinT] [OptionalBActiveHigh]
// MCP9808_AlertMin 20 1
commandResult_t MCP9808_AlertMin(const void* context, const char* cmd, const char* args, int cmdFlags) {
float min;
int bActiveHigh;
Tokenizer_TokenizeString(args, TOKENIZER_ALLOW_QUOTES | TOKENIZER_DONT_EXPAND);
if (Tokenizer_CheckArgsCountAndPrintWarning(cmd, 1)) {
return CMD_RES_NOT_ENOUGH_ARGUMENTS;
}
min = Tokenizer_GetArgFloat(0);
bActiveHigh = Tokenizer_GetArgIntegerDefault(1, 0);
MCP9808_SetTcritical(min);
// SET ALERT PARAMETERS
uint16_t cfg = MCP9808_GetConfigRegister();
cfg &= ~0x0001; // set comparator mode
if (bActiveHigh) {
cfg &= ~0x0002; // set polarity HIGH
}
else {
cfg |= 0x0002; // set polarity LOW
}
// TA > TCRIT only
cfg |= 0x0004; // use only critical
cfg |= 0x0008; // enable alert
MCP9808_SetConfigRegister(cfg);
return CMD_RES_OK;
}
// driver initialization
// startDriver MCP9808 [ClkPin] [DatPin] [OptionalTargetChannel]
// startDriver MCP9808 26 24
// startDriver MCP9808 26 24 1
// startDriver MCP9808 12 13 1
// Sample config for module from here: https://www.elektroda.pl/rtvforum/topic3988466.html
/*
startDriver MCP9808 7 8 1
MCP9808_Adr 0x30
MCP9808_Cycle 1
*/
void MCP9808_Init() {
//uint8_t buff[4];
// g_softI2C.pin_clk = Tokenizer_GetArgIntegerDefault(1, 26);
// g_softI2C.pin_data = Tokenizer_GetArgIntegerDefault(2, 24);
g_softI2C.pin_clk = Tokenizer_GetPin(1, 26);
g_softI2C.pin_data = Tokenizer_GetPin(2, 24);
g_targetChannel = Tokenizer_GetArgIntegerDefault(3,-1);
Soft_I2C_PreInit(&g_softI2C);
//cmddetail:{"name":"MCP9808_Adr","args":"[HexAdr]",
//cmddetail:"descr":"Sets the I2C address of MCP9808, like 0x30",
//cmddetail:"fn":"MCP9808_Adr","file":"driver/drv_mcp9808.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("MCP9808_Adr", MCP9808_Adr, NULL);
//cmddetail:{"name":"MCP9808_AlertRange","args":"[MinT] [MaxT] [OptionalBActiveHigh]",
//cmddetail:"descr":"Setup MCP9809 temperature alert for range mode",
//cmddetail:"fn":"MCP9808_AlertRange","file":"driver/drv_mcp9808.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("MCP9808_AlertRange", MCP9808_AlertRange, NULL);
//cmddetail:{"name":"MCP9808_AlertMin","args":"[MinT] [OptionalBActiveHigh]",
//cmddetail:"descr":"Setup MCP9809 temperature alert for min mode",
//cmddetail:"fn":"MCP9808_AlertMin","file":"driver/drv_mcp9808.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("MCP9808_AlertMin", MCP9808_AlertMin, NULL);
//cmddetail:{"name":"MCP9808_Calibrate","args":"[DeltaTemperature]",
//cmddetail:"descr":"",
//cmddetail:"fn":"MCP9808_Calibrate","file":"driver/drv_mcp9808.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("MCP9808_Calibrate", MCP9808_Calibrate, NULL);
//cmddetail:{"name":"MCP9808_Cycle","args":"[DelayInSeconds]",
//cmddetail:"descr":"Sets MCP9808 measurement interval",
//cmddetail:"fn":"MCP9808_cycle","file":"driver/drv_mcp9808.c","requires":"",
//cmddetail:"examples":""}
CMD_RegisterCommand("MCP9808_Cycle", MCP9808_cycle, NULL);
}
void MCP9808_OnEverySecond() {
if (g_mcp_secondsUntilNextMeasurement <= 0) {
MCP9808_Measure();
g_mcp_secondsUntilNextMeasurement = g_mcp_secondsBetweenMeasurements;
}
if (g_mcp_secondsUntilNextMeasurement > 0) {
g_mcp_secondsUntilNextMeasurement--;
}
}
void MCP9808_AppendInformationToHTTPIndexPage(http_request_t* request, int bPreState)
{
if (bPreState)
return;
hprintf255(request, "<h2>MCP9808 Temperature=%f</h2>", g_temp);
}