Você está na página 1de 32

Tutorial 8.

Reading of MPU6050 sensor (Accelerometer and


Gyroscope) in Microcontroller of STM32F4 series.
Start Tutorial 8. Reading of MPU6050 sensor (Accelerometer and Gyroscope) in Microcontroller of
STM32F4 series.

The objective of this tutorial is to show how to configure our Ophyra


development card to read the MPU6050 sensor. This sensor is an
integrated Accelerometer and Gyroscope with I2C communication. To
demonstrate its operation we will make an example where we will send
the data read from the sensor to the RS232 port to visualize them in the
compiler terminal.

Configure Hardware using


STM32CubeMX.
The first thing we will do is the corresponding configuration of the
resources of our card in STM32CubeMX as follows:

We created a new project (Image 1) and selected the STN32F407VG


microcontroller, as we already know, which is the one corresponding to
our Ophyra card.
Image 1. New Project in STM32CubeMX.

Image 2. Selection of the microcontroller.

As already mentioned, the RS232 communication will be used to display


the information coming from the MPU6050 sensor. So we will use the
resource "USART 3", so we look for it in the left part of the "Pinout"
window, we select it and we enable it. Then, in the part where it says
"Mode" we select the "Asynchronous" option, and in the section that
says "Hardware Flow Control (RS232)" we leave it in the "Disable"
option, that is, disabled. Now we can see the pins corresponding to "TX"
and "RX", ie the corresponding pins to transmit and receive are enabled
and put green as you can see in image 3.

Image 3. Enabling the RS-232 port number 3.


The next step is to enable the I2C port number 1. The MMPU6050
sensor is connected to this port. As you know this port uses two pins or
ports to perform the communication:

 SDA: Bidirectional synchronous serial port, through which data is


transmitted from device to device.
 SCL: Synchronous data serial port, this generates a clock signal
with the speed of data transfer to the sensor.

In the section "pinout" we enable the port I2C1 and put it in "I2C" mode,
as shown in Figure 4. Also in the image seen in the microcontroller pins
ports are enabled PB7 = I2C_SDA and PB6 = I2C_SCL . These ports
are connected by default to the sensor, therefore it is not necessary to
move or rename them.

An additional device (an EEPROM memory) is also connected


to port I2C1, as detailed in table 1. Both devices have their ID or slave
identification address configured as hardware, as shown in the table. In
the I2C protocol, the ID is always sent at the beginning of a
communication between master-slave devices. These addresses are
used to control which slave device the master device will communicate
with. When a slave device recognizes its ID, it responds to the master
device through a recognition signal (acknowledgemt in English), it is at
that moment when communication is established between them.

Table 1. Devices connected to the I2C1 port of Ophyra.

If we want to use another device with I2C protocol, it will not be possible
to use the I2C1 bus , since it is not mapped to any physical pin of the
expansion ports CN1, CN2 and CN3; however the Ophyra
microcontroller has 2 additional I2C ports, which are possible to enable
(I2C2 or I2C3). We recommend reviewing the Ophyra manual in
section 5.14 Expansion ports to identify in which connector we have an
additional I2C port available.
Image 4. Enabling the I2C port and devices connected to the same
port.
Then we click on the "Configuration" tab and enter the configuration
windows of each activated resource (see image 5). In the picture 6 the
configuration window of the RS-232 protocol is observed. We make sure
that the settings are properly activated and we click on the accept
button. Now we do the same with the configuration of the I2C port.
Image 5. Buttons to select.
Image 6. Parameters of the RS-232 port and the I2C port.

In the configuration tab we find in connectivity "Conecctivity" the I2C


protocol. Clicking on this button shows some configurations:

 I2C Speed Mode: Speed mode.


 I2C Clock Speed (Hz): Speed frequency.
 Clock No Strech Mode: Mode that encourages communication
speed.
 Primary Address Length selection: Primary communication
address.
 Dual Address Acknowledge: Recognize the address.
 Primary slave address: Primary slave address.
 General Call Adreess detection: Detection of address recognition.

Image 7 . Generation of code .

Click on "Apply" and then "Ok". Now we can proceed to generate the
code, by clicking on the "Generate Source Code ..." icon, located at the
top of the main window, where the following window will be displayed:
Picture 8 . Proyect settings window .

Once in this window we proceed to configure the following parameters:


