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
- Use (high<<8)|low to form a 16-bit unsigned value.
- If the value is at least 2^15, subtract 2^16 to convert it to a signed value.
- Compare raw>=0x8000 and raw>0x8000 at 0x8000.
Results to retain
- A 5-row conversion table and 2 boundary value asserts.
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
- Is it within the signed range -32768~32767?
- Is 0x8000 interpreted as -32768?
Raw values and physical units
Starting conditions
Acceleration , with two sensitivity conditions: 16384 LSB/g and 8192 LSB/g. Apply 131 or 16.4 LSB/(°/s) to gyro raw=1310.
Procedure
- Calculate acceleration and angular velocity for each sensitivity condition.
- Explain why the same raw value represents a different physical quantity when the sensor settings change.
- In
MPU_Initof Week7-1_I2C_IMU_manual.ipynb, read the value written toGYRO_CONFIGand 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
- An acceleration and gyro conversion table, and 3 configuration checks.
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
- Did you avoid dividing library outputs already in g or °/s again as if they were raw values?
- Did you avoid assuming that MPU6050 and MPU9250 are the same sensor with the same conversion constants?
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
- Divide the raw arrays for both conditions by the sensitivity of 16384 LSB/g to convert them to acceleration units. Use
mean(axis=0)andstd(axis=0)on each array to calculate the mean and standard deviation for each axis. - 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.
- 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
- A table for both conditions and a 3-axis time series plot.
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
- Did you add only bias to the same noise samples?
- Did you interpret the mean and standard deviation as different metrics?