IKEA Vindstyrka & ESPHome Integration

Ikea introduced a new air quality sensor called Vindstyrka. At €40 it brings along a display, zigbee and an excellent Sensirion SEN54. The screen shows PM2.5, temperature, humidity and an indicator for tVOC.

The Sensirion Sen54 can do a bit more. Can we get it via Esphome? Answer: Yes, we can. Many thanks to Oleksii Kutuzov for his initial investigation.

Short “How to”: Open the sensor, find the pins names VCC, GND, SDA and SCL underneath the LCD connector. Connect an D1 Mini or similar to it. Do a little ESPHome YAML. Done. About 1 hour work.

As a first step, remove the protective plastic from the front, by inserting a fingernail between the screen and the box. It is lightly taped. To unscrewfrom behind, use a T6 Torx. Don’t unscrew completely at first, as you need to push an inner sensor casing out of the box. Loosen all four screws and push the inner casing out.

Locate the I2C bus connector in the lower part of the board. Carefully solder the needed wires. Pay attention to the flat ribbon connector of the LCD screen, it does not like your solder iron.

The YAML for ESPHome assumes a D1 Mini and I2C bus connections on D1 for SCL and D2 for SCA. Please adjust, if needed.

esphome:
  name: vindstryka
  friendly_name: Vindstryka
  platform: ESP8266
  board: d1_mini
# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "dWh+jnSCUSii2lAHl1hWlYEIKgsl5CpO0+5SK85Q4X4="

ota:
  password: "2bd359935280c9823bfdde61ec3218d"

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

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

# I2C config as SEN54 is connected on that bus
i2c:
  scl: D1
  sda: D2
  scan: true
  id: bus_a

# Example configuration entry
sensor:
  - platform: sen5x
    id: sen54
    pm_1_0:
      name: " PM <1µm Weight concentration"
      id: pm_1_0
      accuracy_decimals: 1
    pm_2_5:
      name: " PM <2.5µm Weight concentration"
      id: pm_2_5
      accuracy_decimals: 1
    pm_4_0:
      name: " PM <4µm Weight concentration"
      id: pm_4_0
      accuracy_decimals: 1
    pm_10_0:
      name: " PM <10µm Weight concentration"
      id: pm_10_0
      accuracy_decimals: 1
    temperature:
      name: "Temperature"
      id: Sen54_T
      accuracy_decimals: 1
    humidity:
      name: "Humidity"
      id: Sen54_H
      accuracy_decimals: 0
    voc:
      name: "VOC"
      id: tVOC
      algorithm_tuning:
        index_offset: 100
        learning_time_offset_hours: 12
        learning_time_gain_hours: 12
        gating_max_duration_minutes: 180
        std_initial: 50
        gain_factor: 230
    temperature_compensation:
      offset: 0
      normalized_offset_slope: 0
      time_constant: 0
    acceleration_mode: low
    store_baseline: true
    address: 0x69
    update_interval: 10s

captive_portal:

This will read the I2C bus every 10 seconds. The log in ESPHome will show all SEN54 readings:

[10:00:10][D][sensor:126]: ' PM <1µm Weight concentration': Sending state 11.50000 µg/m³ with 1 decimals of accuracy
[10:00:10][D][sensor:126]: ' PM <2.5µm Weight concentration': Sending state 12.10000 µg/m³ with 1 decimals of accuracy
[10:00:10][D][sensor:126]: ' PM <4µm Weight concentration': Sending state 12.10000 µg/m³ with 1 decimals of accuracy
[10:00:10][D][sensor:126]: ' PM <10µm Weight concentration': Sending state 12.10000 µg/m³ with 1 decimals of accuracy
[10:00:10][D][sensor:126]: 'Temperature': Sending state 25.50000 °C with 1 decimals of accuracy
[10:00:10][D][sensor:126]: 'Humidity': Sending state 45.18000 % with 0 decimals of accuracy
[10:00:10][D][sensor:126]: 'VOC': Sending state 101.00000  with 0 decimals of accuracy

Looks like we have an interference with the IKEA sensor controller. There is a regular error message in the logs:

[10:02:30][E][sensirion_i2c:026]: CRC8 Checksum invalid at pos 1! 0xFE != 0xAC

But it seems not to affect the IKEA devices nor the ESPHome integration

7 Likes

Hi! Your solution works for logigng the data.
I am using a nodemcuv3 externally to not mess up with the temperatures.

BUT: The readings are not the same as the ones on the display!

Both readings are up-to-date.

The Zigbee readings match the ones shown on the devices display.
The ESP readings match after turning on the device but seem to diverge with time.

1 Like

I did the same as proposed, and found out the D1 mini heats up inside the box and messes up the temperature reading. Therefore I have a significant offset on both the display and the I2C reading.

My understanding is the I2C bus is the raw measurements from the Sensirion SEN54 which IKEA device is using but they likely make some computation before showing values on the display and zigbee.

Now I’m thinking that I should put the esp outside the box and look for probing the signal sent to zigbee. Apart from the I2C bus there’s also an Rx Tx set of TPs that might be what we need.

How did you get the zigbee value in your home assistant? Using the ikea zigbee hub?

Cheers,

1 Like

Hi!
The Zigbee values are read out via ZHA (they match the values on the display 100%).

I think that there is a calibration courve stored in the device for temp/humid which is applied to the raw values before they are displayed.

I ended up setting a correction in the home assistant sensor config yml. Not perfect, but closer to the “real world” readings.

@Webeling
Can you please give a bit more details on connections? I found pins names VCC, GND, SDA and SCL and I have ACEIRMC D1 Mini NodeMCU ESP32 ESP-WROOM-32 WLAN WiFi Bluetooth IoT Development Board 5V
https://www.amazon.com/dp/B08PNWB81Z?psc=1&ref=ppx_yo2ov_dt_b_product_details
What pins from D1 I need to use and which one to connect to which one in the Vindstyrka

Thank you in advance

Image of D1 board pins

Sorry, I don’t know this board and can’t promise anything. As a guidance: https://www.fambach.net/d1-mini-esp8266-modul-2-2/ has the pin out for a ESP32 D1 mini. According to that the IO21 and IO22 are the ones for the I2C bus. Note that the YAML above is for D1 Mini with an ESP8266. You need to change the lines:

  platform: ESP8266
  board: d1_mini

I’ve been sniffing the I2C communications to figure out the correction factors that IKEA applies to the temp/humidity values.

Turns out IKEA sends three commands to the sensor:
0x0202 (read data ready flag)
0x03C4 (read processed measurements)
0x03D2 (undocumented in the data sheet for the SEN54)
0x03F5 (undocumented, response is similar to 0x03D2)

It turns out that the first “undocumented” command (0x03D2) is documented for another model of sensor, it returns the raw/unprocessed temperature and humidity values. The second undocumented command (0x03F5) has a similar response to the first one.

It looks like IKEA processes these raw values to display the temp/humidity.

IKEA did not program any of the compensation constants in the sensor, they are all factory default.

The idea is now to emulate the sensor so I can feed the VINDSTYRKA a range of values and see how the display responds, this should result in a compensation constant or slope that can be used to correct the data.

Hello,

About SENSIRION sensor SEN54, command 0x03D2 is documented here …

in this page:

on Technical Downloads select “How to read RH/T, VOC, and NOx raw signals” Application Note …

but don’t find anything about `0x03F5 …

Good work!
Best regards!

I continued my research on Github:

Currently I’m logging all the values for an extended period of time to figure out what the significance of that damn mystery value is.

I also contacted Sensirion, they pointed me to the same document but did not mention the “mystery” data.

Unfortunately I don’t have a non-IKEA SEN54, so I can’t check if this command is standard or if it was implemented specifically for IKEA.

1 Like

Hi,

Just made all with the instruction with integration of the D1 mini.
Maybe somebody have this kind of the problem.
Vindstyrka showing about +3 +4 degrees more than few other temperature sensors that installed near.

Thank you

Any updates on your quest with the module?