main
matt Add MTA-156 input revision and document enclosure and cable-fit limits 16485bb
esphome:
  name: fan-controller
  friendly_name: Cabinet fan controller
  includes:
    - control_policy.h
  on_boot:
    priority: -100
    then:
      - output.set_level: {id: pwm1, level: 100%}
      - output.set_level: {id: pwm2, level: 100%}
      - switch.turn_on: pwm_enabled
  on_shutdown:
    then:
      - switch.turn_off: pwm_enabled

esp32:
  board: esp32-c3-devkitm-1
  flash_size: 4MB
  framework:
    type: esp-idf
logger:
  hardware_uart: UART0
wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  reboot_timeout: 0s
api:
  reboot_timeout: 0s
  encryption:
    key: !secret api_encryption_key
ota:
  - platform: esphome
    password: !secret ota_password
    on_begin:
      then:
        - switch.turn_off: pwm_enabled
    on_error:
      then:
        - output.set_level: {id: pwm1, level: 100%}
        - output.set_level: {id: pwm2, level: 100%}
        - switch.turn_on: pwm_enabled

output:
  - platform: ledc
    id: pwm1
    pin: GPIO0
    frequency: 25000 Hz
    channel: 0
  - platform: ledc
    id: pwm2
    pin: GPIO1
    frequency: 25000 Hz
    channel: 1
switch:
  - platform: gpio
    id: pwm_enabled
    internal: true
    pin:
      number: GPIO7
      inverted: true
    restore_mode: ALWAYS_OFF
  - platform: template
    name: Full speed override
    id: full_override
    optimistic: true
    restore_mode: RESTORE_DEFAULT_ON
status_led:
  pin: GPIO10
one_wire:
  - platform: gpio
    pin: GPIO6
sensor:
  - platform: dallas_temp
    id: cabinet_temperature
    name: Cabinet temperature
    update_interval: 5s
    resolution: 12
    on_value:
      then:
        - lambda: |-
            if (std::isfinite(x)) {
              id(last_temperature_ms) = millis();
              id(temperature_seen) = true;
            }
  - platform: pulse_counter
    id: rpm1
    name: Fan 1 speed
    pin: GPIO4
    use_pcnt: false
    internal_filter: 20us
    count_mode:
      rising_edge: INCREMENT
      falling_edge: DISABLE
    update_interval: 5s
    unit_of_measurement: rpm
    accuracy_decimals: 0
    filters:
      - multiply: 0.5
  - platform: pulse_counter
    id: rpm2
    name: Fan 2 speed
    pin: GPIO5
    use_pcnt: false
    internal_filter: 20us
    count_mode:
      rising_edge: INCREMENT
      falling_edge: DISABLE
    update_interval: 5s
    unit_of_measurement: rpm
    accuracy_decimals: 0
    filters:
      - multiply: 0.5
  - platform: template
    id: demand
    name: Fan demand
    unit_of_measurement: '%'
    accuracy_decimals: 0
    update_interval: never
binary_sensor:
  - platform: template
    id: cooling_fault
    name: Cooling fault
    device_class: problem
globals:
  - id: last_temperature_ms
    type: uint32_t
    initial_value: '0'
  - id: temperature_seen
    type: bool
    initial_value: 'false'
interval:
  - interval: 1s
    then:
      - lambda: |-
          const auto now = millis();
          const auto result = fan_controller::decide(
            id(cabinet_temperature).state, now-id(last_temperature_ms), now,
            id(rpm1).state, id(rpm2).state, id(temperature_seen), id(full_override).state);
          id(pwm1).set_level(result.duty);
          id(pwm2).set_level(result.duty);
          id(demand).publish_state(result.duty*100.0f);
          id(cooling_fault).publish_state(result.fault);