Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AtomS3U microphone #26

Open
viotemp1 opened this issue May 14, 2024 · 5 comments
Open

AtomS3U microphone #26

viotemp1 opened this issue May 14, 2024 · 5 comments

Comments

@viotemp1
Copy link

viotemp1 commented May 14, 2024

Hello,

I'm trying to use this component with AtomS3U - SPM1423, but this has only MIC_CLK & MIC_DATA pins.
Any ideea what to do with the ws_pin? It looks like it's mandatory.

Screenshot 2024-05-14 at 20 24 03

I tried also this external mic (based on the same chip) - pdm - the same, the WS pin is missing.

Regards,
V

@stas-sl
Copy link
Owner

stas-sl commented May 14, 2024

Hi!

Unfortunately, PDM mics currently are not supported, there was an attempt to support them, you can read previous discussion and you can also check out branch https://github.com/stas-sl/esphome-sound-level-meter/tree/pdm_support, but seems like there are still some issues, I just can’t try it myself as I don’t have those mics.

@viotemp1
Copy link
Author

viotemp1 commented May 15, 2024

Hello,

I tried that branch and I get sound_level: 118.52 all the time.
MAybe you can find some hints in M5Stack PDM
I'll check more into the source code.
Thanks!

@viotemp1
Copy link
Author

I made a fork and changed a bit fork according to the M5Stack PDM example. It's working now, not sure about the values ranges and calibration, but I do not need that.
IMG_5092

Thanks for help!

@karrui
Copy link

karrui commented Jun 11, 2024

@viotemp1 can you share your config on how you got it working? I'm trying to get an Atom Echo to work as a sound level meter too, and it also uses a pdm mic.

@viotemp1
Copy link
Author

viotemp1 commented Jun 12, 2024

@viotemp1 can you share your config on how you got it working? I'm trying to get an Atom Echo to work as a sound level meter too, and it also uses a pdm mic.

This is my config for M5Stack Core2 AWS

# GPIOs
# 25              - side LEDs
# 26,36              - Groove Port B Black (DAC/ADC)
# 32, 33          - Groove Port A Red
# 21, 22          - I2CA - internal
# 18, 23, 38      - SPI

# 5, 15, 4        - TFT

## 13 14           - Groove Port C Blue (RX/TX)
# 27              - Digital RGB LED Weatherproof Strip SK6812
# (34-39) does not support output pin mode

# I2C
# Bus Internal
# 0x34  -   AXP192 Power management
# 0x35  -   ATECC608 HW Encryption
# 0x38  -   FT6336U Touch Screen
# 0x51  -   BM8563 RTC
# 0x68  -   MPU6886 Accelerometer/Gyroscope


substitutions:
  esp_name: "decibel-meter"
  esp_name1: "decibel_meter"
  ip: ...
  board: m5stack-core2
  mic_clk: GPIO0 # internal
  mic_data: GPIO34 # internal
  i2s_bclk: GPIO12 # internal for speaker
  groove_port_c_rx_pin: GPIO13 # ext MIC CLK
  groove_port_c_tx_pin: GPIO14 # ext MIC DATA
  aws_core2_side_leds_pin: GPIO25
  groove_port_a_sda_pin: GPIO32 # (IR Tx)
  groove_port_a_scl_pin: GPIO33 # (IR Rx)
  groove_port_b_dac_pin: GPIO26
  groove_port_b_adc_pin: GPIO36
  internal_i2c_sda_pin: GPIO21
  internal_i2c_scl_pin: GPIO22
  internal_spi_clk_pin: GPIO18
  internal_spi_mosi_pin: GPIO23
  internal_spi_miso_pin: GPIO38
  display_cs_pin: GPIO5
  display_dc_pin: GPIO15
  display_reset_pin: GPIO4
  count_volume_change: "2"

globals:
  - id: display_switch_var
    type: bool
    # initial_value: 'true'
    restore_value: yes
  - id: touch_x
    type: int
    initial_value: '0'
  - id: touch_y
    type: int
    initial_value: '0'
  - id: touch_state
    type: int
    initial_value: '0'

  
esphome:
  name: $esp_name
  friendly_name: $esp_name
  on_boot:
    - priority: -100.0
      then:
        # - light.turn_on: ${esp_name1}_led
        # - delay: 5s
        # - light.turn_off: ${esp_name1}_led
        # - switch.turn_on: ${esp_name1}_display_switch
        # -  lambda: |-
        #     ESP_LOGI("boot", "display_switch_var:  %s", id(display_switch_var) ? "ON" : "OFF");
        #     if (id(display_switch_var)) {
        #       id(${esp_name1}_display_switch).turn_on();
        #     }
          - logger.log: 
              level: INFO
              format: "boot finished"

