This commit is contained in:
2025-04-04 04:48:13 +02:00
commit 2790bfa772
50 changed files with 6158 additions and 0 deletions

20
main/CMakeLists.txt Normal file
View File

@@ -0,0 +1,20 @@
idf_component_register(SRCS
"hw/i2cbrn.c"
"hw/i2cbrn.h"
"components/util.c"
"components/util.h"
"hw/bme680b.c"
"hw/bme680b.h"
"hw/ccs811.c"
"hw/ccs811.h"
"hw/ina260.c"
"hw/ina260.h"
"hw/mcp23018.c"
"hw/mcp23018.h"
"hw/mpu9250.c"
"hw/mpu9250.h"
"components/sensors.c"
"components/sensors.h"
"main.c"
INCLUDE_DIRS ".")

88
main/components/sensors.c Normal file
View File

@@ -0,0 +1,88 @@
#include "sensors.h"
#define BLINK_GPIO 2
static uint8_t s_led_state = 0;
static void configure_led(void)
{
gpio_reset_pin(BLINK_GPIO);
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
}
void i2c_sensors_task(void *pvParameters)
{
// initialize the xLastWakeTime variable with the current time.
TickType_t last_wake_time = xTaskGetTickCount();
const TickType_t I2C0_TASK_SAMPLING_RATE = 5;
//
// initialize i2c device configuration
bme680b_init();
mpu9250_init();
mcp23018_init();
ina260_init();
ccs811_init();
configure_led();
int16_t accel[3], gyro[3], temp;
float accel_f[3], gyro_f[3], temp_f;
uint16_t eCO2;
uint16_t tvoc;
uint32_t volts;
uint32_t current;
uint32_t power;
// task loop entry point
for (;;)
{
//
// handle sensor
bme680_data_t data;
esp_err_t result = bme680_get_data(BME680_DEV_HANDLE, &data);
if (result != ESP_OK)
{
ESP_LOGE(TAG_BME, "bme680 device read failed (%s)", esp_err_to_name(result));
}
else
{
data.barometric_pressure = data.barometric_pressure / 100;
// ESP_LOGI(TAG, "dewpoint temperature:%.2f °C", data.dewpoint_temperature);
ESP_LOGI(TAG_BME, "air temperature: %.2f °C", data.air_temperature);
ESP_LOGI(TAG_BME, "relative humidity: %.2f %%", data.relative_humidity);
ESP_LOGI(TAG_BME, "barometric pressure: %.2f hPa", data.barometric_pressure);
// ESP_LOGI(TAG, "gas resistance: %.2f kOhms", data.gas_resistance / 1000);
// ESP_LOGI(TAG, "iaq score: %u (%s)", data.iaq_score, bme680_air_quality_to_string(data.iaq_score));
}
ccs811_get_data(&eCO2, &tvoc);
ESP_LOGI(TAG_CCS, "eCO₂: %d ppm, TVOC: %d ppb", eCO2, tvoc);
if (mpu9250_read_sensor_data(MPU9250_DEV_HANDLE, accel, gyro, &temp) == ESP_OK)
{
mpu9250_convert_data(accel, gyro, temp, accel_f, gyro_f, &temp_f);
ESP_LOGI(TAG_MPU, "Accel: X=%.2f g, Y=%.2f g, Z=%.2f g", accel_f[0], accel_f[1], accel_f[2]);
ESP_LOGI(TAG_MPU, "Gyro: X=%.2f°/s, Y=%.2f°/s, Z=%.2f°/s", gyro_f[0], gyro_f[1], gyro_f[2]);
ESP_LOGI(TAG_MPU, "Temperature: %.2f °C", temp_f);
}
else
{
ESP_LOGE(TAG_MPU, "Failed to read sensor data");
}
ina260_readParams(&volts, &current, &power);
ina260_printParams(volts, current, power);
gpio_set_level(BLINK_GPIO, s_led_state);
/* Toggle the LED state */
s_led_state = !s_led_state;
vTaskDelaySecUntil(&last_wake_time, I2C0_TASK_SAMPLING_RATE);
}
//
// free resources
bme680_delete(BME680_DEV_HANDLE);
vTaskDelete(NULL);
}

23
main/components/sensors.h Normal file
View File

@@ -0,0 +1,23 @@
#ifndef SENSORS_COMPONENT
#define SENSORS_COMPONENT
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "util.h"
#include "driver/gpio.h"
#include <bme680.h>
#include "esp_mac.h"
#include "../hw/bme680b.h"
#include "../hw/ccs811.h"
#include "../hw/i2cbrn.h"
#include "../hw/mcp23018.h"
#include "../hw/ina260.h"
#include "../hw/mpu9250.h"
#include "esp_log.h"
void i2c_sensors_task(void *pvParameters);
#endif

7
main/components/util.c Normal file
View File

@@ -0,0 +1,7 @@
#include "util.h"
void vTaskDelaySecUntil(TickType_t *previousWakeTime, const unsigned int sec)
{
const TickType_t xFrequency = ((sec * 100) / portTICK_PERIOD_MS);
vTaskDelayUntil(previousWakeTime, xFrequency);
}

9
main/components/util.h Normal file
View File

@@ -0,0 +1,9 @@
#ifndef UTIL_COMPONENT
#define UTIL_COMPONENT
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
void vTaskDelaySecUntil(TickType_t *previousWakeTime, const unsigned int sec);
#endif

51
main/hw/bme680b.c Normal file
View File

@@ -0,0 +1,51 @@
#include "bme680.h"
#include "bme680b.h"
#include "esp_log.h"
#include "i2cbrn.h"
bme680_config_t BME680_DEV_CFG = I2C_BME680_CONFIG_DEFAULT;
bme680_handle_t BME680_DEV_HANDLE;
void bme680_print_registers(bme680_handle_t handle)
{
/* configuration registers */
bme680_control_measurement_register_t ctrl_meas_reg;
bme680_control_humidity_register_t ctrl_humi_reg;
bme680_config_register_t config_reg;
bme680_control_gas0_register_t ctrl_gas0_reg;
bme680_control_gas1_register_t ctrl_gas1_reg;
/* attempt to read control humidity register */
bme680_get_control_humidity_register(handle, &ctrl_humi_reg);
/* attempt to read control measurement register */
bme680_get_control_measurement_register(handle, &ctrl_meas_reg);
/* attempt to read configuration register */
bme680_get_configuration_register(handle, &config_reg);
/* attempt to read control gas 0 register */
bme680_get_control_gas0_register(handle, &ctrl_gas0_reg);
/* attempt to read control gas 1 register */
bme680_get_control_gas1_register(handle, &ctrl_gas1_reg);
ESP_LOGI(TAG_BME, "Variant Id (0x%02x): %s", handle->variant_id, uint8_to_binary(handle->variant_id));
ESP_LOGI(TAG_BME, "Configuration (0x%02x): %s", config_reg.reg, uint8_to_binary(config_reg.reg));
ESP_LOGI(TAG_BME, "Control Measurement (0x%02x): %s", ctrl_meas_reg.reg, uint8_to_binary(ctrl_meas_reg.reg));
ESP_LOGI(TAG_BME, "Control Humidity (0x%02x): %s", ctrl_humi_reg.reg, uint8_to_binary(ctrl_humi_reg.reg));
ESP_LOGI(TAG_BME, "Control Gas 0 (0x%02x): %s", ctrl_gas0_reg.reg, uint8_to_binary(ctrl_gas0_reg.reg));
ESP_LOGI(TAG_BME, "Control Gas 1 (0x%02x): %s", ctrl_gas1_reg.reg, uint8_to_binary(ctrl_gas1_reg.reg));
}
void bme680b_init() {
// init device
bme680_init(i2c0_bus_hdl, &BME680_DEV_CFG, &BME680_DEV_HANDLE);
if (BME680_DEV_HANDLE == NULL)
{
ESP_LOGE(TAG_BME, "bme680 handle init failed");
assert(BME680_DEV_HANDLE);
}
bme680_print_registers(BME680_DEV_HANDLE);
}

13
main/hw/bme680b.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef BME680_COMPONENT
#define BME680_COMPONENT
#include <bme680.h>
#include "i2cbrn.h"
#define TAG_BME "BME680"
extern bme680_config_t BME680_DEV_CFG;
extern bme680_handle_t BME680_DEV_HANDLE;
void bme680_print_registers(bme680_handle_t handle);
void bme680b_init();
#endif

46
main/hw/ccs811.c Normal file
View File

@@ -0,0 +1,46 @@
#include "ccs811.h"
#define CONFIG_FREERTOS_HZ 100
i2c_device_config_t CCS811_DEV_CFG = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x5A,
.scl_speed_hz = 100000,
};
i2c_master_dev_handle_t CCS811_DEV_HANDLE;
void ccs811_init()
{
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &CCS811_DEV_CFG, &CCS811_DEV_HANDLE));
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CCS811_WAKE, 0);
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CCS811_POWER, 1);
vTaskDelay(10 / portTICK_PERIOD_MS);
uint8_t reset_seq[4] = {0x11, 0xE5, 0x72, 0x8A};
i2c_write_register(CCS811_DEV_HANDLE, 0xFF, reset_seq, sizeof(reset_seq)); //Reset
vTaskDelay(10 / portTICK_PERIOD_MS);
uint8_t status;
uint16_t version;
i2c_read_register_8(CCS811_DEV_HANDLE, 0x00, &status);
i2c_read_register_16(CCS811_DEV_HANDLE, 0x24, &version);
ESP_LOGW(TAG_CCS, "CCS811 status: %d, version: %d", status, version);
i2c_write_register(CCS811_DEV_HANDLE, 0xF4, NULL, 0); //start
vTaskDelay(10 / portTICK_PERIOD_MS);
i2c_write_register_8(CCS811_DEV_HANDLE, 0x10, 0x0001); // MODE 1 interrupts vypnuté
i2c_read_register_8(CCS811_DEV_HANDLE, 0x00, &status);
i2c_read_register_16(CCS811_DEV_HANDLE, 0x24, &version);
ESP_LOGW(TAG_CCS, "CCS811 status: %d, version: %d", status, version);
}
esp_err_t ccs811_get_data(uint16_t * eCO2, uint16_t * tvoc)
{
uint8_t ccsResult[8];
esp_err_t ret = i2c_read_register(CCS811_DEV_HANDLE, 0x05, ccsResult, 8);
if (ret == ESP_OK)
{
*eCO2 = (ccsResult[0] << 8) | ccsResult[1];
*tvoc = (ccsResult[2] << 8) | ccsResult[3];
ESP_LOGI(TAG_CCS, "CCS Status: %d, Error %d", ccsResult[4], ccsResult[5]);
}
return ret;
}

15
main/hw/ccs811.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef CCS811_COMPONENT
#define CCS811_COMPONENT
#include "i2cbrn.h"
#include "mcp23018.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#define TAG_CCS "CCS811"
extern i2c_device_config_t CCS811_DEV_CFG;
extern i2c_master_dev_handle_t CCS811_DEV_HANDLE;
void ccs811_init();
esp_err_t ccs811_get_data(uint16_t * eCO2, uint16_t * tvoc);
#endif

204
main/hw/i2cbrn.c Normal file
View File

