23. Chapter Attitude Sensor MPU6050
In this chapter, we will learn about a MPU6050 Attitude sensor, which integrates an Accelerometer and Gyroscope.
23.1. Project Read a MPU6050 Sensor Module
In this project, we will read Acceleration and Gyroscope Data of the MPU6050 Sensor.
23.1.1. Component List
|
Jumper Wires x4 |
MPU6050 |
|
23.1.2. Component knowledge
23.1.2.1. MPU6050
MPU6050 Sensor Module is a complete 6-axis Motion Tracking Device. It combines a 3-axis Gyroscope, a 3-axis Accelerometer and a DMP (Digital Motion Processor) all in a small package. The settings of the Accelerometer and Gyroscope of MPU6050 can be changed. A precision wide range digital temperature sensor is also integrated to compensate data readings for changes in temperature, and temperature values can also be read. The MPU6050 Module follows the I2C communication protocol and the default address is 0x68.
The port description of the MPU6050 Module is as follows:
Pin name |
Pin number |
Description |
|---|---|---|
VCC |
1 |
Positive pole of power supply with voltage 5V |
GND |
2 |
Negative pole of power supply |
SCL |
3 |
I2C communication clock pin |
SDA |
4 |
I2C communication data pin |
XDA |
5 |
I2C host data pin which can be connected to other devices. |
XCL |
6 |
I2C host clock pin which can be connected to other devices. |
AD0 |
7 |
I2C address bit control pin. Low level: the device address is 0x68 High level: the device address is 0x69 |
INT |
8 |
Output interrupt pin |
For more detail, please refer to the MPU6050 datasheet.
MPU6050 is widely used to assist with balancing vehicles, robots and aircraft, mobile phones and other products which require stability to control stability and attitude or which need to sense same.
23.1.3. Circuit
Schematic diagram
|
Hardware connection. If you need any support,please feel free to contact us via:
|
23.1.4. Sketch
In this chapter, we will learn to obtain MPU6050 data and print them.
23.1.4.1. Sketch_MPU6050
First, enter where the project is located:
$ cd ~/Freenove_Kit/Pi4j/Sketches/Sketch_23_MPU6050
Enter the command to run the code.
$ jbang MPU6050RAW.java
When the code is running, pick up the entire board with and make any movements such as shaking it left and right, turning it upside down, etc. You can observe the changes in data on the terminal interface.
Press Ctrl+C to exit the program.
You can run the following command to open the code with Geany to view and edit it.
$ geany MPU6050RAW.java
Click the icon to run the code.
If the code fails to run, please check Geany Configuration.
The following is program code:
1// Shebang line for JBang to execute this script directly
2///usr/bin/env jbang "$0" "$@" ; exit $?
3
4// Dependencies for this script
5//DEPS org.slf4j:slf4j-api:2.0.12
6//DEPS org.slf4j:slf4j-simple:2.0.12
7//DEPS com.pi4j:pi4j-core:2.7.0
8//DEPS com.pi4j:pi4j-plugin-raspberrypi:2.7.0
9//DEPS com.pi4j:pi4j-plugin-gpiod:2.7.0
10//DEPS com.pi4j:pi4j-plugin-linuxfs:2.7.0
11
12// Importing necessary Pi4J and Java libraries
13import com.pi4j.Pi4J;
14import com.pi4j.context.Context;
15import com.pi4j.io.i2c.I2C;
16import com.pi4j.io.i2c.I2CConfig;
17import com.pi4j.io.i2c.I2CConfigBuilder;
18import com.pi4j.io.i2c.I2CProvider;
19import com.pi4j.util.Console;
20
21import java.io.File;
22import java.util.ArrayList;
23import java.util.Arrays;
24
25// MPU6050 class to interface with the MPU6050 sensor
26class MPU6050 {
27 // MPU6050 Register Addresses
28 private static final byte WHO_AM_I = 0x75;
29 private static final byte SMPLRT_DIV = 0x19;
30 private static final byte CONFIG = 0x1A;
31 private static final byte GYRO_CONFIG = 0x1B;
32 private static final byte ACCEL_CONFIG = 0x1C;
33 private static final byte PWR_MGMT_1 = 0x6B;
34
35 private static final byte ACCEL_XOUT_H = 0x3B;
36 private static final byte GYRO_XOUT_H = 0x43;
37
38 private I2C i2c;
39 private int bus;
40 private int address;
41
42 // Constructor to initialize MPU6050 with bus and address
43 public MPU6050(int bus, int address) {
44 this.bus = bus;
45 this.address = address;
46 initializeI2C();
47 initializeMPU6050();
48 }
49
50 // Constructor to initialize MPU6050 with bus string and address
51 public MPU6050(String busString, int address) {
52 this.address = address;
53 try {
54 this.bus = Integer.parseInt(busString.split("i2c-")[1]);
55 } catch (Exception e) {
56 this.bus = 1;
57 }
58 initializeI2C();
59 initializeMPU6050();
60 }
61
62 // Method to initialize I2C communication
63 private void initializeI2C() {
64 Context pi4j = Pi4J.newAutoContext();
65 I2CProvider i2CProvider = pi4j.provider("linuxfs-i2c");
66 I2CConfigBuilder i2cConfigBuilder = I2C.newConfigBuilder(pi4j).bus(bus);
67 I2CConfig i2cConfig = i2cConfigBuilder.device(address).build();
68 this.i2c = i2CProvider.create(i2cConfig);
69 }
70
71 // Static method to list all I2C devices
72 public static String[] listI2CDevices() {
73 ArrayList<String> devs = new ArrayList<>();
74 File dir = new File("/dev");
75 File[] files = dir.listFiles();
76 if (files != null) {
77 for (File file : files) {
78 if (file.getName().startsWith("i2c-")) {
79 devs.add(file.getName());
80 }
81 }
82 }
83 String[] tmp = devs.toArray(new String[devs.size()]);
84 Arrays.sort(tmp);
85 return tmp;
86 }
87
88 // Method to initialize MPU6050 settings
89 private void initializeMPU6050() {
90 i2c.writeRegister(PWR_MGMT_1, 0x01);
91 i2c.writeRegister(SMPLRT_DIV, 0x00);
92 i2c.writeRegister(CONFIG, 0x00);
93 i2c.writeRegister(GYRO_CONFIG, 0x08);
94 i2c.writeRegister(ACCEL_CONFIG, 0x00);
95 }
96
97 // Method to read the WHO_AM_I register for device identification
98 public byte testWhoAmI() {
99 byte[] whoAmI = new byte[1];
100 i2c.readRegister(WHO_AM_I, whoAmI);
101 return whoAmI[0];
102 }
103
104 // Method to get raw accelerometer data
105 public int[] getRawAccel() {
106 int[] data = new int[3];
107 byte[] buffer = new byte[6];
108 i2c.readRegister(ACCEL_XOUT_H, buffer, buffer.length);
109 data[0] = (buffer[0] << 8) | (buffer[1] & 0xFF);
110 data[1] = (buffer[2] << 8) | (buffer[3] & 0xFF);
111 data[2] = (buffer[4] << 8) | (buffer[5] & 0xFF);
112 return data;
113 }
114
115 // Method to get raw gyroscope data
116 public int[] getRawGyro() {
117 int[] data = new int[3];
118 byte[] buffer = new byte[6];
119 i2c.readRegister(GYRO_XOUT_H, buffer, buffer.length);
120 data[0] = (buffer[0] << 8) | (buffer[1] & 0xFF);
121 data[1] = (buffer[2] << 8) | (buffer[3] & 0xFF);
122 data[2] = (buffer[4] << 8) | (buffer[5] & 0xFF);
123 return data;
124 }
125
126 // Method to close the I2C connection
127 public void close() {
128 i2c.close();
129 }
130}
131
132public class MPU6050RAW {
133 public static final int MPU6050_ADDRESS = 0x68;
134
135 public static void myPrintln(String format, Object... args) {
136 Console console = new Console();
137 console.println(String.format("\u001B[32m" + format + "\u001B[0m", args));
138 }
139
140 public static void main(String[] args) {
141 MPU6050 mpu = null;
142 try {
143 mpu = new MPU6050(MPU6050.listI2CDevices()[0], MPU6050_ADDRESS);
144
145 // Test WHO AM I register
146 int whoAmI = mpu.testWhoAmI();
147 myPrintln("WHO AM I: 0x%02X", whoAmI);
148 if (whoAmI == MPU6050_ADDRESS) {
149 myPrintln("MPU6050 device identified correctly.");
150 } else {
151 myPrintln("Failed to identify MPU6050 device. Got: 0x%02X", whoAmI);
152 }
153
154 while (true) {
155 int[] accel = mpu.getRawAccel();
156 int[] gyro = mpu.getRawGyro();
157 myPrintln("a/g: %8d %8d %8d %8d %10d %10d",
158 accel[0], accel[1], accel[2], gyro[0], gyro[1], gyro[2]);
159 myPrintln("a/g: %.2f g %.2f g %.2f g %.2f d/s %.2f d/s %.2f d/s\n",
160 (float)accel[0]/16384, (float)accel[1]/16384, (float)accel[2]/16384,
161 (float)gyro[0]/131, (float)gyro[1]/131, (float)gyro[2]/131);
162 Thread.sleep(300);
163 }
164 } catch (InterruptedException e) {
165 e.printStackTrace();
166 Thread.currentThread().interrupt();
167 } finally {
168 if (mpu != null) {
169 mpu.close();
170 }
171 }
172 }
173}
Define the commonly used registers of MPU6050.
1private static final byte WHO_AM_I = 0x75;
2private static final byte SMPLRT_DIV = 0x19;
3private static final byte CONFIG = 0x1A;
4private static final byte GYRO_CONFIG = 0x1B;
5private static final byte ACCEL_CONFIG = 0x1C;
6private static final byte PWR_MGMT_1 = 0x6B;
7
8private static final byte ACCEL_XOUT_H = 0x3B;
9private static final byte GYRO_XOUT_H = 0x43;
Initialize the I2C interface of the Raspberry Pi.
1private void initializeI2C() {
2 Context pi4j = Pi4J.newAutoContext();
3 I2CProvider i2CProvider = pi4j.provider("linuxfs-i2c");
4 I2CConfigBuilder i2cConfigBuilder = I2C.newConfigBuilder(pi4j).bus(bus);
5 I2CConfig i2cConfig = i2cConfigBuilder.device(address).build();
6 this.i2c = i2CProvider.create(i2cConfig);
7}
Configure MPU6050 so that it can work properly.
1private void initializeMPU6050() {
2 i2c.writeRegister(PWR_MGMT_1, 0x01);
3 i2c.writeRegister(SMPLRT_DIV, 0x00);
4 i2c.writeRegister(CONFIG, 0x00);
5 i2c.writeRegister(GYRO_CONFIG, 0x08);
6 i2c.writeRegister(ACCEL_CONFIG, 0x00);
7}
Get the I2C address of MPU6050. This is only used for testing.
1public byte testWhoAmI() {
2 byte[] whoAmI = new byte[1];
3 i2c.readRegister(WHO_AM_I, whoAmI);
4 return whoAmI[0];
5}
Get raw acceleration data.
1public int[] getRawAccel() {
2 int[] data = new int[3];
3 byte[] buffer = new byte[6];
4 i2c.readRegister(ACCEL_XOUT_H, buffer, buffer.length);
5 data[0] = (buffer[0] << 8) | (buffer[1] & 0xFF);
6 data[1] = (buffer[2] << 8) | (buffer[3] & 0xFF);
7 data[2] = (buffer[4] << 8) | (buffer[5] & 0xFF);
8 return data;
9}
Get raw gyroscope data.
1public int[] getRawGyro() {
2 int[] data = new int[3];
3 byte[] buffer = new byte[6];
4 i2c.readRegister(GYRO_XOUT_H, buffer, buffer.length);
5 data[0] = (buffer[0] << 8) | (buffer[1] & 0xFF);
6 data[1] = (buffer[2] << 8) | (buffer[3] & 0xFF);
7 data[2] = (buffer[4] << 8) | (buffer[5] & 0xFF);
8 return data;
9}
Define the I2C address of MPU6050.
public static final int MPU6050_ADDRESS = 0x68;
Get the I2C address from the MPU6050 register and determine whether it is consistent with the predefined address.
1// Test WHO AM I register
2int whoAmI = mpu.testWhoAmI();
3myPrintln("WHO AM I: 0x%02X", whoAmI);
4if (whoAmI == MPU6050_ADDRESS) {
5 myPrintln("MPU6050 device identified correctly.");
6} else {
7 myPrintln("Failed to identify MPU6050 device. Got: 0x%02X", whoAmI);
8}
Get the raw data of the accelerometer and gyroscope of MPU6050, convert them and print them out.
1while (true) {
2 int[] accel = mpu.getRawAccel();
3 int[] gyro = mpu.getRawGyro();
4 myPrintln("a/g: %8d %8d %8d %8d %10d %10d",
5 accel[0], accel[1], accel[2], gyro[0], gyro[1], gyro[2]);
6 myPrintln("a/g: %.2f g %.2f g %.2f g %.2f d/s %.2f d/s %.2f d/s\n",
7 (float)accel[0]/16384, (float)accel[1]/16384, (float)accel[2]/16384,
8 (float)gyro[0]/131, (float)gyro[1]/131, (float)gyro[2]/131);
9 Thread.sleep(300);
10}
Thread exception capture ensures that the code runs normally.
1catch (InterruptedException e) {
2 e.printStackTrace();
3 Thread.currentThread().interrupt();
4}
When terminating the execution of the code, shut down the MPU6050 device and disable the I2C functionality on the Raspberry Pi.
1finally {
2 if (mpu != null) {
3 mpu.close();
4 }
5}



