Fan: platform: template really confused, help unconfuse me!

I have been trying to get this right and looking for example / code for a while…so I am hoping I didnt miss something!

The boiler plate is left off in the below. Here is the project:

I have removed the control board from multiple Vornado fans; they all work with some kind of triac that when brought low at 5v opens a 110vac line to the fan at various speeds and for oscillation. I cut the trace for the 5v generator, then soldered in an ESP32 and put in my own 5v (using an old usb charger to the esp32). I wanted to use this janky setup to make sure it worked before I put in an m5 stamp for size.

Each of the switches works fine. The fan works great this way. But I want to make it a “real fan” in HA, but I cannot for the life of me get the oscillation to work in HA to the device. I repeat everything works great from the web ui on the device. Just not in HA. So I am focusing on the fan: template here. There appears to be no id(myfan).oscilate_off() or the like as there is for the switches and also I cannot figure out how to make the swing turn off when the fan is off. So the oscillation state is never the same in HA as on the device…

Given how every single fan I have opened works the same way - ac lines for windings that represent speed it seems like we almost need another sub-type of fan where each switch is a speed. So you would feed in a config of GPIOs for each speed and swing. I have opened up 14 fans each of them works exactly the same way, so if you were to take a 4 chan relay board you could use interlocking to automate it and it would be the same config.

Maybe I am missing something fundamental here…but I appreciate the help.

BTW speed step works perfectly!


switch:
  - platform: gpio
    name: High
    id: high
    interlock: &interlock_group [high, medlow, medium, low]
    pin:
      number: 48
      inverted: true
      mode:
        output: true
        open_drain: true

  - platform: gpio
    name: Medium Low
    id: medlow
    interlock: *interlock_group
    pin:
      number: 47
      inverted: true
      mode:
        output: true
        open_drain: true  

  - platform: gpio
    name: Swing
    id: swing
    pin:
      number: 46
      inverted: true
      mode:
        output: true
        open_drain: true   

  - platform: gpio
    name: Medium
    id: medium
    interlock: *interlock_group    
    pin:
      number: 45
      inverted: true
      mode:
        output: true
        open_drain: true      

  - platform: gpio
    name: Low
    id: low
    interlock: *interlock_group    
    pin:
      number: 21
      inverted: true
      mode:
        output: true
        open_drain: true 


fan:
  - platform: template
    name: "Virtual Fan"
    id: thefan
    has_oscillating: true
    speed_count: 4
    restore_mode: RESTORE_DEFAULT_OFF
    on_oscillating_set:
      - lambda: |-
          if (id(thefan).oscillating) {
            id(swing).turn_on();
          } else {
            id(swing).turn_off();
          }
    on_speed_set:
      - lambda: |-
          if (id(thefan).speed == 1) {
            id(low).turn_on();
          } else if (id(thefan).speed == 2) {
            id(medlow).turn_on();
          } else if (id(thefan).speed == 3) {
            id(medium).turn_on();
          } else if (id(thefan).speed == 4) {
            id(high).turn_on();
          } else {
            id(high).turn_on();
          }
    on_turn_on:
      - lambda: |-
          id(low).turn_on();
    on_turn_off:
      - lambda: |-
          id(swing).turn_off();
          id(low).turn_off();
          id(medlow).turn_off();
          id(medium).turn_off();
          id(high).turn_off();

That is the software interlock that you have already implemented. If you read the warnings on how this can be a fire risk. It’s not going to be in a component that typ controls ac power.

Warning
These are software interlocks. As such, a software bug (which can always happen) can still activate both switches at the same time. Similarly, at reset time (before any of ESPHome’s code runs) the relay GPIO pins may have pull-ups active, so the relay may be active before ESPHome can manually deactivate them.
So it is highly recommended to use hardware interlocks (like SPDT-type relays) that ensure that two GPIOs are never active at the same time.

If you look at the last example in lambda calls, oscillating is true or false.

call.set_oscillating(true);

https://esphome.io/components/fan/#lambda-calls

Yeah that is a bummer that oscillate was not implemented in the simpler manner, but alas I can switch over to that call.x method in my other functions as well to be consistent. Ideally there should be the same methods of access for all actions…so I was hoping this was an oversight, but alas…

Triacs with open drain and an ESP32 should not (cannot) be activated in the situation mentioned. A bit of the magic of open drain. Also, I am not sure what case this is written for (maybe reversing, then I would worry) but on all these fans I am automating if I connect across multiple windings nothing happens that is unexpected. - the fan operates normally, the fuses don’t blow, the motors do not overheat, etc…this is likely because of how the windings are built out.

Fuses are our friends on high current/line voltage projects :slightly_smiling_face: