i2c Interfacing¶
References¶
The code for interfacing with the sensor over i2c was largely taken from this article by Joshua Hrisko.
Source Code for joystick_reader
Spec Sheets
How it’s implemented¶
Two modules define classes which interface with the sensor. mpu9250_i2c
collects the raw data. joystick_reader
stores and averages sensor data over time and makes it available to the Blender addon when needed.
The sensor uses inter-integrated circuit, or “i squared c” to communicate with the Raspberry Pi. I2C consists of two wires; the SDA (Serial data line) and SCL (Serial clock line) and pull up resistors which keep those lines high until pulled low. The SCL switches between high and low at a fixed rate. Based on the offset between the highs and lows of the SCL line and highs and lows of the SDA line, I2C devices can interpret bit data. i2C transfers data grouped into 8 bits (1 byte). The first byte of the transfer is always the address of the receiving device so more than one device can be connected at a time, except for the last bit, which indicates whether the master device should write (0) or read (1) bits from the slave device.
The next address of a transfer is the address of the internal register of the receiving I2C device. This is generally followed with data to write starting at that location.
mpu9250_i2c
handles the I2C communication in this project. It initializes the accelerometer by transmitting bytes to appropriate registers to reset it to a standard mode with the mpu9250_i2c.MPU6050_start()
function. This tells the sensor, among other things, to sample the gyroscope at 250 degrees per second.
As the blender addon thread loops, mpu9250_i2c.mpu6050_conv()
is called regularly. This function uses mpu9250_i2c.read_raw_bits()
to extract bits from the registers in the mpu9250 where sensor readings are stored. It actually extracts one byte from the specified register and then extracts the byte from the subsequent register. Those two bytes, the high byte and the low byte, together form the reading for that sensor. Each reading is converted to degrees and adjusted based on the sensitivity setting of the sensor (250 degrees per second).
The JoystickReader
class is used to interface between the blender addon and the mpu9250 conversion module. JoystickReader contains an instance of Axis
for each of the 3 acceleration sensors and each of the 3 gyroscope sensors, 6 total. JoystickReader collects values from mpu6050_conv and passes them to the Axis objects. The Axis objects keep running averages of recently read values based on their settings. JoystickReader also tracks what GPIO pins the trigger button and the top button of the Joystick are wired to. It sets up the GPIO system using the RPi.GPIO library.
When JoystickReader.get_averages
is called by the blender addon, JoystickReader retrieves the current average (or the last read, if that setting is selected) from each Axis. JoystickReader also determines whether the GPIO lines that the trigger and top are wired to are high or low. JoystickReader then assembles that in a dictionary and returns it for use by the Blender addon.
return {
'ax':self.acceleration_x.average,
'ay':self.acceleration_y.average,
'az':self.acceleration_z.average,
'wx':self.gyro_x.average,
'wy':self.gyro_y.average,
'wz':self.gyro_z.average,
'top': GPIO.input(self.top_pin),
'trigger': GPIO.input(self.trigger_pin)
}
MPU9250_i2c¶
This module interfaces directly with the sensor.
This code was largely taken from this article by Joshua Hrisko.
-
mpu9250_i2c.
MPU6050_start
()[source]¶ This function initializes the sensor in the following manner:
Set the sample rate div to zero (no change in the sample rate.)
Set the power management register to all zeros, with the following effects:
Set to not sleep mode.
Set to normal sample mode.
Set to normal gyro power mode.
Set to normal voltage generator mode.
Set to default clock speed.
Write the power management register again, to reset internal registers.
Write the config register with all zeros, with the following effects:
Set FIFO mode to normal.
Set FSYNC to normal.
Set DLPF_CFG to normal.
Write all zeros to the GYRO_CONFIG register with the following effects:
Set sample rate to 250 degrees/second
Do not bypass DPLF
Write all zeros to the ACCEL_CONFIG register, setting the accel sample rate to +- 2g/second.
Write a 1 to INT_ENABLE register, to enable interrupt when sensor gets any reading.
- Returns
A tuple of (gyro sample rate, acceleration sample rate)
- Return type
-
mpu9250_i2c.
read_raw_bits
(register)[source]¶ This reads the raw bits at a high sensor register and the raw bits at the subsequent register (the low byte). It combines those value to get the total read for the sensor.
- Parameters
register (byte) – The high byte of a sensor read register.
- Returns
The sensor reading, 16 bits.
- Return type
-
mpu9250_i2c.
mpu6050_conv
()[source]¶ Gets the sensor readings for each register by calling
read_raw_bits()
for each sensor register.Converts those readings to floats of the appropriate magnitude by multiplying by the quantity per second that the sensor is set to.
- Returns
A tuple of (ax, ay, az, wx, wy, wz)
- Return type
-
mpu9250_i2c.
MPU6050_ADDR
= 104¶ The i2c address of the sensor, which is 104.
-
mpu9250_i2c.
PWR_MGMT_1
= 107¶ Power management register
¶ Bit
Name
Description
7
H_RESET
1 resets internal registers and restores default. Auto clears.
6
SLEEP
Sets chip to sleep mode.
5
CYCLE
Sets chip to a single sample mode. (Not used)
4
GYRO_STANDBY
Lower power mode for Gyros.
3
PD_PTAT
Power done internal PTAT voltage generator. (Not used)
2-0
CLKSEL
Selects clock speed.
-
mpu9250_i2c.
SMPLRT_DIV
= 25¶ Sample Rate Divider register.
Internal sample rate divided by this number to generate the final sample rate.
¶ Bit
Name
Description
7-0
SMPLRT_DIV
Sample Rate Divider
Final Sample Rate = Internal_Sample_Rate / (1 + SMPLRT_DIV)
-
mpu9250_i2c.
CONFIG
= 26¶ Configuration.
¶ Bit
Name
Description
7
reserved
6
FIFO_MODE
1 means additional writes will not be added to fifo
5-3
EXT_SYNC_SET
Enables FSYNC pin data to be sampled for short strobes
2-0
DLPF_CFG”
Not used
-
mpu9250_i2c.
GYRO_CONFIG
= 27¶ Gyroscope configuration
¶ Bit
Name
Description
7
XGYRO_Cten
X Gyro Self Test
6
YGYRO_Cten
Y Gyro Self Test
5
ZGYRO_Cten
Z Gyro Self Test
4-3
GYRO_FS_SEL
Sets Gyro sample rate
2
reserved
1
Fchoice_b
Bypass dplf - not used
- GYRO_FS_SEL sample rates are:
00 = +250 degrees/second
01 = +500 degrees/second
10 = +1000 degrees/second
11 = +2000 degrees/second
-
mpu9250_i2c.
ACCEL_CONFIG
= 28¶ Accelerometer configuration
¶ Bit
Name
Description
7
ax_st_en
X Accel Self Test
6
ay_st_en
Y Accel Self Test
5
az_st_en
Z Accel Self Test
4-3
ACCEL_FS_SEL
Sets Accel Sample rate
2-0
reserved
- ACCEL_FS_SEL sample rates are:
00 = +-2 g/second
01 = +-4 g/second
10 = +-8 g/second
11 = +-16 g/second
-
mpu9250_i2c.
INT_ENABLE
= 56¶ Interrupt Enable
¶ Bit
Name
Description
7
WOM_EN
1 - enable interrupt for wake on motion
6
reserved
5
FIFO_OVERFLOW_EN
1 - enable interrupt fifo overflow
4
FSYNC_INT_EN
1 - enable fsync interrupt
3
reserved
2
reserved
1
RAW_RDY_EN
1 - enable raw sensor data ready interrupt
-
mpu9250_i2c.
ACCEL_XOUT_H
= 59¶ X-Accelerometer High Byte
-
mpu9250_i2c.
ACCEL_YOUT_H
= 61¶ Y-Accelerometer High Byte
-
mpu9250_i2c.
ACCEL_ZOUT_H
= 63¶ Z-Accelerometer High Byte
-
mpu9250_i2c.
GYRO_XOUT_H
= 67¶ X-Gyro High Byte
-
mpu9250_i2c.
GYRO_YOUT_H
= 69¶ Y-Gyro High Byte
-
mpu9250_i2c.
GYRO_ZOUT_H
= 71¶ Z-Gyro High Byte
-
mpu9250_i2c.
bus
= None¶ bus is initialized to smbus
- Type
-
mpu9250_i2c.
gyro_sens
= 250¶ set to returned value from
MPU6050_start()
, which is 250 degrees per second
-
mpu9250_i2c.
accel_sens
= 2¶ set to returned value from
MPU6050_start()
, which is 2 Gs per second
joystick_reader¶
Interfaces with the mpu9250_i2c.py script. JoystickReader
retrieves values from that script, and stores them in Axis
objects.
The Axis objects average values as they come in based on their parameters.
When the Blender addon needs readings, JoystickReader collects the averages from each Axis and returns them as a dictionary.
-
class
joystick_reader.
Axis
(name, keep_vals=10, weight=0)[source]¶ Stores rolling average of recorded values for an axis.
- Parameters
-
name
¶ name of the axis
-
vals
¶ last few values recorded
-
average
¶ current average
-
keep_vals
¶ number of values to keep
-
weight
¶ weights the last reading
-
class
joystick_reader.
JoystickReader
(trigger_pin, top_pin, keepvals=10, weight=0)[source]¶ Interfaces with sensor and updates axis objects with readings.
- Parameters
trigger_pin (int) – The raspberry Pi GPIO pin that the trigger button is wired to.
top_pin (int) – The raspberry Pi GPIO pin that the top button is wired to.
keep_vals (int) – The number of sensor readings each axes will store for averaging.
weight (float) – The factor by which each axis will weight the last-read sensor value.
-
axes
¶ A list of the used axes.
Includes self.acceleration_x, self.acceleration_y, self.acceleration_z, self.gyro_x, self.gyro_y, and self.gyro_z
- Ref
joystick_reader.Axis
- Type
-
load_pins
(trigger_pin, top_pin)[source]¶ Change the RPi.GPIO pins for the top and trigger line.
Turns off input detection for previously active pins.
-
load_keep_vals_and_weight
(new_keep_vals, new_weight)[source]¶ Changes retained values length and last value weighting for all axes.
-
get_round_of_random_values
()[source]¶ Adds a value between -5 and 5 to each Axis.
Used for debugging Blender addon outside of Raspberry Pi environment.
-
get_vals_from_sensor
()[source]¶ Gets values from
mpu9250_i2c.py
, which interfaces with the sensor.Passes sensor reads to appropriate Axis object.
If sensor fails to read, sets global error flag.