1. Project Name , a name is placed for the project, which in our case
will be Tutorial_AccGyro_Serial .
2. In Project Location , in this field you only have to make sure that
the address where your Workspace is located is located for Atollic
TrueSTUDIO, in our example the Wokspace is located in C: \
Users \ Fernando \ Atollic \ TrueSTUDIO \
ARM_workspace_7.1. Once the location is selected automatically,
the "Toolchain Folder Location" section will be filled.
3. In the Toolchain / IDE , here we must select our software that we
will use to program, that being a free Software, we will use Atollic
TrueSTUDIO, therefore we select TrueSTUDIO.
4. Select the Code Generator tab and click on the option shown in
the image.
5. By clicking on this option we configure the STM32 CubeMX to
generate the configuration files separated from
the "main" file . This step is optional and depends on the
programmer's preference.

Finally we click on "OK", and then the window that shows the generation
of the project will be displayed, in which we will click on "Open Project".

Perform program in Atollic


TrueSTUDIO.
Once STM32CubeMx opens TrueStudio, we go to the project explorer
where the current project is shown as shown in the following image. We
display the folder of our project, and in the directory "Src" we look for the
file "main.c" and we double it to be displayed in the text window.
Image 9. Selecting the "main" file.

Within the "USER CODE BEGIN Includes" section we add the directives
that are observed in image 10. The first two lines correspond to standard
C libraries, while the third line corresponds to the slave address or ID of
the MPU6050 sensor (see table 1). It should be noted that the address
0x68 is shown in table 1 and 0xD0 is shown in the image. This is so,
because the number 0x68 was previously made a shift to the left
remaining at the value of 0xD0. This shift is necessary because in the
I2C protocol, the least significant bit of the ID is used as a write / read
command. This bit is manipulated by the master device, setting it to 1
when you want to read information and 0 when you want to write to the
slave device.

Image 10. Initial directives to include in the program.

Next write the code that shows the following image.


Figure 11. Variables and sensor configuration sections.

The section marked with number 1 corresponds to the variables used to


transmit and receive data from the MPU6050 sensor.

Section 2 sends the first sensor configuration data. The data that is sent
is 0x6B and 0x00; the first is the address of the sensor configuration
record. The second data corresponds to the data to be written to the
sensor. According to the sensor specification sheet when a zero is
written to the 0x6B register, the sensor exits the standby or standby
state and begins to perform the acceleration and rotation
measurements. The instruction used to send data is:

HAL_I2C_Master_Transmit ( Arg1 , Arg2 , Arg3 , Arg4 , Arg5 );

As you can see, this instruction requires 5 parameters:

 Arg1: The I2C port with which you are working is specified.
 Arg2: Is the ID or address of the slave device.
 Arg3: Buffer or array of data to be sent to the slave device.
 Arg4: Amount of data to send .
 Arg5: Maximum waiting time.

Section 3 configures the sampling frequency of the sensor at 1KHz,


writing the data 0x07 in the internal register 0x19 of the sensor.

Now we write the code shown in figure 12. This section of code in
general reads the data coming from the Accelerometer, Gyroscope and
temperature; and sends them to the USB-Serial port, for viewing on any
serial terminal. In this particular case we will use the serial terminal that
is integrated with Atollic-TrueStudio.
Image 12. Program section to be executed in infinite while loop .

Next we will describe each section of the code:

Section 1 sends only one data (0x3B) to the sensor. This causes the
sensor to position its pointer in the 0x3B register. This register
corresponds to the most significant byte of the X axis of the
Accelerometer. The sensor data sheet specifies that all readings made
by the sensor are stored in stacked records in its internal memory. In
addition, each reading is 16 bits in length, so it uses 2 bytes for each
axis sensed. Therefore, there are 6 bytes for the Accelerometer data (ie
2 bytes for each Cartesian axis: X, Y, Z), 6 bytes for the Gyroscope data
and 2 bytes for the temperature sensor data. In total there are 14 bytes
that have to be read to obtain the complete sensor information.
Section 2 , reads the 14 bytes of information, by means of the following
instruction:

HAL_I2C_Master_Receive ( Arg1, Arg2, Arg3, Arg4, Arg5 );

As you can see, this instruction requires 5 parameters:

 Arg1: The I2C port with which you are working is specified.
 Arg2: Is the ID or address of the slave device.
 Arg3: Buffer or data array where the information coming from the
slave device is stored .
 Arg4: Amount of data to be received .
 Arg5: Maximum waiting time.

Section 3 is responsible for assembling the data in floating 32-bit


words. The first thing you do is a concatenation (at 16 bits) of the most
significant byte with the least significant byte of each acceleration axis,
temperature sensor and gyroscope. Then divide each concatenation by
a factor of sensitivity or conversion, as specified in the data sheet of the
sensor.

Section 4 is in charge of sending the obtained data to the USB-Serial


port of Ophyra, for its deployment in the serial terminal of Atollic. For
more details on sending and reading data through the serial port,
see tutorial 7 .

Finally we compile our program to generate the * .HEX file and download
it to our card. To do this, follow steps 1 to 5 of this GUIDE .

Upload program to our Ophyra


Development card.
The last step is to program your Ophyra card. If you have never done it,
follow steps 6 through 12 of this GUIDE .

Conclusions
After loading the program to the Ophyra card, we will open the terminal
of the serial port that is integrated in Atollic TRUESTUDIO. In the picture
13 the button that we must press is shown so that we will have the
terminal. Note : This button can vary from location according to the
configuration of your program, for it is necessary that you identify it well.
Image 13. Button to open the serial terminal of Atollic.

Clicking on the button will open a configuration window like the one
shown in image 14.
Image 14. Configuration window of the Atollic serial terminal.

We select the COM port corresponding to our Ophyra card, the other
parameters are not modified as this was configured by default the
Ophyra serial port; finally we click on OK. Atollic will open a window in
the lower part of the window, next to the console. In this window we will
observe the data sent by Ophyra (see image 15).

For this example, a chain of data corresponding to each reading of the


axes of the accelerometer-gyroscope and of the temperature sensor will
be observed. Accelerometer measurement units are configured
in gravities or G ; for the Gyroscope they are given in º / sec and for the
thermometer in ºC . By default the Accelerometer is configured for a
range of 2G , but can be configured for ranges of 4, 8 and
16G. Similarly, the Gyroscope is set to a sensitivity of 250 º / sec , but
can be configured for sensitivities of 500, 1000 and 2000 º / sec.

To end or close the communication with the serial port, we must press
the button that is highlighted in red in image 15.
Figure 15. Activated Atollic serial terminal. Deployment of data.
We have configured and programmed the MPU6050 sensor in Ophyra
through the I2C serial port. We also use the RS232 serial port, to
visualize the information coming from the sensor in the Atollic terminal.

We suggest you to do more complicated exercises such as the


configuration of the sensor at another sampling rate, Accelerometer
measurement range and Gyroscope sensitivity.
Amlaku yalew
Hi friends, In I wanted to present my project that I have tried using HAL libraries
only. I hope it's a useful sharing. Please do not hesitate to add your questions and
comments.
In this article, a friend asked me a question about the MPU6050 sensor related to my
project ( PICproje.org ).

Project creation phase, video description:


Let us define the variables we will use according to the project.
uint8_t TxBuffer [2];
uint8_t RxBuffer [7];
uint8_t DataBuffer [14];
int16_t DataBuffer16 [7];
uint8_t MPU6050_INT_State = 0;
int16_t gyro_x_temp, gyro_y_temp, gyro_z_temp, accel_x_temp,
accel_y_temp, accel_z_temp, temp_raw;
float temp, gyro_x, gyro_y, gyro_z, accel_x, accel_y, accel_z;
Let's define the functions we will use later.
static void Error_Handler (void);
static void MPU6050_Extract_Readings (void);
The Error_Handler () function will be a function that we can use to detect any
errors. If I detect errors in the condition (if) controls that I have created, I can direct
this function to the program and insert the program into the infinite while loop. This is
a serious help in the development phase.
The MPU6050_Extract_Readings () function converts raw data from the sensor into
its final form.
Now we write the required values to the registers required for the MPU6050 to work
as we wish. I did not write the meaning of these values, you can see what they do
easily by looking at the Register Map of the module.
TxBuffer [0] = 0x80;
HAL_I2C_Mem_Write (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_PWR_MGMT_1, 1, TxBuffer, 1, 1000);
Hal_delay (200);
TxBuffer [0] = 0x00;
HAL_I2C_Mem_Write (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_PWR_MGMT_1, 1, TxBuffer, 1, 1000);
Hal_delay (200);
TxBuffer [0] = 0xF8;
HAL_I2C_Mem_Write (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_FIFO_EN, 1, TxBuffer, 1, 1000);
Hal_delay (200);
TxBuffer [0] = 0x10;
HAL_I2C_Mem_Write (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_FIFO_EN, 1, TxBuffer, 1, 1000);
Hal_delay (200);
HAL_I2C_Mem_Read (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_ACCEL_CONFIG, I2C_MEMADD_SIZE_8BIT,
RxBuffer, 1, 1000);
Hal_delay (200);
RxBuffer [0] | = 0x18;
HAL_I2C_Mem_Write (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_ACCEL_CONFIG, 1, RxBuffer, 1, 1000);
HAL_I2C_Mem_Read (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_INT_ENABLE, I2C_MEMADD_SIZE_8BIT,
RxBuffer, 1, 1000);
Hal_delay (200);
RxBuffer [0] | = 0x11;
HAL_I2C_Mem_Write (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_INT_ENABLE, 1, RxBuffer, 1, 1000);
HAL_I2C_Mem_Read (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_INT_PIN_CFG, I2C_MEMADD_SIZE_8BIT,
RxBuffer, 1, 1000);
Hal_delay (200);
RxBuffer [0] | = 0x30;
HAL_I2C_Mem_Write (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_INT_PIN_CFG, 1, RxBuffer, 1, 1000);
HAL_I2C_Mem_Read (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_CONFIG, I2C_MEMADD_SIZE_8BIT, RxBuffer, 1,
1000);
Hal_delay (200);
RxBuffer [0] | = 0x06;
HAL_I2C_Mem_Write (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_CONFIG, 1, RxBuffer, 1, 1000);
From this point on, the processor will read and convert data continuously in the main
while loop. You can use the incoming data as desired.
/ * Infinite loop * /
/ * USER CODE BEGIN WHILE * /
while (1)
{
while (MPU6050_INT_State == 1)
{
HAL_GPIO_WritePin (GPIOD, LD4_Green_Pin, GPIO_PIN_SET);
// MPU6050_I2C_Mem_Read_Multi
(MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_ACCEL_XOUT_H, DataBuffer, 14);
HAL_I2C_Mem_Read (& hi2c1, MPU6050_DEFAULT_ADDRESS,
MPU6050_RA_ACCEL_XOUT_H, I2C_MEMADD_SIZE_8BIT,
DataBuffer, 14, 10000);
for (int i = 0; i <7; i ++)
{
DataBuffer16 [i] = (int16_t) (((uint16_t) DataBuffer [2 * i] << 8) |
DataBuffer [2 * i + 1]);
}
MPU6050_Extract_Readings ();
MPU6050_INT_State = 0;
}
HAL_GPIO_WritePin (GPIOD, LD4_Green_Pin, GPIO_PIN_RESET);
}
/ * USER CODE END WHILE * /
Our function to work when cutting occurs.
void HAL_GPIO_EXTI_Callback (uint16_t GPIO_Pin)
{
if (GPIO_Pin == GPIO_PIN_5)
{
MPU6050_INT_State = 1;
}
}
Our debugging function. (Not used in this application.)
static void Error_Handler (void)
{
while (1)
{
HAL_GPIO_TogglePin (GPIOD, LD5_Red_Pin);
Hal_delay (250);
}
}
The function in which we process raw data. In this function, the letters ar F at are
added to the end of the numbers to perform the operations with float numbers by the
FPU unit. Otherwise, the process would be done software with a floating-point
number, which would seriously slow down the program. Friends who work with
different processors should pay attention to this issue.
void MPU6050_Extract_Readings ()
{
// Extract accel readings
accel_x_temp = DataBuffer16 [0];
accel_x = (float) accel_x_temp / 2048.0F;
accel_y_temp = DataBuffer16 [1];
accel_y = (float) accel_y_temp / 2048.0F;
accel_z_temp = DataBuffer16 [2];
accel_z = (float) accel_z_temp / 2048.0F;
// Extract temperature readings
temp_raw = DataBuffer16 [3];
temp = temp_raw / 340.0F;
// Extract gyro readings
gyro_x_temp = DataBuffer16 [4];
gyro_x = (float) gyro_x_temp / 131.0F;
gyro_y_temp = DataBuffer16 [5];
gyro_y = (float) gyro_y_temp / 131.0F;
gyro_z_temp = DataBuffer16 [6];
gyro_z = (float) gyro_z_temp / 131.0F;
// Set accel offset
accel_x + = Accelx_offset;
accel_y + = Accely_offset;
accel_z + = Accelz_offset;
// Set temp offset
temp + = Temp_offset;
// Set gyro offset
gyro_x + = Gyrox_offset;
gyro_y + = Gyroy_offset;
gyro_z + = Gyroz_offset;
}
Finally, you can download the header file of the sensor including the offset map and
the offset values in our data processing function .
If you include this file at the top of your main.c file, you won't have any problems.
Good luck with.

Você também pode gostar