Bird
Raised Fist0
Arduinoprogramming~10 mins

Reading I2C sensor data in Arduino - Step-by-Step Execution

Choose your learning style10 modes available
Concept Flow - Reading I2C sensor data
Start
↓
Initialize I2C bus
↓
Request data from sensor
↓
Wait for sensor response
↓
Read bytes from sensor
↓
Process data
↓
Use or display data
↓
Repeat or End
The program starts by setting up the I2C bus, then requests data from the sensor, waits for the response, reads the data bytes, processes them, and finally uses or shows the data.
Execution Sample
Arduino
Wire.begin();
Wire.requestFrom(0x68, 2);
if (Wire.available() >= 2) {
  int data = (Wire.read() << 8) | Wire.read();
}
This code initializes I2C, requests 2 bytes from sensor at address 0x68, and reads the data if available.
Execution Table
StepActionI2C Bus StateData RequestedData AvailableData ReadResult
1Wire.begin()I2C bus initialized----
2Wire.requestFrom(0x68, 2)Bus active2 bytes from 0x68Waiting--
3Check Wire.available()Bus active2 bytes requested2 bytes available-Ready to read
4Wire.read() first byteBus active-2 bytes availableFirst byte read (e.g. 0x1A)-
5Wire.read() second byteBus active-1 byte leftSecond byte read (e.g. 0xCF)-
6Combine bytes----Data = 0x1ACF (6863 decimal)
7Use data----Data processed or displayed
8End or repeat----Loop or stop
💡 Execution stops after reading and processing requested bytes from sensor.
Variable Tracker
VariableStartAfter Step 4After Step 5After Step 6Final
dataundefined0x1A00 (first byte shifted)0x1ACF (combined two bytes)0x1ACF0x1ACF
Key Moments - 3 Insights
Why do we check Wire.available() before reading?
Because Wire.available() tells us how many bytes the sensor has sent and are ready to read. Reading without checking might cause errors or wrong data. See step 3 in execution_table.
Why do we shift the first byte by 8 bits before combining?
Because the sensor sends data in two bytes: high byte and low byte. Shifting the first byte left by 8 bits moves it to the high position, so when combined with the second byte, it forms the full 16-bit value. See step 6 in execution_table.
What happens if the sensor sends fewer bytes than requested?
Wire.available() will return fewer bytes, so the if condition fails and we don't read incomplete data. This prevents errors. See step 3 in execution_table.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 3, how many bytes are available to read?
A1 byte
B0 bytes
C2 bytes
D3 bytes
💡 Hint
Check the 'Data Available' column at step 3 in execution_table.
At which step is the data combined into a single integer?
AStep 6
BStep 5
CStep 4
DStep 7
💡 Hint
Look for the step where bytes are shifted and combined in execution_table.
If Wire.available() returned 1 instead of 2 at step 3, what would happen?
AData would be read correctly
BThe if condition would fail and no data read
CThe program would crash immediately
DThe sensor would send more data automatically
💡 Hint
Refer to the if condition check in step 3 of execution_table and key_moments.
Concept Snapshot
Reading I2C sensor data:
1. Initialize I2C with Wire.begin()
2. Request bytes from sensor with Wire.requestFrom(address, bytes)
3. Check Wire.available() to confirm bytes ready
4. Read bytes with Wire.read()
5. Combine bytes if needed (e.g., shift high byte)
6. Use or display the processed data
Full Transcript
This visual execution shows how to read data from an I2C sensor using Arduino's Wire library. First, the I2C bus is initialized with Wire.begin(). Then, the program requests 2 bytes from the sensor at address 0x68 using Wire.requestFrom(). It waits until Wire.available() confirms 2 bytes are ready to read. The program reads the first byte, shifts it left by 8 bits, then reads the second byte and combines both to form a 16-bit integer. Finally, the data is processed or displayed. The execution table tracks each step, showing bus state, data availability, and variable changes. Key moments clarify why checking Wire.available() is important and why bytes are combined with shifting. The quiz tests understanding of these steps. This step-by-step trace helps beginners see exactly how I2C sensor data is read and handled in Arduino code.

Practice

(1/5)
1. What is the main purpose of the Wire.begin() function in Arduino when reading I2C sensor data?
easy
A. To initialize the I2C communication bus
B. To read data from the sensor
C. To write data to the sensor
D. To close the I2C communication

Solution

  1. Step 1: Understand the role of Wire.begin()

    The Wire.begin() function sets up the Arduino to use the I2C bus, preparing it to communicate with I2C devices.
  2. Step 2: Differentiate from other functions

    Reading or writing data happens after initialization; Wire.begin() does not perform these actions.
  3. Final Answer:

    To initialize the I2C communication bus -> Option A
  4. Quick Check:

    Wire.begin() initializes I2C [OK]
Hint: Remember: begin() always starts communication [OK]
Common Mistakes:
  • Confusing Wire.begin() with reading or writing functions
  • Thinking Wire.begin() sends or receives data
  • Skipping Wire.begin() before communication
