I'm working on a project using an Arduino Zero where I have multiple devices connected to the I2C bus. My setup includes:
SH110X 1.3 inch OLED Display (0x3C)
DS3231 RTC Module (0x57)
ICP20100 (0x63) and ICP10125 (0x64) Pressure Sensors (mounted on a custom PCB)
SD Card Module (connected via SPI)
Each of these devices is connected to the I2C bus, and I'm experiencing issues where the OLED display stops working when both ICP sensors are connected (actually, my whole program freezes, since the serial communication also stops working). I read something quick about the I2C bus and I suspect it might be due to pull-up resistor conflicts but I would like to get your guide on this.
Here are the details:
Current Observations:
OLED Display (SSD1306): Works fine when the sensors are not connected.
RTC Module (DS3231): I believe this module has onboard 4.7K pull-up resistors.
ICP20100 and ICP10125: These sensors are mounted on a custom PCB that I designed. The PCB includes pull-up resistors for the I2C bus.
Power Supply: Confirmed to be sufficient for all devices.
Steps Taken:
I2C Scanner: Confirms addresses of all devices (plus some additional addresses related to Zero's hardware), no address conflicts.
Testing Individually: Each device works perfectly when connected alone.
Testing in sets: both the RTC and the OLED Display work properly at the same time. As soon as I connect the pressure sensors, everything stops working.
My Questions:
How can I effectively diagnose if pull-up resistor conflict is the issue?
What is the best practice for managing pull-up resistors on a shared I2C bus with multiple devices?
Is it advisable to remove onboard pull-up resistors from some devices? If so, how can this be safely done?
Could there be any other potential issues I am overlooking?
An oscilloscope will show us digital signal waveforms.
Could have added digital signals need to propagate properly without distortion effects at the receiver.
We need 5v to 0v logic levels with good edge shaping.
The first image suggests a very large I2C pull-up resistor with distortion of our signal i.e. capacitance charging.
The second has good edges, proper 5v to 0v levels, a proper value pull-up is being used.
Hello, I cheked the resistance where you told me after I connected everything.
between + and SDA/CL: 2.5-2.6K
between GND and SDA/SCL: 3.1-3.2K
I also measured after I disconnected the custom PCB with my sensors.
between + and SDA/CL: 2.9-3.0K
between GND and SDA/SCL: 3.6-37K
Do you think this is still the issue? should I proceed with jumping the resistors in the boards to get it a bit higher?
Unfortunately, I don't have an oscilloscope to check the signals.
Weirdly enough, and maybe in another topic, I found out that some resistances in another part of my system changes when I connect and disconnect common GND to them. I am using the brown breadboard to detect when a channel is being selected. This are connected to pins 3-12 in the Arduino. I am using a simple voltage divider to get 3.3V signals. The R values are around 5K and 10K
When the GND of the board is connected, I read a lower resistance value than when the board is isolated from the system. Do you think this is something to consider or affecting the I2C resistance? I honestly don't understand why this is happening.
No, I have the level shifters in my custom PCB. I am actually able to communicate with the sensors independently (before trying to expand the system with the display)
Can you show a schematic of the custom PCB ? The level shifter must have pullup on both sides.
How long are the wires to the sensors ?
How are the modules powered ? With 5V or 3.3V ?
Can you give a link to RTC module (a link to where you bought it).
The ATSAMD21G18 on your Arduino Zero is a 3.3V processor. That means that the I2C bus is a 3.3V I2C bus. It works best if every device has also a 3.3V I2C bus.
It is possible to measure the pullup in the circuit.
Use this sketch:
void setup()
{
Wire.begin();
}
void loop() {}
Run the sketch. Measure the short circuit current from SDA to GND and from SCL to GND.
They should be below 3mA. I prefer a value between 1mA and 3mA.
Keep in mind that: "OLED displays are known for disturbing the I2C bus for others".
Hello sorry for the late reply.
I will certainly gather all the information and share it later when I get back to my workshop because I have still other problems and it is maybe better to arrange all the information in a way that I can properly share.
In the meantime, I swapped the display for a smaller one (0.96in), and changed the library to the SSD1306 and it works, surprisingly. I did not change anything else. I do not know why that particular display model is not working in my sketch. I used it in an example just to see if it was broken but no, it works without problems with a different sketch.
Anyway, now I have some other issue regarding I2C itself. I need to think how to formulate my question but I think I would be posting back soon.
I would like to know the reason why one display did not work and the other did, but I honestly could go on knowing that I can display my information on it.
You are not the only one with such problems. OLED displays are not always nice on a I2C bus. If a OLED display does not work in a certain specific situation, then find something that does work.
OLED displays have an internal voltage generator for the display that can be noisy. The SDA and SCL pins of the OLED display are for a 3.3V bus, but somehow they can even cause trouble on a 3.3V I2C bus.
Thanks for the information. I have, however, another problem with the communication, but for this I need to explain a bit more what I am doing right now.
Setting aside the RTC, SD card, and display modules, I need to read values from ten I2C pressure sensors (DUTx = pressure sensor model ICP-20100) which all share the same I2C address 0x64. I am using a multiplexor system with an integrated power supply to change channel and read the values from the sensors.
I tested the channel switching to see if the Arduino Zero recognizes the signals from the MUX, and it does. I can display the channel selection from 1 to 10.
Also, WITHOUT connecting the MUX, my sketch works and gets the required data from the sensors when I just keep the SDA1 and SCL1 signals permanently connected from DUT1 directly to the Arduino (without passing through the MUX), and then I "simulate" the channel switching by applying 5V with a jumper wire to the Pull-down resistors arrangement.
The problem that I have is when I actually connect the MUX and the Zero, and run the switching. Immediately the whole system stops working. I cannot read data, channel detection does not work, display freezes, the SD card does not record, etc.
My guess is that this is something to do with me "interrupting" the transmission of the data when I jump from one channel to another without a proper "ending" of the data. I switch channels every 1s, cyclically.
I read here that there are problems with "Stuck I2C busses". Do you think this is a potential reason of the crashing of the whole system?
Data acquisition system/multimeter with 6 input slots, 10 different input modules selectable, up to 14k measurements/s
7.5 digit resolution, 650k memory, Ethernet, USB and GPIB interfaces
The 3700A Series offers scalable, instrument-grade switching and multi-channel measurement solutions optimized for automated testing of electronic products and components
It is not a I2C MUX per se, but it has been adapted (not by me but by an external company) to be able to also received both the SDA and the SCL signals per each channel
Oh yes it knows. The MUX has digital pins that can be configured as outputs and are set high whenever the corresponding channel is multiplexed. It is a bit hard to see in the diagram but what I mean are the "ChX Active (-RVX)" signal pointing to the Arduino block. These signals come from the voltage divider generating the 3.3V that the GPIO pins of the Zero need. The MUX is proving the 5V signals going on top of the 5K resistors.
My display shows the channel that is being active at the moment.
When it actually works, I am just permanently connecting the data and clock lines of one sensor (i.e. SDA1 and SCL1) to my Arduino. Then, I feed 5 volts to the pins marked "1 MUX" in this picture.
Below you can see the black jumper wire delivering 5V being connected in the first pin and the display reading "Selected Channel 1", and to the right, the pin 10 being selected and the displays confirms the selection.
I realize that I am only changing the channel, and the SDA and SCL lines are not being disconnected, so maybe it is why it is working. But when I actually connect the MUX cable selecting the channels (a cable with 10 wires connected each to one of the yellow PCB pins), and the MUX starts to actually "switch" the SDA and SCL among channels, everything stops working.
Can you please post your basic code that interfaces with the MUX and sensors.
Are you connecting to each sensor in turn to initialise them in the setup part of your code, so they are ready to communicate?
Can you please post a copy of your circuit, a picture of a hand drawn circuit in jpg, png?
Hand drawn and photographed is perfectly acceptable.
Please include ALL hardware, power supplies, component names and pin labels.
Is it better if I upload the whole sketch (500 lines, mostly dealing with SD card, calculations, and display things)? or is it better if I just delete every non-relevant function and just leave the things about the MUX and sensor initialization?