esp32:
  board: $board
  framework:
    type: arduino

external_components:
  - source: github://viotemp1/esphome-sound-level-meter 
  - source:
      type: local
      path: my_components

# Enable logging
logger:
  level: !secret log_level # DEBUG
  # level: DEBUG
  logs:
    api.connection: ERROR
    component: ERROR
    graph: ERROR
    main: INFO
    remote.pronto: INFO
    uptime.sensor: INFO


# Enable Home Assistant API
api:
  encryption:
    key: ...

ota:
  password: ...

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  use_address: $ip
  domain: .local
  reboot_timeout: !secret reboot_timeout
  fast_connect: on
  manual_ip:
    static_ip: $ip
    gateway: 10.0.0.1
    subnet: 255.255.255.0
color:
  - id: color_blue
    red: 0%
    green: 0%
    blue: 100%
  - id: color_red
    red: 100%
    green: 0%
    blue: 0%
  - id: color_green
    red: 0%
    green: 100%
    blue: 0%
  - id: color_white
    red: 100%
    green: 100%
    blue: 100%
  - id: color_black
    red: 0%
    green: 0%
    blue: 0%
  - id: color_dark_green
    red: 0%
    green: 50%
    blue: 0%
  - id: color_dark_red
    red: 50%
    green: 0%
    blue: 0%
  - id: color_dark_blue
    red: 0%
    green: 0%
    blue: 50%
    
font:
  - file: "gfonts://Roboto@medium"
    id: font_roboto
    size: 22
  - file: "gfonts://Roboto@medium"
    id: font_roboto_med
    size: 56
  - file: "gfonts://Roboto@medium"
    id: font_roboto_big
    size: 80
  - file: "gfonts://Roboto@medium"
    id: font_roboto_10
    size: 10
  - file: "gfonts://Roboto@medium"
    id: font_roboto_20
    size: 20

light:
  - platform: neopixelbus
    type: GRB
    variant: SK6812
    pin: $aws_core2_side_leds_pin
    num_leds: 10
    name: "${esp_name1}_LED_Light"
    id: ${esp_name1}_led
    restore_mode: ALWAYS_OFF

# remote_receiver:
#   pin:
#     number: $groove_port_a_scl_pin # GPIO33 # (IR Rx)
#     inverted: true
#   dump: raw # all raw

remote_transmitter:
  pin: $groove_port_a_sda_pin # GPIO32 # (IR Tx)
  carrier_duty_percent: 50%

button:
  - platform: restart
    name: ${esp_name1}_Restart
    id: ${esp_name1}_restart_switch
  - platform: template
    name: "${esp_name1}_Sound Level Meter Toggle"
    on_press:
      - sound_level_meter.toggle: my_sound_level_meter
....

time:
  - platform: homeassistant
    id: esptime

spi:
  clk_pin: $internal_spi_clk_pin
  mosi_pin: $internal_spi_mosi_pin
  miso_pin: $internal_spi_miso_pin

i2c:
   - id: bus_internal
     sda: $internal_i2c_sda_pin
     scl: $internal_i2c_scl_pin
     frequency: 800kHz
     scan: True

switch:
  - platform: template
    name: "${esp_name1} Display Switch"
    id: ${esp_name1}_display_switch
    lambda: |-
      if (id(display_switch_var)) {
        return true;
      } else {
        return false;
      }
    turn_on_action:
        - lambda: |-
            id(display_switch_var) = true;
            id(axp192_id).set_brightness(0.75);
    turn_off_action:
        - lambda: |-
            id(display_switch_var) = false;
            id(axp192_id).set_brightness(0.0);

