Course materials · Microprocessor Applications

I²C communication

English translation

Learning objectives

The same two bytes can represent very different physical quantities depending on the sign and sensor range settings. Verify the conversion starting with boundary values.

Execution conditions

Basic exercise: provided bytes and synthetic sensor data. Real I²C example: requires a Linux I²C device and smbus2 (python -m pip install smbus2).

Convert two bytes to a signed value

Starting conditions

The byte pairs are (0x40,0x00),(0xC0,0x00),(0x7F,0xFF),(0x80,0x00),(0xFF,0xFF). The first byte is the high byte.

Procedure

  1. Use (high<<8)|low to form a 16-bit unsigned value.
  2. If the value is at least 2^15, subtract 2^16 to convert it to a signed value.
  3. Compare raw>=0x8000 and raw>0x8000 at 0x8000.

Results to retain

pairs=[(0x40,0),(0xC0,0),(0x7F,0xFF),(0x80,0),(0xFF,0xFF)]
def signed16(high,low):
    value=(high<<8)|low
    return value-65536 if value>=32768 else value
print([signed16(*p) for p in pairs])
# TODO: Add unsigned and expected values, and boundary assert checks.

Record results and self-check

high:

low:

unsigned:

signed:

Your prediction:

Points to check

Raw values and physical units

Starting conditions

Acceleration raw=[16384−81920]\mathrm{raw}=\begin{bmatrix}16384&-8192&0\end{bmatrix}, with two sensitivity conditions: 16384 LSB/g and 8192 LSB/g. Apply 131 or 16.4 LSB/(°/s) to gyro raw=1310.

Procedure

  1. Calculate acceleration and angular velocity for each sensitivity condition.
  2. Explain why the same raw value represents a different physical quantity when the sensor settings change.
  3. In MPU_Init of Week7-1_I2C_IMU_manual.ipynb, read the value written to GYRO_CONFIG and the section that divides the gyro raw value. List checks for determining whether the settings are correct, grouped by register bits, sensitivity, and units. This step requires only code reading; no device connection or file execution is needed.

Results to retain

acc_raw=[16384,-8192,0]
for scale in [16384.,8192.]:print('acc [g]',[v/scale for v in acc_raw])
print('gyro [deg/s]',1310/131,1310/16.4)
# TODO: Record a sensitivity and units table and items to check against the original settings.

Record results and self-check

raw:

Configured sensitivity:

Converted value:

Unit:

Points to check

Deviation in stationary sensor records

Starting conditions

Use seed=7 to generate 100 3-axis samples by adding noise with a standard deviation of 120 LSB to [0,0,16384] LSB. The sensitivity is 16384 LSB/g.

Procedure

  1. Divide the raw arrays for both conditions by the sensitivity of 16384 LSB/g to convert them to acceleration units. Use mean(axis=0) and std(axis=0) on each array to calculate the mean and standard deviation for each axis.
  2. Calculate the Euclidean norm of the three axis values in each row to obtain each sample's acceleration magnitude. Apply the same operation to the original record and to a record with a 500 LSB bias added to the X axis.
  3. In one table, record the per-axis means, per-axis standard deviations, and mean acceleration magnitude for each condition, and plot the 3-axis time series. Distinguish changes in the X-axis mean from changes in its standard deviation to explain the difference between offset and noise.

Results to retain

import numpy as np
rng=np.random.default_rng(7)
raw=np.array([0,0,16384])+rng.normal(0,120,size=(100,3))
biased=raw+np.array([500,0,0])
# TODO: Add conversion to g, statistics, and plots.

Record results and self-check

Condition:

Mean by axis [g]:

Standard deviation by axis [g]:

Mean vector magnitude [g]:

Points to check