-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[P177] Add plugin Environment - XDB401 I2C Pressure
- Loading branch information
1 parent
6260306
commit 398ed46
Showing
5 changed files
with
303 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,128 @@ | ||
#include "_Plugin_Helper.h" | ||
#ifdef USES_P177 | ||
|
||
// ####################################################################################################### | ||
// ################################ Plugin 177 XDB401 I2C Pressure Sensor ################################ | ||
// ####################################################################################################### | ||
|
||
/** Changelog: | ||
* 2025-02-22 tonhuisman: Initial plugin development, direct I2C access, | ||
* based on this documentation: https://www.letscontrolit.com/forum/viewtopic.php?t=10568#p71993 (attachment) | ||
*/ | ||
|
||
# define PLUGIN_177 | ||
# define PLUGIN_ID_177 177 | ||
# define PLUGIN_NAME_177 "Environment - XDB401 I2C Pressure" | ||
# define PLUGIN_VALUENAME1_177 "Pressure" | ||
# define PLUGIN_VALUENAME2_177 "Temperature" | ||
|
||
# include "./src/PluginStructs/P177_data_struct.h" | ||
|
||
boolean Plugin_177(uint8_t function, struct EventStruct *event, String& string) | ||
{ | ||
boolean success = false; | ||
|
||
switch (function) | ||
{ | ||
case PLUGIN_DEVICE_ADD: | ||
{ | ||
auto& dev = Device[++deviceCount]; | ||
dev.Number = PLUGIN_ID_177; | ||
dev.Type = DEVICE_TYPE_I2C; | ||
dev.VType = Sensor_VType::SENSOR_TYPE_DUAL; | ||
dev.FormulaOption = true; | ||
dev.ValueCount = 2; | ||
dev.SendDataOption = true; | ||
dev.TimerOption = true; | ||
dev.TimerOptional = true; | ||
dev.PluginStats = true; | ||
break; | ||
} | ||
|
||
case PLUGIN_GET_DEVICENAME: | ||
{ | ||
string = F(PLUGIN_NAME_177); | ||
break; | ||
} | ||
|
||
case PLUGIN_GET_DEVICEVALUENAMES: | ||
{ | ||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[0], PSTR(PLUGIN_VALUENAME1_177)); | ||
strcpy_P(ExtraTaskSettings.TaskDeviceValueNames[1], PSTR(PLUGIN_VALUENAME2_177)); | ||
break; | ||
} | ||
|
||
case PLUGIN_I2C_HAS_ADDRESS: | ||
{ | ||
success = P177_I2C_ADDR == event->Par1; | ||
break; | ||
} | ||
|
||
# if FEATURE_I2C_GET_ADDRESS | ||
case PLUGIN_I2C_GET_ADDRESS: | ||
{ | ||
event->Par1 = P177_I2C_ADDR; | ||
success = true; | ||
break; | ||
} | ||
# endif // if FEATURE_I2C_GET_ADDRESS | ||
|
||
case PLUGIN_SET_DEFAULTS: | ||
{ | ||
P177_PRESSURE_SCALE_FACTOR = 1; // Default to 1 | ||
break; | ||
} | ||
|
||
case PLUGIN_WEBFORM_LOAD: | ||
{ | ||
addFormNumericBox(F("Pressure scaling factor"), F("scale"), P177_PRESSURE_SCALE_FACTOR, 1); | ||
|
||
addFormNumericBox(F("Temperature offset"), F("tempoffset"), P177_TEMPERATURE_OFFSET); | ||
addUnit(F("x 0.1C")); | ||
addFormNote(F("Offset in units of 0.1 degree Celsius")); | ||
|
||
success = true; | ||
break; | ||
} | ||
|
||
case PLUGIN_WEBFORM_SAVE: | ||
{ | ||
P177_PRESSURE_SCALE_FACTOR = getFormItemInt(F("scale"), 1000); | ||
P177_TEMPERATURE_OFFSET = getFormItemInt(F("tempoffset"), 0); | ||
|
||
success = true; | ||
break; | ||
} | ||
|
||
case PLUGIN_INIT: | ||
{ | ||
success = initPluginTaskData(event->TaskIndex, new (std::nothrow) P177_data_struct()); | ||
break; | ||
} | ||
|
||
case PLUGIN_READ: | ||
{ | ||
P177_data_struct *P177_data = static_cast<P177_data_struct *>(getPluginTaskData(event->TaskIndex)); | ||
|
||
if (nullptr != P177_data) { | ||
success = P177_data->plugin_read(event); | ||
} | ||
|
||
break; | ||
} | ||
|
||
case PLUGIN_TEN_PER_SECOND: | ||
{ | ||
P177_data_struct *P177_data = static_cast<P177_data_struct *>(getPluginTaskData(event->TaskIndex)); | ||
|
||
if (nullptr != P177_data) { | ||
success = P177_data->plugin_ten_per_second(event); | ||
} | ||
|
||
break; | ||
} | ||
} | ||
return success; | ||
} | ||
|
||
#endif // ifdef USES_P177 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
#include "../PluginStructs/P177_data_struct.h" | ||
|
||
#ifdef USES_P177 | ||
|
||
|
||
P177_data_struct::~P177_data_struct() {} | ||
|
||
bool P177_data_struct::plugin_ten_per_second(struct EventStruct *event) { | ||
bool is_ok; | ||
uint8_t byteData; | ||
|
||
if (P177_SensorMode_e::IdleMode == _sensorMode) { | ||
_cycles--; | ||
|
||
if (_cycles) { // Skip until counted down to 0 | ||
return false; | ||
} | ||
byteData = I2C_read8_reg(P177_I2C_ADDR, P177_COMMAND_REG, &is_ok); | ||
|
||
if (is_ok && (0 == bitRead(byteData, 3))) { // Not currently reading | ||
I2C_write8_reg(P177_I2C_ADDR, P177_COMMAND_REG, P177_START_READ); | ||
_sensorMode = P177_SensorMode_e::SensingMode; | ||
_cycles = P177_SKIP_CYCLES; // Restart timer after a read is started | ||
} | ||
return false; | ||
} | ||
|
||
if (P177_SensorMode_e::SensingMode == _sensorMode) { | ||
byteData = I2C_read8_reg(P177_I2C_ADDR, P177_COMMAND_REG, &is_ok); | ||
|
||
if (!is_ok || (1 == bitRead(byteData, 3))) { // Currently reading | ||
return false; | ||
} | ||
_sensorMode = P177_SensorMode_e::ReportingMode; | ||
} | ||
|
||
uint32_t prData; | ||
uint16_t tmData; | ||
|
||
# if P177_LOG | ||
String log = F("P177 : RAW data: "); | ||
# endif // if P177_LOG | ||
size_t i = 0; | ||
|
||
for (; i < 3; ++i) { // first 3 bytes pressure | ||
prData << 8; | ||
byteData = I2C_read8_reg(P177_I2C_ADDR, P177_DATA_REG_1 + i); | ||
prData |= byteData; | ||
# if P177_LOG | ||
log += strformat(F("0x%02X "), byteData); | ||
# endif // if P177_LOG | ||
} | ||
# if P177_LOG | ||
log += strformat(F("prData: 0x%06X, "), prData); | ||
# endif // if P177_LOG | ||
|
||
for (; i < P177_DATA_BYTES; ++i) { // 2 more bytes temperature | ||
tmData << 8; | ||
byteData = I2C_read8_reg(P177_I2C_ADDR, P177_DATA_REG_1 + i); | ||
tmData |= byteData; | ||
# if P177_LOG | ||
log += strformat(F("0x%02X "), byteData); | ||
# endif // if P177_LOG | ||
} | ||
|
||
# if P177_LOG | ||
log += strformat(F(" tmData: 0x%04X"), tmData); | ||
addLog(LOG_LEVEL_INFO, log); | ||
# endif // if P177_LOG | ||
|
||
_sensorMode = P177_SensorMode_e::IdleMode; // Start a new cycle | ||
|
||
if ((prData == _rawPressure) && (tmData == _rawTemperature)) { | ||
return false; | ||
} | ||
_rawPressure = prData; | ||
_rawTemperature = tmData; | ||
_updated = true; | ||
return true; | ||
} | ||
|
||
bool P177_data_struct::plugin_read(struct EventStruct *event) { | ||
if (!_updated) { | ||
// Needed to get the 1st value, or can get the latest value when sampled too frequently. | ||
plugin_ten_per_second(event); | ||
} | ||
|
||
if (_updated) { | ||
float _pressure = _rawPressure; | ||
|
||
if (_rawPressure & 0x80000) { | ||
_pressure = -1 * (_rawPressure & 0x3FFFF); | ||
} | ||
_pressure /= (0x80000 / P177_PRESSURE_SCALE_FACTOR); | ||
|
||
float _temperature = _rawTemperature; | ||
|
||
if (_rawTemperature & 0x8000) { | ||
_temperature = -1 * (_rawTemperature & 0x3FFF); | ||
} | ||
_temperature /= 256; | ||
|
||
if (P177_TEMPERATURE_OFFSET != 0) { | ||
_temperature += (P177_TEMPERATURE_OFFSET / 10); // In 0.1 degree steps | ||
} | ||
|
||
UserVar.setFloat(event->TaskIndex, 0, _pressure); | ||
UserVar.setFloat(event->TaskIndex, 1, _temperature); | ||
_updated = false; | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
#endif // ifdef USES_P177 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#ifndef PLUGINSTRUCTS_P177_DATA_STRUCT_H | ||
#define PLUGINSTRUCTS_P177_DATA_STRUCT_H | ||
|
||
#include "../../_Plugin_Helper.h" | ||
|
||
#ifdef USES_P177 | ||
# include "../Helpers/I2C_access.h" | ||
|
||
# define P177_LOG 1 // Set to 1 to enable raw data logging at INFO level | ||
|
||
# define P177_I2C_ADDR 0x7F // Fixed address | ||
|
||
# define P177_COMMAND_REG 0x30 | ||
# define P177_START_READ 0x0A | ||
# define P177_DATA_REG_1 0x06 | ||
# define P177_DATA_BYTES 5 | ||
|
||
# define P177_SKIP_CYCLES 5 // Skip this number of 10/sec cycles when in IdleMode | ||
|
||
# define P177_PRESSURE_SCALE_FACTOR PCONFIG_LONG(0) // Pressure scaling factor | ||
# define P177_TEMPERATURE_OFFSET PCONFIG(0) // Temperature compensation in 0.1 degree steps | ||
|
||
enum class P177_SensorMode_e : uint8_t { | ||
IdleMode = 0u, | ||
SensingMode = 1u, | ||
ReportingMode = 2u, | ||
}; | ||
|
||
/******************************************* | ||
* P177 Plugin taskdata struct | ||
******************************************/ | ||
struct P177_data_struct : public PluginTaskData_base { | ||
public: | ||
|
||
P177_data_struct() = default; | ||
~P177_data_struct(); | ||
|
||
bool plugin_ten_per_second(struct EventStruct *event); | ||
|
||
bool plugin_read(struct EventStruct *event); | ||
|
||
uint32_t _rawPressure{}; | ||
uint16_t _rawTemperature{}; | ||
P177_SensorMode_e _sensorMode = P177_SensorMode_e::IdleMode; | ||
uint8_t _cycles = 1; // Start cycle immediately | ||
bool _updated = false; | ||
}; | ||
|
||
#endif // ifdef USES_P177 | ||
#endif // ifndef PLUGINSTRUCTS_P177_DATA_STRUCT_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters