BME280 i2c error: SCL is held low on the bus

Hi all,
i’ve been looking for a solution everywhere, but haven’t foud any solution and it’s driving me crazy.
I’m building a weather station, with a wind speed sensor, light meter, rain sensor and bme280 via i2c.

Well, all work on the breadboard, but when i put it on a perfboard with the same wiring, i obtain this error

[18:06:25][C][i2c.arduino:038]: I2C Bus:
[18:06:25][C][i2c.arduino:039]:   SDA Pin: GPIO21
[18:06:25][C][i2c.arduino:040]:   SCL Pin: GPIO22
[18:06:25][C][i2c.arduino:041]:   Frequency: 50000 Hz
[18:06:25][C][i2c.arduino:047]:   Recovery: failed, SCL is held low on the bus
[18:06:25][I][i2c.arduino:054]: Results from i2c bus scan:
[18:06:25][E][i2c.arduino:062]: Unknown error at address 0x08
[18:06:25][E][i2c.arduino:062]: Unknown error at address 0x09

and so on for every i2c address.
if i put it on the breadborad

[18:11:36][C][i2c.arduino:038]: I2C Bus:
[18:11:36][C][i2c.arduino:039]:   SDA Pin: GPIO21
[18:11:36][C][i2c.arduino:040]:   SCL Pin: GPIO22
[18:11:36][C][i2c.arduino:041]:   Frequency: 50000 Hz
[18:11:36][C][i2c.arduino:044]:   Recovery: bus successfully recovered
[18:11:36][I][i2c.arduino:054]: Results from i2c bus scan:
[18:11:36][I][i2c.arduino:060]: Found i2c device at address 0x77

everything works.

I’ve checked every wiring on the perfboard with the multimeter, no short circuit, everything works… the cable is an awg28 used to
This is the wiring



Clearly the wiring on the perfboard is incomplete, seems like the cable is making some resistance?
forgive me for the not perfect soldering, i’m not an expert…

and this is my yaml configuration.

substitutions:
  nome: weather-station
  nome_esteso: Stazione meteo
  updtime_interval: 60s
  wifi_interval: 60s
  update_interval: 60s

esphome:
  name: $nome

esp32:
  board: az-delivery-devkit-v4
  framework:
    type: arduino

# Enable Home Assistant API
api:
  encryption:
    key: !secret api_encryption_key

ota:
  password: !secret ota_password


wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  manual_ip:
    static_ip: !secret weather_station_ip
    gateway: !secret gateway
    subnet: 255.255.255.0
  domain: !secret domain
  reboot_timeout: 5min

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Weather Station Fallback Hotspot"
    password: !secret ap_password

captive_portal:

# Enable logging
logger:

mqtt:
  broker: !secret mqtt_broker
  username: !secret mqtt_user
  password: !secret mqtt_pass
  discovery: True
  client_id: weather-1.40

i2c:
  sda: 21
  scl: 22
  scan: True
  id: bus_bme

text_sensor:
  - platform: template
    name: $(nome_esteso) Uptime
    id: weather_station_uptime
    icon: mdi:clock-start

switch:
  - platform: restart
    name: "$nome_esteso Restart"

sensor:
  - platform: wifi_signal
    name: "$(nome_esteso) Wifi Signal Sensor"
    update_interval: 300s
    id: weather_station_wifi_signal_sensor
    
  - platform: uptime
    name: $(nome_esteso) Uptime Sensor
    id: weather_station_uptime_sensor
    update_interval: 300s
    on_raw_value:
      then:
        - text_sensor.template.publish:
            id: weather_station_uptime
            state: !lambda |-
              int seconds = round(id(weather_station_uptime_sensor).raw_state);
              int days = seconds / (24 * 3600);
              seconds = seconds % (24 * 3600);
              int hours = seconds / 3600;
              seconds = seconds % 3600;
              int minutes = seconds /  60;
              seconds = seconds % 60;
              return (
                (days ? String(days) + "d " : "") +
                (hours ? String(hours) + "h " : "") +
                (minutes ? String(minutes) + "m " : "") +
                (String(seconds) + "s")
              ).c_str();

#########################################
# PULSE COUNTER FOR ANEMOMETER
#########################################
  
  - platform: pulse_counter
    pin: 
      number: 23
      mode: INPUT_PULLUP
    unit_of_measurement: 'm/s'
    name: 'Sensore Vento'
    icon: 'mdi:weather-windy'
    id: wind_sensor
    count_mode:
      rising_edge: DISABLE
      falling_edge: INCREMENT
    internal_filter: 13us
    update_interval: 2s
    accuracy_decimals: 2
    filters:
      - sliding_window_moving_average:
          window_size: 4
          send_every: 4
          send_first_at: 1
      # rotations_per_sec = pulses / 2 / 60
      # circ_m = 0.06 * 2 * 3.14 = 0.3768
      # mps = 1.18 * circ_m * rotations_per_sec
      # mps = 1.18 * 0.3768 / 2 / 60 = 0,0037052
      #- multiply: 0.0031939525
      - multiply: 0.0037052
      #- max:
      #    window_size: 20
      #    send_every: 5
      #    send_first_at: 1


    on_value:
      then:
        - sensor.template.publish:
            id: sensore_vento_kmh
            state: !lambda "return x;"
        - sensor.template.publish:
            id: sensore_vento_ms
            state: !lambda "return x;"
        
    
