Middleware to implement the RRH46410 sensor module interface. This module implements the ZMOD4XXX Middleware Interface.
Overview
This module provides an API for configuring and controlling the RRH46410 sensor module (ZMOD4410 + MCU).
I2C communication with the RRH46410 sensor module is realized by connecting with the rm_comms_i2c module.
Features
The RRH46410 sensor interface implementation has the following key features:
- Initialize the sensor for measurement
- Start a measurement at any time
- Input current humidity for best performance.
- Receive status for wait until the measurement is done. This will also be signaled by an interrupt
- Get the measruement results from the sensor module
- Different from ZMOD sensors, no libraries are needed.
Configuration
Build Time Configurations for rm_rrh46410
The following build time configurations are defined in fsp_cfg/rm_rrh46410_cfg.h:
Configuration | Options | Default | Description |
Parameter Checking |
-
Default (BSP)
-
Enabled
-
Disabled
| Default (BSP) | If selected code for parameter checking is included in the build. |
Operation Mode |
-
IAQ 2nd Gen and Rel IAQ
-
IAQ 2nd Gen ULP and Rel IAQ ULP
-
Public Building AQ Standard (PBAQ)
| IAQ 2nd Gen and Rel IAQ | Select operation mode. |
Configurations for Sensor > RRH46410 Gas Sensor Module (rm_rrh46410)
This module can be added to the Stacks tab via New Stack > Sensor > RRH46410 Gas Sensor Module (rm_rrh46410).
Configuration | Options | Default | Description |
Name | Name must be a valid C symbol | g_rrh46410_sensor0 | Module name. |
Comms I2C Callback | Name must be a valid C symbol | rrh46410_comms_i2c_callback | A user COMMS I2C callback function can be provided. |
IRQ Callback | Name must be a valid C symbol | rrh46410_irq_callback | A user IRQ callback function can be provided. |
Pin Configuration
This module use SDA and SCL pins of I2C Master, SCI I2C and IICA Master.
Usage Notes
RRH46410 datasheet is here.
The RRH46410 has three modes of operation.
The RRH46410 will respond to TVOC immediately upon start-up; however, a conditioning period of 48 hours followed by a sensor module restart in an ambient environment is recommended to improve stability and obtain maximum performance.
Best results are achieved with continuous operation because the module algorithm can learn about the environment over time.
Operation mode | Description | Data |
IAQ 2nd Generation and Relative IAQ | Using AI for improved ppm TVOC, IAQ and eCO2 functionality (recommended for new designs). Lightweight algorithm reacts to air quality changes and outputs a relative IAQ | IAQ, TVOC[mg/m^3], EtOH[ppm], eCO2[ppm], Rel IAQ |
IAQ 2nd Generation Ultra Low Power and Relative IAQ Ultra Low Power | Using AI for improved ppm TVOC, IAQ and eCO2 functionality. Lightweight algorithm reacts to air quality changes and outputs a relative IAQ. This operation mode offers a much lower power consumption. | IAQ, TVOC[mg/m^3], EtOH[ppm], eCO2[ppm], Rel IAQ |
Public Building AQ Standard (PBAQ) | For highly accurate and consistent sensor readings to fulfill public building standards. | TVOC[mg/m^3], EtOH[ppm] |
If an RTOS is used, blocking and bus lock is available.
- If blocking of an I2C bus is required, it is necessary to create a semaphore for blocking.
- If bus lock is required, it is necessary to create a mutex for bus lock. Bus lock is only available when a semaphore for blocking is used.
Limitations
- I2C Master (r_sau_i2c) is not supported. RRH46410 needs clock stretching, but is not supported by SAU I2C.
- The following commands are currently not supported.
- Get Product ID
- Get Tracking Number
- Set Operation Mode -> Sensor cleaning
- Config GPIO
- Get GPIO
- Set GPIO
- Clear GPIO
- Read Flash Shadow
- Write Flash Shadow
- Write Flash
- Reset
Notifications
- The RRH46410 sensor module needs a reset before operation; please input a reset signal to the RES_N pin (active low).
- The RRH46410 sensor module needs some time (e.g. 1s) for self initialization after power-on and reset.
Bus Initialization
The RRH46410 interface expects a bus instance to be opened before opening any RRH46410 device. The interface will handle switching between devices on the bus but will not open or close the bus instance. The user should open the bus with the appropriate I2C Master Interface open call.
Initialization
Initialize with RM_RRH46410_Open().
From measurement start to data acquisition
After normal completion, start the measurement with RM_RRH46410_MeasurementStart(). An endless loop continuously checks the status of the RRH46410 sensor module and reads its data. The measurement results are subsequently processed, and the air quality values are calculated.
If IRQ is enabled
- Wait until RM_ZMOD4XXX_EVENT_MEASUREMENT_COMPLETE is received via IRQ callback.
- Call RM_RRH46410_Read(). This function will read the measurement results.
- Wait until RM_ZMOD4XXX_EVENT_MEASUREMENT_COMPLETE is received.
- Call the DataCalculate API according to the mode.
If IRQ is disabled
- Call RM_RRH46410_Read(). This function will read the measurement results.
- If RM_ZMOD4XXX_EVENT_MEASUREMENT_NOT_COMPLETE is received in callback, user should wait some time and then call RM_RRH46410_Read() again.
- Wait until RM_ZMOD4XXX_EVENT_MEASUREMENT_COMPLETE is received.
- Call the DataCalculate API according to the mode.
Examples
Basic Example
These are basic examples of minimal use of RRH46410 sensor implementation in an application.
IAQ 2nd Gen.
void rm_rrh46410_iaq_2nd_gen_basic_example (void)
{
float humidity = RRH46410_DEFAULT_HUMIDITY_50F;
rm_comms_i2c_bus_extended_cfg_t * p_extend =
(rm_comms_i2c_bus_extended_cfg_t *) g_rrh46410_cfg.p_comms_instance->p_cfg->p_extend;
p_driver_instance->
p_api->
open(p_driver_instance->p_ctrl, p_driver_instance->p_cfg);
#if BSP_CFG_RTOS
if (NULL != p_extend->p_blocking_semaphore)
{
#if BSP_CFG_RTOS == 1 // AzureOS
tx_semaphore_create(p_extend->p_blocking_semaphore->p_semaphore_handle,
p_extend->p_blocking_semaphore->p_semaphore_name,
(ULONG) 0);
#elif BSP_CFG_RTOS == 2 // FreeRTOS
*(p_extend->p_blocking_semaphore->p_semaphore_handle) =
xSemaphoreCreateCountingStatic((UBaseType_t) 1,
(UBaseType_t) 0,
p_extend->p_blocking_semaphore->p_semaphore_memory);
#endif
}
if (NULL != p_extend->p_bus_recursive_mutex)
{
#if BSP_CFG_RTOS == 1 // AzureOS
tx_mutex_create(p_extend->p_bus_recursive_mutex->p_mutex_handle,
p_extend->p_bus_recursive_mutex->p_mutex_name,
TX_INHERIT);
#elif BSP_CFG_RTOS == 2 // FreeRTOS
*(p_extend->p_bus_recursive_mutex->p_mutex_handle) =
xSemaphoreCreateRecursiveMutexStatic(p_extend->p_bus_recursive_mutex->p_mutex_memory);
#endif
}
#endif
handle_error(err);
#if RRH46410_IRQ_ENABLE
g_rrh46410_irq_callback_flag = 0;
#endif
g_rrh46410_i2c_callback_flag = 0;
handle_error(err);
while (0U == g_rrh46410_i2c_callback_flag)
{
}
g_rrh46410_i2c_callback_flag = 0;
while (1)
{
handle_error(err);
while (0U == g_rrh46410_i2c_callback_flag)
{
}
g_rrh46410_i2c_callback_flag = 0;
#if RRH46410_IRQ_ENABLE
while (0U == g_rrh46410_irq_callback_flag)
{
}
g_rrh46410_irq_callback_flag = 0;
#else
#endif
do
{
handle_error(err);
while (0U == g_rrh46410_i2c_callback_flag)
{
}
g_rrh46410_i2c_callback_flag = 0;
{
}
if (FSP_SUCCESS == err)
{
}
{
}
else
{
handle_error(err);
}
}
}
IAQ 2nd Gen. ULP
void rm_rrh46410_iaq_2nd_gen_ulp_basic_example (void)
{
float humidity = RRH46410_DEFAULT_HUMIDITY_50F;
rm_comms_i2c_bus_extended_cfg_t * p_extend =
(rm_comms_i2c_bus_extended_cfg_t *) g_rrh46410_cfg.p_comms_instance->p_cfg->p_extend;
p_driver_instance->
p_api->
open(p_driver_instance->p_ctrl, p_driver_instance->p_cfg);
#if BSP_CFG_RTOS
if (NULL != p_extend->p_blocking_semaphore)
{
#if BSP_CFG_RTOS == 1 // AzureOS
tx_semaphore_create(p_extend->p_blocking_semaphore->p_semaphore_handle,
p_extend->p_blocking_semaphore->p_semaphore_name,
(ULONG) 0);
#elif BSP_CFG_RTOS == 2 // FreeRTOS
*(p_extend->p_blocking_semaphore->p_semaphore_handle) =
xSemaphoreCreateCountingStatic((UBaseType_t) 1,
(UBaseType_t) 0,
p_extend->p_blocking_semaphore->p_semaphore_memory);
#endif
}
if (NULL != p_extend->p_bus_recursive_mutex)
{
#if BSP_CFG_RTOS == 1 // AzureOS
tx_mutex_create(p_extend->p_bus_recursive_mutex->p_mutex_handle,
p_extend->p_bus_recursive_mutex->p_mutex_name,
TX_INHERIT);
#elif BSP_CFG_RTOS == 2 // FreeRTOS
*(p_extend->p_bus_recursive_mutex->p_mutex_handle) =
xSemaphoreCreateRecursiveMutexStatic(p_extend->p_bus_recursive_mutex->p_mutex_memory);
#endif
}
#endif
handle_error(err);
#if RRH46410_IRQ_ENABLE
g_rrh46410_irq_callback_flag = 0;
#endif
g_rrh46410_i2c_callback_flag = 0;
handle_error(err);
while (0U == g_rrh46410_i2c_callback_flag)
{
}
g_rrh46410_i2c_callback_flag = 0;
while (1)
{
handle_error(err);
while (0U == g_rrh46410_i2c_callback_flag)
{
}
g_rrh46410_i2c_callback_flag = 0;
#if RRH46410_IRQ_ENABLE
while (0U == g_rrh46410_irq_callback_flag)
{
}
g_rrh46410_irq_callback_flag = 0;
#else
#endif
do
{
handle_error(err);
while (0U == g_rrh46410_i2c_callback_flag)
{
}
g_rrh46410_i2c_callback_flag = 0;
{
}
if (FSP_SUCCESS == err)
{
}
{
}
else
{
handle_error(err);
}
}
}
PBAQ
void rm_rrh46410_pbaq_basic_example (void)
{
float humidity = RRH46410_DEFAULT_HUMIDITY_50F;
rm_comms_i2c_bus_extended_cfg_t * p_extend =
(rm_comms_i2c_bus_extended_cfg_t *) g_rrh46410_cfg.p_comms_instance->p_cfg->p_extend;
p_driver_instance->
p_api->
open(p_driver_instance->p_ctrl, p_driver_instance->p_cfg);
#if BSP_CFG_RTOS
if (NULL != p_extend->p_blocking_semaphore)
{
#if BSP_CFG_RTOS == 1 // AzureOS
tx_semaphore_create(p_extend->p_blocking_semaphore->p_semaphore_handle,
p_extend->p_blocking_semaphore->p_semaphore_name,
(ULONG) 0);
#elif BSP_CFG_RTOS == 2 // FreeRTOS
*(p_extend->p_blocking_semaphore->p_semaphore_handle) =
xSemaphoreCreateCountingStatic((UBaseType_t) 1,
(UBaseType_t) 0,
p_extend->p_blocking_semaphore->p_semaphore_memory);
#endif
}
if (NULL != p_extend->p_bus_recursive_mutex)
{
#if BSP_CFG_RTOS == 1 // AzureOS
tx_mutex_create(p_extend->p_bus_recursive_mutex->p_mutex_handle,
p_extend->p_bus_recursive_mutex->p_mutex_name,
TX_INHERIT);
#elif BSP_CFG_RTOS == 2 // FreeRTOS
*(p_extend->p_bus_recursive_mutex->p_mutex_handle) =
xSemaphoreCreateRecursiveMutexStatic(p_extend->p_bus_recursive_mutex->p_mutex_memory);
#endif
}
#endif
handle_error(err);
#if RRH46410_IRQ_ENABLE
g_rrh46410_irq_callback_flag = 0;
#endif
g_rrh46410_i2c_callback_flag = 0;
handle_error(err);
while (0U == g_rrh46410_i2c_callback_flag)
{
}
g_rrh46410_i2c_callback_flag = 0;
while (1)
{
handle_error(err);
while (0U == g_rrh46410_i2c_callback_flag)
{
}
g_rrh46410_i2c_callback_flag = 0;
#if RRH46410_IRQ_ENABLE
while (0U == g_rrh46410_irq_callback_flag)
{
}
g_rrh46410_irq_callback_flag = 0;
#else
#endif
do
{
handle_error(err);
while (0U == g_rrh46410_i2c_callback_flag)
{
}
g_rrh46410_i2c_callback_flag = 0;
{
}
if (FSP_SUCCESS == err)
{
}
{
}
else
{
handle_error(err);
}
}
}
◆ rm_rrh46410_init_process_params_t
struct rm_rrh46410_init_process_params_t |
RRH46410 initialization process block
Data Fields |
volatile bool |
communication_finished |
Communication flag for blocking. |
volatile rm_zmod4xxx_event_t |
event |
Callback event. |
◆ rm_rrh46410_instance_ctrl_t
struct rm_rrh46410_instance_ctrl_t |
◆ RM_RRH46410_Open()
Opens and configures the RRH46410 sensor module. Implements rm_zmod4xxx_api_t::open.
- Return values
-
FSP_SUCCESS | RRH46410 successfully configured. |
FSP_ERR_ASSERTION | Null pointer, or one or more configuration options is invalid. |
FSP_ERR_ALREADY_OPEN | Module is already open. This module can only be opened once. |
FSP_ERR_TIMEOUT | Communication is timeout. |
FSP_ERR_ABORTED | Communication is aborted. |
◆ RM_RRH46410_Close()
This function should be called when close the sensor module. Implements rm_zmod4xxx_api_t::close.
- Return values
-
FSP_SUCCESS | Successfully closed. |
FSP_ERR_ASSERTION | Null pointer passed as a parameter. |
FSP_ERR_NOT_OPEN | Module is not open. |
◆ RM_RRH46410_MeasurementStart()
This function should be called when start a measurement. Implements rm_zmod4xxx_api_t::measurementStart.
- Return values
-
FSP_SUCCESS | Successfully started. |
FSP_ERR_ASSERTION | Null pointer passed as a parameter. |
FSP_ERR_NOT_OPEN | Module is not opened configured. |
FSP_ERR_TIMEOUT | Communication is timeout. |
FSP_ERR_ABORTED | Communication is aborted. |
◆ RM_RRH46410_MeasurementStop()
This function should be called when stop a measurement. Implements rm_zmod4xxx_api_t::measurementStop.
- Return values
-
FSP_SUCCESS | Successfully stopped. |
FSP_ERR_ASSERTION | Null pointer passed as a parameter. |
FSP_ERR_NOT_OPEN | Module is not opened configured. |
FSP_ERR_TIMEOUT | Communication is timeout. |
FSP_ERR_ABORTED | Communication is aborted. |
◆ RM_RRH46410_Read()
This function should be called to get measurement results after measurement finishes. To check measurement status either polling or busy/interrupt pin can be used. Implements rm_zmod4xxx_api_t::read.
- Return values
-
FSP_SUCCESS | Successfully results are read. |
FSP_ERR_ASSERTION | Null pointer passed as a parameter. |
FSP_ERR_NOT_OPEN | Module is not opened configured. |
FSP_ERR_TIMEOUT | Communication is timeout. |
FSP_ERR_ABORTED | Communication is aborted. |
◆ RM_RRH46410_Iaq2ndGenDataCalculate()
This function should be called when calculating gas data from measurement results. Implements rm_zmod4xxx_api_t::iaq2ndGenDataCalculate.
- Return values
-
FSP_SUCCESS | Successfully gas data is calculated. |
FSP_ERR_ASSERTION | Null pointer passed as a parameter. |
FSP_ERR_NOT_OPEN | Module is not opened configured. |
FSP_ERR_UNSUPPORTED | Unsupported operation mode. |
FSP_ERR_SENSOR_MEASUREMENT_NOT_FINISHED | Measurement is not finished. |
◆ RM_RRH46410_PbaqDataCalculate()
This function should be called when calculating gas data from measurement results. Implements rm_zmod4xxx_api_t::pbaqDataCalculate.
- Return values
-
FSP_SUCCESS | Successfully gas data is calculated. |
FSP_ERR_ASSERTION | Null pointer passed as a parameter. |
FSP_ERR_NOT_OPEN | Module is not opened configured. |
FSP_ERR_UNSUPPORTED | Unsupported operation mode. |
FSP_ERR_SENSOR_MEASUREMENT_NOT_FINISHED | Measurement is not finished. |
◆ RM_RRH46410_TemperatureAndHumiditySet()
This function should be called before Read. Humidity measurements are needed for ambient compensation. temperature is not supported. Implements rm_zmod4xxx_api_t::temperatureAndHumiditySet.
- Return values
-
FSP_SUCCESS | Successfully humidity is set. |
FSP_ERR_ASSERTION | Null pointer passed as a parameter. |
FSP_ERR_NOT_OPEN | Module is not opened configured. |