Skip to content

ESP32-S3 ESP-IDF Components (I2C, 1-wire, SPI, ADC, etc.) GUVA-S12SD AHTXX AK8975 AS7341 BH1750FVI BME680 BMP280 BMP390 CCS811 ENS160 HDC1080 HMC5883L LTR390UV MMC56X3 MPU6050 SGP4X SHT4X SSD1306 TLV493D VEML7700 DS18B20 MAX31865

License

Notifications You must be signed in to change notification settings

K0I05/ESP32-S3_ESP-IDF_COMPONENTS

Repository files navigation

Welcome

K0I05 License: MIT Language Framework Edited with VS Code Build with PlatformIO PlatformIO CI Codacy Badge Maintenance

Thanks for visiting and hope you find something useful. This repository is a library of peripheral, scheduling, storage, and utility components that are compatible with the ESP32 espressif IoT development framework (esp-idf). The code base is maintained as well as one person can manage in their spare time. The development environment is under Visual Studio Code with the PlatformIO (6.1.18) and ESP-IDF (v5.4.0) extensions. There is always room for improvement to optimize the code base and open to suggestions.

ESP32-S3 Components

PlatformIO components with examples for the ESP32-S3 chipset. This is a revised release utilizing esp-idf suggested design patterns through handles and using i2c_master.h for I2C transactions. The drivers are organized in the components folder within the Visual Studio Code and PlatformIO environment.

The folder structure for components, and associated example, are outlined as follows:

|--components
|  |
|  |--peripherals
|  |  |
|  |  |--adc
|  |  |--i2c
|  |  |  |
|  |  |  |--esp_bmp280
|  |  |  |  |--documentation
|  |  |  |      |- BMP280 Datasheet.pdf
|  |  |  |  |--include
|  |  |  |      |- bmp280_version.h
|  |  |  |      |- bmp280.h
|  |  |  |  |- bmp280.c
|  |  |  |  |- CMakeLists.txt
|  |  |  |  |- LICENSE
|  |  |  |  |- README.md
|  |  |  |  |- idf_component.yml
|  |  |  |  |- library.json
|  |  |
|  |  |--owb
|  |  |--spi
|  |  |--uart
|  |
|  |
|  |--utilities
|  |--schedule
|  |--storage
|
|--templates
|  |--component
|  |  |--include
|  |  |  |- version.h.in
|  |
|  |--components
|  |  |--esp_bmp280
|  |  |  |- library.json.in
|  |  |  |- idf_componet.yml.in
|
|--include
|  |- app_config.h
|  |- bmp280_task.h
|
|--src
|  |- bmp280_task.c
|  |- main.c
|
|- platformio.ini

The component C header version, yml, and json files are automically generated from templates. The templates utilized to generate these files are located as follows;

  • C header version template file: templates/component/include/version.h.in.
  • yml template file: templates/components/[component]/idf_component.yml.in.
  • json template file: templates/components/[component]/library.json.in.

If information must be updated, be sure to update the template and not the generated file. Otherwise, files are overwritten when the version is updated. See the component's CMakeLists.txt file for more details.

To get started, locate and open the app_config.h file from the include folder and configure GPIO pins as needed. Now, locate and open the main.c file from the src folder and go to the void app_main( void ) subroutine to enable the device of interest. The example code is located in the [sensor]_task.h and [sensor]_task.c files.

/**
 * @brief Main application entry point.
 */
void app_main( void ) {
    /* start a component example */
    /* note: only one component can run at a time */
    
    //i2c0_component_example_start(I2C_COMPONENT_AHTXX);
    //i2c0_component_example_start(I2C_COMPONENT_AS7341);
    //i2c0_component_example_start(I2C_COMPONENT_BH1750);
    //i2c0_component_example_start(I2C_COMPONENT_BMP280);
    i2c0_component_example_start(I2C_COMPONENT_BMP390);
    //i2c0_component_example_start(I2C_COMPONENT_CCS811);
    //i2c0_component_example_start(I2C_COMPONENT_ENS160);
    //i2c0_component_example_start(I2C_COMPONENT_HDC1080);
    //i2c0_component_example_start(I2C_COMPONENT_HMC5883L);
    //i2c0_component_example_start(I2C_COMPONENT_MLX90614);
    //i2c0_component_example_start(I2C_COMPONENT_MPU6050);
    //i2c0_component_example_start(I2C_COMPONENT_SGP4X);
    //i2c0_component_example_start(I2C_COMPONENT_SHT4X);
    //i2c0_component_example_start(I2C_COMPONENT_SSD1306);
    //i2c0_component_example_start(I2C_COMPONENT_TLV493D);
    //i2c0_component_example_start(I2C_COMPONENT_VEML7700);
}

