Skip to content

Platform agnostic C driver for the Winsen MH-Z19B Infrared CO2 Sensor

License

Notifications You must be signed in to change notification settings

raulgotor/winsen_mh_z19b

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Contributors Forks Stargazers Issues MIT License


Winsen MH-Z19B Driver

Platform agnostic C driver for the Winsen MH-Z19B Infrared CO2 Sensor
Explore the docs »

View Demo · Report Bug · Request Feature

Table of Contents

  1. Getting Started
  2. Usage
  3. Roadmap
  4. Contributing
  5. License
  6. Contact
  7. Acknowledgements

Getting Started

To get a local copy up and running follow these simple steps.

Installation

  1. Navigate to your project's source directory

  2. Clone the repo

    git clone https://github.com/raulgotor/winsen_mh_z19b.git
  3. Write a transfer function (see next section)

Usage

Transfer function

A transfer function glues the driver logic with the current device specific API. The transfer function needs to be injected to the driver, so it can access your device specific UART peripheral while remaining agnostic to the platform you are using it at.

The transfer function should match with the following prototype:

/*!
 * @brief UART transfer function prototype
 *
 * The transfer function that will be registered with the `mh_z19b_init` function
 * must follow this prototype
 *
 * @note If the operation to perform is a read operation:
 *          - `p_tx_buffer` must be null
 *          - `tx_buffer_size` must be 0
 *
 * @note If the operation to perform is a write operation:
 *          - `p_rx_buffer` must be null
 *          - `rx_buffer_size` must be 0
 *
 * @note `p_rx_buffer` and `p_tx_buffer` cannot be both null
 *
 * @param[out]          p_rx_buffer         Pointer to the buffer where to read
 *                                          the data to
 * @param[in]           rx_buffer_size      Size of the read buffer
 * @param[in]           p_tx_buffer         Pointer to the buffer where to read
 *                                          the data from
 * @param[in]           tx_buffer_size      Size of the write buffer
 *
 * @return              mh_z19b_error_t      Operation result
 * @retval              MH_Z19B_ERROR_SUCCESS
 *                                          Everything went well
 * @retval              MH_Z19B_ERROR_BAD_PARAMETER
 *                                          Parameter is null
 */
typedef mh_z19b_error_t (*mh_z19b_xfer_func )(uint8_t * const p_rx_buffer,
                                            size_t const rx_buffer_size,
                                            uint8_t const * const p_tx_buffer,
                                            size_t const tx_buffer_size);
   

Transfer function and module initialization example

An example of a transfer function for Espressif's esp-idf would be:

static mh_z19b_error_t xfer_func(uint8_t const * const p_rx_buffer,
                                 size_t const rx_buffer_size,
                                 uint8_t * const p_tx_buffer,
                                 size_t const tx_buffer_size)
{

        mh_z19b_error_t result = MH_Z19_ERROR_SUCCESS;
        bool is_rx_operation = true;
        int uart_result;

        if ((NULL == p_rx_buffer) != (0 == rx_buffer_size)) {
                result = MH_Z19B_ERROR_BAD_PARAMETER;

        } else if ((NULL == p_tx_buffer) != (0 == tx_buffer_size)) {
                result = MH_Z19B_ERROR_BAD_PARAMETER;

        } else if ((NULL == p_rx_buffer) && (NULL == p_tx_buffer)) {
                result = MH_Z19B_ERROR_BAD_PARAMETER;
        } else if (0 != tx_buffer_size) {
                is_rx_operation = false;
        }

        if ((MH_Z19B_ERROR_SUCCESS == result) && (is_rx_operation)) {
                uart_result = uart_read_bytes(UART_NUM_2,
                                              (void *)p_rx_buffer,
                                              (uint32_t)rx_buffer_size, 100);

                if (-1 == uart_result) {
                        result = MH_Z19B_ERROR_IO_ERROR;
                }

        } else if (MH_Z19B_ERROR_SUCCESS == result) {
                uart_result = uart_write_bytes(UART_NUM_2,
                                               (void *)p_tx_buffer,
                                               (uint32_t)tx_buffer_size);

                if (-1 == uart_result) {
                        result = MH_Z19B_ERROR_IO_ERROR;
                }
        }

        return result;
}

Below an implementation example for an ESP32 MCU using esp-idf is suggested:

  • Device specific UART bus configuration and initialization
  • Driver initialization with injection of the transfer function
  1. Initialize the UART bus
    static uart_port_t const m_uart_instance = UART_NUM_2;
    static int const m_uart_tx_pin = 33;
    static int const m_uart_rx_pin = 32;
    
    bool sensor_init(void) {
    
         uart_config_t const uart_config = {
                         .baud_rate = 9600,
                         .data_bits = UART_DATA_8_BITS,
                         .parity = UART_PARITY_DISABLE,
                         .stop_bits = UART_STOP_BITS_1,
                         .flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
         };
    
         int const uart_buffer_size = (1024 * 2);
         bool success = true;
    
         esp_err_t esp_result;
         QueueHandle_t uart_queue;
         BaseType_t task_result;
         mh_z19b_error_t mh_z19_result;
    
         esp_result = uart_set_pin(
                         m_uart_instance,
                         m_uart_tx_pin,
                         m_uart_rx_pin,
                         UART_PIN_NO_CHANGE,
                         UART_PIN_NO_CHANGE);
    
         success = (ESP_OK == esp_result);
    
         if (success) {
                 esp_result = uart_param_config(m_uart_instance, &uart_config);
    
                 success = (ESP_OK == esp_result);
         }
    
         if (success) {
                 esp_result = uart_driver_install(
                                 m_uart_instance,
                                 uart_buffer_size,
                                 uart_buffer_size,
                                 10,
                                 &uart_queue,
                                 0);
    
                 success = (ESP_OK == esp_result);
         }
         
         if (success) {
                 mh_z19b_result = mh_z19b_init(xfer_func);
    
                 success = (MH_Z19B_ERROR_SUCCESS == mh_z19_result);
         }
    
         if (success) {
                 mh_z19b_result = mh_z19b_enable_abc(false);
    
                 success = (MH_Z19B_ERROR_SUCCESS == mh_z19_result);
         }
    }

Reading the CO2 concentration

Below there is an example for performing temperature readings.

uint32_t co2_ppm;
mh_z19b_error_t result;

result = mh_z19b_get_gas_concentration(&co2_ppm);


if (MH_Z19B_ERROR_SUCCESS == result) {
        printf("CO2 concentration is %d ppm\n", co2_ppm);
}

Further documentation

Please refer to the in code documentation and to the Winsen MH-Z19B Datasheet

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Distributed under the MIT License. See LICENSE for more information.

Contact

Raúl Gotor

Project Link: https://github.com/raulgotor/winsen_mh_z19b

Acknowledgements

About

Platform agnostic C driver for the Winsen MH-Z19B Infrared CO2 Sensor

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published