2. Which of the following is the correct syntax to request 2 bytes of data from an I2C device with address 0x40 using the Wire library?
easy
A. Wire.readFrom(0x40, 2);
B. Wire.request(0x40, 2);
C. Wire.requestFrom(0x40, 2);
D. Wire.getFrom(0x40, 2);

Solution

  1. Step 1: Recall the correct Wire library function

    The function to request bytes from an I2C device is Wire.requestFrom(address, quantity).
  2. Step 2: Match the syntax with the options

    Only Wire.requestFrom(0x40, 2); uses the correct function name and parameters.
  3. Final Answer:

    Wire.requestFrom(0x40, 2); -> Option C
  4. Quick Check:

    requestFrom(address, bytes) is correct [OK]
Hint: Use requestFrom() to get bytes from I2C device [OK]
Common Mistakes:
  • Using incorrect function names like request() or readFrom()
  • Mixing up parameter order
  • Forgetting to specify the number of bytes
3. Consider this Arduino code snippet reading two bytes from an I2C sensor:
Wire.requestFrom(0x50, 2);
if (Wire.available() >= 2) {
  byte highByte = Wire.read();
  byte lowByte = Wire.read();
  int value = (highByte << 8) | lowByte;
  Serial.println(value);
}
If the sensor sends bytes 0x01 and 0xF4, what will be printed?
medium
A. 500
B. 400
C. 5000
D. 256

Solution

  1. Step 1: Understand byte combination

    The code shifts the first byte (0x01) left by 8 bits and ORs it with the second byte (0xF4). This forms a 16-bit number.
  2. Step 2: Calculate the combined value

    0x01 << 8 = 0x0100 (256 decimal), 0xF4 = 244 decimal, sum = 256 + 244 = 500.
  3. Final Answer:

    500 -> Option A
  4. Quick Check:

    (0x01 << 8) + 0xF4 = 500 [OK]
Hint: Shift high byte 8 bits left, then OR with low byte [OK]
Common Mistakes:
  • Adding bytes without shifting
  • Mixing byte order (low byte first)
  • Printing raw bytes instead of combined value
4. This code tries to read a byte from an I2C sensor but does not work correctly:
Wire.begin();
Wire.beginTransmission(0x30);
Wire.write(0x00);
Wire.endTransmission();
byte data = Wire.read();
Serial.println(data);
What is the main problem?
medium
A. Wire.beginTransmission() address is wrong
B. Wire.read() is called without requesting data first
C. Wire.write() should be after Wire.read()
D. Wire.endTransmission() should be called twice

Solution

  1. Step 1: Check the sequence of I2C functions

    The code sends a command but never calls Wire.requestFrom() to ask for data before reading.
  2. Step 2: Understand Wire.read() usage

    Wire.read() only returns data after Wire.requestFrom() has been called and data is available.
  3. Final Answer:

    Wire.read() is called without requesting data first -> Option B
  4. Quick Check:

    Must requestFrom() before read() [OK]
Hint: Always requestFrom() before reading data [OK]
Common Mistakes:
  • Calling Wire.read() without requestFrom()
  • Misunderstanding beginTransmission() purpose
  • Not checking if data is available before reading
5. You want to read temperature data from an I2C sensor that sends two bytes: the first byte is the integer part, the second byte is the fractional part in hundredths (e.g., 25 and 75 means 25.75°C). Which code snippet correctly reads and prints the temperature as a float?
hard
A. Wire.requestFrom(0x48, 2); if (Wire.available() >= 2) { byte intPart = Wire.read(); byte fracPart = Wire.read(); float temp = intPart + fracPart / 100; Serial.println(temp); }
B. Wire.requestFrom(0x48, 2); if (Wire.available() >= 2) { byte fracPart = Wire.read(); byte intPart = Wire.read(); float temp = intPart + fracPart / 100.0; Serial.println(temp); }
C. Wire.requestFrom(0x48, 2); byte intPart = Wire.read(); byte fracPart = Wire.read(); float temp = intPart + fracPart * 100; Serial.println(temp);
D. Wire.requestFrom(0x48, 2); if (Wire.available() >= 2) { byte intPart = Wire.read(); byte fracPart = Wire.read(); float temp = intPart + fracPart * 0.01; Serial.println(temp); }

Solution

  1. Step 1: Confirm correct byte order and availability check

    The sensor sends integer part first, then fractional part. The code must check availability before reading both bytes.
  2. Step 2: Calculate temperature correctly

    Fractional part is in hundredths, so divide by 100 or multiply by 0.01. Wire.requestFrom(0x48, 2); if (Wire.available() >= 2) { byte intPart = Wire.read(); byte fracPart = Wire.read(); float temp = intPart + fracPart * 0.01; Serial.println(temp); } uses fracPart * 0.01, which is correct and clear.
  3. Final Answer:

    the snippet with fracPart * 0.01 -> Option D
  4. Quick Check:

    Check availability, read int then frac, multiply frac by 0.01 [OK]
Hint: Check data availability and multiply fraction by 0.01 [OK]
Common Mistakes:
  • Reading bytes in wrong order
  • Not checking Wire.available() before reading
  • Multiplying fraction by 100 instead of dividing
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard