IKEA FÖRNUFTIG in Home-Assistant

Hey everyone.

Are you not supposed to cut the unused leg of the encoder?
I cut all 5 legs on that side and connected the required 4 to the ESP8266.
However, I’m having issues with the manual control. WIFI control works great!

Encoder Position 1 results in speed 1, D1: L, D5: H, D6: L, D7: L. It should be off.
Encoder Position 2 results in speed 2, D1: L, D5: L, D6: H, D7: L. It should be speed 1.
Encoder Position 3 results in speed 2, D1: L, D5: L, D6: H, D7: L. Correct
Encoder Position 4 results in speed 3, D1: L, D5: L, D6: L, D7: H. Correct

Positions 1 and 2 aren’t behaving as intended.

Thanks for your help,
Dan

Great project!
I just wanted to add this for posterity since it stumped me for a while: I used a MP2315 step down converter (using it to step down to 3.3V) and a Wemos D1 Mini, and I couldn’t flash the D1 Mini after soldering all the wires. I just got this error:
A fatal error occurred: Failed to connect to Espressif device: Timed out waiting for packet header
I was able to flash the firmware when i plugged in the 24V power supply of the fan. Don’t know why this happens but it does! So try plugging in the power supply if you are experiencing problems with the initial flashing.

Did anyone of you use a 5V <-> 3.3V level shifter, as Wemos use 3.3V GPIO and Förnuftig is at 5V.
I don’t want to fry my Wemo and was wondering about that.

1 Like

Somewhat of a stupid question but how did you wire up the fan following the guide in Making the stupid dumb. Vindriktning and Förnuftig - Qball's Weblog? Having never wired up a PWM fan before I really don’t want to let out the magic smoke and it’s really hard to see from the pictures in that guide.

Hi, how do you set up automation to set the speed of the fan? Thanks

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.

1 Like

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?