Once these initial steps are done, compile and upload the program, assuming your development board is equivalent to the esp32s3box. Otherwise, you will have to configure the environment for your development board and recompile before uploading the program.

Basic Example

All components use the same implementation model and a basic example is provided below.

To get started, create a new PlatformIO project, and copy the esp_bmp390 component to the components folder. Setup your development board and environment in PlatformIO, and copy the example code to overwrite default code in the main.c file. I2C port and GPIO assigments: the example assigns I2C_NUM_0 to the master I2C port, SDA is assigned to GPIO number 45, and SCL is assigned to GPIO number 48. Interface the BMP390 sensor to the development board, compile example, and upload the binary to the device. Open the serial terminal to monitor the output. Reset the board to view configured registers at startup.

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <string.h>
#include <esp_log.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>

// bmp390 component
#include <bmp390.h>

#define TSK_MINIMAL_STACK_SIZE         (1024)

#define I2C0_MASTER_PORT               I2C_NUM_0
#define I2C0_MASTER_SDA_IO             GPIO_NUM_45 // blue
#define I2C0_MASTER_SCL_IO             GPIO_NUM_48 // yellow

#define I2C0_TASK_NAME                 "bmp390_tsk"
#define I2C0_TASK_SAMPLING_RATE        (10) // seconds
#define I2C0_TASK_STACK_SIZE           (TSK_MINIMAL_STACK_SIZE * 8)
#define I2C0_TASK_PRIORITY             (tskIDLE_PRIORITY + 2)

#define I2C0_MASTER_CONFIG_DEFAULT {                                \
        .clk_source                     = I2C_CLK_SRC_DEFAULT,      \
        .i2c_port                       = I2C0_MASTER_PORT,         \
        .scl_io_num                     = I2C0_MASTER_SCL_IO,       \
        .sda_io_num                     = I2C0_MASTER_SDA_IO,       \
        .glitch_ignore_cnt              = 7,                        \
        .flags.enable_internal_pullup   = true, }

#define APP_TAG                         "ESP-IDF BMP390 COMPONENT [APP]"

static inline void print_registers(bmp390_handle_t handle) {
    /* configuration registers */
    bmp390_power_control_register_t     power_ctrl_reg;
    bmp390_configuration_register_t     config_reg;
    bmp390_oversampling_register_t      oversampling_reg;
    bmp390_output_data_rate_register_t  output_data_rate_reg;
    bmp390_interrupt_control_register_t interrupt_ctrl_reg;

    /* attempt to read configuration register */
    bmp390_get_configuration_register(handle, &config_reg);

    /* attempt to read oversampling register */
    bmp390_get_oversampling_register(handle, &oversampling_reg);

    /* attempt to read to power control register */
    bmp390_get_power_control_register(handle, &power_ctrl_reg);

    /* attempt to read to output data rate register */
    bmp390_get_output_data_rate_register(handle, &output_data_rate_reg);

    /* attempt to read to interrupt control register */
    bmp390_get_interrupt_control_register(handle, &interrupt_ctrl_reg);


    ESP_LOGI(APP_TAG, "Configuration (0x%02x): %s", config_reg.reg,           uint8_to_binary(config_reg.reg));
    ESP_LOGI(APP_TAG, "Oversampling  (0x%02x): %s", oversampling_reg.reg,     uint8_to_binary(oversampling_reg.reg));
    ESP_LOGI(APP_TAG, "Data Rate     (0x%02x): %s", output_data_rate_reg.reg, uint8_to_binary(output_data_rate_reg.reg));
    ESP_LOGI(APP_TAG, "Power Control (0x%02x): %s", power_ctrl_reg.reg,       uint8_to_binary(power_ctrl_reg.reg));
    ESP_LOGI(APP_TAG, "Int Control   (0x%02x): %s", interrupt_ctrl_reg.reg,   uint8_to_binary(interrupt_ctrl_reg.reg));

    if(interrupt_ctrl_reg.bits.irq_data_ready_enabled) ESP_LOGE(APP_TAG, "bmp390 irq data ready is enabled");
}

