Merge 35f236ce0389d36c891f59bae3bdce5e7c758d7d into 298cbec7fc7b32abd30b7e00b37ad71e3ab0ec81

This commit is contained in:
PurpleCloudX 2024-11-25 19:43:32 +08:00 committed by GitHub
commit b682f5424b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 314 additions and 59 deletions

@ -1,4 +1,5 @@
cmake_minimum_required(VERSION 3.1)
set(CMAKE_C_STANDARD 11)
idf_component_register( idf_component_register(
SRCS bmx280.c SRCS bmx280.c
INCLUDE_DIRS "include" INCLUDE_DIRS "include"

27
Kconfig

@ -1,4 +1,25 @@
menu "BMX280 Options" menu "BMX280 Options"
choice I2C_DRIVER_SETTING
prompt "I2C driver setting"
help
Select I2C Driver: I2C Legacy Driver: I2C.h , I2C Master Driver i2c_master.h for ESP-IDF >= 5.3 AND Set I2C Clock Speed.
default USE_I2C_LEGACY_DRIVER
config USE_I2C_LEGACY_DRIVER
bool "I2C Legacy Driver (I2C.h)"
help
Use I2C Legacy Driver (I2C.h).
config USE_I2C_MASTER_DRIVER
bool "I2C Master Driver (i2c_master.h)"
help
Use I2C Master Driver (i2c_master.h) for ESP-IDF >= 5.3.
config BMX280_I2C_CLK_SPEED_HZ
int "I2C Clock Speed (Hz)"
default 100000
range 1000 400000
help
Set the I2C clock speed in Hz.
endchoice
choice BMX280_EXPECT_DEVICE choice BMX280_EXPECT_DEVICE
prompt "Installed Sensor Model" prompt "Installed Sensor Model"
help help
@ -20,15 +41,15 @@ menu "BMX280 Options"
default BMX280_ADDRESS_DETECT default BMX280_ADDRESS_DETECT
config BMX280_ADDRESS_DETECT config BMX280_ADDRESS_DETECT
bool "Auto" bool "Auto"
config BMX280_ADDERSS_LO config BMX280_ADDRESS_LO
bool "0x76 (SDO LOW)" bool "0x76 (SDO LOW)"
config BMX280_ADDERSS_HI config BMX280_ADDRESS_HI
bool "0x77 (SDO HIGH)" bool "0x77 (SDO HIGH)"
endchoice endchoice
config BMX280_TIMEOUT config BMX280_TIMEOUT
int "Read/Write Timeout" int "Read/Write Timeout"
default 5 default 50
help help
Number of ticks to wait for I2C read/write operations. Number of ticks to wait for I2C read/write operations.

@ -10,55 +10,21 @@ Add the module as a requirement to your main module, or other modules.
Example Code Example Code
------------ ------------
```c To use the legacy i2c.h driver, please refer to the [example_with_i2c.h](examples/bmx280_example_without_i2c_master.c).
#include "esp_log.h"
#include "bmx280.h"
void app_main(void) To use the i2c_master.h driver (ESP-IDF >= 5.3):
{
// Entry Point
//ESP_ERROR_CHECK(nvs_flash_init());
i2c_config_t i2c_cfg = {
.mode = I2C_MODE_MASTER,
.sda_io_num = GPIO_NUM_17,
.scl_io_num = GPIO_NUM_16,
.sda_pullup_en = false,
.scl_pullup_en = false,
.master = { * First, run `idf.py menuconfig` to configure the project.
.clk_speed = 100000
}
};
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &i2c_cfg)); * Navigate to Component Config -> BMX280 Options -> I2C driver setting -> I2C Master Driver (i2c_master.h).
ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0));
bmx280_t* bmx280 = bmx280_create(I2C_NUM_0); * Press the 'S' key to save the configuration.
if (!bmx280) { * You can then use the I2C Master driver to complete your code.
ESP_LOGE("test", "Could not create bmx280 driver.");
return;
}
ESP_ERROR_CHECK(bmx280_init(bmx280)); For example code, please see the [example_with_i2c_master.h](examples/bmx280_example_with_i2c_master.c).
bmx280_config_t bmx_cfg = BMX280_DEFAULT_CONFIG; **Note:** If you want to use the legacy i2c.h driver, no changes are needed; continue using `bmx280_create` to create the anonymous structure `bmx280`. If you use the i2c_master.h driver, you need to use `bmx280_create_master` to create the structure.
ESP_ERROR_CHECK(bmx280_configure(bmx280, &bmx_cfg));
while (1)
{
ESP_ERROR_CHECK(bmx280_setMode(bmx280, BMX280_MODE_FORCE));
do {
vTaskDelay(pdMS_TO_TICKS(1));
} while(bmx280_isSampling(bmx280));
float temp = 0, pres = 0, hum = 0;
ESP_ERROR_CHECK(bmx280_readoutFloat(bmx280, &temp, &pres, &hum));
ESP_LOGI("test", "Read Values: temp = %f, pres = %f, hum = %f", temp, pres, hum);
}
}
```
License License
------- -------

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

147
bmx280.c

@ -70,10 +70,19 @@
#define BMP280_ID2 0x58 #define BMP280_ID2 0x58
struct bmx280_t{ struct bmx280_t{
#if !(CONFIG_USE_I2C_MASTER_DRIVER)
// I2C port. // I2C port.
i2c_port_t i2c_port; i2c_port_t i2c_port;
// Slave Address of sensor. // Slave Address of sensor.
uint8_t slave; uint8_t slave;
#else
// I2C master handle via port with configuration
i2c_master_dev_handle_t i2c_dev;
// I2C master configuration
i2c_device_config_t dev_cfg;
// I2C master handle via port
i2c_master_bus_handle_t bus_handle;
#endif
// Chip ID of sensor // Chip ID of sensor
uint8_t chip_id; uint8_t chip_id;
// Compensation data // Compensation data
@ -122,7 +131,36 @@ struct bmx280_t{
* Returns false if the sensor was not found. * Returns false if the sensor was not found.
* @param bmx280 The driver structure. * @param bmx280 The driver structure.
*/ */
#if !(CONFIG_USE_I2C_MASTER_DRIVER)
#define bmx280_validate(bmx280) (!(bmx280->slave == 0xDE && bmx280->chip_id == 0xAD)) #define bmx280_validate(bmx280) (!(bmx280->slave == 0xDE && bmx280->chip_id == 0xAD))
#else
#define bmx280_validate(bmx280) (!(bmx280->i2c_dev == NULL && bmx280->chip_id == 0xAD))
#endif
#if CONFIG_USE_I2C_MASTER_DRIVER
/**
* Read from sensor.
* @param bmx280 Driver Sturcture.
* @param dev_addr Chip addresses.
*/
static esp_err_t bmx280_device_create(bmx280_t *bmx280, const uint16_t dev_addr)
{
ESP_LOGI("bmx280", "device_create for BMP280/BME280 sensors on ADDR %X", dev_addr);
bmx280->dev_cfg.device_address = dev_addr;
// Add device to the I2C bus
esp_err_t err = i2c_master_bus_add_device(bmx280->bus_handle, &bmx280->dev_cfg, &bmx280->i2c_dev);
if (err == ESP_OK)
{
ESP_LOGI("bmx280", "device_create success on 0x%x", dev_addr);
return err;
}
else
{
ESP_LOGE("bmx280", "device_create error on 0x%x", dev_addr);
return err;
}
}
#endif
/** /**
* Read from sensor. * Read from sensor.
@ -134,6 +172,7 @@ struct bmx280_t{
*/ */
static esp_err_t bmx280_read(bmx280_t *bmx280, uint8_t addr, uint8_t *dout, size_t size) static esp_err_t bmx280_read(bmx280_t *bmx280, uint8_t addr, uint8_t *dout, size_t size)
{ {
#if !(CONFIG_USE_I2C_MASTER_DRIVER)
esp_err_t err; esp_err_t err;
i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_cmd_handle_t cmd = i2c_cmd_link_create();
if (cmd) if (cmd)
@ -157,11 +196,16 @@ static esp_err_t bmx280_read(bmx280_t *bmx280, uint8_t addr, uint8_t *dout, size
{ {
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
#else
return i2c_master_transmit_receive(bmx280->i2c_dev, &addr, sizeof(addr), dout, size, CONFIG_BMX280_TIMEOUT);
#endif
} }
static esp_err_t bmx280_write(bmx280_t* bmx280, uint8_t addr, const uint8_t *din, size_t size) static esp_err_t bmx280_write(bmx280_t* bmx280, uint8_t addr, const uint8_t *din, size_t size)
{ {
esp_err_t err; esp_err_t err;
#if !(CONFIG_USE_I2C_MASTER_DRIVER)
i2c_cmd_handle_t cmd = i2c_cmd_link_create(); i2c_cmd_handle_t cmd = i2c_cmd_link_create();
if (cmd) if (cmd)
{ {
@ -184,12 +228,20 @@ static esp_err_t bmx280_write(bmx280_t* bmx280, uint8_t addr, const uint8_t *din
{ {
return ESP_ERR_NO_MEM; return ESP_ERR_NO_MEM;
} }
#else
for(uint8_t i = 0; i < size; i++)
{
uint8_t dat[2] = {(addr + i), din[i]};
if ((err = i2c_master_transmit(bmx280->i2c_dev, dat, 2, CONFIG_BMX280_TIMEOUT)) != ESP_OK)
return err;
}
return ESP_OK;
#endif
} }
static esp_err_t bmx280_probe_address(bmx280_t *bmx280) static esp_err_t bmx280_probe_address(bmx280_t *bmx280)
{ {
esp_err_t err = bmx280_read(bmx280, BMX280_REG_CHPID, &bmx280->chip_id, sizeof bmx280->chip_id); esp_err_t err = bmx280_read(bmx280, BMX280_REG_CHPID, &bmx280->chip_id, sizeof bmx280->chip_id);
if (err == ESP_OK) if (err == ESP_OK)
{ {
if ( if (
@ -202,31 +254,43 @@ static esp_err_t bmx280_probe_address(bmx280_t *bmx280)
#endif #endif
) )
{ {
#if !(CONFIG_USE_I2C_MASTER_DRIVER)
ESP_LOGI("bmx280", "Probe success: address=%hhx, id=%hhx", bmx280->slave, bmx280->chip_id); ESP_LOGI("bmx280", "Probe success: address=%hhx, id=%hhx", bmx280->slave, bmx280->chip_id);
return ESP_OK; #else
ESP_LOGI("bmx280", "Probe success: address=%hhx, id=%hhx", bmx280->dev_cfg.device_address, bmx280->chip_id);
#endif
return ESP_OK;
} }
else else
{ {
ESP_LOGE("bmx280", "Sensor model may be incorrect. Please check the sensor model configuration. If unsure, set it to AUTO.");
err = ESP_ERR_NOT_FOUND; err = ESP_ERR_NOT_FOUND;
} }
} }
#if !(CONFIG_USE_I2C_MASTER_DRIVER)
ESP_LOGW("bmx280", "Probe failure: address=%hhx, id=%hhx, reason=%s", bmx280->slave, bmx280->chip_id, esp_err_to_name(err)); ESP_LOGW("bmx280", "Probe failure: address=%hhx, id=%hhx, reason=%s", bmx280->slave, bmx280->chip_id, esp_err_to_name(err));
#else
ESP_LOGW("bmx280", "Probe failure: address=%hhx, id=%hhx, reason=%s", bmx280->dev_cfg.device_address, bmx280->chip_id, esp_err_to_name(err));
#endif
return err; return err;
} }
static esp_err_t bmx280_probe(bmx280_t *bmx280) static esp_err_t bmx280_probe(bmx280_t *bmx280)
{ {
#if !(CONFIG_USE_I2C_MASTER_DRIVER)
ESP_LOGI("bmx280", "Probing for BMP280/BME280 sensors on I2C %d", bmx280->i2c_port); ESP_LOGI("bmx280", "Probing for BMP280/BME280 sensors on I2C %d", bmx280->i2c_port);
esp_err_t err;
#if CONFIG_BMX280_ADDRESS_HI #if CONFIG_BMX280_ADDRESS_HI
bmx280->slave = 0xEE; bmx280->slave = 0xEE;
return bmx280_probe_address(bmx280); err = bmx280_probe_address(bmx280);
if (err != ESP_OK) ESP_LOGE("bmx280", "Sensor not found at 0x77 , Please check the address.");
return err;
#elif CONFIG_BMX280_ADDRESS_LO #elif CONFIG_BMX280_ADDRESS_LO
bmx280->slave = 0xEC; bmx280->slave = 0xEC;
return bmx280_probe_address(bmx280); err = bmx280_probe_address(bmx280);
if (err != ESP_OK) ESP_LOGE("bmx280", "Sensor not found at 0x76 , Please check the address.");
return err;
#else #else
esp_err_t err;
bmx280->slave = 0xEC; bmx280->slave = 0xEC;
if ((err = bmx280_probe_address(bmx280)) != ESP_OK) if ((err = bmx280_probe_address(bmx280)) != ESP_OK)
{ {
@ -240,6 +304,38 @@ static esp_err_t bmx280_probe(bmx280_t *bmx280)
} }
return err; return err;
#endif #endif
#else
ESP_LOGI("bmx280", "Probing for BMP280/BME280 sensors on I2C");
esp_err_t err;
#if CONFIG_BMX280_ADDRESS_HI
err = bmx280_device_create(bmx280, 0x77);
if (err != ESP_OK) return err;
err = bmx280_probe_address(bmx280);
if (err != ESP_OK) ESP_LOGE("bmx280", "Sensor not found at 0x77 , Please check the address.");
return err;
#elif CONFIG_BMX280_ADDRESS_LO
err = bmx280_device_create(bmx280, 0x76);
if (err != ESP_OK) return err;
err = bmx280_probe_address(bmx280);
if (err != ESP_OK) ESP_LOGE("bmx280", "Sensor not found at 0x76 , Please check the address.");
return err;
#else
err = bmx280_device_create(bmx280, 0x76);
if (err != ESP_OK) return err;
if ((err = bmx280_probe_address(bmx280)) != ESP_OK)
{
err = bmx280_device_create(bmx280, 0x77);
if (err != ESP_OK) return err;
if ((err = bmx280_probe_address(bmx280)) != ESP_OK)
{
ESP_LOGE("bmx280", "Sensor not found.");
bmx280->i2c_dev = NULL;
bmx280->chip_id = 0xAD;
}
}
return err;
#endif
#endif
} }
static esp_err_t bmx280_reset(bmx280_t *bmx280) static esp_err_t bmx280_reset(bmx280_t *bmx280)
@ -309,22 +405,55 @@ static esp_err_t bmx280_calibrate(bmx280_t *bmx280)
return ESP_OK; return ESP_OK;
} }
bmx280_t* bmx280_create(i2c_port_t port) #if !(CONFIG_USE_I2C_MASTER_DRIVER)
bmx280_t* bmx280_create_legacy(i2c_port_t port)
{ {
bmx280_t* bmx280 = malloc(sizeof(bmx280_t)); bmx280_t* bmx280 = malloc(sizeof(bmx280_t));
if (bmx280) if (bmx280)
{ {
memset(bmx280, 0, sizeof(bmx280_t)); memset(bmx280, 0, sizeof(bmx280_t));
bmx280->i2c_port = port; bmx280->i2c_port = port;
bmx280->slave = 0xDE; bmx280->slave = 0xDE;
bmx280->chip_id = 0xAD; bmx280->chip_id = 0xAD;
} }
else
{
ESP_LOGE("bmx280", "Failed to allocate memory for bmx280.");
bmx280_close(bmx280);
return NULL;
}
return bmx280; return bmx280;
} }
#else
bmx280_t* bmx280_create_master(i2c_master_bus_handle_t bus_handle)
{
bmx280_t* bmx280 = malloc(sizeof(bmx280_t));
if (bmx280)
{
memset(bmx280, 0, sizeof(bmx280_t));
bmx280->bus_handle = bus_handle;
bmx280->dev_cfg.dev_addr_length = I2C_ADDR_BIT_LEN_7;
bmx280->dev_cfg.device_address = 0xDE;
bmx280->dev_cfg.scl_speed_hz =CONFIG_BMX280_I2C_CLK_SPEED_HZ;
bmx280->i2c_dev = NULL;
bmx280->chip_id = 0xAD;
}
else
{
ESP_LOGE("bmx280", "Failed to allocate memory for bmx280.");
bmx280_close(bmx280);
return NULL;
}
return bmx280;
}
#endif
void bmx280_close(bmx280_t *bmx280) void bmx280_close(bmx280_t *bmx280)
{ {
#if CONFIG_USE_I2C_MASTER_DRIVER
if(bmx280->i2c_dev!=NULL)
i2c_master_bus_rm_device(bmx280->i2c_dev);
#endif
free(bmx280); free(bmx280);
} }

@ -0,0 +1,64 @@
#include "esp_log.h"
#include "bmx280.h"
#include "driver/i2c_types.h"
#define I2C_PORT_AUTO -1
#define BMX280_SDA_NUM GPIO_NUM_13
#define BMX280_SCL_NUM GPIO_NUM_14
i2c_master_bus_handle_t i2c_bus_init(uint8_t sda_io, uint8_t scl_io)
{
i2c_master_bus_config_t i2c_bus_config = {
.i2c_port = I2C_PORT_AUTO,
.sda_io_num = sda_io,
.scl_io_num = scl_io,
.clk_source = I2C_CLK_SRC_DEFAULT,
.glitch_ignore_cnt = 7,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus_handle;
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_bus_config, &bus_handle));
ESP_LOGI("test","I2C master bus created");
return bus_handle;
}
esp_err_t bmx280_dev_init(bmx280_t** bmx280,i2c_master_bus_handle_t bus_handle)
{
*bmx280 = bmx280_create_master(bus_handle);
if (!*bmx280) {
ESP_LOGE("test", "Could not create bmx280 driver.");
return ESP_FAIL;
}
ESP_ERROR_CHECK(bmx280_init(*bmx280));
bmx280_config_t bmx_cfg = BMX280_DEFAULT_CONFIG;
ESP_ERROR_CHECK(bmx280_configure(*bmx280, &bmx_cfg));
return ESP_OK;
}
void app_main(void)
{
// Entry Point
//ESP_ERROR_CHECK(nvs_flash_init());
i2c_master_bus_handle_t bus_handle = i2c_bus_init(BMX280_SDA_NUM, BMX280_SCL_NUM);
bmx280_t* bmx280 = NULL;
ESP_ERROR_CHECK(bmx280_dev_init(&bmx280,bus_handle));
ESP_ERROR_CHECK(bmx280_setMode(bmx280, BMX280_MODE_CYCLE));
float temp = 0, pres = 0, hum = 0;
for(int i = 0; i < 10; i++)
{
do {
vTaskDelay(pdMS_TO_TICKS(1));
} while(bmx280_isSampling(bmx280));
ESP_ERROR_CHECK(bmx280_readoutFloat(bmx280, &temp, &pres, &hum));
ESP_LOGI("test", "Read Values: temp = %f, pres = %f, hum = %f", temp, pres, hum);
vTaskDelay(pdMS_TO_TICKS(1000));
}
bmx280_close(bmx280);
i2c_del_master_bus(bus_handle);
ESP_LOGI("test", "Restarting now.");
esp_restart();
}

@ -0,0 +1,51 @@
#include "esp_log.h"
#include "bmx280.h"
#define BMX280_SDA_NUM GPIO_NUM_13
#define BMX280_SCL_NUM GPIO_NUM_14
void app_main(void)
{
// Entry Point
//ESP_ERROR_CHECK(nvs_flash_init());
i2c_config_t i2c_cfg = {
.mode = I2C_MODE_MASTER,
.sda_io_num = BMX280_SDA_NUM,
.scl_io_num = BMX280_SCL_NUM,
.sda_pullup_en = false,
.scl_pullup_en = false,
.master = {
.clk_speed = CONFIG_BMX280_I2C_CLK_SPEED_HZ
}
};
ESP_ERROR_CHECK(i2c_param_config(I2C_NUM_0, &i2c_cfg));
ESP_ERROR_CHECK(i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0));
bmx280_t* bmx280 = bmx280_create(I2C_NUM_0);
if (!bmx280) {
ESP_LOGE("test", "Could not create bmx280 driver.");
return;
}
ESP_ERROR_CHECK(bmx280_init(bmx280));
bmx280_config_t bmx_cfg = BMX280_DEFAULT_CONFIG;
ESP_ERROR_CHECK(bmx280_configure(bmx280, &bmx_cfg));
ESP_ERROR_CHECK(bmx280_setMode(bmx280, BMX280_MODE_CYCLE));
float temp = 0, pres = 0, hum = 0;
while (1)
{
do {
vTaskDelay(pdMS_TO_TICKS(1));
} while(bmx280_isSampling(bmx280));
ESP_ERROR_CHECK(bmx280_readoutFloat(bmx280, &temp, &pres, &hum));
ESP_LOGI("test", "Read Values: temp = %f, pres = %f, hum = %f", temp, pres, hum);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}

@ -16,9 +16,18 @@ extern "C" {
#include <stdint.h> #include <stdint.h>
#include <limits.h> #include <limits.h>
#include "driver/i2c.h" #include <assert.h>
#include "sdkconfig.h" #include "sdkconfig.h"
#include "bmx280_bits.h"
#if !(CONFIG_USE_I2C_MASTER_DRIVER)
#include "driver/i2c.h"
#else
#include "driver/i2c_master.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#endif
#define BMXAPI extern #define BMXAPI extern
/** /**
@ -26,14 +35,28 @@ extern "C" {
*/ */
typedef struct bmx280_t bmx280_t; typedef struct bmx280_t bmx280_t;
#include "bmx280_bits.h" #if CONFIG_USE_I2C_MASTER_DRIVER
/**
* Create an instance of the BMX280 driver.
* @param bus_handle The I2C master handle via port.
* @return A non-null pointer to the driver structure on success.
*/
BMXAPI bmx280_t* bmx280_create_master(i2c_master_bus_handle_t bus_handle);
// legacy define for existing code bases
#define bmx280_create(port) bmx280_create_legacy(port)
#define bmx280_create_legacy(port) static_assert(0, "You have the wrong driver configuration for using the legacy I2C driver.")
#else
/** /**
* Create an instance of the BMX280 driver. * Create an instance of the BMX280 driver.
* @param port The I2C port to use. * @param port The I2C port to use.
* @return A non-null pointer to the driver structure on success. * @return A non-null pointer to the driver structure on success.
*/ */
BMXAPI bmx280_t* bmx280_create(i2c_port_t port); BMXAPI bmx280_t* bmx280_create_legacy(i2c_port_t port);
// legacy define for existing code bases
#define bmx280_create(port) bmx280_create_legacy(port)
#define bmx280_create_master(port) static_assert(0, "You have the wrong driver configuration for using the new I2C master driver.")
#endif
/** /**
* Destroy your the instance. * Destroy your the instance.
* @param bmx280 The instance to destroy. * @param bmx280 The instance to destroy.