ESPHome on RPi Pico W: choosing wrong i2c pins will brick the device

Shoving a quick edit in here. You can read the troubleshooting process below, but long story short, select your i2c pins with care on Pico.

Hi, so, this is a weird one.

Sonoff Dual is doing weird things and wants to be replaced, so, I decided to build something instead, as you do.

I’m basing this device on a Raspberry Pi Pico, because in my country, you can’t get cheap ESP32s, but you can get Picos cheaply without having to import. Pico is looking sexier to me than ESP8266, but anyway.

So it has 2 relays, 2 touch sensors (for the relays), a lux sensor, a temp sensor, a PIR sensor, and a small strip of WS8something LEDs to be night lights (not yet connected).

The YAML validates fine, and so then I installed via OTA update. It said successful, but weirdness has occurred. I cannot get logs from it. ESPHome is showing it as online, but I can’t connect to it to see if it’s reading the sensors correctly or not.

Luckily I still had the uf2 file from the initial installation (no sensors, just basic setup), and when I reinstalled that, it all worked again.

… I’m going to try commenting out sensors and recompiling. Hmm. I’ll be back.

EDIT the first: I commented out everything except the basics. Validated fine. Installed via OTA. During the compile, it threw a weird error, I’ll just post the relevant bit:

Compiling /data/pico001-test/.pioenvs/pico001-test/src/esphome/components/api/user_services.cpp.o
In file included from /data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/vector:72,
                 from /data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/functional:62,
                 from src/esphome/core/component.h:4,
                 from src/esphome/components/api/proto.h:3,
                 from src/esphome/components/api/api_pb2.h:5,
                 from src/esphome/components/api/api_pb2.cpp:3:
/data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {long long unsigned int}; _Tp = long long unsigned int; _Alloc = std::allocator<long long unsigned int>]':
/data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/bits/vector.tcc:426:7: note: parameter passing for argument of type 'std::vector<long long unsigned int>::iterator' changed in GCC 7.1
  426 |       vector<_Tp, _Alloc>::
      |       ^~~~~~~~~~~~~~~~~~~
/data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/bits/vector.tcc: In member function 'std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {long long unsigned int}; _Tp = long long unsigned int; _Alloc = std::allocator<long long unsigned int>]':
/data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/bits/vector.tcc:121:21: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<long long unsigned int*, std::vector<long long unsigned int> >' changed in GCC 7.1
  121 |    _M_realloc_insert(end(), std::forward<_Args>(__args)...);
      |    ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Compiling /data/pico001-test/.pioenvs/pico001-test/src/esphome/components/logger/logger.cpp.o

However, the compile completed, and the device updated successfully and I can access it. So I guess … enable the next bit and see what happens.

One moment.

EDIT the second: So, I enabled just i2c, and the compiler threw a new error:

Compiling /data/pico001-test/.pioenvs/pico001-test/src/esphome/components/api/user_services.cpp.o
In file included from /data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/vector:72,
                 from /data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/functional:62,
                 from src/esphome/core/component.h:4,
                 from src/esphome/components/api/proto.h:3,
                 from src/esphome/components/api/api_pb2.h:5,
                 from src/esphome/components/api/api_pb2.cpp:3:
/data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/bits/vector.tcc: In member function 'void std::vector<_Tp, _Alloc>::_M_realloc_insert(std::vector<_Tp, _Alloc>::iterator, _Args&& ...) [with _Args = {long long unsigned int}; _Tp = long long unsigned int; _Alloc = std::allocator<long long unsigned int>]':
/data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/bits/vector.tcc:426:7: note: parameter passing for argument of type 'std::vector<long long unsigned int>::iterator' changed in GCC 7.1
  426 |       vector<_Tp, _Alloc>::
Compiling /data/pico001-test/.pioenvs/pico001-test/src/esphome/components/i2c/i2c.cpp.o
      |       ^~~~~~~~~~~~~~~~~~~
/data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/bits/vector.tcc: In member function 'std::vector<_Tp, _Alloc>::reference std::vector<_Tp, _Alloc>::emplace_back(_Args&& ...) [with _Args = {long long unsigned int}; _Tp = long long unsigned int; _Alloc = std::allocator<long long unsigned int>]':
/data/cache/platformio/packages/toolchain-rp2040-earlephilhower/arm-none-eabi/include/c++/10.3.0/bits/vector.tcc:121:21: note: parameter passing for argument of type '__gnu_cxx::__normal_iterator<long long unsigned int*, std::vector<long long unsigned int> >' changed in GCC 7.1
  121 |    _M_realloc_insert(end(), std::forward<_Args>(__args)...);
      |    ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Compiling /data/pico001-test/.pioenvs/pico001-test/src/esphome/components/i2c/i2c_bus_arduino.cpp.o

The compile completes successfully, and uploads via OTA. And now the device is dead again. Power cycling does not bring it back, I’ll need to manually flash it again.

After that, I’m going to comment out i2c again and see if it’ll compile with other sensors.

I’ll be back.

1 Like

So, it seems to matter what pins you use for SDA and SCL. The pinout, if you look more carefully that I did, shows a bunch of different options for i2c interfaces, but they’re labelled i2c0 and i2c1. Only use i2c0, or else the pico won’t boot. Pins 0 and 1 seems safe.

Here’s what I did.

I stripped the breadboard and started over, recompiling at every step to eliminate that component.

  1. Pico on the breadboard, power rails ready. All good.

  2. Touch sensors as light switches. All good.

  3. Relays for the switches to trigger. All good, it works. Satisfying clicks.

  4. Motion sensor (AM312). All good.

  5. i2c. Not good. Very bad.

Now that I’m using pins 0 and 1 for i2c, the system boots.

If you use other pins, the code will validate, compile, and install, but will brick the device, and you will need to manually re-flash it.

I have not yet managed to actually get a sensor working using i2c, but that could be a for a host of other reasons.

Leaving this up in case someone else bangs their head against this.

2 Likes

Small update, had some time to mess around with it.

So, while the Pico will boot using pins 0 and 1, I get no joy actually connecting sensors to them. I get a constant error about SCL being held low on the bus.

I have tried to eliminate any finger errors, including building a breakout board for the Pico cos I suspected the breadboard was knackered, manually testing continuity of each line, and making sure SDA and SCL have a resistor to ground. Everything looks as expected. No dice.

However, after staring at the pinout diagram for a while, I had a duh moment. While there are many pins that can do i2c (allegedly), pins 20 and 21 are in fact dedicated to i2c - like, there isn’t anything else special stacked onto them.

So, if I use pin 20 for SDA, and 21 for SCL, everything works as expected.

Well, still some weirdness. BMP280 is still up itself, either I have a bad batch or … I dunno. 3 sensors, 3 fails.

Good old BMP180 working great, though, but it’s a shame to not have the Humidity sensor.

TSL2561 working great too.

I’m going to bed. As you were.

2 Likes

Changing to pins 20 and 21 as you suggested solved my problem (after two days of trying everything I could find). Thanks!