@@ -0,0 +1,204 @@
#include "i2cbrn.h"
i2c_master_bus_config_t i2c0_bus_cfg = {
.clk_source = I2C_CLK_SRC_DEFAULT,
.i2c_port = I2C_NUM_0,
.scl_io_num = GPIO_NUM_9,
.sda_io_num = GPIO_NUM_8,
.glitch_ignore_cnt = 7,
.flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t i2c0_bus_hdl;
esp_err_t i2c_master_bus_detect_devices(i2c_master_bus_handle_t handle)
{
const uint16_t probe_timeout_ms = 50; // timeout in milliseconds
uint8_t address;
printf(" 0 1 2 3 4 5 6 7 8 9 a b c d e f\r\n");
for (int i = 0; i < 128; i += 16)
{
printf("%02x: ", i);
for (int j = 0; j < 16; j++)
{
fflush(stdout);
address = i + j;
esp_err_t ret = i2c_master_probe(handle, address, probe_timeout_ms);
if (ret == ESP_OK)
{
printf("%02x ", address);
}
else if (ret == ESP_ERR_TIMEOUT)
{
printf("UU ");
}
else
{
printf("-- ");
}
}
printf("\r\n");
}
return ESP_OK;
}
/**
* @brief Writes data to a specific register of an I2C device.
*
* @param dev_handle I2C device handle
* @param reg_addr Register address to write to
* @param data Pointer to the data buffer to write
* @param len Number of bytes to write
* @return esp_err_t ESP_OK on success, or an error code
*/
esp_err_t i2c_write_register(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t *data, size_t len)
{
if (len == 0) {
// If no data, send just the register address
return i2c_master_transmit(dev_handle, &reg_addr, 1, I2C_TIMEOUT_MS_VALUE);
}
uint8_t buffer[len + 1];
buffer[0] = reg_addr;
memcpy(&buffer[1], data, len);
esp_err_t ret = i2c_master_transmit(dev_handle, buffer, sizeof(buffer), I2C_TIMEOUT_MS_VALUE);
if (ret == ESP_OK)
{
ESP_LOGV(TAG_I2C, "Write to register 0x%02X successful", reg_addr);
}
else
{
ESP_LOGE(TAG_I2C, "Write to register 0x%02X failed: %s", reg_addr, esp_err_to_name(ret));
}
return ret;
}
/**
* @brief Reads data from a specific register of an I2C device.
*
* @param dev_handle I2C device handle
* @param reg_addr Register address to read from
* @param data Pointer to a buffer to store read data
* @param len Number of bytes to read
* @return esp_err_t ESP_OK on success, or an error code
*/
esp_err_t i2c_read_register(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t *data, size_t len)
{
esp_err_t ret = i2c_master_transmit_receive(dev_handle, &reg_addr, 1, data, len, I2C_TIMEOUT_MS_VALUE);
if (ret == ESP_OK)
{
ESP_LOGV(TAG_I2C, "Read from register 0x%02X successful", reg_addr);
}
else
{
ESP_LOGE(TAG_I2C, "Read from register 0x%02X failed: %s", reg_addr, esp_err_to_name(ret));
}
return ret;
}
/**
* @brief Writes a 16-bit value to a specific register of an I2C device.
*
* @param dev_handle I2C device handle
* @param reg_addr Register address to write to
* @param value 16-bit value to write
* @return esp_err_t ESP_OK on success, or an error code
*/
esp_err_t i2c_write_register_16(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint16_t value)
{
uint8_t buffer[3];
buffer[0] = reg_addr; // Register address
buffer[1] = (value >> 8); // High byte
buffer[2] = (value & 0xFF); // Low byte
esp_err_t ret = i2c_master_transmit(dev_handle, buffer, sizeof(buffer), I2C_TIMEOUT_MS_VALUE);
if (ret == ESP_OK)
{
ESP_LOGV(TAG_I2C, "Write to register 0x%02X successful (Value: 0x%04X)", reg_addr, value);
}
else
{
ESP_LOGE(TAG_I2C, "Write to register 0x%02X failed: %s", reg_addr, esp_err_to_name(ret));
}
return ret;
}
/**
* @brief Reads a 16-bit value from a specific register of an I2C device.
*
* @param dev_handle I2C device handle
* @param reg_addr Register address to read from
* @param value Pointer to store the read 16-bit value
* @return esp_err_t ESP_OK on success, or an error code
*/
esp_err_t i2c_read_register_16(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint16_t *value)
{
uint8_t buffer[2];
esp_err_t ret = i2c_master_transmit_receive(dev_handle, &reg_addr, 1, buffer, sizeof(buffer), I2C_TIMEOUT_MS_VALUE);
if (ret == ESP_OK)
{
*value = (buffer[0] << 8) | buffer[1]; // Combine MSB and LSB
ESP_LOGV(TAG_I2C, "Read from register 0x%02X successful (Value: 0x%04X)", reg_addr, *value);
}
else
{
ESP_LOGE(TAG_I2C, "Read from register 0x%02X failed: %s", reg_addr, esp_err_to_name(ret));
}
return ret;
}
/**
* @brief Writes an 8-bit value to a specific register of an I2C device.
*
* @param dev_handle I2C device handle
* @param reg_addr Register address to write to
* @param value 8-bit value to write
* @return esp_err_t ESP_OK on success, or an error code
*/
esp_err_t i2c_write_register_8(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t value)
{
uint8_t buffer[2];
buffer[0] = reg_addr; // Register address
buffer[1] = value; // 8-bit value
esp_err_t ret = i2c_master_transmit(dev_handle, buffer, sizeof(buffer), I2C_TIMEOUT_MS_VALUE);
if (ret == ESP_OK)
{
ESP_LOGV(TAG_I2C, "Write to register 0x%02X successful (Value: 0x%02X)", reg_addr, value);
}
else
{
ESP_LOGE(TAG_I2C, "Write to register 0x%02X failed: %s", reg_addr, esp_err_to_name(ret));
}
return ret;
}
/**
* @brief Reads an 8-bit value from a specific register of an I2C device.
*
* @param dev_handle I2C device handle
* @param reg_addr Register address to read from
* @param value Pointer to store the read 8-bit value
* @return esp_err_t ESP_OK on success, or an error code
*/
esp_err_t i2c_read_register_8(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t *value)
{
esp_err_t ret = i2c_master_transmit_receive(dev_handle, &reg_addr, 1, value, 1, I2C_TIMEOUT_MS_VALUE);
if (ret == ESP_OK)
{
ESP_LOGV(TAG_I2C, "Read from register 0x%02X successful (Value: 0x%02X)", reg_addr, *value);
}
else
{
ESP_LOGE(TAG_I2C, "Read from register 0x%02X failed: %s", reg_addr, esp_err_to_name(ret));
}
return ret;
}

20
main/hw/i2cbrn.h Normal file
View File

@@ -0,0 +1,20 @@
#ifndef I2CBRN_COMPONENT
#define I2CBRN_COMPONENT
#define I2C_TIMEOUT_MS_VALUE 20
#include <string.h>
#include "esp_log.h"
#define TAG_I2C "cani2c"
#include "driver/i2c_master.h"
extern i2c_master_bus_config_t i2c0_bus_cfg;
extern i2c_master_bus_handle_t i2c0_bus_hdl;
esp_err_t i2c_master_bus_detect_devices(i2c_master_bus_handle_t handle);
esp_err_t i2c_write_register(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t *data, size_t len);
esp_err_t i2c_read_register(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t *data, size_t len);
esp_err_t i2c_write_register_16(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint16_t value);
esp_err_t i2c_read_register_16(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint16_t *value);
esp_err_t i2c_write_register_8(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t value);
esp_err_t i2c_read_register_8(i2c_master_dev_handle_t dev_handle, uint8_t reg_addr, uint8_t *value);
#endif

53
main/hw/ina260.c Normal file
View File

@@ -0,0 +1,53 @@
#include "ina260.h"
i2c_device_config_t INA260_DEV_CFG = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x40,
.scl_speed_hz = 100000,
};
i2c_master_dev_handle_t INA260_DEV_HANDLE;
void ina260_init()
{
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &INA260_DEV_CFG, &INA260_DEV_HANDLE));
i2c_write_register_16(INA260_DEV_HANDLE, 0x00, 0x0FFF); // set ina max averaging and max time
}
void ina260_readParams(uint32_t *volt, uint32_t *cur, uint32_t *pow)
{
for (uint8_t reg_addr = 1; reg_addr <= 3; reg_addr++)
{
uint8_t reg_value[2] = {0}; // Buffer for storing register data
// Perform the register read
ESP_ERROR_CHECK(i2c_master_transmit_receive(INA260_DEV_HANDLE, &reg_addr, 1, reg_value, sizeof(reg_value), I2C_TIMEOUT_MS_VALUE));
switch (reg_addr)
{
case 1:
*cur = *((uint16_t *)reg_value);
break;
case 2:
*volt = *((uint16_t *)reg_value);
break;
case 3:
*pow = *((uint16_t *)reg_value);
break;
default:
break;
}
}
}
void ina260_printParams(uint32_t volt, uint32_t cur, uint32_t pow)
{
cur *= 125;
ESP_LOGI(TAG_INA, "Current: %ld.%ld mA", cur / 10000, cur % 10000);
cur *= 125;
ESP_LOGI(TAG_INA, "Voltage: %ld.%ld V", volt / 10000, volt % 10000);
ESP_LOGI(TAG_INA, "Power: %ld.%ld W", pow / 10000, pow % 10000);
}

