IKEA FÖRNUFTIG in Home-Assistant

lul


:arrow_down: Rotary switch (optional)

esphome:

output:
  - platform: esp8266_pwm
    pin: D1
    frequency: 150 Hz
    id: pwm_output
    min_power: 0.5
    max_power: 0.5
    
fan:
  - platform: speed
    output: pwm_output
    name: "Fornuftig Air Purifier"
    id: "fornuftig_fan"
    on_speed_set:
      lambda: |-
        if(id(fornuftig_fan).speed != id(fan_speed) && id(fornuftig_fan).state){
          id(fan_speed) = id(fornuftig_fan).speed;
          id(set_fan_freq).publish_state(id(fornuftig_fan).speed);
        }
    on_turn_on:
      lambda: |-
        if(id(fornuftig_fan).speed > 15){
          id(set_fan_freq).publish_state(id(fornuftig_fan).speed);
        }else{
          id(set_fan_freq).publish_state(id(speed_1));
        }
    on_turn_off:
      - output.esp8266_pwm.set_frequency:
          id: pwm_output
          frequency: !lambda 'return int(0);'
    
binary_sensor:
  - platform: template
    id: 'knob_0'
    filters:
      - delayed_on_off: 300ms
    lambda: |-
      if (!id(knob_1).state && !id(knob_2).state && !id(knob_3).state) {
        return true;
      } else {
        return false;
      }
    on_press: 
      lambda: |-
        if(!id(speed_0)){
          auto call = id(fornuftig_fan).turn_off();
          call.perform();
        }else{
          auto call = id(fornuftig_fan).turn_on();
          call.set_speed(id(speed_0));
          call.perform();
        }

  - platform: gpio
    id: 'knob_1'
    pin:
      number: D7
      mode: INPUT_PULLUP
      inverted: true
    filters:
      - delayed_on_off: 100ms
    on_press: 
      then:
        - fan.turn_on:
            id: fornuftig_fan
            speed: !lambda 'return id(speed_1);'
    
    
  - platform: gpio
    id: 'knob_2'
    pin:
      number: D6
      mode: INPUT_PULLUP
      inverted: true
    filters:
      - delayed_on_off: 100ms
    on_press: 
      then:
        - fan.turn_on:
            id: fornuftig_fan
            speed: !lambda 'return id(speed_2);'
  
  
  - platform: gpio
    id: 'knob_3'
    pin:
      number: D5
      mode: INPUT_PULLUP
      inverted: true
    filters:
      - delayed_on_off: 100ms
    on_press:
      then:
        - fan.turn_on:
            id: fornuftig_fan
            speed: !lambda 'return id(speed_3);'
    
    
      
      
sensor:
  - platform: template
    id: set_fan_freq
    filters:
      - multiply: 3
      - lambda: |-
          if (id(fornuftig_fan).state){
            if(x > 300){ // limit max frequency
              return 300;
              
            }else if(x < 60 && x > 3){ // limit low frequency
              return 60;
              
            } else if(x <= 3){
              return 0;
              
            } else {
              return x;
              
            }
          }else{
            return 0;
          }
    on_value:
      then:
        - output.esp8266_pwm.set_frequency:
            id: pwm_output
            frequency: !lambda 'return int(x);'
        - lambda: |- 
            // send current status to homeassistant
            if(x){
              auto call = id(fornuftig_fan).turn_on();
              call.set_speed(int(x)/3);
              call.perform();
            }else{
              auto call = id(fornuftig_fan).turn_off();
              call.perform();
            }



    
  - platform: homeassistant
    id: ha_fornuftig_speed_0
    entity_id: input_number.fornuftig_speed_0
    on_value:
      - globals.set:
          id: speed_0
          value: !lambda 'return int(x);'
          
          
  - platform: homeassistant
    id: ha_fornuftig_speed_1
    entity_id: input_number.fornuftig_speed_1
    on_value:
      - globals.set:
          id: speed_1
          value: !lambda 'return int(x);'
         
         
  - platform: homeassistant
    id: ha_fornuftig_speed_2
    entity_id: input_number.fornuftig_speed_2
    on_value:
      - globals.set:
          id: speed_2
          value: !lambda 'return int(x);'
        
        
  - platform: homeassistant
    id: ha_fornuftig_speed_3
    entity_id: input_number.fornuftig_speed_3
    on_value:
      - globals.set:
          id: speed_3
          value: !lambda 'return int(x);'
        
        
        
