Program Listing for File xensiv_pas_gas_ino.cpp
↰ Return to documentation for file (src/xensiv_pas_gas_ino.cpp)
#include "xensiv_pas_gas_ino.hpp"
#define GASINO_ASSERT_RET(x) \
if (x != XENSIV_PAS_GAS_OK) \
{ \
return x; \
}
#define PAS_GAS_SERIAL_PAL_INIT_EXTERNAL
XENSIV_PAS_GASIno::XENSIV_PAS_GASIno(GasType_t gasType, TwoWire *wire, uint8_t intPin)
: i2c(wire), uart(nullptr), intPin(intPin), gasType(gasType)
{
}
XENSIV_PAS_GASIno::XENSIV_PAS_GASIno(GasType_t gasType, HardwareSerial *serial, uint8_t intPin)
: i2c(nullptr), uart(serial), intPin(intPin), gasType(gasType)
{
}
XENSIV_PAS_GASIno::~XENSIV_PAS_GASIno() {}
Error_t XENSIV_PAS_GASIno::begin()
{
int32_t ret = XENSIV_PAS_GAS_OK;
xensiv_pas_gas_interface_t itf;
void *ctx;
if (nullptr != i2c)
{
#ifndef PAS_GAS_SERIAL_PAL_INIT_EXTERNAL
i2c->begin();
i2c->setClock(freqHz);
#endif
itf = XENSIV_PAS_GAS_INTERFACE_I2C;
ctx = i2c;
}
else if (nullptr != uart)
{
#ifndef PAS_GAS_SERIAL_PAL_INIT_EXTERNAL
uart->begin(baudrateBps);
#endif
itf = XENSIV_PAS_GAS_INTERFACE_UART;
ctx = uart;
}
else
{
return XENSIV_PAS_GAS_INVALID_SENSOR_INTERFACE;
}
switch (gasType)
{
case SENSOR_R290:
ret = xensiv_pas_gas_r290_init(&dev, itf, ctx);
break;
case SENSOR_CO2:
ret = xensiv_pas_gas_co2_init(&dev, itf, ctx);
break;
case SENSOR_A2L:
ret = xensiv_pas_gas_a2l_init(&dev, itf, ctx);
break;
default:
return XENSIV_PAS_GAS_INVALID_SENSOR_TYPE;
}
if (ret != XENSIV_PAS_GAS_OK)
return ret;
if (unusedPin != intPin)
{
pinMode(intPin, INPUT_PULLUP);
}
// Set sensor to idle mode
xensiv_pas_gas_measurement_config_t measConf;
ret = xensiv_pas_gas_get_measurement_config(&dev, &measConf);
if (ret != XENSIV_PAS_GAS_OK)
return ret;
measConf.b.op_mode = XENSIV_PAS_GAS_OP_MODE_IDLE;
ret = xensiv_pas_gas_set_measurement_config(&dev, measConf);
return ret;
}
Error_t XENSIV_PAS_GASIno::end()
{
if (nullptr != i2c)
{
#ifndef PAS_GAS_SERIAL_PAL_INIT_EXTERNAL
#if !defined(ARDUINO_ARCH_ESP32)
i2c->end();
#endif
#endif
}
else if (nullptr != uart)
{
#ifndef PAS_GAS_SERIAL_PAL_INIT_EXTERNAL
uart->end();
#endif
}
/* Deinitialize interrupt pin */
if (unusedPin != intPin)
{
detachInterrupt(digitalPinToInterrupt(intPin));
}
return XENSIV_PAS_GAS_OK;
}
Error_t XENSIV_PAS_GASIno::startMeasure(int16_t periodInSec, int16_t alarmTh, void (*cback)(void *),
bool earlyNotification)
{
xensiv_pas_gas_measurement_config_t measConf;
xensiv_pas_gas_interrupt_config_t intConf;
int32_t ret = XENSIV_PAS_GAS_OK;
/* Get meas configuration*/
ret = xensiv_pas_gas_get_measurement_config(&dev, &measConf);
GASINO_ASSERT_RET(ret);
measConf.b.op_mode = XENSIV_PAS_GAS_OP_MODE_IDLE;
ret = xensiv_pas_gas_set_measurement_config(&dev, measConf);
GASINO_ASSERT_RET(ret);
/* Get int configuration */
ret = xensiv_pas_gas_get_interrupt_config(&dev, &intConf);
GASINO_ASSERT_RET(ret);
/* Default configuration */
measConf.b.op_mode = XENSIV_PAS_GAS_OP_MODE_SINGLE;
intConf.b.int_func = XENSIV_PAS_GAS_INTERRUPT_FUNCTION_DRDY;
if (periodInSec > 0)
{
ret = xensiv_pas_gas_set_measurement_rate(&dev, periodInSec);
GASINO_ASSERT_RET(ret);
measConf.b.op_mode = XENSIV_PAS_GAS_OP_MODE_CONTINUOUS;
}
if (alarmTh > 0)
{
ret = xensiv_pas_gas_set_alarm_threshold(&dev, alarmTh);
GASINO_ASSERT_RET(ret);
intConf.b.alarm_typ = XENSIV_PAS_GAS_ALARM_TYPE_LOW_TO_HIGH;
intConf.b.int_func = XENSIV_PAS_GAS_INTERRUPT_FUNCTION_ALARM;
}
else
{
ret = xensiv_pas_gas_set_alarm_threshold(&dev, 0x0000);
GASINO_ASSERT_RET(ret);
intConf.b.alarm_typ = XENSIV_PAS_GAS_ALARM_TYPE_HIGH_TO_LOW;
}
if (cback != nullptr)
{
/* Enable sensor interrupt */
intConf.b.int_typ = XENSIV_PAS_GAS_INTERRUPT_TYPE_HIGH_ACTIVE;
#if defined(ARDUINO_ARCH_SAMD) || defined(ARDUINO_ARCH_RENESAS) || defined(ARDUINO_ARCH_PSOC6)
PinStatus int_event;
#else
uint8_t int_event;
#endif
int_event = RISING;
if (true == earlyNotification)
{
/* In this case it would be useful to have an interrupt
for both the rising and falling edge. */
int_event = CHANGE;
}
/* Enable mcu interrupt */
attachInterrupt(digitalPinToInterrupt(intPin), (void (*)())cback, int_event);
}
else
{
/* Disable sensor interrupt */
intConf.b.int_func = XENSIV_PAS_GAS_INTERRUPT_FUNCTION_NONE;
if (unusedPin != intPin)
{
/* Disable mcu interrupt */
detachInterrupt(digitalPinToInterrupt(intPin));
}
}
/* This option will disable the alarm interrupt function */
if (true == earlyNotification)
{
intConf.b.int_func = XENSIV_PAS_GAS_INTERRUPT_FUNCTION_EARLY;
}
ret = xensiv_pas_gas_set_interrupt_config(&dev, intConf);
GASINO_ASSERT_RET(ret);
ret = xensiv_pas_gas_set_measurement_config(&dev, measConf);
return ret;
}
Error_t XENSIV_PAS_GASIno::getGasConcentration(float &gasRawValue)
{
int32_t ret = XENSIV_PAS_GAS_OK;
int16_t raw = 0;
/* Initially set to 0.*/
gasRawValue = 0;
/* Read the data */
ret = xensiv_pas_gas_get_result(&dev, (uint16_t *)&raw);
GASINO_ASSERT_RET(ret);
switch (gasType)
{
case SENSOR_R290:
/* Convert to float */
gasRawValue = static_cast<float>(raw) / 100.0f; // R290: convert to %LFL
break;
case SENSOR_A2L:
/* Convert to float */
gasRawValue = static_cast<float>(raw) / 100.0f; // A2L: convert to %LFL
break;
case SENSOR_CO2:
/* Convert to float */
gasRawValue = static_cast<float>(raw); // CO2: convert to ppm
break;
default:
return XENSIV_PAS_GAS_INVALID_SENSOR_TYPE;
}
/* Clear masks from status register */
ret = xensiv_pas_gas_clear_measurement_status(
&dev, (XENSIV_PAS_GAS_REG_MEAS_STS_INT_STS_CLR_MSK | XENSIV_PAS_GAS_REG_MEAS_STS_ALARM_CLR_MSK));
GASINO_ASSERT_RET(ret);
return ret;
}
Error_t XENSIV_PAS_GASIno::stopMeasure()
{
int32_t ret = XENSIV_PAS_GAS_OK;
xensiv_pas_gas_measurement_config_t measConf;
/* Get meas configuration*/
ret = xensiv_pas_gas_get_measurement_config(&dev, &measConf);
GASINO_ASSERT_RET(ret);
/* Set meas configuration to idle mode */
measConf.b.op_mode = XENSIV_PAS_GAS_OP_MODE_IDLE;
ret = xensiv_pas_gas_set_measurement_config(&dev, measConf);
return ret;
}
Error_t XENSIV_PAS_GASIno::getDiagnosis(Diag_t &diagnosis)
{
int32_t ret = XENSIV_PAS_GAS_OK;
/* Get current status */
ret = xensiv_pas_gas_get_status(&dev, &diagnosis);
GASINO_ASSERT_RET(ret);
/* Clear read flags */
ret = xensiv_pas_gas_clear_status(&dev, (XENSIV_PAS_GAS_REG_SENS_STS_ICCER_CLR_MSK |
XENSIV_PAS_GAS_REG_SENS_STS_ORVS_CLR_MSK |
XENSIV_PAS_GAS_REG_SENS_STS_ORTMP_CLR_MSK));
return ret;
}
Error_t XENSIV_PAS_GASIno::setABOC(ABOC_t aboc, int16_t abocRef)
{
xensiv_pas_gas_measurement_config_t measConf;
int32_t ret = XENSIV_PAS_GAS_OK;
/* Get meas configuration */
ret = xensiv_pas_gas_get_measurement_config(&dev, &measConf);
GASINO_ASSERT_RET(ret);
/* Set compensation offset */
ret = xensiv_pas_gas_set_offset_compensation(&dev, (uint16_t)abocRef);
GASINO_ASSERT_RET(ret);
/* Set meas configuration with ABOC */
measConf.b.boc_cfg = aboc;
ret = xensiv_pas_gas_set_measurement_config(&dev, measConf);
return ret;
}
Error_t XENSIV_PAS_GASIno::performForcedCompensation(uint16_t GASRef)
{
return xensiv_pas_gas_perform_forced_compensation(&dev, GASRef);
}
Error_t XENSIV_PAS_GASIno::setPressRef(uint16_t pressRef)
{
int32_t ret = XENSIV_PAS_GAS_OK;
ret = xensiv_pas_gas_set_pressure_compensation(&dev, pressRef);
return ret;
}
Error_t XENSIV_PAS_GASIno::reset()
{
int32_t ret = XENSIV_PAS_GAS_OK;
ret = xensiv_pas_gas_cmd(&dev, XENSIV_PAS_GAS_CMD_SOFT_RESET);
GASINO_ASSERT_RET(ret);
return ret;
}
Error_t XENSIV_PAS_GASIno::getProductID(uint8_t &prodID, uint8_t &revID)
{
int32_t ret = XENSIV_PAS_GAS_OK;
xensiv_pas_gas_id_t id;
ret = xensiv_pas_gas_get_id(&dev, &id);
GASINO_ASSERT_RET(ret);
prodID = id.b.prod;
revID = id.b.rev;
return ret;
}
Error_t XENSIV_PAS_GASIno::getRegister(uint8_t regAddr, uint8_t *data, uint8_t len)
{
return xensiv_pas_gas_get_reg(&dev, regAddr, data, len);
}
Error_t XENSIV_PAS_GASIno::setRegister(uint8_t regAddr, const uint8_t *data, uint8_t len)
{
return xensiv_pas_gas_set_reg(&dev, regAddr, data, len);
}
const char *XENSIV_PAS_GASIno::getGasConcentrationUnitStr()
{
switch (gasType)
{
case SENSOR_R290:
return "%LFL"; // R290
case SENSOR_CO2:
return "ppm"; // CO2
case SENSOR_A2L:
return "%LFL"; // A2L
default:
return "";
}
}
Error_t XENSIV_PAS_GASIno::clearForcedCompensation()
{
switch (gasType)
{
case SENSOR_CO2:
return xensiv_pas_gas_cmd(&dev, (xensiv_pas_gas_cmd_t)XENSIV_PAS_GAS_CO2_CMD_RESET_FCS);
case SENSOR_A2L:
return xensiv_pas_gas_cmd(&dev, (xensiv_pas_gas_cmd_t)XENSIV_PAS_GAS_A2L_CMD_RESET_FCS);
default:
return XENSIV_PAS_GAS_OK;
}
}
const char *XENSIV_PAS_GASIno::getPasGasErrorStr(Error_t err)
{
switch (err)
{
case XENSIV_PAS_GAS_OK:
return "OK";
case XENSIV_PAS_GAS_ERR_COMM:
return "Communication error";
case XENSIV_PAS_GAS_ERR_WRITE_TOO_LARGE:
return "Write too large";
case XENSIV_PAS_GAS_ERR_NOT_READY:
return "Not ready";
case XENSIV_PAS_GAS_ICCERR:
return "Serial command error";
case XENSIV_PAS_GAS_ORVS:
return "VDD5V out of range";
case XENSIV_PAS_GAS_ORTMP:
return "Temperature out of range";
case XENSIV_PAS_GAS_READ_NRDY:
return "GAS value not ready";
case XENSIV_PAS_GAS_INVALID_SENSOR_INTERFACE:
return "Invalid sensor interface";
case XENSIV_PAS_GAS_INVALID_PARAMETER:
return "Invalid parameter";
default:
return "Unknown error";
}
}