[esp32_camera] Allow sharing i2c bus (#9137)

Co-authored-by: Keith Burzinski <kbx81x@gmail.com>
This commit is contained in:
Jesse Hills 2025-06-19 18:31:19 +12:00 committed by GitHub
parent 2c17b2bacc
commit 4d0f8528d2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 134 additions and 94 deletions

View File

@ -1,5 +1,6 @@
from esphome import automation, pins
import esphome.codegen as cg
from esphome.components import i2c
from esphome.components.esp32 import add_idf_component
import esphome.config_validation as cv
from esphome.const import (
@ -7,6 +8,7 @@ from esphome.const import (
CONF_CONTRAST,
CONF_DATA_PINS,
CONF_FREQUENCY,
CONF_I2C_ID,
CONF_ID,
CONF_PIN,
CONF_RESET_PIN,
@ -149,7 +151,8 @@ CONF_ON_IMAGE = "on_image"
camera_range_param = cv.int_range(min=-2, max=2)
CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
CONFIG_SCHEMA = cv.All(
cv.ENTITY_BASE_SCHEMA.extend(
{
cv.GenerateID(): cv.declare_id(ESP32Camera),
# pin assignment
@ -167,12 +170,16 @@ CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
),
}
),
cv.Required(CONF_I2C_PINS): cv.Schema(
cv.Optional(CONF_I2C_PINS): cv.Schema(
{
cv.Required(CONF_SDA): pins.internal_gpio_output_pin_number,
cv.Required(CONF_SCL): pins.internal_gpio_output_pin_number,
}
),
cv.Optional(CONF_I2C_ID): cv.Any(
cv.use_id(i2c.InternalI2CBus),
msg="I2C bus must be an internal ESP32 I2C bus",
),
cv.Optional(CONF_RESET_PIN): pins.internal_gpio_output_pin_number,
cv.Optional(CONF_POWER_DOWN_PIN): pins.internal_gpio_output_pin_number,
# image
@ -204,7 +211,9 @@ CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
ENUM_GAIN_CEILING, upper=True
),
# white balance
cv.Optional(CONF_WB_MODE, default="AUTO"): cv.enum(ENUM_WB_MODE, upper=True),
cv.Optional(CONF_WB_MODE, default="AUTO"): cv.enum(
ENUM_WB_MODE, upper=True
),
# test pattern
cv.Optional(CONF_TEST_PATTERN, default=False): cv.boolean,
# framerates
@ -231,11 +240,15 @@ CONFIG_SCHEMA = cv.ENTITY_BASE_SCHEMA.extend(
),
cv.Optional(CONF_ON_IMAGE): automation.validate_automation(
{
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(ESP32CameraImageTrigger),
cv.GenerateID(CONF_TRIGGER_ID): cv.declare_id(
ESP32CameraImageTrigger
),
}
),
}
).extend(cv.COMPONENT_SCHEMA)
).extend(cv.COMPONENT_SCHEMA),
cv.has_exactly_one_key(CONF_I2C_PINS, CONF_I2C_ID),
)
SETTERS = {
# pin assignment
@ -280,6 +293,10 @@ async def to_code(config):
extclk = config[CONF_EXTERNAL_CLOCK]
cg.add(var.set_external_clock(extclk[CONF_PIN], extclk[CONF_FREQUENCY]))
if i2c_id := config.get(CONF_I2C_ID):
i2c_hub = await cg.get_variable(i2c_id)
cg.add(var.set_i2c_id(i2c_hub))
else:
i2c_pins = config[CONF_I2C_PINS]
cg.add(var.set_i2c_pins(i2c_pins[CONF_SDA], i2c_pins[CONF_SCL]))
cg.add(var.set_max_update_interval(1000 / config[CONF_MAX_FRAMERATE]))

View File

@ -1,9 +1,9 @@
#ifdef USE_ESP32
#include "esp32_camera.h"
#include "esphome/core/log.h"
#include "esphome/core/hal.h"
#include "esphome/core/application.h"
#include "esphome/core/hal.h"
#include "esphome/core/log.h"
#include <freertos/task.h>
@ -16,6 +16,12 @@ static const char *const TAG = "esp32_camera";
void ESP32Camera::setup() {
global_esp32_camera = this;
#ifdef USE_I2C
if (this->i2c_bus_ != nullptr) {
this->config_.sccb_i2c_port = this->i2c_bus_->get_port();
}
#endif
/* initialize time to now */
this->last_update_ = millis();
@ -246,6 +252,13 @@ void ESP32Camera::set_i2c_pins(uint8_t sda, uint8_t scl) {
this->config_.pin_sccb_sda = sda;
this->config_.pin_sccb_scl = scl;
}
#ifdef USE_I2C
void ESP32Camera::set_i2c_id(i2c::InternalI2CBus *i2c_bus) {
this->i2c_bus_ = i2c_bus;
this->config_.pin_sccb_sda = -1;
this->config_.pin_sccb_scl = -1;
}
#endif // USE_I2C
void ESP32Camera::set_reset_pin(uint8_t pin) { this->config_.pin_reset = pin; }
void ESP32Camera::set_power_down_pin(uint8_t pin) { this->config_.pin_pwdn = pin; }

View File

@ -2,13 +2,17 @@
#ifdef USE_ESP32
#include <esp_camera.h>
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#include "esphome/core/automation.h"
#include "esphome/core/component.h"
#include "esphome/core/entity_base.h"
#include "esphome/core/helpers.h"
#include <esp_camera.h>
#include <freertos/FreeRTOS.h>
#include <freertos/queue.h>
#ifdef USE_I2C
#include "esphome/components/i2c/i2c_bus.h"
#endif // USE_I2C
namespace esphome {
namespace esp32_camera {
@ -118,6 +122,9 @@ class ESP32Camera : public EntityBase, public Component {
void set_pixel_clock_pin(uint8_t pin);
void set_external_clock(uint8_t pin, uint32_t frequency);
void set_i2c_pins(uint8_t sda, uint8_t scl);
#ifdef USE_I2C
void set_i2c_id(i2c::InternalI2CBus *i2c_bus);
#endif // USE_I2C
void set_reset_pin(uint8_t pin);
void set_power_down_pin(uint8_t pin);
/* -- image */
@ -210,6 +217,9 @@ class ESP32Camera : public EntityBase, public Component {
uint32_t last_idle_request_{0};
uint32_t last_update_{0};
#ifdef USE_I2C
i2c::InternalI2CBus *i2c_bus_{nullptr};
#endif // USE_I2C
};
// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)