Can't get Sensor (SEN55) connected to ESP32 and ESPHome

So, I’m out of ideas and options here. I tried to google it up but the few posts and reddit subs I found were’nt really helpful. I currently try to connect the Sensirion Sen55 to my Home Assistant using an ESP32 flashed with ESPHome. To connect the Sen55 to the ESP32 I used the Adafruit Breaker Board in the middle. The Breaker Board and the Sen55 are connected with the JST GH 6 Pin Cable and the breaker board and the ESP32 are connected through a JST SH 4 Pin Cable. The ESP32 and the adafruit LEDs are working. Cables are 150mm and 100mm long. Nothing else on the breaker board or ESP32.

ESP32 board: ESP32 NodeMCU Development Board
Adafruit adapter board: Adafruit SEN54 or SEN55 Adapter Breakout - STEMMA QT / Qwiic : ID 5964 : Adafruit Industries, Unique & fun DIY electronics and kits
Dupont Cable: SparkFun Qwiic - flexibles Adapterkabel, 4 Pin Dupont Female, 150mm - kaufen bei BerryBase

I connected:
GND → GND
VIN → 3V3
SDA → GP16 (I also tried 21)
SCL → GP17 (I also tried 22)

The EPS32 is powered through a 5V power supply.

To clarify, the ESP32 can connect to ESPHome and HA and will show up as a device but without devices and entities. And as the logs below show, the SEN5X can’t connect and therefore there is no data.

I already tried:

  • changing GPIOs
  • re-installing ESPHome
  • removing the address: 0x69 (as currently shown in YAML)
  • lowering the frequency to 10 kHz
  • changing the different GNDs on the ESP32

Here is my YAML:

substitutions:
  # --- Grenzwerte für Ampelanzeige ---
  pm1_green_max: "10"
  pm1_yellow_max: "25"
  pm25_green_max: "15"
  pm25_yellow_max: "35"
  pm10_green_max: "45"
  pm10_yellow_max: "100"
  voc_green_max: "100"
  voc_yellow_max: "200"
  nox_green_max: "100"
  nox_yellow_max: "200"

esphome:
  name: luftsensor-stromraum
  friendly_name: Luftsensor Stromraum

esp32:
  board: esp32dev
  framework:
    type: esp-idf

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: redacted

ota:
  - platform: esphome
    password: redacted

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Luftsensor-Stromraum"
    password: redacted

captive_portal:

# ---------- Hardware-Bus zum SEN55 ----------
i2c:
  sda: 16
  scl: 17
  scan: true

# ---------- interne Speicherwerte für Ampel-Logik ----------
globals:
  - id: pm1_val
    type: float
    restore_value: no
    initial_value: '0.0'

  - id: pm25_val
    type: float
    restore_value: no
    initial_value: '0.0'

  - id: pm10_val
    type: float
    restore_value: no
    initial_value: '0.0'

  - id: voc_val
    type: float
    restore_value: no
    initial_value: '0.0'

  - id: nox_val
    type: float
    restore_value: no
    initial_value: '0.0'

# ---------- eigentliche Messwerte vom SEN55 ----------
sensor:
  - platform: sen5x
    # address: 0x69
    pm_1_0:
      name: "Feinstaub PM1.0"
      id: pm1
      unit_of_measurement: "µg/m³"
      icon: mdi:blur
      filters:
        - median:
            window_size: 5
            send_every: 1
    pm_2_5:
      name: "Feinstaub PM2.5"
      id: pm25
      unit_of_measurement: "µg/m³"
      icon: mdi:blur
      filters:
        - median:
            window_size: 5
            send_every: 1
    pm_10_0:
      name: "Feinstaub PM10"
      id: pm10
      unit_of_measurement: "µg/m³"
      icon: mdi:blur
      filters:
        - median:
            window_size: 5
            send_every: 1
    humidity:
      name: "Luftfeuchtigkeit"
      unit_of_measurement: "%"
      icon: mdi:water-percent
    temperature:
      name: "Temperatur"
      unit_of_measurement: "°C"
      icon: mdi:thermometer
    voc:
      name: "VOC Index"
      id: voc_index
      icon: mdi:chemical-weapon
      filters:
        - median:
            window_size: 5
            send_every: 1
    nox:
      name: "NOx Index"
      id: nox_index
      icon: mdi:smog
      filters:
        - median:
            window_size: 5
            send_every: 1

  # Spiegel die aktuellen Messwerte in globale Variablen,
  # damit wir sie in der Ampel-Logik sauber vergleichen können.
  - platform: template
    id: pm1_shadow
    internal: true
    update_interval: 5s
    lambda: |-
      id(pm1_val) = id(pm1).state;
      id(pm25_val) = id(pm25).state;
      id(pm10_val) = id(pm10).state;
      id(voc_val) = id(voc_index).state;
      id(nox_val) = id(nox_index).state;
      return 0;

# ---------- Text-Sensoren für die Farbstufen (gruen / gelb / rot) ----------
text_sensor:
  - platform: template
    name: "PM1.0 Ampel"
    icon: mdi:traffic-light
    update_interval: 5s
    lambda: |-
      const float g = atof("${pm1_green_max}");
      const float y = atof("${pm1_yellow_max}");
      float v = id(pm1_val);
      if (v < g) return {"gruen"};
      else if (v <= y) return {"gelb"};
      else return {"rot"};

  - platform: template
    name: "PM2.5 Ampel"
    icon: mdi:traffic-light
    update_interval: 5s
    lambda: |-
      const float g = atof("${pm25_green_max}");
      const float y = atof("${pm25_yellow_max}");
      float v = id(pm25_val);
      if (v < g) return {"gruen"};
      else if (v <= y) return {"gelb"};
      else return {"rot"};

  - platform: template
    name: "PM10 Ampel"
    icon: mdi:traffic-light
    update_interval: 5s
    lambda: |-
      const float g = atof("${pm10_green_max}");
      const float y = atof("${pm10_yellow_max}");
      float v = id(pm10_val);
      if (v < g) return {"gruen"};
      else if (v <= y) return {"gelb"};
      else return {"rot"};

  - platform: template
    name: "VOC Ampel"
    icon: mdi:traffic-light
    update_interval: 5s
    lambda: |-
      const float g = atof("${voc_green_max}");
      const float y = atof("${voc_yellow_max}");
      float v = id(voc_val);
      if (v < g) return {"gruen"};
      else if (v <= y) return {"gelb"};
      else return {"rot"};

  - platform: template
    name: "NOx Ampel"
    icon: mdi:traffic-light
    update_interval: 5s
    lambda: |-
      const float g = atof("${nox_green_max}");
      const float y = atof("${nox_yellow_max}");
      float v = id(nox_val);
      if (v < g) return {"gruen"};
      else if (v <= y) return {"gelb"};
      else return {"rot"};

  - platform: template
    name: "Luftstatus Gesamt"
    icon: mdi:air-filter
    update_interval: 5s
    lambda: |-
      auto worst = std::string("gruen");
      auto worse = [&](std::string a, std::string b)->std::string{
        auto rank = [&](std::string s)->int{
          if (s == "gruen") return 0;
          if (s == "gelb")  return 1;
          return 2;
        };
        return (rank(a) >= rank(b)) ? a : b;
      };
      auto eval = [&](float v, float g, float y)->std::string{
        if (v < g) return "gruen";
        else if (v <= y) return "gelb";
        else return "rot";
      };
      worst = worse(worst, eval(id(pm1_val),  atof("${pm1_green_max}"),  atof("${pm1_yellow_max}")));
      worst = worse(worst, eval(id(pm25_val), atof("${pm25_green_max}"), atof("${pm25_yellow_max}")));
      worst = worse(worst, eval(id(pm10_val), atof("${pm10_green_max}"), atof("${pm10_yellow_max}")));
      worst = worse(worst, eval(id(voc_val),  atof("${voc_green_max}"),  atof("${voc_yellow_max}")));
      worst = worse(worst, eval(id(nox_val),  atof("${nox_green_max}"),  atof("${nox_yellow_max}")));
      return {worst.c_str()};

# ---------- Binäre Komfort-/Sicherheits-Flags für Home Assistant ----------
binary_sensor:
  - platform: template
    name: "Luft OK (ohne Maske)"
    device_class: safety
    lambda: |-
      return id(pm1_val)  < atof("${pm1_green_max}")
          && id(pm25_val) < atof("${pm25_green_max}")
          && id(pm10_val) < atof("${pm10_green_max}")
          && id(voc_val)  < atof("${voc_green_max}")
          && id(nox_val)  < atof("${nox_green_max}");
    filters:
      - delayed_on: 10s
      - delayed_off: 10s

  - platform: template
    name: "Luft belastet (Maske empfohlen)"
    device_class: safety
    lambda: |-
      bool any_yellow =
        ((id(pm1_val)  >= atof("${pm1_green_max}")  && id(pm1_val)  <= atof("${pm1_yellow_max}")) ||
         (id(pm25_val) >= atof("${pm25_green_max}") && id(pm25_val) <= atof("${pm25_yellow_max}")) ||
         (id(pm10_val) >= atof("${pm10_green_max}") && id(pm10_val) <= atof("${pm10_yellow_max}")) ||
         (id(voc_val)  >= atof("${voc_green_max}")  && id(voc_val)  <= atof("${voc_yellow_max}")) ||
         (id(nox_val)  >= atof("${nox_green_max}")  && id(nox_val)  <= atof("${nox_yellow_max}")));
      bool all_green =
         id(pm1_val)  < atof("${pm1_green_max}")
      && id(pm25_val) < atof("${pm25_green_max}")
      && id(pm10_val) < atof("${pm10_green_max}")
      && id(voc_val)  < atof("${voc_green_max}")
      && id(nox_val)  < atof("${nox_green_max}");
      return any_yellow && !all_green;
    filters:
      - delayed_on: 10s
      - delayed_off: 10s

  - platform: template
    name: "Luft stark belastet (Tür zu, Maske Pflicht)"
    device_class: safety
    lambda: |-
      return id(pm1_val)  > atof("${pm1_yellow_max}")
          || id(pm25_val) > atof("${pm25_yellow_max}")
          || id(pm10_val) > atof("${pm10_yellow_max}")
          || id(voc_val)  > atof("${voc_yellow_max}")
          || id(nox_val)  > atof("${nox_yellow_max}");
    filters:
      - delayed_on: 5s
      - delayed_off: 10s

Here is my log:

INFO ESPHome 2025.10.3
INFO Reading configuration /config/esphome/luftsensor-stromraum.yaml...
INFO Generating C++ source...
INFO Compiling app...
Processing luftsensor-stromraum (board: esp32dev; framework: espidf; platform: https://github.com/pioarduino/platform-espressif32/releases/download/54.03.21-2/platform-espressif32.zip)
--------------------------------------------------------------------------------
INFO Package configuration completed successfully
INFO Package configuration completed successfully
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
 - framework-espidf @ 3.50402.0 (5.4.2) 
 - tool-cmake @ 3.30.2 
 - tool-esp-rom-elfs @ 2024.10.11 
 - tool-esptoolpy @ 5.0.2 
 - tool-mklittlefs @ 3.2.0 
 - tool-ninja @ 1.13.1 
 - tool-scons @ 4.40801.0 (4.8.1) 
 - toolchain-xtensa-esp-elf @ 14.2.0+20241119
Reading CMake configuration...
Dependency Graph
|-- noise-c @ 0.1.10
RAM:   [=         ]  10.5% (used 34484 bytes from 327680 bytes)
Flash: [=====     ]  51.6% (used 947246 bytes from 1835008 bytes)
========================= [SUCCESS] Took 20.88 seconds =========================
INFO Successfully compiled program.
INFO Connecting to 192.168.68.84 port 3232...
INFO Connected to 192.168.68.84
INFO Uploading /data/build/luftsensor-stromraum/.pioenvs/luftsensor-stromraum/firmware.bin (947648 bytes)
Uploading: [============================================================] 100% Done...

INFO Upload took 17.33 seconds, waiting for result...
INFO OTA successful
INFO Successfully uploaded program.
INFO Starting log output from 192.168.68.84 using esphome API
INFO Successfully resolved luftsensor-stromraum @ 192.168.68.84 in 0.000s
INFO Successfully connected to luftsensor-stromraum @ 192.168.68.84 in 4.168s
INFO Successful handshake with luftsensor-stromraum @ 192.168.68.84 in 0.435s
[19:08:49.791][I][app:185]: ESPHome version 2025.10.3 compiled on Oct 30 2025, 19:02:15
[19:08:49.791][C][wifi:679]: WiFi:
[19:08:49.791][C][wifi:458]:   Local MAC: redacted
[19:08:49.792][C][wifi:465]:   IP Address: 192.168.68.84
[19:08:49.797][C][wifi:469]:   SSID: [redacted]
[19:08:49.797][C][wifi:469]:   BSSID: [redacted]
[19:08:49.797][C][wifi:469]:   Hostname: 'luftsensor-stromraum'
[19:08:49.797][C][wifi:469]:   Signal strength: -58 dB ▂▄▆█
[19:08:49.797][C][wifi:469]:   Channel: 5
[19:08:49.797][C][wifi:469]:   Subnet: redacted
[19:08:49.797][C][wifi:469]:   Gateway: redacted
[19:08:49.797][C][wifi:469]:   DNS1: redacted
[19:08:49.797][C][wifi:469]:   DNS2: redacted
[19:08:49.886][C][logger:261]: Logger:
[19:08:49.886][C][logger:261]:   Max Level: DEBUG
[19:08:49.886][C][logger:261]:   Initial Level: DEBUG
[19:08:49.886][C][logger:267]:   Log Baud Rate: 115200
[19:08:49.886][C][logger:267]:   Hardware UART: UART0
[19:08:49.887][C][logger:274]:   Task Log Buffer Size: 768
[19:08:49.887][C][i2c.idf:081]: I2C Bus:
[19:08:49.887][C][i2c.idf:082]:   SDA Pin: GPIO16
[19:08:49.887][C][i2c.idf:082]:   SCL Pin: GPIO17
[19:08:49.887][C][i2c.idf:082]:   Frequency: 50000 Hz
[19:08:49.887][C][i2c.idf:092]:   Recovery: bus successfully recovered
[19:08:49.888][C][i2c.idf:102]: Results from bus scan:
[19:08:49.888][C][i2c.idf:104]: Found no devices
[19:08:49.888][C][template.sensor:015]: Template Sensor 'pm1_shadow'
[19:08:49.888][C][template.sensor:015]:   State Class: ''
[19:08:49.888][C][template.sensor:015]:   Unit of Measurement: ''
[19:08:49.888][C][template.sensor:015]:   Accuracy Decimals: 1
[19:08:49.889][C][template.sensor:362]:   Update Interval: 5.0s
[19:08:49.889][C][template.text_sensor:014]: Template Sensor 'PM1.0 Ampel'
[19:08:49.889][C][template.text_sensor:021]:   Icon: 'mdi:traffic-light'
[19:08:49.970][C][template.text_sensor:014]: Template Sensor 'PM2.5 Ampel'
[19:08:49.970][C][template.text_sensor:021]:   Icon: 'mdi:traffic-light'
[19:08:49.970][C][template.text_sensor:014]: Template Sensor 'PM10 Ampel'
[19:08:49.971][C][template.text_sensor:021]:   Icon: 'mdi:traffic-light'
[19:08:49.971][C][template.text_sensor:014]: Template Sensor 'VOC Ampel'
[19:08:49.971][C][template.text_sensor:021]:   Icon: 'mdi:traffic-light'
[19:08:49.971][C][template.text_sensor:014]: Template Sensor 'NOx Ampel'
[19:08:49.971][C][template.text_sensor:021]:   Icon: 'mdi:traffic-light'
[19:08:49.971][C][template.text_sensor:014]: Template Sensor 'Luftstatus Gesamt'
[19:08:49.972][C][template.text_sensor:021]:   Icon: 'mdi:air-filter'
[19:08:49.972][C][template.binary_sensor:016]: Template Binary Sensor 'Luft OK (ohne Maske)'
[19:08:49.973][C][template.binary_sensor:019]:   Device Class: 'safety'
[19:08:49.990][C][template.binary_sensor:016]: Template Binary Sensor 'Luft belastet (Maske empfohlen)'
[19:08:49.991][C][template.binary_sensor:019]:   Device Class: 'safety'
[19:08:50.090][C][template.binary_sensor:016]: Template Binary Sensor 'Luft stark belastet (Tür zu, Maske Pflicht)'
[19:08:50.090][C][template.binary_sensor:019]:   Device Class: 'safety'
[19:08:50.090][C][sen5x:253]: SEN5X:
[19:08:50.091][C][sen5x:254]:   Address: 0x69
[19:08:50.091][W][sen5x:258]: Communication failed
[19:08:50.091][C][sen5x:277]:   Product name: 
[19:08:50.091][C][sen5x:277]:   Firmware version: 0
[19:08:50.091][C][sen5x:277]:   Serial number 00.00.00
[19:08:50.091][C][sen5x:362]:   Update Interval: 60.0s
[19:08:50.092][C][sen5x:015]:   PM  1.0 'Feinstaub PM1.0'
[19:08:50.092][C][sen5x:015]:     State Class: 'measurement'
[19:08:50.092][C][sen5x:015]:     Unit of Measurement: 'µg/m³'
[19:08:50.092][C][sen5x:015]:     Accuracy Decimals: 2
[19:08:50.092][C][sen5x:025]:     Device Class: 'pm1'
[19:08:50.097][C][sen5x:029]:     Icon: 'mdi:blur'
[19:08:50.097][C][sen5x:015]:   PM  2.5 'Feinstaub PM2.5'
[19:08:50.097][C][sen5x:015]:     State Class: 'measurement'
[19:08:50.097][C][sen5x:015]:     Unit of Measurement: 'µg/m³'
[19:08:50.097][C][sen5x:015]:     Accuracy Decimals: 2
[19:08:50.098][C][sen5x:025]:     Device Class: 'pm25'
[19:08:50.098][C][sen5x:029]:     Icon: 'mdi:blur'
[19:08:50.099][C][sen5x:015]:   PM 10.0 'Feinstaub PM10'
[19:08:50.099][C][sen5x:015]:     State Class: 'measurement'
[19:08:50.099][C][sen5x:015]:     Unit of Measurement: 'µg/m³'
[19:08:50.099][C][sen5x:015]:     Accuracy Decimals: 2
[19:08:50.099][C][sen5x:025]:     Device Class: 'pm10'
[19:08:50.172][C][sen5x:029]:     Icon: 'mdi:blur'
[19:08:50.172][C][sen5x:015]:   Temperature 'Temperatur'
[19:08:50.172][C][sen5x:015]:     State Class: 'measurement'
[19:08:50.172][C][sen5x:015]:     Unit of Measurement: '°C'
[19:08:50.172][C][sen5x:015]:     Accuracy Decimals: 2
[19:08:50.173][C][sen5x:025]:     Device Class: 'temperature'
[19:08:50.173][C][sen5x:029]:     Icon: 'mdi:thermometer'
[19:08:50.173][C][sen5x:015]:   Humidity 'Luftfeuchtigkeit'
[19:08:50.173][C][sen5x:015]:     State Class: 'measurement'
[19:08:50.173][C][sen5x:015]:     Unit of Measurement: '%'
[19:08:50.173][C][sen5x:015]:     Accuracy Decimals: 2
[19:08:50.174][C][sen5x:025]:     Device Class: 'humidity'
[19:08:50.174][C][sen5x:029]:     Icon: 'mdi:water-percent'
[19:08:50.174][C][sen5x:015]:   VOC 'VOC Index'
[19:08:50.174][C][sen5x:015]:     State Class: 'measurement'
[19:08:50.174][C][sen5x:015]:     Unit of Measurement: ''
[19:08:50.174][C][sen5x:015]:     Accuracy Decimals: 0
[19:08:50.175][C][sen5x:025]:     Device Class: 'aqi'
[19:08:50.176][C][sen5x:029]:     Icon: 'mdi:chemical-weapon'
[19:08:50.176][C][sen5x:015]:   NOx 'NOx Index'
[19:08:50.176][C][sen5x:015]:     State Class: 'measurement'
[19:08:50.176][C][sen5x:015]:     Unit of Measurement: ''
[19:08:50.176][C][sen5x:015]:     Accuracy Decimals: 0
[19:08:50.186][C][sen5x:025]:     Device Class: 'aqi'
[19:08:50.187][C][sen5x:029]:     Icon: 'mdi:smog'
[19:08:50.193][E][component:154]:   sen5x.sensor is marked FAILED: unspecified
[19:08:50.297][C][captive_portal:116]: Captive Portal:
[19:08:50.298][D][text_sensor:085]: 'PM10 Ampel': Sending state 'rot'
[19:08:50.298][C][esphome.ota:093]: Over-The-Air updates:
[19:08:50.298][C][esphome.ota:093]:   Address: luftsensor-stromraum.local:3232
[19:08:50.298][C][esphome.ota:093]:   Version: 2
[19:08:50.298][C][esphome.ota:100]:   Password configured
[19:08:50.299][C][safe_mode:018]: Safe Mode:
[19:08:50.299][C][safe_mode:018]:   Successful after: 60s
[19:08:50.299][C][safe_mode:018]:   Invoke after: 10 attempts
[19:08:50.299][C][safe_mode:018]:   Duration: 300s
[19:08:50.299][C][web_server.ota:241]: Web Server OTA
[19:08:50.299][C][api:222]: Server:
[19:08:50.299][C][api:222]:   Address: luftsensor-stromraum.local:6053
[19:08:50.299][C][api:222]:   Listen backlog: 4
[19:08:50.299][C][api:222]:   Max connections: 8
[19:08:50.300][C][api:229]:   Noise encryption: YES
[19:08:50.309][C][mdns:179]: mDNS:
[19:08:50.309][C][mdns:179]:   Hostname: luftsensor-stromraum

What Esp32 board exactly?

This one from adafruit: Adafruit SEN54 or SEN55 Adapter Breakout - STEMMA QT / Qwiic : ID 5964 : Adafruit Industries, Unique & fun DIY electronics and kits

This ESP32 board: ESP32 NodeMCU Development Board (https://www.berrybase.de/esp32-nodemcu-development-board)

Ok, but it doesn’t have “JST SH 4 Pin” connector. How’s your wiring ?

Here are pictures. Can only post 1 picture per post every 5 minutes:

I use this cable: SparkFun Qwiic - flexibles Adapterkabel, 4 Pin Dupont Female, 150mm - kaufen bei BerryBase

Picture 2

Adafruit board

I don’t see anything incorrect with wiring. That 6-pin cable has all pins in line like the adafruit one? No sensor on your images…

I did not take a picture of the Sen55 because it’s just a connector. Nevertheless, here you go. Since its just a connector there is no chance putting it in the wrong way or upside down or something. The 6 pin cable is the one recommended from adafruit and sensirion. JST GH 6 pin 1.25mm cable.

Is your cable the correct way round to the sensor?The one on adafruits page you linked to has the red lead on the left on the adapter board you have it on the right. If it is wired 1 to 1 shouldn’t make a difference but I’d check.

Or perhaps your cable is wired incorrectly?

From the logs the I2C bus is working but no sensor is found. So connections to esp are ok. Sensor cable looks prewired so not much you can do there. Wonder if it is a power issue to the sensor?

Yes, that’s true. Didn’t see that. But I’m not sure that is possible because the connector is like a usb connector. The pins are closer to one side of the connector end than to the other (if you understand what I mean). So, the cable can’t be put in the wrong way.

Edited my post, not the first time an incorrectly wired cable has been supplied, I would check datasheet pin out.

Sadly I don’t have a multimeter. I already thought the 6 pin cable or the Sen55 could be broken. But I have no way to check if the 6 pin cable delivers electricity or if the sen55 is broken. Any ideas?

@EBME2 Funny thing, I switched both ends of the cable and now the red is on the other side. Nevertheless, does not work either.

Whilst I’d recommend a multimeter anyway, you don’t need for this just get the data sheet for both the adapter board and the sensor and map out each. My guess is the person who assembled had the connector upside down. You can usually release the contacts with a sharp point to press in the release tab.

Just checked it (see picture). After switching the ends (now it looks like in the adafruit image) the pins are in correct order. Red (voltage) is in pin 1 like in the datasheet, then GND etc. and on the adafruit its correct too.

That’s why I asked if the cable has all the pins “in line”. According to you photo it looks correct.

So my two doubts here are bad connector and the fact that Sensirion datasheet states clearly that the supply voltage is 5V. I didn’t find schematics of your adafruit board, but any boost circuit doesn’t jump on my eyes there.
So who you want to believe?

I personally would power the circuit from 5V pin.

“This adapter breakout will make an instant friendship with all SEN5x boards, thanks to
a JST GH-compatible connector in the middle so that you can plug a 6-pin GH
cable (JST GH 1.25mm Pitch 6 Pin Cable - 100mm long : ID 5754 : Adafruit Industries, Unique & fun DIY electronics and kits) directly between your SEN and this adapter. In the middle
is a small switch-cap boost converter that will generate 5V at 100mA to power the fan
and electronics in the SEN5x even if you’re using 3V power and logic”

Nevertheless, I’ve tried it with 5V instead of 3V3 right now and it doesn’t change anything.

Edit: I can’t write new posts for 21 hours since this is my first day in this forum and there seems to be a limit for the first day. Seems crazy, but okay…

Ok, double check that all connectors have tight fit, especially those that connect on Esp. Next step would be probing with multimeter…
Ps. I personally would skip the adafruit board at this point.