sensor:
  - platform: wifi_signal
    name: "${esp_name1}_WiFi_Signal"
    id: wifi_signal_sensor
    update_interval: 60s
  - platform: uptime
    name: "${esp_name1}_Uptime"
    id: ${esp_name1}_uptime_sensor
    accuracy_decimals: 0
    internal: true
    update_interval: 1s
  - platform: mpu6886
    i2c_id: bus_internal
    address: 0x68
    temperature:
      name: "${esp_name1}_Temperature"
  - platform: axp192
    id: axp192_id
    model: M5CORE2
    address: 0x34
    i2c_id: bus_internal
    update_interval: 30s
    brightness: 75%
    battery_level:
      name: "${esp_name1} Battery Level"
      id: "${esp_name1}_battery_level"
  - platform: template
    name: "${esp_name1} Vin Voltage"
    id: "${esp_name1}_get_vin_voltage"
    lambda: return id(axp192_id).GetVinVoltage();
    update_interval: 60s
    force_update: True
    unit_of_measurement: "V"
  - platform: template
    name: "${esp_name1} Battery Voltage"
    id: "${esp_name1}_get_bat_voltage"
    lambda: return id(axp192_id).GetBatVoltage();
    update_interval: 60s
    force_update: True
    unit_of_measurement: "V"
  - platform: template
    name: "${esp_name1} APS Voltage"
    id: "${esp_name1}_get_aps_voltage"
    lambda: return id(axp192_id).GetAPSVoltage();
    update_interval: 60s
    force_update: True
    unit_of_measurement: "V"
  - platform: homeassistant
    name: "${esp_name1} Living Threshold"
    entity_id: input_number.decibel_meter_living_threshold
    id: decibel_meter_living_threshold
    internal: true
  - platform: template
    name: "Sound Level Peak 1min"
    id: ${esp_name1}_sound_level_peak_1min
    # lambda: return id(${esp_name1}_sound_level_peak).state;
    update_interval: 1s
    unit_of_measurement: dBZ # dBA
    filters:
      - max:
          window_size: 60
          send_every: 1
          send_first_at: 1
  
text_sensor:
  - platform: wifi_info
    ip_address:
      name: ${esp_name1}_IP_Address
    ssid:
      name: ${esp_name1}_ESP_Connected_SSID
      id: wifi_info_ssid_sensor
    bssid:
      name: ${esp_name1}_ESP_Connected_BSSID
    mac_address:
      name: ${esp_name1}_ESP_Mac_Wifi_Address
  - platform: template
    name: "display_text"
    id: display_text
    internal: True
    # lambda: |-
    #   return {""};
    update_interval: 60s
    # on_value:
    #   then:
    #     - lambda: |-
    #         ESP_LOGI("display_text", "value changed %s", x.c_str());


binary_sensor:
  - platform: status
    name: ${esp_name}_Status
    id: esp32_status
  - platform: homeassistant
    name: "HA Decibel Meter Living Enabled"
    entity_id: input_boolean.decibel_meter_living
    id: ha_decibel_meter_living_enabled
    internal: True
    on_press:
      then:
        - sound_level_meter.turn_on
    on_release:
      then:
        - sound_level_meter.turn_off
  - platform: template
    name: "${esp_name}_high_sound_level"
    id: ${esp_name1}_high_sound_level
    lambda: |-
      if (id(${esp_name1}_sound_level_peak).state > id(decibel_meter_living_threshold).state) {
        if (!id(ir_volume_down_up_script).is_running()) {
            id(ir_volume_down_up_script).execute();
        }
        return true;
      } else {
        return false;
      }
  - platform: template
    name: "${esp_name}_high_sound_level_running"
    lambda: |-
      if (id(ir_volume_down_up_script).is_running()) {
        return true;
      } else {
        return false;
      }


i2s:
  ws_pin: $groove_port_c_rx_pin #: GPIO13 # ext MIC CLK
  din_pin: $groove_port_c_tx_pin #: GPIO14 # ext MIC DATA
  sample_rate: 16000 # 44100 48000
  bits_per_sample: 16
  dma_buf_count: 2
  dma_buf_len: 128
  use_apll: true # true false
  bits_shift: 0 # 8 0 4
  # pdm: true

