esphome / feature-requests

ESPHome Feature Request Tracker
https://esphome.io/
417 stars 26 forks source link

Restart/Reinitialise SPI action #2412

Closed samuelolteanu closed 1 year ago

samuelolteanu commented 1 year ago

Describe the problem you have/What new integration you would like

Please describe your use case for this integration and alternatives you've tried:

I'm using a max7219 7 digit display together with a relay and a triac (servo controlled) after that relay for limiting the power of an electric water boiler on the same esp for solar pv matching reasons. The moment relay is closed, the triac will make some noise/spikes/whatever they do and the display sometimes will show nonsense, dimm, not show anything or anything in between. Tried a power supply with two outputs, same thing, and then i gave up and made an HA automation to restart the esp after each time relay is opening the circuit. Is it possible to restart only the SPI component without wifi disconnect? Additional context

xdecock commented 1 year ago

Would it be possible to test something like that?

# Script to restart max7219
script:
  - id: restart_max7219
    then:
      - lambda: id(id_of_max7219).setup()

... on_xxxx:
      then:
        script.execute: restart_max7219

From what i read i don't see any obvious memory leak in the setup

samuelolteanu commented 1 year ago

That was quick... It works. This is my full yaml setup for anyone intersted. Thank you very much sir.

external_components:
  source: github://pr#5446
  components: [ spi ]

esphome:
  name: esp32s2-3
  friendly_name: esp32s2-3

esp32:
  board: esp32-s2-saola-1
  framework:
    type: arduino

logger:
  level: warn

api:

ota:

mdns:

time:
  - platform: sntp
    id: sntp_time

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
        static_ip: 192.168.0.205
        gateway: 192.168.0.1
        subnet: 255.255.255.0
        dns1: 1.1.1.1
        dns2: 8.8.8.8
  ap:

captive_portal:

button:
  - platform: safe_mode
    name: "esp32s2-3 Restart (Safe Mode)"

binary_sensor:
  - platform: status
    name: "Connected Status"
    id: ha_connected
    on_release:
      then:
        - switch.turn_off: template_switch

  - platform: homeassistant
    name: "Releu Pompa"
    entity_id: switch.releu_pompa_apa_rece_real
    id: pump_relay

switch:
  - platform: restart
    name: "Restart"

  - platform: gpio
    pin: 8 #25 albs str
    id: ntc_vcc

  - platform: gpio
    pin: 9 # portocaliu
    id: ntc_vcc2

  - platform: gpio
    name: "Releu Ventilator Triac"
    pin: 5
    restore_mode: ALWAYS_OFF
    id: releu_ventilator
    inverted: True

  - platform: gpio
    name: "Releu Boiler Electric Real"
    id: releu_boiler_real
    inverted: True
    pin: 6
    restore_mode: ALWAYS_OFF

  - platform: template
    name: "Releu Boiler Electric"
    id: template_switch
    optimistic: on
    restore_mode: ALWAYS_OFF
    on_turn_on:
        - number.set:
              id: putere_setata_boiler
              value: 0
        - delay: 1s
        - switch.turn_on: releu_boiler_real
        - delay: 0.5s
        - switch.turn_on: releu_ventilator
        - delay: 0.1s
        - number.set:
              id: putere_setata_boiler
              value: 1550
        - number.set:
              id: servo_number
              value: 100
        - script.execute: restart_max7219

    on_turn_off:
      - number.set:
              id: putere_setata_boiler
              value: 0
      - number.set:
              id: servo_number
              value: -100
      - delay: 1s
      - switch.turn_off: releu_boiler_real
      - delay: 5s
      - switch.turn_off: releu_ventilator
#    on_turn_on:
#        - switch.turn_on: releu_boiler_real
#        - delay: 5s
#        - switch.turn_on: releu_ventilator
#    on_turn_off:
#      - switch.turn_off: releu_boiler_real
#      - delay: 5s
#      - switch.turn_off: releu_ventilator
#      - delay: 1s
#      - number.set:
#              id: servo_number
#              value: 100

interval:
  - interval: 1s
    then:
      - switch.turn_on: ntc_vcc
      - component.update: adc_33
      - switch.turn_off: ntc_vcc
      - delay: 0.1s
      - switch.turn_on: ntc_vcc2
      - component.update: adc_36
      - switch.turn_off: ntc_vcc2

 #     - switch.turn_on: ntc_vcc
 #     - switch.turn_on: ntc_vcc2
 #     - component.update: adc_33
 #     - component.update: adc_36
 #     - switch.turn_off: ntc_vcc
 #     - switch.turn_off: ntc_vcc2

sensor:
  - platform: uptime
    name: Uptime Sensor
    update_interval: 60s

  - platform: homeassistant
    entity_id: sensor.boiler_1500w_shelly1pm_power
    id: boiler_power_set
    accuracy_decimals: 1

  - platform: homeassistant
    name: "Temperatura Boiler"
    entity_id: sensor.solar_boiler_temperature
    id: solar_boiler_temp
    accuracy_decimals: 1

  - platform: homeassistant
    name: "Presiune Apa"
    entity_id: sensor.presiune_apa_rece_fantana
    id: water_pressure
    accuracy_decimals: 0

  - platform: homeassistant
    name: "Debit Apa"
    entity_id: sensor.litri_pe_minut
    id: water_flow
    accuracy_decimals: 1

  - platform: homeassistant
    name: "Cantitate Apa"
    entity_id: sensor.apa_rece_zilnic
    id: water_amount
    accuracy_decimals: 1

  - platform: template
    name: "Temperatura Boiler Electric"
    state_class: measurement
    device_class: temperature
    unit_of_measurement: "°C"
    accuracy_decimals: 3
    update_interval: 1s
    id: electric_boiler_temp
    lambda: |-
        return (id(sus).state + id(jos).state) / 2;
    filters:
       - or:
         - throttle: 60s
         - delta: 1

  - platform: template
    name: "Temperatura Boiler Electric Sus NTC"
    state_class: measurement
    device_class: temperature
    unit_of_measurement: "°C"
    accuracy_decimals: 3
    update_interval: 1s
    id: sus
    lambda: |-
        return id(adc_36).state;
    filters:
    #  - lambda: return 8.8388598477 * pow(x, 2) - 62.5523099704 * x + 119.4653070224;
      - lambda: return -38.4482508832 * x + 107.5305932918;
      - or:
         - throttle: 60s
         - delta: 1

  - platform: template
    name: "Temperatura Boiler Electric Varf Tija Termostrat NTC"
    state_class: measurement
    device_class: temperature
    unit_of_measurement: "°C"
    accuracy_decimals: 3
    update_interval: 1s
    id: jos
    lambda: |-
        return id(adc_33).state;
    filters:
   #   - lambda: return 8.8388598477 * pow(x, 2) - 62.5523099704 * x + 119.4653070224;
      - lambda: return -38.4482508832 * x + 107.5305932918;
      - or:
         - throttle: 60s
         - delta: 1

      #- calibrate_linear: esp32s2
#             #voltaj    ->  temperatura
#       #     - 2.29   ->   21
        #     - 1.665  ->   41
        #     - 0.716  ->   81

#     #- calibrate_linear: esp32
#             #voltaj    ->  temperatura
#       #     - 0.8602   ->  71
#        #    - 1.2891   ->  53
#         #   - 1.8028   ->  37
#         #   - 2.2523   ->  25
#         #   - 2.4192   ->  19
#         #   - 2.4661   ->  18
#         #   - 0.8179   ->  73
#         #   - 0.7521   ->  77
#         #   - 0.6300   ->  83 ?
#         #   - 0.6214   ->  84 ?
#         #   - 0.5970   ->  86 ?
#         #   - 0.5404   ->  89 ?
#         #   - 0.5282   ->  90 ?

  - platform: adc
    attenuation: auto
    pin: 1 # 33 albastru
    name: "adc_33"
    update_interval: never
    id: adc_33
    accuracy_decimals: 4
    filters:
      - median:
          window_size: 60
          send_every: 10
          send_first_at: 1

  - platform: adc
    attenuation: auto
    pin: 2 # 35 portocaliu_striat
    name: "adc_36"
    update_interval: never
    id: adc_36
    accuracy_decimals: 4
    filters:
      - median:
          window_size: 60
          send_every: 5
          send_first_at: 1

servo:
  - id: my_servo
    output: pwm_output
    transition_length: 0s
    auto_detach_time: 5s

output:
  #- platform: x9c
  #  id: x9c_pot
  #  cs_pin: GPIO13
  # inc_pin: GPIO14
  #  ud_pin: GPIO15
  #  initial_value: 0.1

  - platform: ledc
    id: pwm_output
    pin: 7 #19 verde
    frequency: 50 Hz

number:
  #- platform: template
  #  name: "ntc_target"
  #  optimistic: true
  #  min_value: 0
  #  max_value: 100
  #  step: 1
  #  set_action:
  #    - output.set_level:
  #        id: x9c_pot
  #        level: !lambda "return x/100.0;"
  - platform: template
    name: Putere Setata Boiler
    id: putere_setata_boiler
    mode: "slider"
    min_value: 0
    max_value: 1550
    step: 1
    initial_value: 1550
    optimistic: True
    set_action:
      then:
        - number.set:
            id: servo_number
            value: !lambda "if (x <= 100) return -100; else return round(0.1002279156 * x - 74.5384985627);"
            #!lambda "return round(0.1002279156 * x - 74.5384985627);"

  - platform: template
    name: Servo Control
    id: servo_number
    min_value: -100
    initial_value: 100
    max_value: 100
    step: 1
    optimistic: True
    set_action:
      then:
        - servo.write:
            id: my_servo
            level: !lambda 'return x / 100.0;'

  - platform: template
    name: "Servo Transition Length"
    min_value: 0
    max_value: 10
    step: 0.1
    optimistic: True
    initial_value: 0
    id: servo_transition
    set_action:
        lambda: |-
           return id(my_servo).set_transition_length(x * 1000);

spi:
  clk_pin: 36
  mosi_pin: 35

display:
  - platform: max7219
    id: max7219_aidi
    cs_pin: 34
    num_chips: 1
    intensity: 7
    lambda: |-
      float electricTemp = id(electric_boiler_temp).state;
      float solarTemp = id(solar_boiler_temp).state;
      float waterFlow = id(water_flow).state;
      float waterAmount = id(water_amount).state;
      bool haConnected = id(ha_connected).state;
      bool boilerReal = id(releu_boiler_real).state;
      bool pumpRelay = id(pump_relay).state; 

      char buf[20]; 

      if (waterFlow > 0) {
        sprintf(buf, "%.1fL%s", waterAmount, pumpRelay ? "ON" : "OFF");
      } else {
        if (haConnected) {
          if (boilerReal) {
            float boilerPowerSet = id(boiler_power_set).state;
            sprintf(buf, "%.0fW%.1fC", boilerPowerSet, electricTemp);
          } else {
            sprintf(buf, "%.1fC%.1fC", electricTemp, solarTemp);
          }
        } else {
          sprintf(buf, "%.3f`C", electricTemp);
        }
      }
      std::string result = buf;
      it.print(result.c_str());

#    lambda: |-
#      float electricTemp = id(electric_boiler_temp).state;
#      float solarTemp = id(solar_boiler_temp).state;
#      float waterFlow = id(water_flow).state;
#      float waterAmount = id(water_amount).state;
#      bool haConnected = id(ha_connected).state;
#      bool boilerReal = id(releu_boiler_real).state;
#    
#      char buf[20];
#      if (waterFlow > 0) {
#        sprintf(buf, "%.1fL", waterAmount);
#      } else {
#        if (haConnected) {
#          if (boilerReal) {
#            float boilerPowerSet = id(boiler_power_set).state;
#            sprintf(buf, "%.0fW%.1fC", boilerPowerSet, electricTemp);
#          } else {
#            sprintf(buf, "%.1fC%.1fC", electricTemp, solarTemp);
#          }
#        } else {
#          sprintf(buf, "%.2f C", electricTemp);
#        }
#      }
#      std::string result = buf;
#      it.print(result.c_str());

 #   lambda: |-
 #     float electricTemp = id(electric_boiler_temp).state;
 #     float solarTemp = id(solar_boiler_temp).state;
 #     float waterFlow = id(water_flow).state;
 #     float waterAmount = id(water_amount).state;
 #     bool haConnected = id(ha_connected).state;
 #   
 #     char buf[20];
 #     if (waterFlow > 0) {
 #       sprintf(buf, "%.1fL", waterAmount);
 #     } else {
 #       if (haConnected) {
 #         sprintf(buf, "%.1fC%.1fC", electricTemp, solarTemp);
 #       } else {
 #         sprintf(buf, "%.1fC", electricTemp);
 #       }
 #     }
 #     std::string result = buf;
 #     it.print(result.c_str());

