ESP32andmore / ECB

3 stars 1 forks source link

A few questions and Dallas temp sensors stopped working #1

Open patfelst opened 4 days ago

patfelst commented 4 days ago

Hi there. I received my ECB last week (Australia), it's really nicely designed board and well documented. I have mine up and running in a 19" server rack, it's driving a 4x fan tray mounted in the top of the rack.

It's working well and from Home Assistant I can turn fans on/off, control speed %, and see individual speed sensors RPM. For my application I've started modifying the ESPHome yaml (the API version, not MQTT) to essentially drive all 4 fans in parallel using only one Dallas temp sensor (see modified code below). For testing, I've initially connected two Dallas sensors, but will probably only need to use one I think.

I was wondering if you could explain the fan speed control lambda code in pseudo code terms? These are the lines I'm talking about: https://github.com/ESP32andmore/ECB/blob/edcfcdddc9d27accf10c0419ec6700f9bfbd6c28/ESPhome/avfan1.yaml#L437-L459

It looks like you may have implemented your own PID controller, but only using P and I terms. Is there a reason you didn't use the PID built into HA? And how did you come up withe the ptemp and itemp values and should I modify these?

To parallel the fan control with temp sensor 1, this is what I came up with, and it seems to work ok:

      - lambda: !lambda |
          // Patrick's mod for all 4 fans to act in parallel based on Fan 1 auto setting and temp sensor 1 temperature
          if (id(auto_fan1).state) {
            float fan_actual_temp =  id(temp1).state;
            float fan_desired_temp = id(set_target_temp_1).state;
            float diff = fan_actual_temp - fan_desired_temp;
            id(fan1_sum) =id(fan1_sum) + diff;
            float fan_pdiff=diff * $ptemp;
            float fan_idiff= id(fan1_sum) * $itemp;
            float fan_set_speed = fan_pdiff + fan_idiff;
            if (fan_set_speed >100) fan_set_speed =100;
            if (fan_set_speed <10) fan_set_speed=1;
            if (id(fan1_sum) >100) id(fan1_sum) = 100;
            if (id(fan1_sum) < -100) id(fan1_sum) = -100;
            if (fan_set_speed <10) {
              fan_set_speed=1;

              // Turn off fan 1
              auto calloff1 = id(fan1_speed).turn_off();           
              calloff1.set_speed(fan_set_speed);
              calloff1.perform();

              // Turn off fan 2
              auto calloff2 = id(fan2_speed).turn_off();           
              calloff2.set_speed(fan_set_speed);
              calloff2.perform();

              // Turn off fan 3
              auto calloff3 = id(fan3_speed).turn_off();           
              calloff3.set_speed(fan_set_speed);
              calloff3.perform();

              // Turn off fan 4
              auto calloff4 = id(fan4_speed).turn_off();           
              calloff4.set_speed(fan_set_speed);
              calloff4.perform();

            } else {
              // Set fan 1 speed
              auto call1 = id(fan1_speed).turn_on();
              call1.set_speed(fan_set_speed);
              call1.perform();

              // Set fan 2 speed
              auto call2 = id(fan2_speed).turn_on();
              call2.set_speed(fan_set_speed);
              call2.perform();

              // Set fan 3 speed
              auto call3 = id(fan3_speed).turn_on();
              call3.set_speed(fan_set_speed);
              call3.perform();

              // Set fan 4 speed
              auto call4 = id(fan4_speed).turn_on();
              call4.set_speed(fan_set_speed);
              call4.perform();

            }
          }

This was working ok for a day or so, but now my Dallas temp sensors are not being detected. I don't even see their addresses in the debug log any more. I've not had time to double check the screw terminal connections yet, will do so on the weekend. Is there anything else that could cause this problem?

Assuming I get them working again, would there be any benefit in me doing the 4 fans in parallel using two temp sensors somehow?

Just a small note, I think there might be an error in the schematic for J1 as it shows it conencted to the GPIO27 one-wire bus along with J2 and J3. The docs say J1 is connected to GPIO26.

image

Apologies for the long issue.

ESP32andmore commented 4 days ago

Patrick, Yes, your modification to the yaml is correct, using the one sensor calculated "fan_set_speed" and making the ".set_speed" to each of the fan components. Basically the algo does jus t the proportional and integral parts of the PID. It simply determines the "error", the weighed (PTEMP) difference between the desired temperature and the actual temp and uses the weighed (ITEMP) sum of the error to arrive at fan_speed. A higher PTEMP will cause the fan speed to ramp more aggressively proportional to the difference between target and actual. A setting of 10-20 is typical. ITEMP has less effect but in effect and is the scaling factor of the running sum of the temperature difference. 0.1 to 0.5 are typical ranges.

Why did we not use the D term? We just found it was unnecessary to get good results with the algo.

Why did we not use the PID controller in ESPHome? It was because we could not have a manual control over the fan with their PID component.

The issue with the one-wire/dallas temp component not finding sensors? Yes this is a problem I have been trying the ESPHome developers to fix since their schema change in July to DS18B20 sensors. 2024.7.3 Broke Platform Dallas_temp · Issue #6119 · esphome/issues (github.com)https://github.com/esphome/issues/issues/6119

Do make sure the screw terminals are tight. But what we are seeing is not related to hardware, but compilation of ESPHome. Some yamls using the new one-wire/dallas temp schema will work and other fail with the errors:

13:55:05 | [W] | [component:170] | Component dallas_temp.sensor cleared Warning flag 13:55:05 | [W] | [dallas.temp.sensor:139] | 'AVfan1 Temperature 3' - Scratch pad checksum invalid! 13:55:05 | [W] | [component:157] | Component dallas_temp.sensor set Warning flag: scratch pad checksum invalid 13:55:05 | [W] | [dallas.temp.sensor:139] | 'AVfan1 Temperature 1' - Scratch pad checksum invalid! 13:55:05 | [W] | [component:157] | Component dallas_temp.sensor set Warning flag: scratch pad checksum invalid 13:55:05 | [W] | [dallas.temp.sensor:139] | 'AVfan1 Temperature 2' - Scratch pad checksum invalid! 13:55:05 | [W] | [component:157] | Component dallas_temp.sensor set Warning flag: scratch pad checksum invalid

And in-house we have not been able to determine the root cause of this but it does seems to be isolated to the ESP32 as one of our ESP32-S3 board compilations never exhibited the problem. If you flash the attached factory flashed .bin it will work, then flash your compiled version and it will not. It is highly frustrating and I wish I had a definitive answer for you. All I can say is rearrange your code and see if it works.

Regarding the schematic, the one on Github is the version 2.0 board, the version 2.1, just removed a one-wire connector, J1, and added a AHT20 sensor and a open-collector header on GPIO26 as J1 I have attached that schematic for you.

Lastly, if for example you want to use multiple sensors in different areas of you rack you could use an average or other weighing of multiple sensors to derive the "fan_actual_temp" value to feed to the Lambda function.

Hope this helps and few free to inquire with any issue you might have.

Best regards, Frank