sound_level_meter:
  id: my_sound_level_meter
  # update_interval specifies over which interval to aggregate audio data
  # you can specify default update_interval on top level, but you can also
  # override it further by specifying it on sensor level
  update_interval: 1s           # default: 60s
  # ignore audio data at startup for this long
  warmup_interval: 3s        # default: 500ms

  # buffer_size is in samples (not bytes), so for float data type
  # number of bytes will be buffer_size * 4
  # buffer_size: 1024             # default: 1024

  # see your mic datasheet to find sensitivity and reference SPL.
  # those are used to convert dB FS to db SPL
  mic_sensitivity: 0dB        # default: empty
  mic_sensitivity_ref: 0dB     # default: empty
  offset: 29dB
  multiplier: 10dB

  groups:
    - sensors:
        - type: eq
          name: Leq_1s
          id: "sound_level"
          internal: true
          update_interval: 0.2s
        - type: peak
          name: "Sound Level Peak"
          id: ${esp_name1}_sound_level_peak
          unit_of_measurement: dBZ # dBZ
          # internal: true
          on_value:
            then:
              lambda: |-
                id(decibel_meter_living_threshold).publish_state(id(decibel_meter_living_threshold).state);
                id(${esp_name1}_sound_level_peak_1min).publish_state(x);

          #     - logger.log: 
          #         level: INFO
          #         format: "sound_level_peak: %.2f"
          #         args: ['x']


graph:
  # Show bare-minimum auto-ranged graph
  - id: sound_level_graph
    duration: 1min
    width: 300
    height: 180
    traces:
      - sensor: decibel_meter_living_threshold
        line_type: SOLID
        continuous: true
        line_thickness: 2
        color: color_red
      - sensor: ${esp_name1}_sound_level_peak
        line_type: SOLID
        continuous: true
        line_thickness: 2
        color: color_blue


script:
  - id: ir_volume_down_up_script
    mode: single
    then:
      # - logger.log: 
      #     format: "High sound level detected. Volume will be adjusted"
      #     level: INFO
...
  - id: turn_on_display
    mode: single
    then:
      - switch.turn_on: ${esp_name1}_display_switch
      - delay: 60s
      - switch.turn_off: ${esp_name1}_display_switch


display:
  - platform: ili9xxx # ili9341
    model: M5STACK # TFT 2.4R (ILI9342) / M5STACK
    cs_pin: $display_cs_pin
    dc_pin: $display_dc_pin
    reset_pin: $display_reset_pin
    # rotation: 90°
    update_interval: 1s
    id: core2_display
    lambda: |-
      int d_width = it.get_width();
      int d_height = it.get_height();
      int d_h_width = int(d_width/2);
      int d_h_height = int(d_height/2);
      // bool battery_level_state = id(${esp_name1}_battery_level).state > 80 ? true : false;
      // ESP_LOGI("display dimensions", "width: %d / d_height: %d", d_width, d_height); // 320x240
      it.fill(COLOR_OFF);

      if (id(${esp_name1}_display_switch).state)
      {
        //auto touch = id(my_touchscreen)->get_touch();
        //if (touch) { // or touch.has_value()
        //  it.filled_circle(touch.value().x, touch.value().y, 10, color_red);
        //}

        // No display_text
        if (id(display_text).state == "") {
          it.strftime(10, 0, id(font_roboto), TextAlign::TOP_LEFT, "%H:%M:%S", id(esptime).now());
          it.printf(d_width-10, 0, id(font_roboto), TextAlign::TOP_RIGHT, "%.02f / %.02f", id(${esp_name1}_sound_level_peak).state, id(${esp_name1}_sound_level_peak_1min).state);
          it.graph(10, 30, id(sound_level_graph));
          
          if (id(esp32_status).state) {
            it.filled_rectangle(0, d_height -25, d_h_width, 25, color_dark_green);
          } 
          else {
            it.filled_rectangle(0, d_height -25, d_h_width, 25, color_dark_red);
          }
          if (id(${esp_name1}_battery_level).state > 80 ) {
            it.filled_rectangle(d_h_width, d_height -25, d_width, 25, color_dark_green);
          }
          else if (id(${esp_name1}_battery_level).state > 50 ) {
            it.filled_rectangle(d_h_width, d_height -25, d_width, 25, color_dark_blue);
          }
          else {
            it.filled_rectangle(d_h_width, d_height -25, d_width, 25, color_dark_red);
          }
          it.printf(d_h_width, d_height, id(font_roboto), TextAlign::BOTTOM_CENTER, "%s / %s / %.0f", id(esp32_status).state ? "ON" : "OFF", id(wifi_info_ssid_sensor).state.c_str(), id(wifi_signal_sensor).state);
          it.printf(d_width, d_height, id(font_roboto), TextAlign::BOTTOM_RIGHT, "%.0f", id(${esp_name1}_battery_level).state);
        }
        // display_text present
        else if (id(display_text).state != ""){
          it.printf(d_h_width, d_h_height, id(font_roboto_med), TextAlign::CENTER_HORIZONTAL , "%s", id(display_text).state.c_str());
        }
      }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants