An I2C Address Scanner For Your Desk
The perfect solution to keep on your desk full-time to check the I2C address of devices with dubious origins, with lack of documentation or of devices that have a programmable address.
Features:
- Powered by USB Type-C
- Uses the microcontroller’s built-in USB-C socket – no soldering of a complicated USB-C receptacle required!
- Uses the microcontroller’s built-in USB-C socket – no soldering of a complicated USB-C receptacle required!
- Selectable 3.3V regulators.
- Use the built-in 3.3V regulator for simplicity or install an external one for more power delivery and stability.
- Use the built-in 3.3V regulator for simplicity or install an external one for more power delivery and stability.
- Switchable output for the scanned I2C device.
- Power the scanned I2C device by the USB’s 5V source or your 3.3V regulator.
- Power the scanned I2C device by the USB’s 5V source or your 3.3V regulator.
- Compatible with Stemma-QT and QWIIC devices.
- Install the optional JST-SH connector with 1.0mm pitch for plug-and-play compatibility with Adafruit’s Stemma-QT or Sparkfun’s QWIIC systems.
- Install the optional JST-SH connector with 1.0mm pitch for plug-and-play compatibility with Adafruit’s Stemma-QT or Sparkfun’s QWIIC systems.
- Compatible with pull-up resistors.
- Empty pads are available on both the display’s and the scanned device’s I2C lines to add a pull-up resistor if needed for your use case.
- Empty pads are available on both the display’s and the scanned device’s I2C lines to add a pull-up resistor if needed for your use case.
- Designed with makers and hackers in mind.
- All of the microcontroller board’s soldered pins are broken out for ease of adding features
- Horizontal row of pins are not included on the board so that you can add pin headers to connect jumper leads directly.
- Designed for ease of connectivity.
- Two sets of pads are broken out for scanning devices, allowing the use of both female and male headers, or a direct and remote mounting system – the sky is the limit!
- Two sets of pads are broken out for scanning devices, allowing the use of both female and male headers, or a direct and remote mounting system – the sky is the limit!
- Wide compatibility.
- Designed for a Waveshare RP2040-Zero microcontroller board (or compatible) but has copper removed in order to maintain compatibility with ESP32-C3-Zero and ESP32-S3-Zero and similar boards – including the use of WiFi and Bluetooth.
- Designed for a Waveshare RP2040-Zero microcontroller board (or compatible) but has copper removed in order to maintain compatibility with ESP32-C3-Zero and ESP32-S3-Zero and similar boards – including the use of WiFi and Bluetooth.
- Part of a large instrumentation suite.
- Multiple devices will maintain size/shape compatibility for uniform appearance.
What you will need:
Here is what you will need to get up and running with your very own I2C scanner – please note that some of these links are affiliate links and support the creator of this project at no extra cost to you.
- (optional) PCB:
- PCBWay
- This link will also take you to the gerber files if you want to order from another supplier but I would ask that you consider using PCBWay to order your boards – their support partially funded the development of this project.
- RP2040-Zero (or compatible):
- Aliexpress: https://s.click.aliexpress.com/e/_c3frVqPd
- Amazon (Canada): https://amzn.to/4mBsttp
- Amazon (USA & Global): https://amzn.to/48v5VXC
- 0.96″ OLED Display (I2C):
- Aliexpress: https://s.click.aliexpress.com/e/_c4FMPfBh
- Amazon (Canada): https://amzn.to/4pym19f
- Amazon (USA & Global): https://amzn.to/4mzMhx8
- (optional) 4-Pin & 3-Pin Headers Male:
- Aliexpress: https://s.click.aliexpress.com/e/_c3w4opQf
- Amazon (Canada): https://amzn.to/4gBvNDv
- Amazon (USA & Global): https://amzn.to/3IonK07
- (optional) 4-Pin Headers Female:
- Aliexpress: https://s.click.aliexpress.com/e/_c44VEN1d
- Amazon (Canada): https://amzn.to/3KjBidO
- Amazon (USA & Global): https://amzn.to/3Ib8Bze
- (optional) Jumper Cap:
- Aliexpress: https://s.click.aliexpress.com/e/_c34cqMEF
- Amazon (Canada): https://amzn.to/4gBNB17
- Amazon (USA & Global): https://amzn.to/4pKms0j
- (optional) AMS1117-3.3 3.3v Regulator:
- Aliexpress: https://s.click.aliexpress.com/e/_c41q77Kr
- Amazon (Canada): https://amzn.to/4nhxXuf
- Amazon (USA & Global): https://amzn.to/42b01Hs
- (optional) 0805 Capacitors 100nF:
- Aliexpress: https://s.click.aliexpress.com/e/_c4bZ3vUT
- Amazon (Canada): https://amzn.to/4pDUfIl
- Amazon (USA & Global): https://amzn.to/4nE6nay
- (optional) 0805 Resistors 4.7k:
- Aliexpress: https://s.click.aliexpress.com/e/_c2yDTXFt
- Amazon (Canada): https://amzn.to/3ImMF49
- Amazon (USA & Global): https://amzn.to/3VwMndW
- (optional) JST-SH 1.0mm Female (Stemma-QT / QWIIC)
- Aliexpress: https://s.click.aliexpress.com/e/_c4nTBVin
- Amazon (Canada): https://amzn.to/42KCf54
- Amazon (USA & Global): https://amzn.to/3Waz7f7
- (optional) 5mm O.D. x 4mm H x m3 Heat-set Insert (for case):
- Aliexpress: https://s.click.aliexpress.com/e/_c3J6lGJN
- Amazon (Canada): https://amzn.to/4mwc4GE
- Amazon (USA & Global): https://amzn.to/4gDXV8Z
- (optional) m3 X 10mm Screw (for case):
- Aliexpress: https://s.click.aliexpress.com/e/_c4ntaKeL
- Amazon (Canada): https://amzn.to/4nlKblM
- Amazon (USA & Global): https://amzn.to/3IwyWrx
- (optional) m2 X 6mm Self-Tapping Screw (for case):
- Aliexpress: https://s.click.aliexpress.com/e/_c3K1W5v5
- Amazon (Canada): https://amzn.to/4nidBkF
- Amazon (USA & Global): https://amzn.to/4muZszi
Assembly Tips
This board is relatively straightforward to build up however there are a few challenges, especially when it comes to the surface mount parts. I would strongly recommend that you solder on the AMS1117 and the JST-SH connectors first if you intend to use them. You can either order a solder stencil from your PCB house and use that to squeegee on some solder paste or you can just pre-tin the pads, place the components onto them, and then use hot air or a hot plate to solder on the parts. Make sure that you check continuity to the JST-SH connectors once soldered – they can be quite finnicky and this is why they are mealy optional.
As for the microcontroller itself – you can either use sockets or solder directly to the board using the pin headers provided with the micro itself but in any case, make sure to put all the headers you intend to use together with the micro, on the board, and solder them in-place – any small alignment issue will make the fitment be a pain in the butt. As for the alignment of the USB connector with the case design – it does accommodate the board being either mounted directly to the PCB or mounted via pin headers (whether they are low profile or regular ones)
Be absolutely sure to select either the internal 3.3V regulator or the external one on the PCB – you must solder the jumper above the footprint for the AMS1117 – either linking the center pad to the leftmost or rightmost, depending on your choice.
You also must select the output voltage for the scanning pads – either 5V or 3.3V by use of the leftmost jumper. You can either solder bridge the center and the upper pad together for 3.3V or the center and the lower pad for 5V. My personal preference is to solder a triplet of male pin headers and use a jumper cap (the extended type with a grip) to select the voltage depending on the situation.
Make sure that your OLED is a “SSD1306” type and I2C – other ones will work but you’ll have to modify the code for it to work!
Code
Check my GitHub repo here for the most up-to-date code but this one will get you up and running if you just want to copy/paste this into the Arduino IDE. I use the Pi Pico as the board and it works just fine.
You do need to add the RP2040 boards into your Arduino IDE if you haven’t yet – here is how to do it: https://learn.adafruit.com/rp2040-arduino-with-the-earlephilhower-core/overview
/*
This code will scan continuously for i2c devices on pins 6 and 7
and display it on a SSD1306 128x64 i2c OLED.
This has been tested on a RP2040-Zero on 14/09/2025 and was
working as intended.
Important pins:
--- RP2040-Zero ---
GP4 = SDA (display)
GP5 = SCL (display)
GP6 = SDA (scanning)
GP7 = SCL (scanning)
--- OLED ---
VCC = 3.3V (3v3 pin - RP2040-Zero's internal regulator)
GND = GND (GND pin on RP2040-Zero)
SCL = GP5 (default)
SDA = GP4 (default)
This code is written by Dan from the Simple Electronics YouTube
channel and is mostly a mashup of library examples and has been
over-commented to be beginner-friendly for all to use.
***THIS SPECIFIC PROJECT DID RELY HEAVILY ON AI FOR CODE***
https://www.youtube.com/SimpleElectronics
The code contributed by Dan is open-source under the MIT Licence
however, the libraries retain their own licensing
Copyright <2025> <Dan, Simple Electronics>
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the “Software”),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <Wire.h> // Needed for communications
#include <Adafruit_GFX.h> // Needed to style the fonts on the display
#include <Adafruit_SSD1306.h> // Needed for the specific OLED display
// OLED display settings
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C // Common address for SSD1306, change if needed
// Create display object on I2C0 (pins 4,5)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// I2C1 pins for RP2040-zero
#define I2C1_SDA 6
#define I2C1_SCL 7
// Create second I2C instance
TwoWire Wire1(I2C1_SDA, I2C1_SCL);
// Array to store previously found devices
uint8_t previousDevices[128];
uint8_t prevDeviceCount = 0;
void setup() {
Serial.begin(115200);
delay(1000);
// Initialize I2C0 for OLED (pins 4,5 - default Wire)
Wire.begin();
// Initialize I2C1 for device scanning
Wire1.begin();
// Initialize OLED display
if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
Serial.println(F("SSD1306 allocation failed"));
for (;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println(F("I2C Scanner Ready"));
display.println(F("Plug device into"));
display.println(F("I2C1 bus"));
display.println();
display.print(F("SDA: Pin "));
display.println(I2C1_SDA);
display.print(F("SCL: Pin "));
display.println(I2C1_SCL);
display.display();
Serial.println("I2C Scanner initialized");
Serial.println("OLED on I2C0 (pins 4,5)");
Serial.println("Scanning I2C1 (pins " + String(I2C1_SDA) + "," + String(I2C1_SCL) + ")");
}
void loop() {
uint8_t currentDevices[128];
uint8_t currentDeviceCount = 0;
// Scan I2C1 bus for devices
for (uint8_t address = 1; address < 127; address++) {
Wire1.beginTransmission(address);
uint8_t error = Wire1.endTransmission();
if (error == 0) {
currentDevices[currentDeviceCount] = address;
currentDeviceCount++;
}
}
// Check if devices have changed
bool devicesChanged = false;
if (currentDeviceCount != prevDeviceCount) {
devicesChanged = true;
} else {
// Compare device lists
for (uint8_t i = 0; i < currentDeviceCount; i++) {
bool found = false;
for (uint8_t j = 0; j < prevDeviceCount; j++) {
if (currentDevices[i] == previousDevices[j]) {
found = true;
break;
}
}
if (!found) {
devicesChanged = true;
break;
}
}
}
// Update display if devices changed
if (devicesChanged) {
display.clearDisplay();
display.setCursor(0, 0);
display.setTextSize(1);
if (currentDeviceCount == 0) {
display.println(F("No I2C devices found"));
display.println(F("on I2C1 bus"));
display.println();
display.println(F("Waiting for device..."));
} else {
display.println(F("I2C Devices Found:"));
display.println();
for (uint8_t i = 0; i < currentDeviceCount; i++) {
display.print(F("0x"));
if (currentDevices[i] < 16) display.print(F("0"));
display.print(currentDevices[i], HEX);
display.print(F(" ("));
display.print(currentDevices[i]);
display.println(F(")"));
// Print to serial as well
Serial.print("Device found at address 0x");
if (currentDevices[i] < 16) Serial.print("0");
Serial.print(currentDevices[i], HEX);
Serial.print(" (");
Serial.print(currentDevices[i]);
Serial.println(")");
}
// Show scan time
display.println();
display.print(F("Scan: "));
display.print(millis() / 1000);
display.println(F("s"));
}
display.display();
// Update previous devices list
prevDeviceCount = currentDeviceCount;
for (uint8_t i = 0; i < currentDeviceCount; i++) {
previousDevices[i] = currentDevices[i];
}
}
delay(1000); // Wait a second to scan again
}
Case / Enclosure
The case is made up of 3 parts: The OLED holder, the lid and the base. I am not sure if it’s a good idea to host a downloadable file on my own site quite yet so you should get them from GitHub
Closing Notes
I think this project is one of those tools that you don’t need all the time but when you do need it, it’s far better to have all built up and in a housing, ready to be used instead of having to breadboard up a new circuit. At the insanely low cost of these microcontroller boards (approximately 4$ CAD at the time of this article) and the ridiculously low price of getting custom boards made (the ones I have here cost under 10$ CAD to have ten of them made, including the upcharge for removing the manufacturing codes on them) – I think this is a no-brainer and should go well in anyone’s workstation!