void i2c0_bmp390_task( void *pvParameters ) {
    // initialize the xLastWakeTime variable with the current time.
    TickType_t          last_wake_time  = xTaskGetTickCount ();
    //
    // initialize i2c device configuration
    bmp390_config_t dev_cfg         = I2C_BMP390_CONFIG_DEFAULT;
    bmp390_handle_t dev_hdl;
    //
    // init device
    bmp390_init(i2c0_bus_hdl, &dev_cfg, &dev_hdl);
    if (dev_hdl == NULL) {
        ESP_LOGE(APP_TAG, "bmp390 handle init failed");
        assert(dev_hdl);
    }

    print_registers(dev_hdl);

    // task loop entry point
    for ( ;; ) {
        ESP_LOGI(APP_TAG, "######################## BMP390 - START #########################");
        //
        // handle sensor

        float temperature, pressure;
        esp_err_t result = bmp390_get_measurements(dev_hdl, &temperature, &pressure);
        if(result != ESP_OK) {
            ESP_LOGE(APP_TAG, "bmp390 device read failed (%s)", esp_err_to_name(result));
        } else {
            pressure = pressure / 100;
            ESP_LOGI(APP_TAG, "air temperature:     %.2f °C", temperature);
            ESP_LOGI(APP_TAG, "barometric pressure: %.2f hPa", pressure);
        }
        //
        ESP_LOGI(APP_TAG, "######################## BMP390 - END ###########################");
        //
        //
        // pause the task per defined wait period
        vTaskDelaySecUntil( &last_wake_time, I2C0_TASK_SAMPLING_RATE );
    }
    //
    // free resources
    bmp390_delete( dev_hdl );
    vTaskDelete( NULL );
}

/**
 * @brief Main application entry point.
 */
void app_main( void ) {
    ESP_LOGI(APP_TAG, "Startup..");
    ESP_LOGI(APP_TAG, "Free memory: %lu bytes", esp_get_free_heap_size());
    ESP_LOGI(APP_TAG, "IDF version: %s", esp_get_idf_version());

    /* set log levels */
    esp_log_level_set("*", ESP_LOG_INFO);
    esp_log_level_set(APP_TAG, ESP_LOG_VERBOSE);

    /* instantiate i2c master bus 0 */
    ESP_ERROR_CHECK( i2c_new_master_bus(&i2c0_bus_cfg, &i2c0_bus_hdl) );

    /* create task pinned to the app core */
    xTaskCreatePinnedToCore( 
        i2c0_bmp390_task,
        I2C0_TASK_NAME, 
        I2C0_TASK_STACK_SIZE, 
        NULL, 
        I2C0_TASK_PRIORITY, 
        NULL, 
        APP_CPU_NUM );
}

ESP Peripheral Components (ADC, I2C, OWB, SPI, UART)

The ESP peripheral components accommodate ADC, I2C, OWB, SPI, and UART device interfacing supported by various device manufacturers.

Supported drivers include the following device peripherals:

The above peripheral drivers have been tested, and validated with a logic analyzer where applicable, and are still under development. With every ESP-IDF release there are bound to be quirks with the code base. If any problems arise please feel free to log an issue and if you would to contribute please contact me.

ESP Utilities Components

The ESP Utilities components are generally used in conjunction with peripheral components for data processing.

Supported components include the following:

  • Kalman Motion: Kalman filter for motion based use-cases that leverage sensors such as a gyroscope and/or accelerometer.
  • Sensirion Gas Index Algorithm: A gas index algorithm for the Sensirion air quality sensors. This code base is maintained by Sensirion.
  • Pressure Tendency: A pressure tendency algorithm that monitors if pressure is rising, falling, or steady over the past 3-hours.
  • Scalar Trend: A scalar trend algorithm that monitors if a scalar variable is rising, falling, or steady over the past hour.
  • Type Utilities: Type definitions common for i2c transactions, byte manipulation, and other tools.
  • UUID Generator: An RFC-4122 Universally Unique Identifier (UUID) generator.

See the Sensirion SGP4X example on how the gas index algorithm is utilized with this sensor.

ESP Schedule Components

The ESP time-into-interval component synchronizes a FreeRTOS task with the system clock and user-defined time interval for temporal conditional scenarios.

ESP Storage Components

The ESP storage components can be used for use-cases that require volatile and/or non-volatile storage.

Supported components include the following:

  • Data-Logger: A user friendly table based data logging component for measurement and control use-cases. See Data-Logger examples for more details, see readme file in the component folder.
  • NVS Ext: A component extension that simplifies the process of reading and writing information to non-volatile storage (NVS). See readme file in the component folder.

Copyright (c) 2024 Eric Gionet ([email protected])

About

ESP32-S3 ESP-IDF Components (I2C, 1-wire, SPI, ADC, etc.) GUVA-S12SD AHTXX AK8975 AS7341 BH1750FVI BME680 BMP280 BMP390 CCS811 ENS160 HDC1080 HMC5883L LTR390UV MMC56X3 MPU6050 SGP4X SHT4X SSD1306 TLV493D VEML7700 DS18B20 MAX31865

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published