FAQ
TL;DR: On ESP8266, SSD1306 libraries may re-init I2C to defaults (0x3C) because "periphBegin ... assumes true"; pass periphBegin=false or use the newer constructor to keep custom SDA/SCL and avoid breaking other devices. [Elektroda, khoam, post #19353356]
Why it matters: This helps Arduino/ESP8266 users move I2C pins without accidentally disabling GPS or other peripherals.
Quick Facts
- Arduino Uno’s I2C is fixed to PC4 (SDA) and PC5 (SCL); it isn’t remappable via Wire.h. [Elektroda, khoam, post #19351827]
- ESP8266 supports Wire.begin(SDA,SCL), but Adafruit_SSD1306::begin defaults periphBegin=true and can re-run Wire.begin() on default pins. [Elektroda, khoam, post #19353356]
- Prefer the SSD1306 constructor with TwoWire*; the old constructor is “deprecated” for I2C on ESP8266. [Elektroda, khoam, post #19355707]
- Typical SSD1306 I2C clocks: 400 kHz during transactions, 100 kHz after (constructor defaults). [Elektroda, khoam, post #19355707]
- Need I2C on non-default pins with Uno? Use software I2C like SoftWire or SoftI2CMaster. [Elektroda, khoam, post #19351836]
Can I change I2C pins on Arduino Uno using Wire.h?
No. The ATmega328P’s hardware I2C is fixed on PC4/PC5. “The Wire library for the Arduino Uno uses a hardware I2C controller.” Use a software I2C library if you need other pins. [Elektroda, khoam, post #19351836]
How do I move I2C to other pins on ESP8266?
Call Wire.begin(SDA, SCL) with GPIO numbers, for example Wire.begin(14, 12). Ensure any display or sensor library does not call Wire.begin() again internally. Set periphBegin=false when initializing SSD1306 to prevent re-initialization. [Elektroda, khoam, post #19353356]
Why did my GPS stop after setting I2C to GPIO14/12 on ESP8266?
Your SSD1306 begin() likely re-initialized Wire on default pins because periphBegin defaults to true. That toggles the default I2C pins and can disrupt a GPS connected there. “periphBegin … assumes true.” Disable it in begin(). [Elektroda, khoam, post #19353356]
How do I stop SSD1306 begin() from changing my I2C pins?
Use this quick fix:
- Initialize I2C first: Wire.begin(SDA, SCL).
- Call display.begin(SSD1306_SWITCHCAPVCC, 0x3C, true, false).
- Confirm GPS or other peripherals on default pins still respond.
This prevents an internal Wire.begin() on defaults. [Elektroda, khoam, post #19353356]
Which SSD1306 constructor should I use on ESP8266?
Use the I2C constructor that accepts TwoWire*: Adafruit_SSD1306(w, h, &Wire, rst_pin, ...). The older single-argument constructor you used is “deprecated.” It offers less control and flexibility on ESP8266. [Elektroda, khoam, post #19355707]
Can I run two I2C buses on Uno or ESP8266?
Uno has one hardware I2C; add another with a software I2C library (SoftWire or SoftI2CMaster). ESP8266 also has one hardware I2C; add a second via software I2C. “The Wire library for the Arduino Uno uses a hardware I2C controller.” [Elektroda, khoam, post #19351836]
Does Wire.h still touch default pins after I reassign I2C on ESP8266?
Wire itself uses the pins you set. However, some libraries call Wire.begin() with no pins by default. Because periphBegin is true, they reconfigure I2C to default pins and may disturb other devices. [Elektroda, khoam, post #19353356]
What I2C address should I use for SSD1306, 0x3C or 0x3D?
0x3C is the default for 32‑pixel‑tall SSD1306 displays. 0x3D is used for other heights. If you omit the address, the library selects an appropriate default. [Elektroda, khoam, post #19353356]
Why is GPIO12 causing conflicts with my GPS on ESP8266?
Your sketch sets SCL to GPIO12 and also uses GPIO12 as SoftwareSerial TX. Sharing one GPIO between I2C SCL and UART TX causes conflicts and breaks GPS communication. Reassign either SCL or TX to a different pin. [Elektroda, pier, post #19353741]
How can I add software I2C on Uno quickly?
Install SoftWire or SoftI2CMaster. Instantiate the software I2C on your chosen SDA/SCL pins. Use it for devices you want off PC4/PC5. Keep the hardware Wire bus free or for other devices as needed. [Elektroda, khoam, post #19351836]
Is calling Wire.begin() without parameters safe after setting custom pins on ESP8266?
No. A parameterless Wire.begin() resets I2C to default pins (GPIO4/5 on ESP8266 variants). That can disrupt peripherals wired to those pins. Always pass SDA/SCL or disable periphBegin in libraries. [Elektroda, khoam, post #19353356]
What I2C speed should I expect with Adafruit SSD1306 on ESP8266?
The recommended constructor uses 400 kHz during transactions and 100 kHz afterward by default. These values are typical for SSD1306 modules and balance speed with reliability. [Elektroda, khoam, post #19355707]
Are PC5 and PC4 free if I move I2C elsewhere on Arduino Uno?
No. You cannot remap Uno’s hardware I2C with Wire.h, so PC4/PC5 remain the I2C pins. If you must move devices, use a software I2C library instead. [Elektroda, khoam, post #19351827]