No I2C Devices found. Temperamental

New here, so forgive me if this is quite a basic question.

I have been working with a ESP32-C3 Super Mini dev board connected to an OLED, the first step of my new project. Please see below connections:

GND > GND
VCC > 3.3v
SCL > GPIO4
SDA > GPIO5

I have connected this in multiple different ways via a breadboard with male jumper wires, directly to the OLED with male to female and then directly between the OLED & The ESP with female to female Dupont jumper wires. I'm satisfied the wiring is correct.

I am running a simple scanner code on Arduino IDE as per the below.

Now, I have achieved the devices found and got the OLED up and running, but the connection was temperamental and unless I held down the ESP into the breadboard, it would turn off.

I figured it needed soldering so I've soldered the ESP32 to header pins and reverted to the above and still no luck. See attached photo of my soldering, not great but satisfactory I believe.

For clarity, even before soldering it has been an absolute struggle to get a simple connection, yet on YouTube videos they seem to have no struggle at all.

Can someone please assist here, I'm stuck. I am so amazed by how challenging it is to get a simple connection. How do products even work!

#include <Wire.h>

#define SDA_PIN 5
#define SCL_PIN 4

void setup() {
  Serial.begin(115200);
  delay(1000);

  Serial.println("\n=== ESP32-C3 I2C Scanner ===");
  Serial.print("Using SDA = ");
  Serial.print(SDA_PIN);
  Serial.print(", SCL = ");
  Serial.println(SCL_PIN);

  Wire.begin(SDA_PIN, SCL_PIN);
  Wire.setClock(100000);  // 100 kHz
}

void loop() {
  byte error, address;
  int nDevices = 0;

  Serial.println("Scanning...");

  for (address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0) {
      Serial.print("I2C device found at 0x");
      if (address < 16) Serial.print('0');
      Serial.println(address, HEX);
      nDevices++;
    }
  }

  if (nDevices == 0) {
    Serial.println("No I2C devices found\n");
  } else {
    Serial.println("Scan done\n");
  }

  delay(1000);
}



I am less than sanguine about the electrical connectivity of some of the pictured solder joints.

You also mention that you were trying simple connections before soldering. Doing so may have damaged either the ESP32 or OLED.

To be fair, I have a few other ESP32-C3's that are unsoldered, I am still getting a significantly lack of connection to I2C devices.

And I'm not at all surprised that if you're doing the former, that you're experiencing the latter.

Change to a better breadboard.

It tells nothing useful for us, only tells You lack knowledge of some kind. Don’t flavour the post with lots of words.

Old failures adds no useful information.

What is the problem? “Nothing works”?

Split the project into smaller parts. First make the controller run reliably using any silly blink diode code. Then add the next device.

Getting tired from all words, tired, stuck on what?

Not sure it's necessary for you to be rude, is it?

On the serial monitor I get 'No I2C connection devices found' when they are all connected correctly, run on the correct code. That is the problem. Is that a sufficient number of words for you to understand the problem?

Maybe rude but honest. Too many posters don’t read the advice given in How to get the best out of this forum - Projects / General Guidance - Arduino Forum.

That’s the wrong way to work.

Make sure the controller is working.

Then add one device and make it work. When it works, add the next device.

Reading the replies #2, 3 and 4 I wish You good luck. Too much is wrong to continue this post.

These two in particular look suspect - cold joints.

Hi banjopc, welcome.

I have a little advice on your pictures.
Did you notice it was very hard to shoot clear pictures, and that you failed at well focused pictures ?
This was probably due to you holding the object in your fingers during the photoshoot.
Todays camera's are supposed to be smart.
But that assumes the algorithm that decides what is smart is doing the job right.
In your case it doesn't.
It sees some flesh.
So it focuses on that; i can do an analysis on your fingerprints, but can hardly read the texts on the PCB let alone see the solder joints.

So please next time you like to show your work to ask for an opinion, do not hold the object with your fingers, make sure the object is static (meaning not moving in any way), and that you are not shooting the photo by holding the camera (or more likely your phone) yourself.
This may be a lengthy reply, and it is not meant to put you down or anything alike, but it is made to not only give you some advice, but also why that was given.

Thanks for that.

I followed the tutorial, similar to another I had, to a T with multiple boards soldered and unsoldered.

When I get to the point of connecting the OLED, that's when it seems to fail for various different reasons.

This time, I'm getting the exit code 1 which is frustrating. I've gone back through the tutorial from the beginning again, with the same outcome.

Noted! I'm new to it since school 20 years ago.

Hi! Welcome to the Forum.

The described symptoms makes me agree with the solder joint problems. But you can do a test to help finding out: the standard SDA and SCL pins on a C3 Supermini are pins 8 and 9. Change your connections to these pins and try again.

Are all of the I2C devices running at 3.3V?

How long are the wires to the I2C devices? I2C is only intended for short distances.

What exactly devices are you using, and are they all rated to run at the speed being used for the I2C bus?

the following works OK on my ESP32C3 Supermini using GPIO5 SDA and GPIO4 SCL

// ESP32C3 Supermini SSD1306 OLED test using Adafruit_SSD1306 library

// program File>Examples?Adafruit_SSD1306>ssd1306_128x32_i2c

// NOTE: for Serial IO Enable USB CDC on Boot 

/**************************************************************************
 This is an example for our Monochrome OLEDs based on SSD1306 drivers

 Pick one up today in the adafruit shop!
 ------> http://www.adafruit.com/category/63_98

 This example is for a 128x32 pixel display using I2C to communicate
 3 pins are required to interface (two I2C and one reset).

 Adafruit invests time and resources providing this open
 source code, please support Adafruit and open-source
 hardware by purchasing products from Adafruit!

 Written by Limor Fried/Ladyada for Adafruit Industries,
 with contributions from the open source community.
 BSD license, check license.txt for more information
 All text above, and the splash screen below must be
 included in any redistribution.
 **************************************************************************/

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128  // OLED display width, in pixels
#define SCREEN_HEIGHT 32  // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library.
// On an arduino UNO:       A4(SDA), A5(SCL)
// On an arduino MEGA 2560: 20(SDA), 21(SCL)
// On an arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET -1        // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C  ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define NUMFLAKES 10  // Number of snowflakes in the animation example

#define LOGO_HEIGHT 16
#define LOGO_WIDTH 16
static const unsigned char PROGMEM logo_bmp[] = { 0b00000000, 0b11000000,
                                                  0b00000001, 0b11000000,
                                                  0b00000001, 0b11000000,
                                                  0b00000011, 0b11100000,
                                                  0b11110011, 0b11100000,
                                                  0b11111110, 0b11111000,
                                                  0b01111110, 0b11111111,
                                                  0b00110011, 0b10011111,
                                                  0b00011111, 0b11111100,
                                                  0b00001101, 0b01110000,
                                                  0b00011011, 0b10100000,
                                                  0b00111111, 0b11100000,
                                                  0b00111111, 0b11110000,
                                                  0b01111100, 0b11110000,
                                                  0b01110000, 0b01110000,
                                                  0b00000000, 0b00110000 };

void setup() {
  Serial.begin(115200);
  Serial.println();  // Wait for display
  delay(2000);
  // I2C - note GPIOs 8 and 9 don't work on ESP32C3 supermini - used for LED_BUILTIN and BOOT_BULILTIN
  Wire.begin(5, 4);  //(8, 9);// ESP32C3 setup I2C SDA and SCL
  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));
    for (;;)
      ;  // Don't proceed, loop forever
  }
  Serial.println(F("SSD1306 allocation OK"));
  // Show initial display buffer contents on the screen --
  // the library initializes this with an Adafruit splash screen.
  display.display();
  delay(2000);  // Pause for 2 seconds

  // Clear the buffer
  display.clearDisplay();

  // Draw a single pixel in white
  display.drawPixel(10, 10, SSD1306_WHITE);

  // Show the display buffer on the screen. You MUST call display() after
  // drawing commands to make them visible on screen!
  display.display();
  delay(2000);
  // display.display() is NOT necessary after every single drawing command,
  // unless that's what you want...rather, you can batch up a bunch of
  // drawing operations and then update the screen all at once by calling
  // display.display(). These examples demonstrate both approaches...

  testdrawline();  // Draw many lines

  testdrawrect();  // Draw rectangles (outlines)

  testfillrect();  // Draw rectangles (filled)

  testdrawcircle();  // Draw circles (outlines)

  testfillcircle();  // Draw circles (filled)

  testdrawroundrect();  // Draw rounded rectangles (outlines)

  testfillroundrect();  // Draw rounded rectangles (filled)

  testdrawtriangle();  // Draw triangles (outlines)

  testfilltriangle();  // Draw triangles (filled)

  testdrawchar();  // Draw characters of the default font

  testdrawstyles();  // Draw 'stylized' characters

  testscrolltext();  // Draw scrolling text

  testdrawbitmap();  // Draw a small bitmap image

  // Invert and restore display, pausing in-between
  display.invertDisplay(true);
  delay(1000);
  display.invertDisplay(false);
  delay(1000);

  testanimate(logo_bmp, LOGO_WIDTH, LOGO_HEIGHT);  // Animate bitmaps
}

void loop() {
}

void testdrawline() {
  int16_t i;

  display.clearDisplay();  // Clear display buffer

  for (i = 0; i < display.width(); i += 4) {
    display.drawLine(0, 0, i, display.height() - 1, SSD1306_WHITE);
    display.display();  // Update screen with each newly-drawn line
    delay(1);
  }
  for (i = 0; i < display.height(); i += 4) {
    display.drawLine(0, 0, display.width() - 1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for (i = 0; i < display.width(); i += 4) {
    display.drawLine(0, display.height() - 1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for (i = display.height() - 1; i >= 0; i -= 4) {
    display.drawLine(0, display.height() - 1, display.width() - 1, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for (i = display.width() - 1; i >= 0; i -= 4) {
    display.drawLine(display.width() - 1, display.height() - 1, i, 0, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for (i = display.height() - 1; i >= 0; i -= 4) {
    display.drawLine(display.width() - 1, display.height() - 1, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  delay(250);

  display.clearDisplay();

  for (i = 0; i < display.height(); i += 4) {
    display.drawLine(display.width() - 1, 0, 0, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }
  for (i = 0; i < display.width(); i += 4) {
    display.drawLine(display.width() - 1, 0, i, display.height() - 1, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);  // Pause for 2 seconds
}

void testdrawrect(void) {
  display.clearDisplay();

  for (int16_t i = 0; i < display.height() / 2; i += 2) {
    display.drawRect(i, i, display.width() - 2 * i, display.height() - 2 * i, SSD1306_WHITE);
    display.display();  // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testfillrect(void) {
  display.clearDisplay();

  for (int16_t i = 0; i < display.height() / 2; i += 3) {
    // The INVERSE color is used so rectangles alternate white/black
    display.fillRect(i, i, display.width() - i * 2, display.height() - i * 2, SSD1306_INVERSE);
    display.display();  // Update screen with each newly-drawn rectangle
    delay(1);
  }

  delay(2000);
}

void testdrawcircle(void) {
  display.clearDisplay();

  for (int16_t i = 0; i < max(display.width(), display.height()) / 2; i += 2) {
    display.drawCircle(display.width() / 2, display.height() / 2, i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillcircle(void) {
  display.clearDisplay();

  for (int16_t i = max(display.width(), display.height()) / 2; i > 0; i -= 3) {
    // The INVERSE color is used so circles alternate white/black
    display.fillCircle(display.width() / 2, display.height() / 2, i, SSD1306_INVERSE);
    display.display();  // Update screen with each newly-drawn circle
    delay(1);
  }

  delay(2000);
}

void testdrawroundrect(void) {
  display.clearDisplay();

  for (int16_t i = 0; i < display.height() / 2 - 2; i += 2) {
    display.drawRoundRect(i, i, display.width() - 2 * i, display.height() - 2 * i,
                          display.height() / 4, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfillroundrect(void) {
  display.clearDisplay();

  for (int16_t i = 0; i < display.height() / 2 - 2; i += 2) {
    // The INVERSE color is used so round-rects alternate white/black
    display.fillRoundRect(i, i, display.width() - 2 * i, display.height() - 2 * i,
                          display.height() / 4, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawtriangle(void) {
  display.clearDisplay();

  for (int16_t i = 0; i < max(display.width(), display.height()) / 2; i += 5) {
    display.drawTriangle(
      display.width() / 2, display.height() / 2 - i,
      display.width() / 2 - i, display.height() / 2 + i,
      display.width() / 2 + i, display.height() / 2 + i, SSD1306_WHITE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testfilltriangle(void) {
  display.clearDisplay();

  for (int16_t i = max(display.width(), display.height()) / 2; i > 0; i -= 5) {
    // The INVERSE color is used so triangles alternate white/black
    display.fillTriangle(
      display.width() / 2, display.height() / 2 - i,
      display.width() / 2 - i, display.height() / 2 + i,
      display.width() / 2 + i, display.height() / 2 + i, SSD1306_INVERSE);
    display.display();
    delay(1);
  }

  delay(2000);
}

void testdrawchar(void) {
  display.clearDisplay();

  display.setTextSize(1);               // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);  // Draw white text
  display.setCursor(0, 0);              // Start at top-left corner
  display.cp437(true);                  // Use full 256 char 'Code Page 437' font

  // Not all the characters will fit on the display. This is normal.
  // Library will draw what it can and the rest will be clipped.
  for (int16_t i = 0; i < 256; i++) {
    if (i == '\n') display.write(' ');
    else display.write(i);
  }

  display.display();
  delay(2000);
}

void testdrawstyles(void) {
  display.clearDisplay();

  display.setTextSize(1);               // Normal 1:1 pixel scale
  display.setTextColor(SSD1306_WHITE);  // Draw white text
  display.setCursor(0, 0);              // Start at top-left corner
  display.println(F("Hello, world!"));

  display.setTextColor(SSD1306_BLACK, SSD1306_WHITE);  // Draw 'inverse' text
  display.println(3.141592);

  display.setTextSize(2);  // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.print(F("0x"));
  display.println(0xDEADBEEF, HEX);

  display.display();
  delay(2000);
}

void testscrolltext(void) {
  display.clearDisplay();

  display.setTextSize(2);  // Draw 2X-scale text
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(10, 0);
  display.println(F("scroll"));
  display.display();  // Show initial text
  delay(100);

  // Scroll in various directions, pausing in-between:
  display.startscrollright(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrollleft(0x00, 0x0F);
  delay(2000);
  display.stopscroll();
  delay(1000);
  display.startscrolldiagright(0x00, 0x07);
  delay(2000);
  display.startscrolldiagleft(0x00, 0x07);
  delay(2000);
  display.stopscroll();
  delay(1000);
}

void testdrawbitmap(void) {
  display.clearDisplay();

  display.drawBitmap(
    (display.width() - LOGO_WIDTH) / 2,
    (display.height() - LOGO_HEIGHT) / 2,
    logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
  display.display();
  delay(1000);
}

#define XPOS 0  // Indexes into the 'icons' array in function below
#define YPOS 1
#define DELTAY 2

void testanimate(const uint8_t *bitmap, uint8_t w, uint8_t h) {
  int8_t f, icons[NUMFLAKES][3];

  // Initialize 'snowflake' positions
  for (f = 0; f < NUMFLAKES; f++) {
    icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
    icons[f][YPOS] = -LOGO_HEIGHT;
    icons[f][DELTAY] = random(1, 6);
    Serial.print(F("x: "));
    Serial.print(icons[f][XPOS], DEC);
    Serial.print(F(" y: "));
    Serial.print(icons[f][YPOS], DEC);
    Serial.print(F(" dy: "));
    Serial.println(icons[f][DELTAY], DEC);
  }

  for (;;) {                 // Loop forever...
    display.clearDisplay();  // Clear the display buffer

    // Draw each snowflake:
    for (f = 0; f < NUMFLAKES; f++) {
      display.drawBitmap(icons[f][XPOS], icons[f][YPOS], bitmap, w, h, SSD1306_WHITE);
    }

    display.display();  // Show the display buffer on the screen
    delay(200);         // Pause for 1/10 second

    // Then update coordinates of each flake...
    for (f = 0; f < NUMFLAKES; f++) {
      icons[f][YPOS] += icons[f][DELTAY];
      // If snowflake is off the bottom of the screen...
      if (icons[f][YPOS] >= display.height()) {
        // Reinitialize to a random position, just off the top
        icons[f][XPOS] = random(1 - LOGO_WIDTH, display.width());
        icons[f][YPOS] = -LOGO_HEIGHT;
        icons[f][DELTAY] = random(1, 6);
      }
    }
  }
}

serial monitor output

SSD1306 allocation OK
x: 31 y: -16 dy: 3
x: 31 y: -16 dy: 1
x: -1 y: -16 dy: 2
x: -14 y: -16 dy: 1
x: 110 y: -16 dy: 3
x: 87 y: -16 dy: 3
x: 66 y: -16 dy: 3
x: 119 y: -16 dy: 4
x: 99 y: -16 dy: 2
x: -9 y: -16 dy: 2

setup

Yes

Standard 8 inch Dupont jumper wire lengths

ESP32-C3 Super Mini with the OLED Display Module I2C IIC 128X64 Pixel 0.96 Inch Display Module Yellow Blue Two-Color Display Compatible with Raspberry Pi Arduino 51 Series MCU STM32 R3 and Mega

Already tried pins 8 & 9 and also tried another Super Mini unsoldered to check, same issues.

Could you point to the OLED and its board you are using ?
Some 12 years ago I've been playing with an OLED (click!), and found (with a lot of help) some problems with the boards of that time (meaning these problems should, but may not be solved on your board).
One of those problems, was that the board didn't support sending (so that includes replying to pings) to the controller.
This last line would explain why the scanner would not work, even if everything else was OK.
This was easily solved by connecting 2 adjacent pins on the connector between glass and PCB, IIRC, but it requires at least medium soldering skills and a suitable soldering iron with a fine tip.
I just searched for this while composing this post, and its pins 19 and 20 which should be tied together.
The other problem was that the power on reset did not last long enough, resulting in a buffer (and so screen content) that was not erased nor usable for any wanted content.
This meant you could control whatever was in that buffer (make it scroll in whatever direction you'd want, or invert it), but you couldn't change the content of that buffer/screen.

Perhaps the old and lengthy thread linked above to may help you, but first you should make sure your solder connections are good as mentioned by the others before me.

By the way: 8 inches of wire may be too long for I2C, so trying to use shorter wires would also be a good idea.

Female jumper wires? I thought you said you were using a breadboard? No female jumpers should be needed at all, unless to connect some component that is breadboard incompatible. But it sounded like all your components are breadboard compatible.

In your photos, you are holding the ESP board in your fingers and there are female jumper wires connected to it. Where is the breadboard and why isn't the ESP plugged into it?

I'm not, based on your description so far!

Assuming all your components are breadboard compatible, I don't see any need to be using jumper wires at all. They are notoriously unreliable and should be avoided, except for connecting components that are not breadboard compatible to the breadboard.

For connecting between components on the breadboard I would recommend using solid-core wire, cut to length and laid flat on the breadboard. This is not only much more robust and reliable but makes it far easier to check wiring & spot mistakes.

I don't know what type of solder or flux you used, but some types of flux have to be rinsed with water or it will cross conduct when it dries.
I use a Kester flux pen and it does a great job, but I always have to take a wet toothbrush rinse and dry.
Take a magnifier and look closely at your board you might just find your issue.

I'm not being mean I'm just being honest, none of those solder joints look great. They should be shiny, not gray and cold. Clean the tip of your iron, tin it (cover it in solder)
Then wipe it clean with a wet cloth. Heat the joints again.
Finally, where are your pullup resistors on the I2C bus? Data and Clock need to be pulled high (I use 2 4.7k resistors) or you will have issues for sure.
Warm regards