mirror of
https://github.com/alexandrebobkov/ESP-Nodes.git
synced 2024-09-19 23:26:26 -04:00
203 lines
8.2 KiB
C
203 lines
8.2 KiB
C
|
|
/* ESP32 Module I2C Master Device
|
|
|
|
Author: Alexander Bobkov
|
|
Date: July 3, 2024
|
|
Modified: July 9, 2024
|
|
|
|
|
|
Adopted from i2c - Simple example
|
|
|
|
Simple I2C example that shows how to initialize I2C
|
|
as well as reading and writing from and to registers for a sensor connected over I2C.
|
|
|
|
The sensor used in this example is a MPU9250 inertial measurement unit.
|
|
|
|
For other examples please check:
|
|
https://github.com/espressif/esp-idf/tree/master/examples
|
|
|
|
See README.md file to get detailed usage of this example.
|
|
|
|
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
|
|
|
Unless required by applicable law or agreed to in writing, this
|
|
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
CONDITIONS OF ANY KIND, either express or implied.
|
|
*/
|
|
#include <stdio.h>
|
|
#include "esp_log.h"
|
|
#include "driver/i2c.h"
|
|
#include "bme280.h"
|
|
|
|
static const char *TAG = "i2c-simple-example";
|
|
|
|
#define I2C_MASTER_SCL_IO CONFIG_I2C_MASTER_SCL /*!< GPIO number used for I2C master clock */
|
|
#define I2C_MASTER_SDA_IO CONFIG_I2C_MASTER_SDA /*!< GPIO number used for I2C master data */
|
|
#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C master i2c port number, the number of i2c peripheral interfaces available will depend on the chip */
|
|
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
|
|
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
|
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
|
#define I2C_MASTER_TIMEOUT_MS 1000
|
|
#define I2C_ACKS 0x1
|
|
#define I2C_ACKM 0x0
|
|
#define I2C_NOACKM 0x1 // I2C NACK value
|
|
#define I2C_WRITE_BIT I2C_MASTER_WRITE
|
|
#define I2C_RED_BIT I2C_MASTER_READ
|
|
|
|
#define MPU9250_SENSOR_ADDR 0x76 /*!< Slave address of the MPU9250 sensor */
|
|
#define MPU9250_WHO_AM_I_REG_ADDR 0xD0 /*!< Register addresses of the "who am I" register */
|
|
|
|
#define MPU9250_PWR_MGMT_1_REG_ADDR 0x88 /*!< Register addresses of the power managment register */
|
|
#define MPU9250_RESET_BIT 7
|
|
|
|
/**
|
|
* @brief Read a sequence of bytes from a MPU9250 sensor registers
|
|
*/
|
|
static esp_err_t mpu9250_register_read(uint8_t reg_addr, uint8_t *data, size_t len)
|
|
{
|
|
return i2c_master_write_read_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, ®_addr, 1, data, len, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
|
}
|
|
|
|
/*static esp_err_t bme280_I2C_burst_read(uint8_t device_address, uint8_t register_address, uint8_t *registers_data, size_t count)
|
|
{
|
|
int command_result = 0;
|
|
//unsigned char array[BME280_I2C_BUFFER_LEN];
|
|
unsigned char pos;
|
|
array[0] = register_address;
|
|
command_result = i2c_master_write_read_device(0, device_address, write_buffer, write_size, *array, read_size, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
|
//error = i2c_master_write_read_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, ®ister_address, 1, registers_data, count, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
|
}*/
|
|
|
|
static esp_err_t bme280_read_raw_temperature(uint8_t device_address, uint8_t *raw_temperature) {
|
|
// BME280_INIT_VALUE LN 136
|
|
// BME280_TEMPERATURE_MSB_REG 0xFA
|
|
// BME280_TEMPERATURE_DATA_LENGTH
|
|
// BME280_TEMPERATURE_DATA_SIZE
|
|
// I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS
|
|
|
|
esp_err_t command_result;
|
|
//unsigned char raw_temperature[BME280_TEMPERATURE_DATA_SIZE] = {0, 0, 0};
|
|
//command_result = i2c_master_read_from_device(0, BME280_I2C_ADDRESS1, *raw_temperature, BME280_TEMPERATURE_DATA_SIZE, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
|
command_result = i2c_master_write_read_device(0, device_address, *raw_temperature, BME280_TEMPERATURE_DATA_SIZE, BME280_TEMPERATURE_REGISTER, 1, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
|
return command_result;
|
|
}
|
|
|
|
/**
|
|
* @brief Write a byte to a MPU9250 sensor register
|
|
*/
|
|
static esp_err_t mpu9250_register_write_byte(uint8_t reg_addr, uint8_t data)
|
|
{
|
|
int ret;
|
|
uint8_t write_buf[2] = {reg_addr, data};
|
|
|
|
ret = i2c_master_write_to_device(I2C_MASTER_NUM, MPU9250_SENSOR_ADDR, write_buf, sizeof(write_buf), I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* @brief i2c master initialization
|
|
|
|
static esp_err_t i2c_master_init(void)
|
|
{
|
|
int i2c_master_port = I2C_MASTER_NUM;
|
|
|
|
i2c_config_t conf = {
|
|
.mode = I2C_MODE_MASTER,
|
|
.sda_io_num = I2C_MASTER_SDA_IO,
|
|
.scl_io_num = I2C_MASTER_SCL_IO,
|
|
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
|
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
|
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
|
};
|
|
|
|
i2c_param_config(i2c_master_port, &conf);
|
|
|
|
return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
|
|
}*/
|
|
|
|
/**
|
|
* @brief Initialize ESP32 as an I2C master device
|
|
*/
|
|
static esp_err_t i2c_driver_initialize(void)
|
|
{
|
|
int i2c_master_port = 0;
|
|
|
|
i2c_config_t conf = {
|
|
.mode = I2C_MODE_MASTER,
|
|
.sda_io_num = GPIO_NUM_21,
|
|
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
|
.scl_io_num = GPIO_NUM_22,
|
|
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
|
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
|
.clk_flags= 0,
|
|
};
|
|
|
|
return i2c_param_config(i2c_master_port, &conf);
|
|
}
|
|
|
|
void app_main(void)
|
|
{
|
|
// CONNECT TO BMP280
|
|
ESP_ERROR_CHECK(i2c_driver_initialize());
|
|
i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
|
|
uint8_t address = 0x76;
|
|
i2c_cmd_handle_t command = i2c_cmd_link_create();
|
|
i2c_master_start(command);
|
|
i2c_master_write_byte(command, (address << 1) | I2C_MASTER_WRITE, I2C_ACKS);// 0x1); // 0x1 -> check ACK from slave
|
|
i2c_master_stop(command);
|
|
esp_err_t cmd_ret = i2c_master_cmd_begin(I2C_NUM_0, command, I2C_MASTER_TIMEOUT_MS / portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(command);
|
|
i2c_driver_delete(I2C_NUM_0);
|
|
if (cmd_ret == ESP_OK)
|
|
ESP_LOGI(TAG, "I2C device found at address 0x%X", address);
|
|
else
|
|
ESP_LOGI(TAG, "error %X", cmd_ret);
|
|
|
|
// REQUEST DEVICE ID
|
|
// The sequence of commands corresponds to the BME-280 I2C protocol
|
|
int len = 1; // 1 byte
|
|
uint8_t *data = malloc(len);
|
|
//uint8_t address = 0x76;
|
|
uint8_t register_address = 0xD0; // Register that stores device ID
|
|
ESP_ERROR_CHECK(i2c_driver_initialize());
|
|
i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
|
|
command = i2c_cmd_link_create();
|
|
// Step 1. START
|
|
i2c_master_start(command);
|
|
// Step 2. Send device address, WRITE bit, and wait for acknowledgment
|
|
i2c_master_write_byte(command, address << 1 | I2C_MASTER_WRITE, 0x1);
|
|
// Step 3. Specify (write) register address, and wait for acknowledgment
|
|
i2c_master_write_byte(command, register_address, 0x1);
|
|
// Step 4. START
|
|
i2c_master_start(command);
|
|
// Step 5. Send device address, READ bit, and wait for acknowledgment
|
|
i2c_master_write_byte(command, address << 1 | I2C_MASTER_READ, 0x1);
|
|
if (len > 1)
|
|
i2c_master_read(command, data, len-1, 0x0);
|
|
// Step 6. Read one byte of data from register
|
|
i2c_master_read_byte(command, data+len-1, 0x1);
|
|
// Step 8. STOP
|
|
i2c_master_stop(command);
|
|
// Step 7. Read one byte of data from register
|
|
cmd_ret = i2c_master_cmd_begin(I2C_NUM_0, command, 1000 / portTICK_PERIOD_MS);
|
|
i2c_cmd_link_delete(command);
|
|
if (cmd_ret == ESP_OK) {
|
|
ESP_LOGI(TAG, "Register read success");
|
|
for (int i = 0; i < len; i++) {
|
|
//printf("0x%02x ", data[i]);
|
|
if (data[i] == 0x60)
|
|
ESP_LOGI(TAG, "Device ID is 0x%X (BME-280)", data[i]);
|
|
else if (data[i] == 0x58)
|
|
ESP_LOGI(TAG, "Device ID is 0x%X (BMP-280)", data[i]);
|
|
else
|
|
ESP_LOGI(TAG, "Device ID is 0x%X", data[i]);
|
|
}
|
|
} else if (cmd_ret == ESP_ERR_TIMEOUT) {
|
|
ESP_LOGW(TAG, "Bus is busy");
|
|
} else {
|
|
ESP_LOGW(TAG, "Read failed");
|
|
}
|
|
free(data);
|
|
i2c_driver_delete(I2C_NUM_0);
|
|
} |