15
main/hw/ina260.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef INA260_COMPONENT
#define INA260_COMPONENT
#include "i2cbrn.h"
#define TAG_INA "INA260"
extern i2c_device_config_t INA260_DEV_CFG;
extern i2c_master_dev_handle_t INA260_DEV_HANDLE;
void ina260_init();
void ina260_readParams(uint32_t *volt, uint32_t *cur, uint32_t *pow);
void ina260_printParams(uint32_t volt, uint32_t cur, uint32_t pow);
#endif

51
main/hw/mcp23018.c Normal file
View File

@@ -0,0 +1,51 @@
#include "mcp23018.h"
// Local buffer for tracking GPIO state
i2c_device_config_t MCP23018_DEV_CFG = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x20,
.scl_speed_hz = 100000,
};
i2c_master_dev_handle_t MCP23018_DEV_HANDLE;
uint8_t gpioa_state = 0x00; // All LOW initially
uint8_t gpiob_state = 0x00; // All LOW initially
void mcp23018_set_pin(i2c_master_dev_handle_t dev_handle, uint8_t pin, uint8_t value)
{
if (pin < 8)
{
// GPIOA (Pins 0-7)
if (value)
gpioa_state |= (1 << pin); // Set bit
else
gpioa_state &= ~(1 << pin); // Clear bit
// Write updated buffer to MCP23018
i2c_write_register_8(dev_handle, MCP23018_GPIOA, gpioa_state);
}
else if (pin < 16)
{
// GPIOB (Pins 8-15)
uint8_t pinB = pin - 8;
if (value)
gpiob_state |= (1 << pinB); // Set bit
else
gpiob_state &= ~(1 << pinB); // Clear bit
// Write updated buffer to MCP23018
i2c_write_register_8(dev_handle, MCP23018_GPIOB, gpiob_state);
}
}
void mcp23018_init()
{
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &MCP23018_DEV_CFG, &MCP23018_DEV_HANDLE));
i2c_write_register_8(MCP23018_DEV_HANDLE, MCP23018_IODIRA, gpioa_state);
i2c_write_register_8(MCP23018_DEV_HANDLE, MCP23018_IODIRB, gpiob_state);
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CS_ADC_CO, 1);
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CS_ADC_NH3, 1);
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CS_ADC_NO2, 1);
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_CS_ADC_UVC, 1);
mcp23018_set_pin(MCP23018_DEV_HANDLE, MCP_LORA_RST, 1);
}

