[SOLVED] Connecting AHT20 Module & SSD1306 Display (Both i2c) to ESP32

Attempting to develop ESP32 (Dev) device equipped with AHT20 (Temperature/Humidity sensor) and SSD1306 (Display). Sensor and Display are i2c and use different addresses. Elements are currently affixed on a breadboard. Thought I had this worked out, but…
If I try to share GPIO21 (i2c SDA) and GPIO22 (i2c SCL), between the AHT20 and SSD1306, the AHT20 is recognized, but the Display is not recognized (and shows error). If I connect the Display directly to SDA & SCL, the Display is recognized and functions as expected. This is reproducible.
I’m relatively certain my code is fine. I’ve tried multiple wiring configurations & can’t seem to get both AHT20 and Display co-functioning. I should be able to run both from a single set of SDA/SLC pins, right? Thoughts?

Solution: Initially, this project seemed to come together nicely. [ESP32 (Dev) device equipped with AHT20 (Temperature/Humidity sensor) and SSD1306 (Display)]. Then (rather suddenly) components refused to play nice. Walked through much troubleshooting with help from the Community and Google AI. In the end, created a second i2c bus using pins 18 and 19, and separated the AHT20 and ssd1306 onto separate i2c buses. This is working so far.
Thanks for the help.

Yes they should work on same bus.
List for possible causes for your problem is long.

The wiring has to be short and rock solid, like if they were both connected “directly”. Long flimsy jumper cables on cheap breadboard is not reliable.
Also, make sure you have correct addresses configured, sufficient pullups, both devices are powered at 3.3V, try different I2C frequency etc…

But you should first test if removing esphome config for AHT allows display to work or you need to disconnect it from wiring?

Hello, You should be able to run both the AHT20 and SSD1306 on the same I²C bus (GPIO21 SDA, GPIO22 SCL), so this is likely a hardware issue rather than code; the most common causes are improper pull-up resistors (I²C typically needs ~4.7kΩ on SDA/SCL, and too many or too few can cause failures), voltage mismatch (ensure both modules are powered at 3.3V with the ESP32), or unreliable breadboard wiring (loose connections or bad rails can make one device disappear when another is added), and while address conflict is unlikely (AHT20 is usually 0x38 and SSD1306 is 0x3C/0x3D), you should still run an I²C scanner to confirm both devices appear together.

Thanks Gents,
Good suggestions. I’ll take a step back, and do some troubleshooting.

OK…,

  • Removed all the cheap jumper wires,
  • Created fresh new short jumpers,
  • Confirmed 3.3 VIN on rail and to both devices,
  • Confirmed both device addresses AHT (0x38) ssd1306 (0x3C),
  • Extended GPIO22 (SCl) and GPIO21 (SDA) to g24 and g26 on breadboard, respectively. Leads from bb i24 (SCl) and i26 (SDA) connect to ssd1306. Leads from bb f24 (SCl) and f26 connect to AHT.

TEST #1: ssd1306 (VIN, GND, SCl, SDA) connected. AHT not connected. ssd1306 Display working.
TEST #2: ssd1306 (VIN, GND, SCl, SDA) connected. AHT (VIN, GND only) connected. Display working.
TEST #3: ssd1306 (VIN, GND, SCl, SDA) connected. AHT (VIN, GND, SCl, SDA) connected. Error. ssd1306 fail. AHT working.
TEST #4: ssd1306 (VIN, GND only) connected. AHT (VIN, GND, SCl, SDA) connected. Display fail (expected, not connected). AHT working.
TEST #2: repeated. ssd1306 working.

Both the AHT and ssd1306 work perfectly when connected independently. However, when both are connected, the ssd1306 fails. I still think this is ‘hardware’ related.

I note there is a configuration variable ‘scan’. It appears to default to ‘true’. How can I view the ‘scan’ result?

Below, find a screenshot of the error.

On your logs at boot. And if you post your logs, do it properly, not some screenshots…

[14:14:10.016][C][logger:219]: Logger:
[14:14:10.016][C][logger:219]:   Max Level: DEBUG
[14:14:10.016][C][logger:219]:   Initial Level: DEBUG
[14:14:10.038][C][logger:226]:   Log Baud Rate: 115200
[14:14:10.038][C][logger:226]:   Hardware UART: UART0
[14:14:10.038][C][logger:235]:   Task Log Buffer Size: 768 bytes
[14:14:10.044][C][i2c.idf:092]: I2C Bus:
[14:14:10.047][C][i2c.idf:093]:   SDA Pin: GPIO21
[14:14:10.047][C][i2c.idf:093]:   SCL Pin: GPIO22
[14:14:10.047][C][i2c.idf:093]:   Frequency: 400000 Hz
[14:14:10.048][C][i2c.idf:103]:   Recovery: bus successfully recovered
[14:14:10.049][C][i2c.idf:113]: Results from bus scan:
[14:14:10.050][C][i2c.idf:119]: Found device at address 0x38
[14:14:10.060][C][template.text_sensor:016]: Template Sensor 'Display Text'
[14:14:10.076][C][aht10:154]: AHT10:
[14:14:10.079][C][aht10:155]:   Address: 0x38
[14:14:10.079][C][aht10:017]:   Temperature 'Outdoor Temp'
[14:14:10.079][C][aht10:017]:     State Class: 'measurement'
[14:14:10.079][C][aht10:017]:     Unit of Measurement: '°F'
[14:14:10.079][C][aht10:017]:     Accuracy Decimals: 2
[14:14:10.080][C][aht10:232]:     Device Class: 'temperature'
[14:14:10.091][C][aht10:017]:   Humidity 'Outdoor Hmty'
[14:14:10.091][C][aht10:017]:     State Class: 'measurement'
[14:14:10.091][C][aht10:017]:     Unit of Measurement: '%'
[14:14:10.091][C][aht10:017]:     Accuracy Decimals: 2
[14:14:10.104][C][aht10:232]:     Device Class: 'humidity'
[14:14:10.104][C][ssd1306_i2c:022]: I2C SSD1306
[14:14:10.104][C][ssd1306_i2c:022]:   Rotations: 0 °
[14:14:10.104][C][ssd1306_i2c:022]:   Dimensions: 128px x 64px
[14:14:10.105][C][ssd1306_i2c:023]:   Model: SSD1306 128x64
[14:14:10.105][C][ssd1306_i2c:023]:   External VCC: NO
[14:14:10.105][C][ssd1306_i2c:023]:   Flip X: YES
[14:14:10.105][C][ssd1306_i2c:023]:   Flip Y: YES
[14:14:10.105][C][ssd1306_i2c:023]:   Offset X: 0
[14:14:10.105][C][ssd1306_i2c:023]:   Offset Y: 0
[14:14:10.105][C][ssd1306_i2c:023]:   Inverted Color: NO
[14:14:10.125][C][ssd1306_i2c:033]:   Address: 0x3C
[14:14:10.135][C][ssd1306_i2c:451]:   Update Interval: 1.0s
[14:14:10.136][E][ssd1306_i2c:038]: Communication failed
[14:14:10.136][E][component:224]:   display is marked FAILED: unspecified
[14:14:10.147][C][captive_portal:134]: Captive Portal:
[14:14:10.167][C][wifi:1505]: WiFi:
[14:14:10.167][C][wifi:1505]:   Local MAC: 88:13:BF:0C:A1:40
[14:14:10.167][C][wifi:1505]:   Connected: YES
[14:14:10.168][C][wifi:1216]:   IP Address: 192.168.2.119
[14:14:10.168][C][wifi:1227]:   SSID: [redacted]
[14:14:10.168][C][wifi:1227]:   BSSID: [redacted]
[14:14:10.168][C][wifi:1227]:   Hostname: 'outdoor-temp-xmtr'
[14:14:10.168][C][wifi:1227]:   Signal strength: -36 dB ▂▄▆█
[14:14:10.168][C][wifi:1227]:   Channel: 10
[14:14:10.168][C][wifi:1227]:   Subnet: 255.255.255.0
[14:14:10.168][C][wifi:1227]:   Gateway: 192.168.2.1
[14:14:10.168][C][wifi:1227]:   DNS1: 192.168.2.1
[14:14:10.168][C][wifi:1227]:   DNS2: 0.0.0.0
[14:14:10.181][C][esphome.ota:071]: Over-The-Air updates:
[14:14:10.181][C][esphome.ota:071]:   Address: outdoor-temp-xmtr.local:3232
[14:14:10.181][C][esphome.ota:071]:   Version: 2
[14:14:10.203][C][esphome.ota:078]:   Password configured
[14:14:10.203][C][safe_mode:026]: Safe Mode:
[14:14:10.203][C][safe_mode:026]:   Successful after: 60s
[14:14:10.203][C][safe_mode:026]:   Invoke after: 10 attempts
[14:14:10.203][C][safe_mode:026]:   Duration: 300s
[14:14:10.204][C][safe_mode:043]:   Bootloader rollback: supported
[14:14:10.225][C][web_server.ota:256]: Web Server OTA
[14:14:10.239][C][api:235]: Server:
[14:14:10.239][C][api:235]:   Address: outdoor-temp-xmtr.local:6053
[14:14:10.239][C][api:235]:   Listen backlog: 4
[14:14:10.239][C][api:235]:   Max connections: 8
[14:14:10.240][C][api:242]:   Noise encryption: YES
[14:14:10.240][C][mdns:194]: mDNS:
[14:14:10.240][C][mdns:194]:   Hostname: outdoor-temp-xmtr
[14:14:18.004][S][sensor]: 'Outdoor Temp' >> 71.39 °F
[14:14:18.004][S][sensor]: 'Outdoor Hmty' >> 45.28 %
[14:14:18.826][S][text_sensor]: 'Display Text' >> 'Initial String'
[14:14:28.004][S][sensor]: 'Outdoor Temp' >> 71.44 °F
[14:14:28.004][S][sensor]: 'Outdoor Hmty' >> 45.30 %

You see scan results there, only aht is detected.
Drop your i2c frequency to 50k for next test.

Thanks Karosm, still negative recognition at 50 kHz.
There is a (Google) note I ran across indicating that some folks experience incompatibility between AHT and ssd1306. Most recommendations are the same as yours. If nothing else works, recommend defining a separate i2c bus. I have tried that, and it appears to solve the immediate problem. Still don’t know why my arrangement seemed to work fine in the beginning, then rather suddenly decided to ‘not’.
New log using 50 kHz below.

[15:43:38.392][C][logger:219]: Logger:
[15:43:38.392][C][logger:219]:   Max Level: DEBUG
[15:43:38.392][C][logger:219]:   Initial Level: DEBUG
[15:43:38.404][C][logger:226]:   Log Baud Rate: 115200
[15:43:38.404][C][logger:226]:   Hardware UART: UART0
[15:43:38.404][C][logger:235]:   Task Log Buffer Size: 768 bytes
[15:43:38.415][C][i2c.idf:092]: I2C Bus:
[15:43:38.424][C][i2c.idf:093]:   SDA Pin: GPIO21
[15:43:38.424][C][i2c.idf:093]:   SCL Pin: GPIO22
[15:43:38.424][C][i2c.idf:093]:   Frequency: 50000 Hz
[15:43:38.425][C][i2c.idf:103]:   Recovery: bus successfully recovered
[15:43:38.425][C][i2c.idf:113]: Results from bus scan:
[15:43:38.426][C][i2c.idf:119]: Found device at address 0x38
[15:43:38.439][C][aht10:154]: AHT10:
[15:43:38.439][C][aht10:155]:   Address: 0x38
[15:43:38.440][C][aht10:017]:   Temperature 'Outdoor Temp'
[15:43:38.440][C][aht10:017]:     State Class: 'measurement'
[15:43:38.440][C][aht10:017]:     Unit of Measurement: '°F'
[15:43:38.440][C][aht10:017]:     Accuracy Decimals: 2
[15:43:38.450][C][aht10:232]:     Device Class: 'temperature'
[15:43:38.469][C][aht10:017]:   Humidity 'Outdoor Hmty'
[15:43:38.469][C][aht10:017]:     State Class: 'measurement'
[15:43:38.469][C][aht10:017]:     Unit of Measurement: '%'
[15:43:38.469][C][aht10:017]:     Accuracy Decimals: 2
[15:43:38.470][C][aht10:232]:     Device Class: 'humidity'
[15:43:38.472][C][ssd1306_i2c:022]: I2C SSD1306
[15:43:38.472][C][ssd1306_i2c:022]:   Rotations: 0 °
[15:43:38.472][C][ssd1306_i2c:022]:   Dimensions: 128px x 64px
[15:43:38.496][C][ssd1306_i2c:023]:   Model: SSD1306 128x64
[15:43:38.496][C][ssd1306_i2c:023]:   External VCC: NO
[15:43:38.496][C][ssd1306_i2c:023]:   Flip X: YES
[15:43:38.496][C][ssd1306_i2c:023]:   Flip Y: YES
[15:43:38.496][C][ssd1306_i2c:023]:   Offset X: 0
[15:43:38.496][C][ssd1306_i2c:023]:   Offset Y: 0
[15:43:38.496][C][ssd1306_i2c:023]:   Inverted Color: NO
[15:43:38.497][C][ssd1306_i2c:033]:   Address: 0x3C
[15:43:38.498][C][ssd1306_i2c:451]:   Update Interval: 1.0s
[15:43:38.508][E][ssd1306_i2c:038]: Communication failed
[15:43:38.532][E][component:224]:   display is marked FAILED: unspecified
[15:43:38.533][C][captive_portal:134]: Captive Portal:
[15:43:38.533][C][wifi:1505]: WiFi:
[15:43:38.533][C][wifi:1505]:   Local MAC: 88:13:BF:0C:A1:40
[15:43:38.533][C][wifi:1505]:   Connected: YES
[15:43:38.536][C][wifi:1216]:   IP Address: 192.168.2.119
[15:43:38.557][C][wifi:1227]:   SSID: [redacted]
[15:43:38.557][C][wifi:1227]:   BSSID: [redacted]
[15:43:38.557][C][wifi:1227]:   Hostname: 'outdoor-temp-xmtr'
[15:43:38.557][C][wifi:1227]:   Signal strength: -39 dB ▂▄▆█
[15:43:38.557][C][wifi:1227]:   Channel: 10
[15:43:38.557][C][wifi:1227]:   Subnet: 255.255.255.0
[15:43:38.557][C][wifi:1227]:   Gateway: 192.168.2.1
[15:43:38.557][C][wifi:1227]:   DNS1: 192.168.2.1
[15:43:38.557][C][wifi:1227]:   DNS2: 0.0.0.0
[15:43:38.559][C][esphome.ota:071]: Over-The-Air updates:
[15:43:38.559][C][esphome.ota:071]:   Address: outdoor-temp-xmtr.local:3232
[15:43:38.559][C][esphome.ota:071]:   Version: 2
[15:43:38.560][C][esphome.ota:078]:   Password configured
[15:43:38.569][C][safe_mode:026]: Safe Mode:
[15:43:38.569][C][safe_mode:026]:   Successful after: 60s
[15:43:38.569][C][safe_mode:026]:   Invoke after: 10 attempts
[15:43:38.569][C][safe_mode:026]:   Duration: 300s
[15:43:38.602][C][safe_mode:043]:   Bootloader rollback: supported
[15:43:38.602][C][web_server.ota:256]: Web Server OTA
[15:43:38.602][C][api:235]: Server:
[15:43:38.602][C][api:235]:   Address: outdoor-temp-xmtr.local:6053
[15:43:38.602][C][api:235]:   Listen backlog: 4
[15:43:38.602][C][api:235]:   Max connections: 8
[15:43:38.605][C][api:242]:   Noise encryption: YES
[15:43:38.656][C][mdns:194]: mDNS:
[15:43:38.656][C][mdns:194]:   Hostname: outdoor-temp-xmtr

Hello, @Grizz952 tell me you query is solve or not?

Best Regard,
Richa

What fixed a lot of I2C problems for me, was simply setting

Scan: False

With Scan set to True, I2C would only run at 10kHz and often run only intermittently. With it set False, it would run at 10, 50 or 100kHz, and no problems with expected data. I’ve no idea why…

Not using the same I/O devices as you are, (5 x MCP9600 on the same bus), so it’s worth trying.

1 Like