#  lambda: |-
 #    float first = id(electric_boiler_temp).state;
 #    float second = id(solar_boiler_temp).state;
 #    float waterFlow = id(water_flow).state;
 #    float waterAmmount = id(water_ammount).state;
 #    char buf[20];
 #    if (waterFlow > 0) {
 #      sprintf(buf, "%.1fL", waterAmmount);
 #    } else{
 #      sprintf(buf, "%.1fC%.1fC", first, second);
 #    }
 #    std::string result = buf;
 #    it.print(result.c_str());

  #  lambda: |-
    #  static int display_state = 0;  // 0 for temperature, 1 for water pressure
    #  float first = id(electric_boiler_temp).state;
    #  float second = id(solar_boiler_temp).state;
    #  float third = id(water_pressure).state;
    #  float waterFlow = id(water_flow).state;
    #  float waterAmmount = id(water_ammount).state;
    #  char buf[20];
    #  if (waterFlow > 0) {
    #    sprintf(buf, "%.1fL", waterAmmount);
    #  } else if (display_state == 0) {
    #    sprintf(buf, "%.1fC%.1fC", first, second);
    #  } else {
    #    sprintf(buf, "%.0f hPa", third);
    #  }
    #  std::string result = buf;
    #  it.print(result.c_str());
    #  if (waterFlow > 0) {
    #    delay(500); // Display water flow for x seconds
    #  } else if (display_state == 0) {
    #    display_state = 1;
    #    delay(500); // Display water pressure for x seconds
    #  } else {
    #    display_state = 0;
    #    delay(2000); // Display temperature for x seconds
    #  }

 #   lambda: |-
 #     static int display_state = 0;  // 0 for temperature, 1 for water pressure
 #     float first = id(electric_boiler_temp).state;
 #     float second = id(solar_boiler_temp).state;
 #     float third = id(water_pressure).state;
 #     float waterFlow = id(water_flow).state;
 #     float waterAmmount = id(water_ammount).state;
 #     char buf[20];
 #     if (waterFlow > 0) {
 #       sprintf(buf, "%.1fL", waterAmmount);
 #     } else if (display_state == 0) {
 #       sprintf(buf, "%.1fC%.1fC", first, second);
 #     } else {
 #       sprintf(buf, "%.0f hPa", third);
 #     }
 #     std::string result = buf;
 #     it.print(result.c_str());
 #     if (waterFlow > 0) {
 #       delay(500); // Display water flow for x seconds
 #     } else if (display_state == 0) {
 #       display_state = 1;
 #       delay(500); // Display water pressure for x seconds
 #     } else {
 #       display_state = 0;
 #       delay(2000); // Display temperature for x seconds
 #     }

#   lambda: |-
#     static int display_state = 0;  // 0 for temperature, 1 for water pressure
#     float first = id(electric_boiler_temp).state;
#     float second = id(solar_boiler_temp).state;
#     float third = id(water_pressure).state;
#     char buf[20];
#     if (display_state == 0) {
#       sprintf(buf, "%.1fC%.1fC", first, second);
#     } else {
#       sprintf(buf, "%.0f hPa", third);
#     }
#     std::string result = buf;
#     it.print(result.c_str());
#     if (display_state == 0) {
#       display_state = 1;
#       delay(500); // Display water pressure for x second
#     } else {
#       display_state = 0;
#       delay(2000); // Display temperature for x second
#     }

#   lambda: |-
#    float first = id (electric_boiler_temp).state;
#    float second = id (solar_boiler_temp).state;
#    char buf [20];
#    sprintf (buf, "%.1fC%.1fC", first, second);
#    std::string result = buf;
#    it.print (result.c_str ());

# Script to restart max7219
script:
  - id: restart_max7219
    then:
      - lambda: id(max7219_aidi).setup();