31
main/hw/mcp23018.h Normal file
View File

@@ -0,0 +1,31 @@
#ifndef MCP23018_COMPONENT
#define MCP23018_COMPONENT
#include "i2cbrn.h"
#define TAG_MCP "MCP23018"
#define MCP23018_IODIRA 0x00 // I/O Direction A
#define MCP23018_IODIRB 0x01 // I/O Direction B
#define MCP23018_GPIOA 0x12 // GPIO Output A
#define MCP23018_GPIOB 0x13 // GPIO Output B
#define MCP_LORA_RST 4
#define MCP_MICS_POWER 5
#define MCP_CCS811_WAKE 6
#define MCP_CCS811_POWER 7
#define MCP_CS_ADC_NH3 8
#define MCP_CS_ADC_CO 9
#define MCP_CS_ADC_NO2 10
#define MCP_CS_ADC_UVC 11
extern i2c_device_config_t MCP23018_DEV_CFG;
extern i2c_master_dev_handle_t MCP23018_DEV_HANDLE;
extern uint8_t gpioa_state;
extern uint8_t gpiob_state;
void mcp23018_set_pin(i2c_master_dev_handle_t dev_handle, uint8_t pin, uint8_t value);
void mcp23018_init();
#endif

46
main/hw/mpu9250.c Normal file
View File

@@ -0,0 +1,46 @@
#include "mpu9250.h"
i2c_device_config_t MPU9250_DEV_CFG = {
.dev_addr_length = I2C_ADDR_BIT_LEN_7,
.device_address = 0x68,
.scl_speed_hz = 100000,
};
i2c_master_dev_handle_t MPU9250_DEV_HANDLE;
esp_err_t mpu9250_read_sensor_data(i2c_master_dev_handle_t dev_handle, int16_t *accel, int16_t *gyro, int16_t *temp)
{
uint8_t buffer[14]; // 6 (Accel) + 2 (Temp) + 6 (Gyro)
esp_err_t ret = i2c_read_register(dev_handle, 0x3B, buffer, 14);
if (ret != ESP_OK)
return ret;
// Convert raw data (Big-Endian)
accel[0] = (buffer[0] << 8) | buffer[1]; // Accel X
accel[1] = (buffer[2] << 8) | buffer[3]; // Accel Y
accel[2] = (buffer[4] << 8) | buffer[5]; // Accel Z
*temp = (buffer[6] << 8) | buffer[7]; // Temperature
gyro[0] = (buffer[8] << 8) | buffer[9]; // Gyro X
gyro[1] = (buffer[10] << 8) | buffer[11]; // Gyro Y
gyro[2] = (buffer[12] << 8) | buffer[13]; // Gyro Z
return ESP_OK;
}
void mpu9250_convert_data(int16_t *accel, int16_t *gyro, int16_t temp, float *accel_out, float *gyro_out, float *temp_out)
{
accel_out[0] = accel[0] / 16384.0; // Accel X in g
accel_out[1] = accel[1] / 16384.0; // Accel Y in g
accel_out[2] = accel[2] / 16384.0; // Accel Z in g
gyro_out[0] = gyro[0] / 131.0; // Gyro X in deg/s
gyro_out[1] = gyro[1] / 131.0; // Gyro Y in deg/s
gyro_out[2] = gyro[2] / 131.0; // Gyro Z in deg/s
*temp_out = (temp / 333.87) + 21.0; // Temperature in °C
}
void mpu9250_init() {
ESP_ERROR_CHECK(i2c_master_bus_add_device(i2c0_bus_hdl, &MPU9250_DEV_CFG, &MPU9250_DEV_HANDLE));
i2c_write_register_16(MPU9250_DEV_HANDLE, 0x6B, 0x0001); // zapni uz tu hovadinu
}

15
main/hw/mpu9250.h Normal file
View File

@@ -0,0 +1,15 @@
#ifndef MPU9250_COMPONENT
#define MPU9250_COMPONENT
#include "i2cbrn.h"
#define TAG_MPU "MPU9250"
extern i2c_device_config_t MPU9250_DEV_CFG;
extern i2c_master_dev_handle_t MPU9250_DEV_HANDLE;
esp_err_t mpu9250_read_sensor_data(i2c_master_dev_handle_t dev_handle, int16_t *accel, int16_t *gyro, int16_t *temp);
void mpu9250_convert_data(int16_t *accel, int16_t *gyro, int16_t temp, float *accel_out, float *gyro_out, float *temp_out);
void mpu9250_init();
#endif

17
main/idf_component.yml Normal file
View File

@@ -0,0 +1,17 @@
## IDF Component Manager Manifest File
dependencies:
## Required IDF version
idf:
version: '>=4.1.0'
# # Put list of dependencies here
# # For components maintained by Espressif:
# component: "~1.0.0"
# # For 3rd party components:
# username/component: ">=1.0.0,<2.0.0"
# username2/component2:
# version: "~1.0.0"
# # For transient dependencies `public` flag can be set.
# # `public` flag doesn't have an effect dependencies of the `main` component.
# # All dependencies of `main` are public by default.
# public: true
k0i05/esp_bme680: ^1.2.5

57
main/main.c Normal file
View File

@@ -0,0 +1,57 @@
/* Blink 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 "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"
#include "sdkconfig.h"
#include "esp_mac.h"
#include <string.h>
#include "components/sensors.h"
#include "components/util.h"
#include "hw/bme680b.h"
#include "hw/ccs811.h"
#include "hw/i2cbrn.h"
#include "hw/ina260.h"
#include "hw/mcp23018.h"
#include "hw/mpu9250.h"
#define TAG "cantest"
#define CONFIG_FREERTOS_HZ 100
void app_main(void)
{
/* instantiate i2c master bus 0 */
ESP_ERROR_CHECK(i2c_new_master_bus(&i2c0_bus_cfg, &i2c0_bus_hdl));
/* scan i2c devices on i2c master bus 0 and print results */
ESP_ERROR_CHECK(i2c_master_bus_detect_devices(i2c0_bus_hdl));
/* create task pinned to the app core */
xTaskCreatePinnedToCore(
i2c_sensors_task,
"I2CTaskBME",
8192,
NULL,
(tskIDLE_PRIORITY + 2),
NULL,
APP_CPU_NUM);
while (1)
{
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}