mirror of
				https://github.com/esphome/esphome.git
				synced 2025-10-30 22:53:59 +00:00 
			
		
		
		
	Add more configuration for microphones - i2s/pdm/adc (#4775)
This commit is contained in:
		| @@ -1 +1,118 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.const import CONF_INPUT | ||||
|  | ||||
| from esphome.core import CORE | ||||
| from esphome.components.esp32 import get_esp32_variant | ||||
| from esphome.components.esp32.const import ( | ||||
|     VARIANT_ESP32, | ||||
|     VARIANT_ESP32C3, | ||||
|     VARIANT_ESP32H2, | ||||
|     VARIANT_ESP32S2, | ||||
|     VARIANT_ESP32S3, | ||||
| ) | ||||
|  | ||||
| CODEOWNERS = ["@esphome/core"] | ||||
|  | ||||
| ATTENUATION_MODES = { | ||||
|     "0db": cg.global_ns.ADC_ATTEN_DB_0, | ||||
|     "2.5db": cg.global_ns.ADC_ATTEN_DB_2_5, | ||||
|     "6db": cg.global_ns.ADC_ATTEN_DB_6, | ||||
|     "11db": cg.global_ns.ADC_ATTEN_DB_11, | ||||
|     "auto": "auto", | ||||
| } | ||||
|  | ||||
| adc1_channel_t = cg.global_ns.enum("adc1_channel_t") | ||||
|  | ||||
| # From https://github.com/espressif/esp-idf/blob/master/components/driver/include/driver/adc_common.h | ||||
| # pin to adc1 channel mapping | ||||
| ESP32_VARIANT_ADC1_PIN_TO_CHANNEL = { | ||||
|     VARIANT_ESP32: { | ||||
|         36: adc1_channel_t.ADC1_CHANNEL_0, | ||||
|         37: adc1_channel_t.ADC1_CHANNEL_1, | ||||
|         38: adc1_channel_t.ADC1_CHANNEL_2, | ||||
|         39: adc1_channel_t.ADC1_CHANNEL_3, | ||||
|         32: adc1_channel_t.ADC1_CHANNEL_4, | ||||
|         33: adc1_channel_t.ADC1_CHANNEL_5, | ||||
|         34: adc1_channel_t.ADC1_CHANNEL_6, | ||||
|         35: adc1_channel_t.ADC1_CHANNEL_7, | ||||
|     }, | ||||
|     VARIANT_ESP32S2: { | ||||
|         1: adc1_channel_t.ADC1_CHANNEL_0, | ||||
|         2: adc1_channel_t.ADC1_CHANNEL_1, | ||||
|         3: adc1_channel_t.ADC1_CHANNEL_2, | ||||
|         4: adc1_channel_t.ADC1_CHANNEL_3, | ||||
|         5: adc1_channel_t.ADC1_CHANNEL_4, | ||||
|         6: adc1_channel_t.ADC1_CHANNEL_5, | ||||
|         7: adc1_channel_t.ADC1_CHANNEL_6, | ||||
|         8: adc1_channel_t.ADC1_CHANNEL_7, | ||||
|         9: adc1_channel_t.ADC1_CHANNEL_8, | ||||
|         10: adc1_channel_t.ADC1_CHANNEL_9, | ||||
|     }, | ||||
|     VARIANT_ESP32S3: { | ||||
|         1: adc1_channel_t.ADC1_CHANNEL_0, | ||||
|         2: adc1_channel_t.ADC1_CHANNEL_1, | ||||
|         3: adc1_channel_t.ADC1_CHANNEL_2, | ||||
|         4: adc1_channel_t.ADC1_CHANNEL_3, | ||||
|         5: adc1_channel_t.ADC1_CHANNEL_4, | ||||
|         6: adc1_channel_t.ADC1_CHANNEL_5, | ||||
|         7: adc1_channel_t.ADC1_CHANNEL_6, | ||||
|         8: adc1_channel_t.ADC1_CHANNEL_7, | ||||
|         9: adc1_channel_t.ADC1_CHANNEL_8, | ||||
|         10: adc1_channel_t.ADC1_CHANNEL_9, | ||||
|     }, | ||||
|     VARIANT_ESP32C3: { | ||||
|         0: adc1_channel_t.ADC1_CHANNEL_0, | ||||
|         1: adc1_channel_t.ADC1_CHANNEL_1, | ||||
|         2: adc1_channel_t.ADC1_CHANNEL_2, | ||||
|         3: adc1_channel_t.ADC1_CHANNEL_3, | ||||
|         4: adc1_channel_t.ADC1_CHANNEL_4, | ||||
|     }, | ||||
|     VARIANT_ESP32H2: { | ||||
|         0: adc1_channel_t.ADC1_CHANNEL_0, | ||||
|         1: adc1_channel_t.ADC1_CHANNEL_1, | ||||
|         2: adc1_channel_t.ADC1_CHANNEL_2, | ||||
|         3: adc1_channel_t.ADC1_CHANNEL_3, | ||||
|         4: adc1_channel_t.ADC1_CHANNEL_4, | ||||
|     }, | ||||
| } | ||||
|  | ||||
|  | ||||
| def validate_adc_pin(value): | ||||
|     if str(value).upper() == "VCC": | ||||
|         return cv.only_on_esp8266("VCC") | ||||
|  | ||||
|     if str(value).upper() == "TEMPERATURE": | ||||
|         return cv.only_on_rp2040("TEMPERATURE") | ||||
|  | ||||
|     if CORE.is_esp32: | ||||
|         value = pins.internal_gpio_input_pin_number(value) | ||||
|         variant = get_esp32_variant() | ||||
|         if variant not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL: | ||||
|             raise cv.Invalid(f"This ESP32 variant ({variant}) is not supported") | ||||
|  | ||||
|         if value not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant]: | ||||
|             raise cv.Invalid(f"{variant} doesn't support ADC on this pin") | ||||
|         return pins.internal_gpio_input_pin_schema(value) | ||||
|  | ||||
|     if CORE.is_esp8266: | ||||
|         from esphome.components.esp8266.gpio import CONF_ANALOG | ||||
|  | ||||
|         value = pins.internal_gpio_pin_number({CONF_ANALOG: True, CONF_INPUT: True})( | ||||
|             value | ||||
|         ) | ||||
|  | ||||
|         if value != 17:  # A0 | ||||
|             raise cv.Invalid("ESP8266: Only pin A0 (GPIO17) supports ADC.") | ||||
|         return pins.gpio_pin_schema( | ||||
|             {CONF_ANALOG: True, CONF_INPUT: True}, internal=True | ||||
|         )(value) | ||||
|  | ||||
|     if CORE.is_rp2040: | ||||
|         value = pins.internal_gpio_input_pin_number(value) | ||||
|         if value not in (26, 27, 28, 29): | ||||
|             raise cv.Invalid("RP2040: Only pins 26, 27, 28 and 29 support ADC.") | ||||
|         return pins.internal_gpio_input_pin_schema(value) | ||||
|  | ||||
|     raise NotImplementedError | ||||
|   | ||||
| @@ -1,133 +1,27 @@ | ||||
| import esphome.codegen as cg | ||||
| import esphome.config_validation as cv | ||||
| from esphome import pins | ||||
| from esphome.components import sensor, voltage_sampler | ||||
| from esphome.components.esp32 import get_esp32_variant | ||||
| from esphome.const import ( | ||||
|     CONF_ATTENUATION, | ||||
|     CONF_RAW, | ||||
|     CONF_ID, | ||||
|     CONF_INPUT, | ||||
|     CONF_NUMBER, | ||||
|     CONF_PIN, | ||||
|     CONF_RAW, | ||||
|     DEVICE_CLASS_VOLTAGE, | ||||
|     STATE_CLASS_MEASUREMENT, | ||||
|     UNIT_VOLT, | ||||
| ) | ||||
| from esphome.core import CORE | ||||
| from esphome.components.esp32 import get_esp32_variant | ||||
| from esphome.components.esp32.const import ( | ||||
|     VARIANT_ESP32, | ||||
|     VARIANT_ESP32C3, | ||||
|     VARIANT_ESP32H2, | ||||
|     VARIANT_ESP32S2, | ||||
|     VARIANT_ESP32S3, | ||||
| ) | ||||
|  | ||||
| from . import ( | ||||
|     ATTENUATION_MODES, | ||||
|     ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, | ||||
|     validate_adc_pin, | ||||
| ) | ||||
|  | ||||
| AUTO_LOAD = ["voltage_sampler"] | ||||
|  | ||||
| ATTENUATION_MODES = { | ||||
|     "0db": cg.global_ns.ADC_ATTEN_DB_0, | ||||
|     "2.5db": cg.global_ns.ADC_ATTEN_DB_2_5, | ||||
|     "6db": cg.global_ns.ADC_ATTEN_DB_6, | ||||
|     "11db": cg.global_ns.ADC_ATTEN_DB_11, | ||||
|     "auto": "auto", | ||||
| } | ||||
|  | ||||
| adc1_channel_t = cg.global_ns.enum("adc1_channel_t") | ||||
|  | ||||
| # From https://github.com/espressif/esp-idf/blob/master/components/driver/include/driver/adc_common.h | ||||
| # pin to adc1 channel mapping | ||||
| ESP32_VARIANT_ADC1_PIN_TO_CHANNEL = { | ||||
|     VARIANT_ESP32: { | ||||
|         36: adc1_channel_t.ADC1_CHANNEL_0, | ||||
|         37: adc1_channel_t.ADC1_CHANNEL_1, | ||||
|         38: adc1_channel_t.ADC1_CHANNEL_2, | ||||
|         39: adc1_channel_t.ADC1_CHANNEL_3, | ||||
|         32: adc1_channel_t.ADC1_CHANNEL_4, | ||||
|         33: adc1_channel_t.ADC1_CHANNEL_5, | ||||
|         34: adc1_channel_t.ADC1_CHANNEL_6, | ||||
|         35: adc1_channel_t.ADC1_CHANNEL_7, | ||||
|     }, | ||||
|     VARIANT_ESP32S2: { | ||||
|         1: adc1_channel_t.ADC1_CHANNEL_0, | ||||
|         2: adc1_channel_t.ADC1_CHANNEL_1, | ||||
|         3: adc1_channel_t.ADC1_CHANNEL_2, | ||||
|         4: adc1_channel_t.ADC1_CHANNEL_3, | ||||
|         5: adc1_channel_t.ADC1_CHANNEL_4, | ||||
|         6: adc1_channel_t.ADC1_CHANNEL_5, | ||||
|         7: adc1_channel_t.ADC1_CHANNEL_6, | ||||
|         8: adc1_channel_t.ADC1_CHANNEL_7, | ||||
|         9: adc1_channel_t.ADC1_CHANNEL_8, | ||||
|         10: adc1_channel_t.ADC1_CHANNEL_9, | ||||
|     }, | ||||
|     VARIANT_ESP32S3: { | ||||
|         1: adc1_channel_t.ADC1_CHANNEL_0, | ||||
|         2: adc1_channel_t.ADC1_CHANNEL_1, | ||||
|         3: adc1_channel_t.ADC1_CHANNEL_2, | ||||
|         4: adc1_channel_t.ADC1_CHANNEL_3, | ||||
|         5: adc1_channel_t.ADC1_CHANNEL_4, | ||||
|         6: adc1_channel_t.ADC1_CHANNEL_5, | ||||
|         7: adc1_channel_t.ADC1_CHANNEL_6, | ||||
|         8: adc1_channel_t.ADC1_CHANNEL_7, | ||||
|         9: adc1_channel_t.ADC1_CHANNEL_8, | ||||
|         10: adc1_channel_t.ADC1_CHANNEL_9, | ||||
|     }, | ||||
|     VARIANT_ESP32C3: { | ||||
|         0: adc1_channel_t.ADC1_CHANNEL_0, | ||||
|         1: adc1_channel_t.ADC1_CHANNEL_1, | ||||
|         2: adc1_channel_t.ADC1_CHANNEL_2, | ||||
|         3: adc1_channel_t.ADC1_CHANNEL_3, | ||||
|         4: adc1_channel_t.ADC1_CHANNEL_4, | ||||
|     }, | ||||
|     VARIANT_ESP32H2: { | ||||
|         0: adc1_channel_t.ADC1_CHANNEL_0, | ||||
|         1: adc1_channel_t.ADC1_CHANNEL_1, | ||||
|         2: adc1_channel_t.ADC1_CHANNEL_2, | ||||
|         3: adc1_channel_t.ADC1_CHANNEL_3, | ||||
|         4: adc1_channel_t.ADC1_CHANNEL_4, | ||||
|     }, | ||||
| } | ||||
|  | ||||
|  | ||||
| def validate_adc_pin(value): | ||||
|     if str(value).upper() == "VCC": | ||||
|         return cv.only_on_esp8266("VCC") | ||||
|  | ||||
|     if str(value).upper() == "TEMPERATURE": | ||||
|         return cv.only_on_rp2040("TEMPERATURE") | ||||
|  | ||||
|     if CORE.is_esp32: | ||||
|         value = pins.internal_gpio_input_pin_number(value) | ||||
|         variant = get_esp32_variant() | ||||
|         if variant not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL: | ||||
|             raise cv.Invalid(f"This ESP32 variant ({variant}) is not supported") | ||||
|  | ||||
|         if value not in ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant]: | ||||
|             raise cv.Invalid(f"{variant} doesn't support ADC on this pin") | ||||
|         return pins.internal_gpio_input_pin_schema(value) | ||||
|  | ||||
|     if CORE.is_esp8266: | ||||
|         from esphome.components.esp8266.gpio import CONF_ANALOG | ||||
|  | ||||
|         value = pins.internal_gpio_pin_number({CONF_ANALOG: True, CONF_INPUT: True})( | ||||
|             value | ||||
|         ) | ||||
|  | ||||
|         if value != 17:  # A0 | ||||
|             raise cv.Invalid("ESP8266: Only pin A0 (GPIO17) supports ADC.") | ||||
|         return pins.gpio_pin_schema( | ||||
|             {CONF_ANALOG: True, CONF_INPUT: True}, internal=True | ||||
|         )(value) | ||||
|  | ||||
|     if CORE.is_rp2040: | ||||
|         value = pins.internal_gpio_input_pin_number(value) | ||||
|         if value not in (26, 27, 28, 29): | ||||
|             raise cv.Invalid("RP2040: Only pins 26, 27, 28 and 29 support ADC.") | ||||
|         return pins.internal_gpio_input_pin_schema(value) | ||||
|  | ||||
|     raise NotImplementedError | ||||
|  | ||||
|  | ||||
| def validate_config(config): | ||||
|     if config[CONF_RAW] and config.get(CONF_ATTENUATION, None) == "auto": | ||||
|   | ||||
| @@ -2,8 +2,9 @@ import esphome.config_validation as cv | ||||
| import esphome.codegen as cg | ||||
|  | ||||
| from esphome import pins | ||||
| from esphome.const import CONF_ID | ||||
| from esphome.components import microphone | ||||
| from esphome.const import CONF_ID, CONF_NUMBER | ||||
| from esphome.components import microphone, esp32 | ||||
| from esphome.components.adc import ESP32_VARIANT_ADC1_PIN_TO_CHANNEL, validate_adc_pin | ||||
|  | ||||
| from .. import ( | ||||
|     i2s_audio_ns, | ||||
| @@ -16,18 +17,59 @@ from .. import ( | ||||
| CODEOWNERS = ["@jesserockz"] | ||||
| DEPENDENCIES = ["i2s_audio"] | ||||
|  | ||||
| CONF_ADC_PIN = "adc_pin" | ||||
| CONF_ADC_TYPE = "adc_type" | ||||
| CONF_PDM = "pdm" | ||||
|  | ||||
| I2SAudioMicrophone = i2s_audio_ns.class_( | ||||
|     "I2SAudioMicrophone", I2SAudioIn, microphone.Microphone, cg.Component | ||||
| ) | ||||
|  | ||||
| CONFIG_SCHEMA = microphone.MICROPHONE_SCHEMA.extend( | ||||
| INTERNAL_ADC_VARIANTS = [esp32.const.VARIANT_ESP32] | ||||
| PDM_VARIANTS = [esp32.const.VARIANT_ESP32, esp32.const.VARIANT_ESP32S3] | ||||
|  | ||||
|  | ||||
| def validate_esp32_variant(config): | ||||
|     variant = esp32.get_esp32_variant() | ||||
|     if config[CONF_ADC_TYPE] == "external": | ||||
|         if config[CONF_PDM]: | ||||
|             if variant not in PDM_VARIANTS: | ||||
|                 raise cv.Invalid(f"{variant} does not support PDM") | ||||
|         return config | ||||
|     if config[CONF_ADC_TYPE] == "internal": | ||||
|         if variant not in INTERNAL_ADC_VARIANTS: | ||||
|             raise cv.Invalid(f"{variant} does not have an internal ADC") | ||||
|         return config | ||||
|     raise NotImplementedError | ||||
|  | ||||
|  | ||||
| BASE_SCHEMA = microphone.MICROPHONE_SCHEMA.extend( | ||||
|     { | ||||
|         cv.GenerateID(): cv.declare_id(I2SAudioMicrophone), | ||||
|         cv.GenerateID(CONF_I2S_AUDIO_ID): cv.use_id(I2SAudioComponent), | ||||
|         cv.Required(CONF_I2S_DIN_PIN): pins.internal_gpio_input_pin_number, | ||||
|     } | ||||
| ).extend(cv.COMPONENT_SCHEMA) | ||||
|  | ||||
| CONFIG_SCHEMA = cv.All( | ||||
|     cv.typed_schema( | ||||
|         { | ||||
|             "internal": BASE_SCHEMA.extend( | ||||
|                 { | ||||
|                     cv.Required(CONF_ADC_PIN): validate_adc_pin, | ||||
|                 } | ||||
|             ), | ||||
|             "external": BASE_SCHEMA.extend( | ||||
|                 { | ||||
|                     cv.Required(CONF_I2S_DIN_PIN): pins.internal_gpio_input_pin_number, | ||||
|                     cv.Required(CONF_PDM): cv.boolean, | ||||
|                 } | ||||
|             ), | ||||
|         }, | ||||
|         key=CONF_ADC_TYPE, | ||||
|     ), | ||||
|     validate_esp32_variant, | ||||
| ) | ||||
|  | ||||
|  | ||||
| async def to_code(config): | ||||
|     var = cg.new_Pvariable(config[CONF_ID]) | ||||
| @@ -35,6 +77,13 @@ async def to_code(config): | ||||
|  | ||||
|     await cg.register_parented(var, config[CONF_I2S_AUDIO_ID]) | ||||
|  | ||||
|     if config[CONF_ADC_TYPE] == "internal": | ||||
|         variant = esp32.get_esp32_variant() | ||||
|         pin_num = config[CONF_ADC_PIN][CONF_NUMBER] | ||||
|         channel = ESP32_VARIANT_ADC1_PIN_TO_CHANNEL[variant][pin_num] | ||||
|         cg.add(var.set_adc_channel(channel)) | ||||
|     else: | ||||
|         cg.add(var.set_din_pin(config[CONF_I2S_DIN_PIN])) | ||||
|         cg.add(var.set_pdm(config[CONF_PDM])) | ||||
|  | ||||
|     await microphone.register_microphone(var, config) | ||||
|   | ||||
| @@ -17,15 +17,36 @@ static const char *const TAG = "i2s_audio.microphone"; | ||||
| void I2SAudioMicrophone::setup() { | ||||
|   ESP_LOGCONFIG(TAG, "Setting up I2S Audio Microphone..."); | ||||
|   this->buffer_.resize(BUFFER_SIZE); | ||||
|  | ||||
| #if SOC_I2S_SUPPORTS_ADC | ||||
|   if (this->adc_) { | ||||
|     if (this->parent_->get_port() != I2S_NUM_0) { | ||||
|       ESP_LOGE(TAG, "Internal ADC only works on I2S0!"); | ||||
|       this->mark_failed(); | ||||
|       return; | ||||
|     } | ||||
|   } else | ||||
| #endif | ||||
|       if (this->pdm_) { | ||||
|     if (this->parent_->get_port() != I2S_NUM_0) { | ||||
|       ESP_LOGE(TAG, "PDM only works on I2S0!"); | ||||
|       this->mark_failed(); | ||||
|       return; | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| void I2SAudioMicrophone::start() { this->state_ = microphone::STATE_STARTING; } | ||||
| void I2SAudioMicrophone::start() { | ||||
|   if (this->is_failed()) | ||||
|     return; | ||||
|   this->state_ = microphone::STATE_STARTING; | ||||
| } | ||||
| void I2SAudioMicrophone::start_() { | ||||
|   if (!this->parent_->try_lock()) { | ||||
|     return;  // Waiting for another i2s to return lock | ||||
|   } | ||||
|   i2s_driver_config_t config = { | ||||
|       .mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM), | ||||
|       .mode = (i2s_mode_t) (I2S_MODE_MASTER | I2S_MODE_RX), | ||||
|       .sample_rate = 16000, | ||||
|       .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, | ||||
|       .channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT, | ||||
| @@ -40,18 +61,33 @@ void I2SAudioMicrophone::start_() { | ||||
|       .bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT, | ||||
|   }; | ||||
|  | ||||
| #if SOC_I2S_SUPPORTS_ADC | ||||
|   if (this->adc_) { | ||||
|     config.mode = (i2s_mode_t) (config.mode | I2S_MODE_ADC_BUILT_IN); | ||||
|     i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); | ||||
|  | ||||
|     i2s_set_adc_mode(ADC_UNIT_1, this->adc_channel_); | ||||
|     i2s_adc_enable(this->parent_->get_port()); | ||||
|   } else { | ||||
| #endif | ||||
|     if (this->pdm_) | ||||
|       config.mode = (i2s_mode_t) (config.mode | I2S_MODE_PDM); | ||||
|  | ||||
|     i2s_driver_install(this->parent_->get_port(), &config, 0, nullptr); | ||||
|  | ||||
|     i2s_pin_config_t pin_config = this->parent_->get_pin_config(); | ||||
|     pin_config.data_in_num = this->din_pin_; | ||||
|  | ||||
|     i2s_set_pin(this->parent_->get_port(), &pin_config); | ||||
| #if SOC_I2S_SUPPORTS_ADC | ||||
|   } | ||||
| #endif | ||||
|   this->state_ = microphone::STATE_RUNNING; | ||||
|   this->high_freq_.start(); | ||||
| } | ||||
|  | ||||
| void I2SAudioMicrophone::stop() { | ||||
|   if (this->state_ == microphone::STATE_STOPPED) | ||||
|   if (this->state_ == microphone::STATE_STOPPED || this->is_failed()) | ||||
|     return; | ||||
|   this->state_ = microphone::STATE_STOPPING; | ||||
| } | ||||
|   | ||||
| @@ -18,14 +18,27 @@ class I2SAudioMicrophone : public I2SAudioIn, public microphone::Microphone, pub | ||||
|  | ||||
|   void loop() override; | ||||
|  | ||||
|   void set_din_pin(uint8_t pin) { this->din_pin_ = pin; } | ||||
|   void set_din_pin(int8_t pin) { this->din_pin_ = pin; } | ||||
|   void set_pdm(bool pdm) { this->pdm_ = pdm; } | ||||
|  | ||||
| #if SOC_I2S_SUPPORTS_ADC | ||||
|   void set_adc_channel(adc1_channel_t channel) { | ||||
|     this->adc_channel_ = channel; | ||||
|     this->adc_ = true; | ||||
|   } | ||||
| #endif | ||||
|  | ||||
|  protected: | ||||
|   void start_(); | ||||
|   void stop_(); | ||||
|   void read_(); | ||||
|  | ||||
|   uint8_t din_pin_{0}; | ||||
|   int8_t din_pin_{I2S_PIN_NO_CHANGE}; | ||||
| #if SOC_I2S_SUPPORTS_ADC | ||||
|   adc1_channel_t adc_channel_{ADC1_CHANNEL_MAX}; | ||||
|   bool adc_{false}; | ||||
| #endif | ||||
|   bool pdm_{false}; | ||||
|   std::vector<uint8_t> buffer_; | ||||
|  | ||||
|   HighFrequencyLoopRequester high_freq_; | ||||
|   | ||||
| @@ -700,8 +700,15 @@ prometheus: | ||||
|  | ||||
| microphone: | ||||
|   - platform: i2s_audio | ||||
|     id: mic_id | ||||
|     id: mic_id_adc | ||||
|     adc_pin: GPIO35 | ||||
|     adc_type: internal | ||||
|  | ||||
|   - platform: i2s_audio | ||||
|     id: mic_id_external | ||||
|     i2s_din_pin: GPIO23 | ||||
|     adc_type: external | ||||
|     pdm: false | ||||
|  | ||||
| speaker: | ||||
|   - platform: i2s_audio | ||||
| @@ -712,7 +719,7 @@ speaker: | ||||
|  | ||||
|  | ||||
| voice_assistant: | ||||
|   microphone: mic_id | ||||
|   microphone: mic_id_external | ||||
|   on_start: | ||||
|     - logger.log: "Voice assistant started" | ||||
|   on_stt_end: | ||||
|   | ||||
		Reference in New Issue
	
	Block a user