IKEA Vindriktning Air Quality Sensor

Has anyone ever experienced Vindriktning’s measurement results drifting off over time (see below) until I reset the Vindriktning (drops back to normal in the graph below)?


What I found odd, looking at the graph

  1. The drift could be set back to zero but always started again after I re-starting the entire Vindriktning
  2. The drift was triggered by spikes (spikes lead to increasing baselines by just 1 or 2 um, which, over time, cause the sensor to drift away)
  3. At first I thought I’m looking at a problem with the ESP, but I got exactly the same results also with a different ESP
  4. To be absolutely sure that it’s not the ESP messing with the Vindriktning’s internal hardware, I disconnected the ESP completely. Still same drift, but had to wait for ~10 days for the measurement results turning the LED turned from green to orange.

Faulty hardware? Or has anyone else experienced the same? Can’t be that “connecting the ESP” damages he Vindriktning?

What I also found odd: From what I read online, there’s hardly any “calibration-intelligence” in the Vindriktning, but looking at the graph there has to be?

Just saw this… Interesting how it evolves… :slight_smile:

8 Likes


i wonder when some of these commercial products using this filter / mesh textile, it also purify the measured air or with other words faking the measurements.

I don’t thinks so. It is not a HEPA filter and all small particles can go through

Just some update on the drift: I got another Vindriktning and did the same ESP-hack. Same result: The result drifts off, not as fast as with the first Vindriktning, but it still does, and is reset with a reboot (very narrow area on the far right).

Anyone else experiencing this? Any way to stop this?

For those allowing the fan to run 100% of the time, the main issue is that the fan will fail sooner, the sensor will get dirty sooner (which will affect its function) and the noise generated by the fan may increase over time as it deteriorates mechanically. For me, these are all good reasons to ensure the fan is turned off when not needed. A simple GPIO line and a transistor can do that. The big issue I am having is the very limited space inside the case, and the fact I would like to include a temperature sensor. The ESP and the PM1006 both generate heat which skew the temperature measurements. The fan itself doesn’t do much with regards to temperature unless you put the sensor in the top section… but heat also rises so I am not sure that is the best place to put the sensor either. Has anyone found a good solution that doesn’t include a software error correction (don’t like this option as the delta is likely not fixed).

Pictures showing the source of heat in the Vindriktning:

Fan:

The sensor itself:

I forgot to take pictures that included the ESP but that too had a spot around 30C

1 Like


My config Ikea Vindriktning Air Quality Sensor + BME680 Sensor + ESP8266 d1 mini:

Vindriktning === ESP8266 d1 mini GPIOS:
5V - 5V
GND - GND
REST - D2 GPIO4

BME680 === ESP8266 d1 mini:
VCC - 3.3V
GND - GND
SDO - GND
SCL - D6 GPIO 12
SDA - D7 GPIO 13

substitutions:
  name: multisensor
  friendly_name: "MultiSensor Air"
 
esphome:
  name: "${name}"
  platform: ESP8266
  board: d1_mini
 
# Enable logging
logger:
 
# Enable Home Assistant API
api:
web_server:
  port: 80
  local: true
  ota: false
 
ota:
  safe_mode: true
  password: "put yours on"
 
wifi:
  ssid: put yours on
  password: "put yours on"
  use_address: 192.168.x.xxx
 
  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "MultiSensor Hotspot"
    password: 'put yours on'
 
captive_portal: 
 
# BME680 sensor
i2c:
  scl: GPIO12 #D6
  sda: GPIO13 #D7
  scan: True
  id: bus_a
 
bme680_bsec:
  address: 0x76
  sample_rate: ulp
 
# Ikea Vindriktning PM2.5 sensor
uart:
  rx_pin: D2
  baud_rate: 9600
 
sensor:
  - platform: pm1006
    pm_2_5:
      name: "Particles PM2.5"
      id: pm_2_5
      accuracy_decimals: 2
      filters:
        - sliding_window_moving_average:
            window_size: 50
            send_every: 10
      disabled_by_default: false
      internal: false
# BME680 sensor
  - platform: bme680_bsec
    temperature:
      name: "Temperature"
      accuracy_decimals: 2
      filters:
        offset: -2
      disabled_by_default: false
      internal: false
    pressure:
      name: "Pressure"
      accuracy_decimals: 2
      unit_of_measurement: "mmHg"
      filters:
         - multiply: 0.75006375541921
      disabled_by_default: false
      internal: false
    humidity:
      name: "Humidity"
      accuracy_decimals: 2
      disabled_by_default: false
      internal: false
    gas_resistance:
      name: "Gas Resistance"
      accuracy_decimals: 2
      disabled_by_default: false
      internal: false
    iaq:
      name: "IAQ"
      id: iaq
      accuracy_decimals: 2
      disabled_by_default: false
      internal: false
    co2_equivalent:
      name: "CO2 Equivalent"
      accuracy_decimals: 2
      disabled_by_default: false
      internal: false
    breath_voc_equivalent:
      name: "Breath VOC Equivalent"
      accuracy_decimals: 2
      disabled_by_default: false
      internal: false
  - platform: uptime
    name: "Uptime"
    disabled_by_default: false
    internal: false
 
text_sensor:
  - platform: bme680_bsec
    iaq_accuracy:
      name: "IAQ Accuracy"
      disabled_by_default: false
      internal: false
 
  - platform: wifi_info
    ip_address:
      name: "IP address"
      disabled_by_default: false
      internal: false
 
  - platform: template
    name: "IAQ Classification"
    disabled_by_default: false
    internal: false
    icon: "mdi:checkbox-marked-circle-outline"
    lambda: |-
      if ( int(id(iaq).state) <= 50) {
        return {"Excellent"};
      }
      else if (int(id(iaq).state) >= 51 && int(id(iaq).state) <= 100) {
        return {"Good"};
      }
      else if (int(id(iaq).state) >= 101 && int(id(iaq).state) <= 150) {
        return {"Lightly polluted"};
      }
      else if (int(id(iaq).state) >= 151 && int(id(iaq).state) <= 200) {
        return {"Moderately polluted"};
      }
      else if (int(id(iaq).state) >= 201 && int(id(iaq).state) <= 250) {
        return {"Heavily polluted"};
      }
      else if (int(id(iaq).state) >= 251 && int(id(iaq).state) <= 350) {
        return {"Severely polluted"};
      }
      else if (int(id(iaq).state) >= 351) {
        return {"Extremely polluted"};
      }
      else {
        return {"error"};
      }
# Ikea Vindriktning PM2.5 sensor
  - platform: template
    name: "PM2.5 Classification"
    disabled_by_default: false
    internal: false
    icon: "mdi:blur"
    lambda: |-
      if ( int(id(pm_2_5).state) <= 25) {
        return {"Excellent"};
      }
      else if (int(id(pm_2_5).state) >= 26 && int(id(pm_2_5).state) <= 50) {
        return {"Good"};
      }
      else if (int(id(pm_2_5).state) >= 51 && int(id(pm_2_5).state) <= 100) {
        return {"Polluted"};
      }
      else if (int(id(pm_2_5).state) >= 101 && int(id(pm_2_5).state) <= 300) {
        return {"Heavily polluted"};
      }
      else if (int(id(pm_2_5).state) >= 301) {
        return {"Extremely polluted"};
      }
      else {
        return {"error"};
      }
button:
  - platform: restart
    id: restart_button
    name: "Restart
6 Likes

the sensor will get dirty sooner (which will affect its function) and the noise generated by the fan may increase over time as it deteriorates mechanically.

This is excatly what was happening to mine. It was making a loud noise. When I inspected the components inside the case, there were lint on the black mesh and the fan top (where the label is) had some dirt as well. I blew it off with air spray. Tested with it before mounting it back on and the noise was gone. The fan seems ok when I spun it. It will probably happen again down the road.

For me, these are all good reasons to ensure the fan is turned off when not needed.

The OP has tested the sensor with the fan being completely turned off, but the reading off.

A simple GPIO line and a transistor can do that.
Do you have image to show how it looks like and what gpio pin used?

I am using a ESP8266 d1 mini and would like to use a light photocell. Since the A0 pin is taken, is there an alternative pin or solution?

The article talks about variable speed but you can also just use it for on/off. When the sensor is not measuring, then ideally the fan would be off. When ready to measure, fan should be turned on and after a few seconds take the measurement if software allows this level of control. I am using a PMS5003 and with that similar sensor it can be done (no need for transistor though with that sensor).

Hej Goram

I am experiencing exactly the same thing but have not found another way than to power cycle the device to reset it.

Best
N3bu

1 Like

Hi!.

I’ve done the way of connecting the EP32 directly to the PM1006 sensor.
I’m receiving values from the sensor so far, but my problem is that such values are way higher than it should be. I’m talking values are from 200 up to 500 and even 600.

What could be the reason?

Thanks!

i have 2, one drift, the other not.
the non-drifting one is in a smoking room where the particle values often goes over 100 or even 200, sometimes even 500

Is there anybody who managed to get the sensor re-calibrated?

When soldering i addecently think i messed up 1 sensors calibration, values dropped by 10 since, and a second unit still displays the old common room values.

The wrong sensor also drops to 0 sometimes.

Can i fix this by anyhow?

I accidently made a connection possible between the connector from sensor, v5 and a resistance. I unmade the connection but somehow the values seem off.

I did it the hard way: I now only use the case of the Vindriktning, but put a Sensirion SPS30 and a Sensirion SCD40 together with an ESP-01S in it. Problem solved. :wink:

did you take photos during your build? Would love to see how it looks.

[EDITED]

The SPS30 has 1 more wire to select between UART or I2C comm (float or connected to ground). The remaining are identical to the original PM1006 : V, RX/TX, GND.

You installed the SPS30 to use UART, right? If so, is the original Ikea circuit board properly light up the front LEDs based on what the new PM sensor reports? Somehow I’d think the Ikea board might not properly read the values but I could be wrong. Perhaps the SPS30 reports values “the same way” as the PM1006 making it a drop in replacement?

The SPS30 comes with its own fan and size wise, it’s a lot thinner. Looking inside a vindri and the location of the holes behind the unit to allow air to come in, did you end up installing the new PM close to the bottom of the unit ~around where the origin fan was located?

Thanx!

Just ordered a new VINDRIKTNING… It arrives around the 27:th… :frowning:
Will post my findings here, hope it reports all the values with ZHA …

Have a look at this topic on reddit.

https://www.reddit.com/r/homeassistant/comments/11mqslk/ikea_vindstyrka_in_ha_connected_through_zha/

1 Like

Consider starting a new thread.

1 Like