globals:
  - id: fan_speed
    type: int
    restore_value: yes
    initial_value: '0'

  - id: speed_0
    type: int
    restore_value: yes
    initial_value: '0'
    
  - id: speed_1
    type: int
    restore_value: yes
    initial_value: '55'
    
  - id: speed_2
    type: int
    restore_value: yes
    initial_value: '65'
    
  - id: speed_3
    type: int
    restore_value: yes
    initial_value: '100'
    

homeassistant:

input_number:
  fornuftig_speed_0:
    name: 'Fornuftig Speed 0'
    min: 0
    max: 100
    step: 1
    mode: slider
    unit_of_measurement: '%'
    icon: mdi:air-filter
  fornuftig_speed_1:
    name: 'Fornuftig Speed 1'
    min: 0
    max: 100
    step: 1
    mode: slider
    unit_of_measurement: '%'
    icon: mdi:air-filter
  fornuftig_speed_2:
    name: 'Fornuftig Speed 2'
    min: 0
    max: 100
    step: 1
    mode: slider
    unit_of_measurement: '%'
    icon: mdi:air-filter
  fornuftig_speed_3:
    name: 'Fornuftig Speed 3'
    min: 0
    max: 100
    step: 1
    mode: slider
    unit_of_measurement: '%'
    icon: mdi:air-filter
3 Likes

Thanks for the instructions, mine is modified now as well :slight_smile:

I used thick silicone double-sided tape and it’s holding firmly. I put 3.3V regulator because that’s what I had lying around.

I tried to replace D0 with D8, but that didn’t work for some reason.
Also, if compiling with A0 as sensor, it must be soldered as well, otherwise WiFi won’t work properly and ESP will boot loop.

Why is it necessary to cut the rotary switch legs if the original board is only used to hold it in place? Or does it interfere with the ESP and provide unreliable readings?

The rotary switch does short one of the outputs to ground, depending on the setting. The original board scans all the inputs (from highest setting to off) and controls the motor accordingly. So if you don0t cut the logs, the switch will fight the ESP when setting the speed. Disconnecting the legs gives full control to the ESP.

Ah sorry, it was a reply to the PWM method which doesn’t power on the original board anymore. I measured the legs and at least for the PWM method it should work without cutting them anymore.

I’m trying the PWM method with a Wemos D1 Mini right now, but for some reason using your code and connecting the D1 pin to the fan pin (and leaving the tacho pin disconnected) won’t make the fan spin at all.
Is there anything I’m missing? The fan itself works, if I touch the bare PWM pin cable it spins up (probably due to induced frequency).

EDIT: Nevermind the fan pin needs a common ground to work properly which I didn’t have in my testing. Works now!

I tried this but unfortunately it doesn’t always switch back on from home assistant after I switch it off. Will have to change the dial to get it back up and running :frowning:

i also get an error when setting to frequency to 0hz:

Frequency 0.000000 can’t be achieved with any bit depth

I am using an ESP32 and am using the ledc output for PWM

Hi.
Could you post the complete code to upload with esphome?

Hi, I just hacked my Fornuftig thanks to your instructions. But I have a question. Can you turn it off by turning the knob if it was previously turned on with ESP?

Hello,

first of all thanks for all your effort into hacking the ikea fan! Just awesome!

I tried to reproduce it but i cannot get the esp to power up… i connected a 5v regulator (with capacitors) to the 24v and gnd pins, i then measured the voltage and it is 4.99V which is fine. i then connected the D1 to the regulator, the led shortly blinks and thats it, when i know measure the volate while the D1 is connected it is around 1.1V…
By now i tried 6 different ESP8266 and a bunch of different regulators, circuit boards, etc… no matter what i am unable to power the esp through the fans power source…
any idea why this is? or at least an idea how i could figure out what exactly would be the problem.

