Connecting multiple I2C devices in Arduino - Time & Space Complexity
When connecting multiple I2C devices, the time to communicate depends on how many devices we talk to.
We want to know how the communication time grows as we add more devices.
Analyze the time complexity of the following code snippet.
#include <Wire.h>
const int deviceCount = 3; // Example device count
const int deviceAddresses[] = {0x20, 0x21, 0x22}; // Example device addresses
const byte data = 0xFF; // Example data to send
void setup() {
Wire.begin();
}
void loop() {
for (int i = 0; i < deviceCount; i++) {
Wire.beginTransmission(deviceAddresses[i]);
Wire.write(data);
Wire.endTransmission();
}
delay(1000);
}
This code sends data to multiple I2C devices one by one in a loop.
- Primary operation: Loop over all devices to send data.
- How many times: Once per device each loop cycle.
Each device adds one more communication step, so time grows steadily with device count.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 10 transmissions |
| 100 | 100 transmissions |
| 1000 | 1000 transmissions |
Pattern observation: Time increases directly with the number of devices.
Time Complexity: O(n)
This means the time to send data grows in a straight line as you add more devices.
[X] Wrong: "Adding more devices won't affect communication time much because I2C is fast."
[OK] Correct: Each device requires its own communication step, so total time adds up with each device.
Understanding how communication time grows with devices helps you design efficient sensor networks and troubleshoot delays.
"What if we send data to all devices in parallel using multiple I2C buses? How would the time complexity change?"
Practice
Solution
Step 1: Understand I2C wiring basics
I2C devices share two wires: SDA (data) and SCL (clock).Step 2: Identify how devices are distinguished
Devices use unique addresses so the master knows which device to talk to.Final Answer:
Each device has a unique address to identify it on the bus -> Option CQuick Check:
Unique addresses allow multiple devices on same wires [OK]
- Thinking devices use separate wires
- Assuming different clock speeds separate devices
- Believing devices use different power pins to communicate
Solution
Step 1: Recall the correct function to start I2C
The Arduino Wire library uses Wire.begin() to start the I2C bus as master.Step 2: Check other options for correctness
Wire.begin(0x3C) sets device as slave with address 0x3C, not for master init. Wire.init() and Wire.start() do not exist in Wire library.Final Answer:
Wire.begin(); -> Option BQuick Check:
Wire.begin() starts I2C master bus [OK]
- Using Wire.begin(address) to start master
- Calling non-existent Wire.init() or Wire.start()
- Not calling Wire.begin() at all
Wire.begin();
Wire.beginTransmission(0x40);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(0x40, 1);
int temp1 = Wire.read();
Wire.beginTransmission(0x41);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(0x41, 1);
int temp2 = Wire.read();
Serial.print(temp1);
Serial.print(", ");
Serial.println(temp2);Solution
Step 1: Understand the communication sequence
The code requests one byte from device 0x40, reads it as temp1 (25), then requests one byte from 0x41, reads it as temp2 (30).Step 2: Check the Serial output commands
Serial.print(temp1) prints 25, then ", ", then Serial.println(temp2) prints 30 with newline.Final Answer:
25, 30 -> Option DQuick Check:
Read values match device addresses in order [OK]
- Mixing up device addresses and values
- Assuming output is reversed
- Thinking code causes compile error
Wire.begin(); Wire.beginTransmission(0x50); Wire.write(0x01); Wire.endTransmission(); Wire.requestFrom(0x50, 1); int val1 = Wire.read(); Wire.beginTransmission(0x50); Wire.write(0x02); Wire.endTransmission(); Wire.requestFrom(0x51, 1); int val2 = Wire.read(); Serial.println(val1 + val2);
Solution
Step 1: Analyze device addresses used
The code writes to 0x50 twice but requests data from 0x50 first, then 0x51 second. If 0x51 device is not connected, no data is returned.Step 2: Understand impact on read values
Reading from 0x51 returns no data, so Wire.read() returns 0, causing sum to be zero or incorrect.Final Answer:
Requesting from 0x51 instead of 0x50 causes no data -> Option AQuick Check:
Address mismatch causes no data read [OK]
- Confusing write and requestFrom addresses
- Forgetting to call Wire.begin() once
- Thinking Wire.write() before requestFrom() is invalid
Solution
Step 1: Understand I2C bus initialization
Wire.begin() must be called once to initialize the bus as master before any communication.Step 2: Read sensors by unique addresses on shared bus
Each sensor has a unique address; read each by calling Wire.requestFrom() with that address on the same SDA and SCL lines.Step 3: Evaluate other options
Calling Wire.begin() multiple times is unnecessary. Using separate wires defeats I2C design. Assigning same address causes conflicts.Final Answer:
Call Wire.begin() once, then read each sensor by its unique address with Wire.requestFrom() -> Option AQuick Check:
One Wire.begin(), unique addresses, shared wires [OK]
- Calling Wire.begin() multiple times
- Trying separate wires for each I2C device
- Using same address for multiple devices
Ready to prove it?
Pass the test and this pattern moves unknown