From: Patrick Felstead @.> Sent: Tuesday, September 17, 2024 5:18 PM To: ESP32andmore/ECB @.> Cc: Subscribed @.***> Subject: [ESP32andmore/ECB] A few questions and Dallas temp sensors stopped working (Issue #1)

Hi there. I received my ECB last week (Australia), it's really nicely designed board and well documented. I have mine up and running in a 19" server rack, it's driving a 4x fan tray mounted in the top of the rack.

It's working well and from Home Assistant I can turn fans on/off, control speed %, and see individual speed sensors RPM. For my application I've started modifying the ESPHome yaml (the API version, not MQTT) to essentially drive all 4 fans in parallel using only one Dallas temp sensor (see modified code below). For testing, I've initially connected two Dallas sensors, but will probably only need to use one I think.

I was wondering if you could explain the fan speed control lambda code in pseudo code terms? These are the lines I'm talking about: https://github.com/ESP32andmore/ECB/blob/edcfcdddc9d27accf10c0419ec6700f9bfbd6c28/ESPhome/avfan1.yaml#L437-L459

It looks like you may have implemented your own PID controller, but only using P and I terms. Is there a reason you didn't use the PID built into HA? And how did you come up withe the ptemp and itemp values and should I modify these?

To parallel the fan control with temp sensor 1, this is what I came up with, and it seems to work ok:

  - lambda: !lambda |
      // Patrick's mod for all 4 fans to act in parallel based on Fan 1 auto setting and temp sensor 1 temperature
      if (id(auto_fan1).state) {
        float fan_actual_temp =  id(temp1).state;
        float fan_desired_temp = id(set_target_temp_1).state;
        float diff = fan_actual_temp - fan_desired_temp;
        id(fan1_sum) =id(fan1_sum) + diff;
        float fan_pdiff=diff * $ptemp;
        float fan_idiff= id(fan1_sum) * $itemp;
        float fan_set_speed = fan_pdiff + fan_idiff;
        if (fan_set_speed >100) fan_set_speed =100;
        if (fan_set_speed <10) fan_set_speed=1;
        if (id(fan1_sum) >100) id(fan1_sum) = 100;
        if (id(fan1_sum) < -100) id(fan1_sum) = -100;
        if (fan_set_speed <10) {
          fan_set_speed=1;

          // Turn off fan 1
          auto calloff1 = id(fan1_speed).turn_off();
          calloff1.set_speed(fan_set_speed);
          calloff1.perform();

          // Turn off fan 2
          auto calloff2 = id(fan2_speed).turn_off();
          calloff2.set_speed(fan_set_speed);
          calloff2.perform();

          // Turn off fan 3
          auto calloff3 = id(fan3_speed).turn_off();
          calloff3.set_speed(fan_set_speed);
          calloff3.perform();

          // Turn off fan 4
          auto calloff4 = id(fan4_speed).turn_off();
          calloff4.set_speed(fan_set_speed);
          calloff4.perform();

        } else {
          // Set fan 1 speed
          auto call1 = id(fan1_speed).turn_on();
          call1.set_speed(fan_set_speed);
          call1.perform();

          // Set fan 2 speed
          auto call2 = id(fan2_speed).turn_on();
          call2.set_speed(fan_set_speed);
          call2.perform();

          // Set fan 3 speed
          auto call3 = id(fan3_speed).turn_on();
          call3.set_speed(fan_set_speed);
          call3.perform();

          // Set fan 4 speed
          auto call4 = id(fan4_speed).turn_on();
          call4.set_speed(fan_set_speed);
          call4.perform();

        }
      }

This was working ok for a day or so, but now my Dallas temp sensors are not being detected. I don't even see their addresses in the debug log any more. I've not had time to double check the screw terminal connections yet, will do so on the weekend. Is there anything else that could cause this problem?

Assuming I get them working again, would there be any benefit in me doing the 4 fans in parallel using two temp sensors somehow?

Just a small note, I think there might be an error in the schematic for J1 as it shows it conencted to the GPIO27 one-wire bus along with J2 and J3. The docs say J1 is connected to GPIO26. image.png (view on web)https://github.com/user-attachments/assets/cd8c5362-1330-4e27-a48b-84bb0846d3a1

Apologies for the long issue.

— Reply to this email directly, view it on GitHubhttps://github.com/ESP32andmore/ECB/issues/1, or unsubscribehttps://github.com/notifications/unsubscribe-auth/BKCWDYUWKCHLKX4KZ4GIBSLZXCMDFAVCNFSM6AAAAABOMKISUOVHI2DSMVQWIX3LMV43ASLTON2WKOZSGUZTEMJXG42DSNQ. You are receiving this because you are subscribed to this thread.

patfelst commented 4 days ago

Thanks for your reponses Frank. Unfortunately as you replied by email, I didn't get the schematic attachment. Maybe you could update the github at some stage?

There is another project like this, and they use a proxy fan so they can use ESPHome PID and also have manual control. Have a look https://github.com/patrickcollins12/esphome-fan-controller/blob/3e850aab559fa558fd9f0713665c326b9b364699/console-fan.yaml#L277

Through trial and error I found that if I remove the web server component, the Dallas sensors work again. It's quite repeatable, i.e. if I add it back in, they stop working again. It must be some kind of ESP32 memory issue, as the docs say "Please note that enabling this component will take up a lot of memory and may decrease stability, especially on ESP8266".

I like the idea of averaging two sensors, with one at the bottom and another at the top of the rack.

Thanks Patrick

fabianmuehlberger commented 3 days ago

Hi, I just bought 2 fan control boards with the intention to use 2 temp sensors, average it and control all 4 fans with just that. I have not been able yet to play with the dallas sensors, probably will check it out during then weekend. @patfelst since the usecase looks similar, would you share your config? working with the same or similar config might help fixing the issue.

@ESP32andmore I would suggest a simpler "starter" config with a more minimal approach.

patfelst commented 3 days ago

Sure happy to share my config, its not tidied up yet. Will do in the next comment.

Tend to agree the example yaml is overly complex, for example the majority of the diagnositcs are not needed, nor is the web server IMO. Also the LCD display code should be removed as many people will not use it.

image

Perhaps a second yaml could be included in the repo with single "auto fan" control and single temp sensor for 4 fans.

patfelst commented 3 days ago

My cut down yaml, with two Dallas sensors, but only one being used for 4x fan control.

EDIT: Now a minimal configuration.

# Four automatically controlled PWM fan outputs (J4-J7), each set by four target temperatures, maintained by four Dallas sensor's temperatures. MQTT enabled. Home Assistant API disabled. DHCP enabled.
# Other control configurations available with modification of Dallas platform LAMBDA function. Contact us at esp32andmore@gmail.com for no cost customization.
# From Tindie https://www.tindie.com/products/esp32/esp32-control-board-ver-21/
# Github instructions https://github.com/ESP32andmore/ECB/tree/main?tab=readme-ov-file
substitutions:
  devicename: "pwm-fanctrl"
  fdevicename: PWM Rack Fan Ctrl
  ip: 192.168.20.145 # For static IP adressing

  alarm_temp: "30" # Threshold for alarm when implemented
  ptemp: "20"
  itemp: "0.1"

  # Connect your Dallas sensors with logger: DEBUG enabled (factory flash default).
  # Open the ESPHome webtool, connect to the ECB board, view the "Logs" window, hit "Reset",
  # and search for Dallas scan addresses and replace the below addresses with your unique ones.
  dallasaddress1: "0x5f00000dfd4e7228"
  dallasaddress2: "0xf200000dfca2d528"

esphome:
  name: ${devicename}
  friendly_name: ${fdevicename}
  comment: Quad PWM fan controller from Tindie "ESP32andmore - ECB"

esp32:
  # board: wemos_d1_mini32
  board: esp32dev
  framework:
    type: arduino

preferences:
  flash_write_interval: 10min

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Avfan1 Fallback Hotspot"
    password: "QBcMjLhesbQV"

captive_portal:

ota:
  - platform: esphome

api:
  encryption:
    key: "cO14KqV..............................................dsIXGzks="

logger:
  level: INFO

globals:
  - id: fan_sum
    type: float
    restore_value: no
    initial_value: "0"

number:
  - platform: template
    id: set_target_temp
    name: Target Temp
    optimistic: True
    min_value: 15
    max_value: 50
    initial_value: "26"
    step: 1
    restore_value: True
    unit_of_measurement: °C
    device_class: "TEMPERATURE"

  - platform: template
    id: set_alarm_temp
    name: Alarm Temp
    optimistic: True
    min_value: 15
    max_value: 80
    initial_value: ${alarm_temp}
    step: 1
    restore_value: true
    unit_of_measurement: °C
    device_class: "TEMPERATURE"

switch:
  - platform: restart
    name: Restart

  - platform: gpio
    name: Relay 0
    pin: GPIO18
    id: relay_0
    restore_mode: restore_default_off

  - platform: template
    id: auto_fan
    name: Fan Auto Mode
    restore_mode: RESTORE_DEFAULT_ON
    optimistic: true
    turn_off_action:
      - fan.turn_off: fan1_speed
      - fan.turn_off: fan2_speed
      - fan.turn_off: fan3_speed
      - fan.turn_off: fan4_speed

  - platform: gpio
    id: oc_port
    name: OC Port
    restore_mode: ALWAYS_OFF
    pin:
      number: 26
      mode:
        output: true
        pullup: true

one_wire:
  - platform: gpio
    pin: GPIO27

output:
  - platform: ledc
    pin: GPIO13
    id: fan1
    frequency: 25600Hz

  - platform: ledc
    pin: GPIO14
    id: fan2
    frequency: 25600Hz

  - platform: ledc
    pin: GPIO25
    id: fan3
    frequency: 25600Hz

  - platform: ledc
    pin: GPIO32
    id: fan4
    frequency: 25600Hz

  - platform: ledc
    pin:
      number: GPIO2
      ignore_strapping_warning: True
    id: alarm_led

light:
  - platform: monochromatic
    id: alarm_light
    output: alarm_led
    name: Alarm Light
    effects:
      - pulse:
          name: "Fast Pulse"
          transition_length: 0.5s
          update_interval: 0.5s
          min_brightness: 0%
          max_brightness: 100%

i2c:
  # - id: bus_a
  #   sda: GPIO21
  #   scl: GPIO22
  #   scan: false
  - id: bus_b
    sda: GPIO16
    scl: GPIO17
    scan: False
    frequency: 800khz

sensor:
  - platform: aht10
    i2c_id: bus_b
    address: 0x38
    variant: AHT20
    temperature:
      id: temp0
      name: Onboard Temperature
      filters:
        - filter_out: NaN
        - offset: -4.0
    humidity:
      name: Onboard Humidity
    update_interval: 5s

  - platform: pulse_counter
    pin: GPIO33
    unit_of_measurement: "rpm"
    name: Fan speed 1
    update_interval: 5s
    filters:
      - multiply: 0.5

  - platform: pulse_counter
    pin: GPIO34
    unit_of_measurement: "rpm"
    name: Fan speed 2
    update_interval: 5s
    filters:
      - multiply: 0.5

  - platform: pulse_counter
    pin: GPIO35
    unit_of_measurement: "rpm"
    name: Fan speed 3
    update_interval: 5s
    filters:
      - multiply: 0.5

  - platform: pulse_counter
    pin: GPIO39
    unit_of_measurement: "rpm"
    name: Fan speed 4
    update_interval: 5s
    filters:
      - multiply: 0.5

  - platform: wifi_signal
    name: WiFi
    update_interval: 30s

  - platform: uptime
    name: Uptime
    update_interval: 30s

  - platform: dallas_temp
    address: ${dallasaddress1}
    update_interval: 2s
    id: temp1
    filters:
      - filter_out: NaN
      - offset: 0.0
    unit_of_measurement: "°C"
    name: Temperature 1
    on_value:
      - if:
          condition:
            for:
              time: 10s
              condition:
                lambda: "return id(temp1).state >= id(set_alarm_temp).state;"
          then:
            - light.turn_on:
                id: alarm_light
                effect: "Fast Pulse"
            - lambda: !lambda |-
                id(alarm_sen).publish_state(true);
          else:
            - light.turn_off:
                id: alarm_light
            - lambda: !lambda |-
                id(alarm_sen).publish_state(false);
      # example using GLOBAL to maintain persistant SUM for each fan
      - lambda: !lambda |
          // Patrick's mod for all 4 fans to act in parallel based on Fan 1 auto setting and temp sensor 1 temperature
          if (id(auto_fan).state) {
            float fan_actual_temp =  id(temp1).state;
            float fan_desired_temp = id(set_target_temp).state;
            float diff = fan_actual_temp - fan_desired_temp;
            id(fan_sum) =id(fan_sum) + diff;
            float fan_pdiff=diff * $ptemp;
            float fan_idiff= id(fan_sum) * $itemp;
            float fan_set_speed = fan_pdiff + fan_idiff;
            if (fan_set_speed >100) fan_set_speed =100;
            if (fan_set_speed <10) fan_set_speed=1;
            if (id(fan_sum) >100) id(fan_sum) = 100;
            if (id(fan_sum) < -100) id(fan_sum) = -100;
            if (fan_set_speed <10) {
              fan_set_speed=1;

              // Turn off fan 1
              auto calloff1 = id(fan1_speed).turn_off();
              calloff1.set_speed(fan_set_speed);
              calloff1.perform();

              // Turn off fan 2
              auto calloff2 = id(fan2_speed).turn_off();
              calloff2.set_speed(fan_set_speed);
              calloff2.perform();

              // Turn off fan 3
              auto calloff3 = id(fan3_speed).turn_off();
              calloff3.set_speed(fan_set_speed);
              calloff3.perform();

              // Turn off fan 4
              auto calloff4 = id(fan4_speed).turn_off();
              calloff4.set_speed(fan_set_speed);
              calloff4.perform();

            } else {
              // Set fan 1 speed
              auto call1 = id(fan1_speed).turn_on();
              call1.set_speed(fan_set_speed);
              call1.perform();

              // Set fan 2 speed
              auto call2 = id(fan2_speed).turn_on();
              call2.set_speed(fan_set_speed);
              call2.perform();

              // Set fan 3 speed
              auto call3 = id(fan3_speed).turn_on();
              call3.set_speed(fan_set_speed);
              call3.perform();

              // Set fan 4 speed
              auto call4 = id(fan4_speed).turn_on();
              call4.set_speed(fan_set_speed);
              call4.perform();

            }
          }

  - platform: dallas_temp
    address: ${dallasaddress2}
    update_interval: 2s
    id: temp2
    filters:
      - filter_out: NaN
      - offset: 0.0 #Calibration
    unit_of_measurement: "°C"
    name: Temperature 2

fan:
  - platform: speed
    output: fan1
    id: fan1_speed
    name: Fan1 Speed
    restore_mode: RESTORE_DEFAULT_OFF

  - platform: speed
    output: fan2
    id: fan2_speed
    name: Fan2 Speed
    restore_mode: RESTORE_DEFAULT_OFF

  - platform: speed
    output: fan3
    id: fan3_speed
    name: Fan3 Speed
    restore_mode: RESTORE_DEFAULT_OFF

  - platform: speed
    output: fan4
    id: fan4_speed
    name: Fan4 Speed
    restore_mode: RESTORE_DEFAULT_OFF

text_sensor:
  - platform: version
    name: Version

binary_sensor:
  - platform: template
    id: alarm_sen
    name: Alarm
    icon: mdi:fire
ESP32andmore commented 2 days ago

Patrick, Thanks for the share. Actually there is a one sensor to many fans YAML auto-control on Github (avfan1-to-m.yaml) ESPhome. And yes the diagnostics is too rich but as it is an example those can easily be stripped out. I have a run-time selectable version of sensors to fans but it has not been fully tested. All your ideas and suggestion are valuable as time permits they will be implemented.

Best Regards, Frank


From: Patrick Felstead @.> Sent: Thursday, September 19, 2024 5:50 AM To: ESP32andmore/ECB @.> Cc: ESP32andmore @.>; Mention @.> Subject: Re: [ESP32andmore/ECB] A few questions and Dallas temp sensors stopped working (Issue #1)

Sure happy to share my config, its not tidied up yet. Will do in the next comment.

Tend to agree the example yaml is overly complex, for example the majority of the diagnositcs are not needed image.png (view on web)https://github.com/user-attachments/assets/41702acd-3a39-4c23-be2f-87ee1a7b9f6f

Perhaps a second yaml could be included in the repo with single "auto fan" control and single temp sensor for 4 fans.

— Reply to this email directly, view it on GitHubhttps://github.com/ESP32andmore/ECB/issues/1#issuecomment-2360529661, or unsubscribehttps://github.com/notifications/unsubscribe-auth/BKCWDYV2JUFOWNB26PXYM3LZXKM6RAVCNFSM6AAAAABOMKISUOVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDGNRQGUZDSNRWGE. You are receiving this because you were mentioned.