just to mention: of course i did check for shorted circuits and disconnected everything except the power i event went so far to connect my regulator directly to the 24v cable connector and disconnected the pcb completely… no luck…

Hello,

I used the instructions and the fan works :slight_smile: Now i want to use it with mqtt. How can i change the code so i can publish commands to the fan?

Thanks

Edit:
Not perfect but i can turn fan on and off and change the level. If i change level and fan is off nothing hapens

fan:
 - platform: speed
   output: fan_out_internal
   id: fan_internal
   state_topic: ka-furnuftig-es/fan/fornftig_fan/state
   command_topic: ka-furnuftig-es/fan/fornftig_fan/cmnd/POWER
   speed_command_topic: ka-furnuftig-es/fan/fornftig_fan/cmnd/speed
   speed_state_topic: ka-furnuftig-es/fan/fornftig_fan/speed_level/state
   name: "$friendly_name Fan"
   speed_count: 3

Thanks for the tutorial.

I have created an automation for the speed of the fan depending on the readings from a sensor.

Perhaps interesting for those who still have the conversion in front of them.

- id: '1561881288569'
  alias: 'Air: Setze Drehzahl Feinstaubfilter Dachboden PM2.5'
  trigger:
    - platform: state
      entity_id: sensor.feinstaub_dachboden_pm2_5
  action:
    - choose:
        - conditions:
            - condition: numeric_state
              entity_id: sensor.feinstaub_dachboden_pm2_5
              value_template: "{{ states('sensor.feinstaub_dachboden_pm2_5') | int }}"
              above: 10
              below: 51
          sequence:
            - service: fan.set_percentage
              data:
                percentage: 33
              target:
                entity_id: fan.feinstaubfilter_dachboden_fan
    - choose:
        - conditions:
            - condition: numeric_state
              entity_id: sensor.feinstaub_dachboden_pm2_5
              value_template: "{{ states('sensor.feinstaub_dachboden_pm2_5') | int }}"
              above: 50
              below: 101
          sequence:
            - service: fan.set_percentage
              data:
                percentage: 66
              target:
                entity_id: fan.feinstaubfilter_dachboden_fan
    - choose:
        - conditions:
            - condition: numeric_state
              entity_id: sensor.feinstaub_dachboden_pm2_5
              value_template: "{{ states('sensor.feinstaub_dachboden_pm2_5') | int }}"
              above: 100
          sequence:
            - service: fan.set_percentage
              data:
                percentage: 100
              target:
                entity_id: fan.feinstaubfilter_dachboden_fan
    - choose:
        - conditions:
            - condition: numeric_state
              entity_id: sensor.feinstaub_dachboden_pm2_5
              value_template: "{{ states('sensor.feinstaub_dachboden_pm2_5') | int }}"
              below: 10
          sequence:
            - service: fan.turn_off
              entity_id: fan.feinstaubfilter_dachboden_fan
1 Like

Thank you very much @tht for the tutorial also, works like a charm! Has anyone got the PWM fan setting figured out with this same wiring configuration without bypassing the manual knob? Looks like @Nierit you bypassed the knob and how has your’s been holding up?

Great tutorial, but now I am stuck. I can get speed 2 and 3 working, but the lowest speed seems impossible. In the ESP home log, it sswitches correctly, but both the knob and digital selection of speed 1 will stop the fan.

At first I thought I had fried my Wemos, but I have tried two other ones and am having the same problem for them all. Anyone knows how I can troubleshoot this?

U sure it stopped? Speed 1 is realy silent here, but a small air movement.

Yep, I have it still open, so I can see that the fan has stopped turning. I found out that if I short D4 and Ground together on the Wemos, the first speed is working, but then it doesn’t respond to other settings anymore.

EDIT: Nevermind: got it working, by changing settings so that speed 2 on the knob was speed 1 coming from the wemos and changed it back again. Don’t get it, but it’s working again :slight_smile: It only took me two weeks to figure out…

Sometimes… :joy:

1 Like

Great tutorial! But I still have one question in my mind. Should i convert 5V to 3v3? As I know d1 mini I/Os are not 5V tolerant

I’ve the same issue, setting to lowest/fan 1 turns the fan completely off. How did you get lowest speed to work?