Delayed initialization I2C bus

Hello, is it possible to delay the initialization of the i2c bus?
I have the VCC sensors pinned to GPIO18 and this pin drops the voltage before sleep.
After waking up esp, I would need GPIO18 to be the first to be initialized before i2c.

I tried the following with no success.

i2c still showing error
Recovery failed: SCL is held LOW on the I2C bus

What other priorities have you tried?

I didn’t try, I calculated that 1000 is the highest.
Is there an even higher priority?

i found this: https://esphome.io/api/namespaceesphome_1_1setup__priority

Priroita 1100 solved my problem
Thanks for the direction

Problem not solved.

even after setting the priority to 1200 and the visible item that the switch before i2c is turned on, GPIO18 does not turn on and remains low.

Don’t know why?
YAML:

  on_boot:
    - priority: 1200
      then:
        - lambda: |-
            pinMode(18, OUTPUT);
            digitalWrite(18, HIGH);
            delay(300);
        - switch.turn_on: i2c_enable # turn on GPIO18
        - delay: 300ms

LOG:

11:06:31.148 -> e[0;32m[I][logger:326]: Log initializede[0m
11:06:31.194 -> e[0;35m[C][status_led:014]: Setting up Status LED...e[0m
11:06:31.194 -> e[0;35m[C][ota:473]: There have been 0 suspected unsuccessful boot attempts.e[0m
11:06:31.194 -> e[0;36m[D][esp32.preferences:114]: Saving 1 preferences to flash...e[0m
11:06:31.194 -> e[0;36m[D][esp32.preferences:143]: Saving 1 preferences to flash: 0 cached, 1 written, 0 failede[0m
11:06:31.194 -> e[0;32m[I][app:029]: Running through setup()...e[0m
11:06:31.521 -> e[0;36m[D][switch:012]: 'weather-station I2C supply' Turning ON.e[0m
11:06:31.567 -> e[0;36m[D][switch:055]: 'weather-station I2C supply': Sending state ONe[0m
11:06:31.567 -> e[0;32m[I][i2c.arduino:183]: Performing I2C bus recoverye[0m
11:06:31.567 -> e[1;31m[E][i2c.arduino:199]: Recovery failed: SCL is held LOW on the I2C buse[0m

Hi,
The issue is related to the I2C priority which is part of the BUS priority and defined as the highest (1000).
IMO any switch initialization with the on_boot (see the code below), with a priority higher than 800 will be overwritten during the boot sequence. Each hardware part is initialized following the priority order defined from the highest to the lowest. And in priority 800 all GPIO switch will be initialized, overwriting any setting previously made with the additional “on_boot” sequence above priority 800.

esphome:
  name: myproject
  friendly_name: thermostat
  on_boot:
     priority: 1001
     then:
       - switch.turn_on: bme280_power_on

I don’t know why the BUS priority has been set to the highest. I’m sure there is a good explanation but I don’t see it.
In no case the solution below is a definitive solution but it allows me to achieve my goal which is to control the power supply of my BME280 measurement module and thus to reduce my consumption to a minimum (my project works with a battery )

So, to get around this and to be able to wakeup from deep sleep + enable my BME280 with one GPIO before the I2C bus initialization, I decided to use my own I2C component modified with a lower priority. I proceed in this way:

In my yaml file, I have added the following to tell the compiler to use any component located in my_components local folder instead of the original one:

external_components:
  - source:
    type: local
    path: my_components

my_components is a local folder located at the same level as my yaml file.
Next I copied the original component folder I2C into my_components.
Once copied locally, I edited the i2c_bus_arduino.h file and searched for the line

float get_setup_priority() const override { return setup_priority::BUS; }

line 24 in my case.

  1. I duplicated line 24 and commented it
  2. In the duplicated line 25, I replaced the priority level “BUS” with “DATA”, which corresponds to a priority level of 600 (lower than the switch priority of 800). See the modified code below
  3. And saved
class ArduinoI2CBus : public I2CBus, public Component {
 public:
  void setup() override;
  void dump_config() override;
  ErrorCode readv(uint8_t address, ReadBuffer *buffers, size_t cnt) override;
  ErrorCode writev(uint8_t address, WriteBuffer *buffers, size_t cnt, bool stop) override;
//  float get_setup_priority() const override { return setup_priority::BUS; }
  float get_setup_priority() const override { return setup_priority::DATA; }

Each time I compile, my modified file is taken in account and the I2C has a priority of 600 lower than the switch priority of 800. Now, no problem to set a priority in between like 700 in my on_boot to enable my BM280 power supply with a GPIO switch. Next the I2C bus with the priority 600 will start its initialization w/o any issue.

esphome:
  name: myproject
  friendly_name: thermostat
  on_boot:
     priority: 700
     then:
       - switch.turn_on: bme280_power_on

Again this is my own workaround before a official solution is documented.
Hope it helps

1 Like

hi, thank you, this is exactly what I came up with a couple of days ago. And it works. Well thank you.
Instead of the DATA variable, it is possible to enter a specific priority number there.