#    on_raw_value:
#      then:
#        - sensor.template.publish:
#            id: sensore_vento
#            state: !lambda "return x;"

    
  - platform: template
    name: "Velocità del Vento Km/h"
    id: sensore_vento_kmh
    unit_of_measurement: 'Km/h'
    update_interval: 5s
    accuracy_decimals: 2
    icon: 'mdi:weather-windy'
    filters:
      - multiply: 3.6

  - platform: template
    name: "Velocità del Vento m/s"
    id: sensore_vento_ms
    unit_of_measurement: 'm/s'
    update_interval: 1s
    accuracy_decimals: 2
    icon: 'mdi:weather-windy'

#########################################
# BME280 TEMPERATURE, PRESSURE, HUMIDITY
#########################################
  - platform: bme280
    address: "0x77"
    update_interval: 1s
    iir_filter: 16x
    temperature:
      name: "Temperatura (BME280)"
      oversampling: 16x
      id: bme280_temperature
    pressure:
      name: "Pressione (BME280)"
      id: bme280_pressure
      icon: mdi:gauge
      oversampling: 16x
      filters:
      #filtro per la correzione della pressione atmosferica basato su dati sperimentali di prossimità
        - multiply: 1.0218963439132181599035757332262
    humidity:
      name: "Umidità (BME280)"
      id: bme280_humidity
      oversampling: 16x
      icon: mdi:water-percent
    
  - platform: template
    name: "Altitudine"
    id: altitude
    lambda: |-
      const float STANDARD_SEA_LEVEL_PRESSURE = 1018; //in hPa, see note
      return ((id(bme280_temperature).state + 273.15) / 0.0065) *
        (powf((STANDARD_SEA_LEVEL_PRESSURE / id(bme280_pressure).state), 0.190234) - 1); // in meter
    update_interval: 15s
    icon: 'mdi:signal'
    unit_of_measurement: 'm'
  - platform: template
    name: "Umidità Assoluta"
    lambda: |-
      const float mw = 18.01534;    // molar mass of water g/mol
      const float r = 8.31447215;   // Universal gas constant J/mol/K
      return (6.112 * powf(2.718281828, (17.67 * id(bme280_temperature).state) /
        (id(bme280_temperature).state + 243.5)) * id(bme280_humidity).state * mw) /
        ((273.15 + id(bme280_temperature).state) * r); // in grams/m^3
    accuracy_decimals: 2
    update_interval: 60s
    icon: 'mdi:water'
    unit_of_measurement: 'g/m³'
  - platform: template
    name: "Punto di brina"
    lambda: |-
      return (243.5*(log(id(bme280_humidity).state/100)+((17.67*id(bme280_temperature).state)/
      (243.5+id(bme280_temperature).state)))/(17.67-log(id(bme280_humidity).state/100)-
      ((17.67*id(bme280_temperature).state)/(243.5+id(bme280_temperature).state))));
    unit_of_measurement: °C
    icon: 'mdi:thermometer-alert'
    update_interval: 60s
    
#########################################
# RAIN SENSOR
#########################################
  - platform: resistance
    sensor: sensore_pioggia_adc
    configuration: UPSTREAM
    resistor: 1kOhm
    name: Sensore pioggia

  - platform: adc
    id: sensore_pioggia_adc
    name: Sensore pioggia ADC
    attenuation: 11db
    pin: 32
    update_interval: 2s
    #filters:
    #  - multiply: 0.846153846153

#########################################
# LIGHT SENSOR
#########################################
  - platform: resistance
    sensor: sensore_luce_adc
    configuration: DOWNSTREAM
    resistor: 1989Ohm
    name: Sensore luce

  - platform: adc
    id: sensore_luce_adc
    name: Sensore luce ADC
    attenuation: 11db
    pin: 33
    update_interval: 2s
    #filters:
    #  - multiply: 0.846153846153

  - platform: template
    name: "Luminosità (Lux)"
    id: luce_lux
    unit_of_measurement: 'lux'
    update_interval: 2s
    accuracy_decimals: 0
    icon: 'mdi:white-balance-sunny'
    lambda: |-
      const float Vin = 3.3;
      const float R1=1.989;
      const float MULTIPLIER = 1.25;
      return MULTIPLIER*500*(Vin-id(sensore_luce_adc).state)/(R1*id(sensore_luce_adc).state);
    


#########################################
# RAIN SENSOR
#########################################
binary_sensor:
  - platform: gpio
    pin: 
      number: 18
      mode: INPUT
      inverted: true
    device_class: moisture
    id: sensore_pioggia
    name: Sensore pioggia
    #icon: mdi:weather-rainy
    #update_interval: 2s

Can someone please point me in the right direction?
Thanks in advance
fabrizio

If it works with the same components on a breadboard and not on a perfboard the problem must be the wiring and/or the soldering. So check both, especially the SCL wiring/soldering, because the error in the log file is quite clear about the cause of the problem.

@jsuanet Thanks very much, what a real badass i am in soldering, i had soldered the wire already twice…
Done it again and it works like charm!
Thank you very much!!!

[EDIT]… enjoyed too early!!! The error has gone, but now no devices found… going to resolder everything…

Well, after soldering again all the components on a new pcb, the sensor work… who knows what i did wrong…
Thanks for helping me out!

Glad the problem is solved :+1: