MPU9250-BMP280 – Giroscópio, Acelerômetro, Magnetômetro e Barômetro

MPU9250-BMP280 consiste em um módulo GY-91 altamente versátil. É equipado com os sensores Invensense MPU9250 e Bosch BMP280 em uma única placa, fornecendo 10 graus de liberdade (10DOF) no total.
O MPU9250 é um módulo de dispositivo de rastreamento de movimento de 9 eixos multi-chip que consiste em um giroscópio de 3 eixos, um acelerômetro de 3 eixos e um magnetômetro de 3 eixos AK8963 além de um sensor de temperatura integrado.
O BMP280 é um sensor de pressão barométrica absoluta especialmente projetado para aplicações móveis. Também é equipado com seu próprio sensor de temperatura assim como o que acompanha o MPU9250.

Funcionamento

MPU9250 e BMP280 compartilham o mesmo barramento de comunicação I2C. A integração com o Arduino no nível do software é muito simples, pois existem bibliotecas prontas para serem usadas. No nível de hardware, o módulo inclui um regulador de 3,3 V na placa, bem como resistores pull-up no barramento I2C.

Como sucessor do amplamente adotado BMP180, o BMP280 oferece alto desempenho em todas as aplicações que requerem medição precisa de pressão. O BMP280 opera com ruído mais baixo, suporta novos modos de filtro, tem a vantagem sobre o BMP180 de ser 63% menor e 13% mais veloz. A comunicação do BMP280 com o dispositivo é realizada usando I2C a 400kHz compartilhada com MPU9250 ou SPI a 1MHz.

Especificações Técnicas MPU9250-BMP280

    • Módulo GY-91: MPU9250 + BMP280
    • Tensão de funcionamento: 3V / 3.3V ~ 5V DC
    • Interface de comunicação: I2C e SPI
    • Comunicação compatível com 3.3V ou 5V

Sensor: MPU9250

    • Faixa do acelerômetro: ± 2g, ± 4g, ± 8g, ± 16g
    • Gama do giroscópio: ± 250Grad / seg, ± 500Grad / Sec, ± 1000Grad / seg, ± 2000Grad / Sec
    • Faixa do magnetômetro: ± 4800µT
    • Conversor AD: 16 bits (saída digital)
    • Graus de liberdade (DOF): 9

Sensor: BMP280

    • Faixa de Pressão: 300 a 1100 hPa
    • Resolução: 0,16 Pa
    • Precisão absoluta: 1 hPa
    • Medição de temperatura incluída
    • Resolução de temperatura: 0,01 °C
    • Precisão Temperatura: 1 °C
    • Frequência de amostragem: 157 Hz (máx.)
    • Regulador de tensão integrado na placa
    • Consumo de energia ultrabaixo
    • Completamente calibrado
    • Dimensões: 2,5 cm x 1,4 cm x 0,3 cm

Pinagem

    • VIN: tensão de alimentação 5V
    • 3V3: saída de 3,3V
    • GND: terra 0V
    • SCL: Clock I2C / Clock SPI
    • SDA: entrada de dados I2C Data / SPI
    • SDO / SAO: Saída de dados SPI / I2C Pino de configuração do endereço escravo
    • NCS: Chip Select para o modo SPI apenas para MPU-9250
    • CSB: Chip Select para BMP280

Simples projeto

A obtenção de dados do sensor será mostrado de forma simples e direta.

Conexão do Sensor MPU9250-BMP280 com Arduino

A conexão com o Arduino é muito simples, siga conforme o esquema abaixo:

MPU9250-BMP280 CONEXÃO ARDUINO UNO

MPU9250 BMP280 - ESQUEMA ARDUINO UNO

MPU9250-BMP280 CONEXÃO ARDUINO MEGA

MPU9250 BMP280 - ESQUEMA ARDUINO MEGA

Código

Primeiramente, devemos incluir as bibliotecas MPU9250 e BMP280. Em seguida, baixe o código para fazermos o experimento com o sensor.

OBS: Talvez seja necessário atualizar as bibliotecas. Então, sugiro atualizar todas pelo Gerenciador de Bibliotecas.

GERENCIADOR DE BIBLIOTECAS

GERENCIADOR DE BIBLIOTECAS

Calibração do MPU9250-BMP280

Feita a atualização das bibliotecas, inicialmente devemos obter os parâmetros de calibração para ser usado definitivamente no sensor.
Com o código já aberto, verifique se a função “Mxyz_init_calibrated ( )” está ativa para se iniciar o processo de calibração.

Sugestão: adquira um cabo USB com um tamanho suficiente para permitir diversos giros, um cabo de uma impressora atende muito bem.

Calibração MPU9250

Então, carregue o código no Arduino, verifique a velocidade no Monitor Serial e aguarde o reconhecimento do sensor.

#include "Wire.h"

// I2Cdev and MPU9250 must be installed as libraries, or else the .cpp/.h files
// for both classes must be in the include path of your project
#include "I2Cdev.h"
#include "MPU9250.h"

// class default I2C address is 0x68
// specific I2C addresses may be passed as a parameter here
// AD0 low = 0x68 (default for InvenSense evaluation board)
// AD0 high = 0x69
MPU9250 accelgyro;
I2Cdev   I2C_M;

uint8_t buffer_m[6];

int16_t ax, ay, az;
int16_t gx, gy, gz;
int16_t mx, my, mz;

float heading;
float tiltheading;

float Axyz[3];
float Gxyz[3];
float Mxyz[3];

#define sample_num_mdate  5000

volatile float mx_sample[3];
volatile float my_sample[3];
volatile float mz_sample[3];

static float mx_centre = 0;
static float my_centre = 0;
static float mz_centre = 0;

volatile int mx_max = 0;
volatile int my_max = 0;
volatile int mz_max = 0;

volatile int mx_min = 0;
volatile int my_min = 0;
volatile int mz_min = 0;

float temperature;
float pressure;
float atm;
float altitude;

void setup()
{
  // join I2C bus (I2Cdev library doesn't do this automatically)
  Wire.begin();

  // initialize serial communication
  // (38400 chosen because it works as well at 8MHz as it does at 16MHz, but
  // it's really up to you depending on your project)
  //Serial.begin(38400);

  Serial.begin(38400);

  // initialize device
  Serial.println("Initializing I2C devices...");
  accelgyro.initialize();

  // verify connection
  Serial.println("Testing device connections...");
  Serial.println(accelgyro.testConnection() ? "MPU9250 connection successful" : "MPU9250 connection failed");

  delay(1000);
  Serial.println("     ");

  // Mxyz_init_calibrated ();

  // Calibration parameter:
  // 11.00         12.00         -7.00

  mx_centre = 11.00;
  my_centre = 12.00;
  mz_centre = -7.00;

}


void loop()
{

  getAccel_Data();
  getGyro_Data();
  getCompassDate_calibrated(); // compass data has been calibrated here
  getHeading();               //before we use this function we should run 'getCompassDate_calibrated()' frist, so that we can get calibrated data ,then we can get correct angle .
  getTiltHeading();

  Serial.println("calibration parameter: ");
  Serial.print(mx_centre);
  Serial.print("         ");
  Serial.print(my_centre);
  Serial.print("         ");
  Serial.println(mz_centre);
  Serial.println("     ");


  Serial.println("Acceleration(g) of X,Y,Z:");
  Serial.print(Axyz[0]);
  Serial.print(",");
  Serial.print(Axyz[1]);
  Serial.print(",");
  Serial.println(Axyz[2]);
  Serial.println("Gyro(degress/s) of X,Y,Z:");
  Serial.print(Gxyz[0]);
  Serial.print(",");
  Serial.print(Gxyz[1]);
  Serial.print(",");
  Serial.println(Gxyz[2]);
  Serial.println("Compass Value of X,Y,Z:");
  Serial.print(Mxyz[0]);
  Serial.print(",");
  Serial.print(Mxyz[1]);
  Serial.print(",");
  Serial.println(Mxyz[2]);
  Serial.println("The clockwise angle between the magnetic north and X-Axis:");
  Serial.print(heading);
  Serial.println(" ");
  Serial.println("The clockwise angle between the magnetic north and the projection of the positive X-Axis in the horizontal plane:");
  Serial.println(tiltheading);
  Serial.println("   ");
  Serial.println();

  delay(1000);

}


void getHeading(void)
{
  heading = 180 * atan2(Mxyz[1], Mxyz[0]) / PI;
  if (heading < 0) heading += 360;
}

void getTiltHeading(void)
{
  float pitch = asin(-Axyz[0]);
  float roll = asin(Axyz[1] / cos(pitch));

  float xh = Mxyz[0] * cos(pitch) + Mxyz[2] * sin(pitch);
  float yh = Mxyz[0] * sin(roll) * sin(pitch) + Mxyz[1] * cos(roll) - Mxyz[2] * sin(roll) * cos(pitch);
  float zh = -Mxyz[0] * cos(roll) * sin(pitch) + Mxyz[1] * sin(roll) + Mxyz[2] * cos(roll) * cos(pitch);
  tiltheading = 180 * atan2(yh, xh) / PI;
  if (yh < 0)    tiltheading += 360;
}


void Mxyz_init_calibrated ()
{

  Serial.println(F("Before using 9DOF,we need to calibrate the compass frist,It will takes about 2 minutes."));
  Serial.print("  ");
  Serial.println(F("During  calibratting ,you should rotate and turn the 9DOF all the time within 2 minutes."));
  Serial.print("  ");
  Serial.println(F("If you are ready ,please sent a command data 'ready' to start sample and calibrate."));
  while (!Serial.find("ready"));
  Serial.println("  ");
  Serial.println("ready");
  Serial.println("Sample starting......");
  Serial.println("waiting ......");

  get_calibration_Data ();

  Serial.println("     ");
  Serial.println("compass calibration parameter ");
  Serial.print(mx_centre);
  Serial.print("     ");
  Serial.print(my_centre);
  Serial.print("     ");
  Serial.println(mz_centre);
  Serial.println("    ");
}


void get_calibration_Data ()
{
  for (int i = 0; i < sample_num_mdate; i++)
  {
    get_one_sample_date_mxyz();
    /*
      Serial.print(mx_sample[2]);
      Serial.print(" ");
      Serial.print(my_sample[2]);                            //you can see the sample data here .
      Serial.print(" ");
      Serial.println(mz_sample[2]);
    */

    if (mx_sample[2] >= mx_sample[1])mx_sample[1] = mx_sample[2];
    if (my_sample[2] >= my_sample[1])my_sample[1] = my_sample[2]; //find max value
    if (mz_sample[2] >= mz_sample[1])mz_sample[1] = mz_sample[2];

    if (mx_sample[2] <= mx_sample[0])mx_sample[0] = mx_sample[2];
    if (my_sample[2] <= my_sample[0])my_sample[0] = my_sample[2]; //find min value
    if (mz_sample[2] <= mz_sample[0])mz_sample[0] = mz_sample[2];

  }

  mx_max = mx_sample[1];
  my_max = my_sample[1];
  mz_max = mz_sample[1];

  mx_min = mx_sample[0];
  my_min = my_sample[0];
  mz_min = mz_sample[0];

  mx_centre = (mx_max + mx_min) / 2;
  my_centre = (my_max + my_min) / 2;
  mz_centre = (mz_max + mz_min) / 2;

}


void get_one_sample_date_mxyz()
{
  getCompass_Data();
  mx_sample[2] = Mxyz[0];
  my_sample[2] = Mxyz[1];
  mz_sample[2] = Mxyz[2];
}


void getAccel_Data(void)
{
  accelgyro.getMotion9(&ax, &ay, &az, &gx, &gy, &gz, &mx, &my, &mz);
  Axyz[0] = (double) ax / 16384;
  Axyz[1] = (double) ay / 16384;
  Axyz[2] = (double) az / 16384;
}


void getGyro_Data(void)
{
  accelgyro.getMotion9(&ax, &ay, &az, &gx, &gy, &gz, &mx, &my, &mz);

  Gxyz[0] = (double) gx * 250 / 32768;
  Gxyz[1] = (double) gy * 250 / 32768;
  Gxyz[2] = (double) gz * 250 / 32768;
}


void getCompass_Data(void)
{
  I2C_M.writeByte(MPU9150_RA_MAG_ADDRESS, 0x0A, 0x01); //enable the magnetometer
  delay(10);
  I2C_M.readBytes(MPU9150_RA_MAG_ADDRESS, MPU9150_RA_MAG_XOUT_L, 6, buffer_m);

  mx = ((int16_t)(buffer_m[1]) << 8) | buffer_m[0] ;
  my = ((int16_t)(buffer_m[3]) << 8) | buffer_m[2] ;
  mz = ((int16_t)(buffer_m[5]) << 8) | buffer_m[4] ;

  Mxyz[0] = (double) mx * 1200 / 4096;
  Mxyz[1] = (double) my * 1200 / 4096;
  Mxyz[2] = (double) mz * 1200 / 4096;
}

void getCompassDate_calibrated ()
{
  getCompass_Data();
  Mxyz[0] = Mxyz[0] - mx_centre;
  Mxyz[1] = Mxyz[1] - my_centre;
  Mxyz[2] = Mxyz[2] - mz_centre;
}

 

Calibração

Feito isso, execute o comando “ready”, gire e movimente o sensor até aparecer os parâmetros de calibração.

CALIBRAÇÃO MPU9250 COM BMP280

Funcionamento do MPU9250-BMP280

Então, copie parâmetros obtidos anteriormente e insira no código com as alterações.

Parâmetro de Calibração

Agora, carregue o código novamente e abra o Monitor Serial.

MPU9250

Vejam os valores apresentados do acelerômetro, giroscópio, magnetômetro e também da proa e da inclinação da proa em relação ao eixo X.
Então, percebe-se que com esse código é possível criar uma grande gama de projetos.

Aplicação com BMP280

Nesse sensor está incluído um barômetro BMP280 que com a aplicação a seguir será possível observar o seu funcionamento.
Então, inclua a biblioteca BMx280I2C.h  e carregue o código.

// BMx280_I2C.ino
//
// shows how to use the BMP280 / BMx280 library with the sensor connected using I2C.
//
// Copyright (c) 2018 Gregor Christandl
//
// connect the AS3935 to the Arduino like this:
//
// Arduino - BMP280 / BME280
// 3.3V ---- VCC
// GND ----- GND
// SDA ----- SDA
// SCL ----- SCL
// some BMP280/BME280 modules break out the CSB and SDO pins as well: 
// 5V ------ CSB (enables the I2C interface)
// GND ----- SDO (I2C Address 0x76)
// 5V ------ SDO (I2C Address 0x77)
// other pins can be left unconnected.

#include <Arduino.h>
#include <Wire.h>

#include <BMx280I2C.h>

#define I2C_ADDRESS 0x76

//create a BMx280I2C object using the I2C interface with I2C Address 0x76
BMx280I2C bmx280(I2C_ADDRESS);

void setup() {
  // put your setup code here, to run once:
	Serial.begin(38400);

	//wait for serial connection to open (only necessary on some boards)
	while (!Serial);

	Wire.begin();

	//begin() checks the Interface, reads the sensor ID (to differentiate between BMP280 and BME280)
	//and reads compensation parameters.
	if (!bmx280.begin())
	{
		Serial.println("begin() failed. check your BMx280 Interface and I2C Address.");
		while (1);
	}

	if (bmx280.isBME280())
		Serial.println("sensor is a BME280");
	else
		Serial.println("sensor is a BMP280");

	//reset sensor to default parameters.
	bmx280.resetToDefaults();

	//by default sensing is disabled and must be enabled by setting a non-zero
	//oversampling setting.
	//set an oversampling setting for pressure and temperature measurements. 
	bmx280.writeOversamplingPressure(BMx280MI::OSRS_P_x16);
	bmx280.writeOversamplingTemperature(BMx280MI::OSRS_T_x16);

	//if sensor is a BME280, set an oversampling setting for humidity measurements.
	if (bmx280.isBME280())
		bmx280.writeOversamplingHumidity(BMx280MI::OSRS_H_x16);
}

void loop() {
  // put your main code here, to run repeatedly:

	delay(1000);

	//start a measurement
	if (!bmx280.measure())
	{
		Serial.println("could not start measurement, is a measurement already running?");
		return;
	}

	//wait for the measurement to finish
	do
	{
		delay(100);
	} while (!bmx280.hasValue());

	Serial.print("Pressure: "); Serial.println(bmx280.getPressure());
	Serial.print("Pressure (64 bit): "); Serial.println(bmx280.getPressure64());
	Serial.print("Temperature: "); Serial.println(bmx280.getTemperature());

	//important: measurement data is read from the sensor in function hasValue() only. 
	//make sure to call get*() functions only after hasValue() has returned true. 
	if (bmx280.isBME280())
	{
		Serial.print("Humidity: "); 
		Serial.println(bmx280.getHumidity());
	}
}

Então, abra o Monitor Serial e observe as leituras da temperatura e pressão atmosférica.

MONITOR SERIAL BMP280

Onde comprar?

LOJAS

 

Conheça também!