08 setembro 2014

Sensor GY-80 - Acelerômetro Giroscópio Magnetômetro e Barômetro

Quatro sensores em uma mesma placa : acelerômetro, giroscópio, magnetômetro e barômetro. Esse é o sensor GY-80, um multi-sensor conhecido como IMU (Inertial Measurement Unit), que reúne numa mesma placa vários dispositivos de medição.

GY-80 acelerometro giroscopio magnetometro barometro

As funções dessa placa são controladas por 4 CIs, cada um com sua função específica :

  • L3G4200D (3-Axis Angular Rate Sensor) - Giroscópio 3 eixos
  • ADXL345 (3-Axis Digital Accelerometer) - Acelerômetro 3 eixos
  • HMC5883L (3-Axis Digital Compass) - Bússola digital / Magnetômetro
  • BMP085 (Barometric Pressure Sensor) - Sensor de temperatura e pressão

A comunicação com o Arduino é feita pela interface I2C, e todos os sensores citados acima são endereçados individualmente. A ligação básica ao Arduino utiliza somente 4 pinos, dos 10 disponíveis no módulo. Observe que você pode alimentar o módulo tanto com 5v como com 3.3v :

GY-80 Pinagem

  • VCC_IN - Utilize este pino para alimentar o sensor com 5v
  • VCC_3.3V - Utilize este pino para alimentar o sensor com 3.3v
  • GND - Conectado ao GND do Arduino
  • SCL - Conectado ao pino analógico A5 do Arduino Uno (ou pino 21 do Arduino Mega)
  • SDA - Conectado ao pino analógico A4 do Arduino Uno (ou pino 20 do Arduino Mega)

Conectando o GY-80 ao Arduino

Vamos mostrar como utilizar separadamente cada sensor ligando-o ao Arduino Uno . Como todos eles utilizam o mesmo barramento I2C, teremos apenas um circuito para todos os programas exemplo : 

Circuito GY-80 e Arduino Uno R3
 
A primeira coisa que você vai notar é que ao alimentar o módulo não há nenhuma indicação de que ele está ligado. A placa não possui nenhum led , logo vamos utilizar um programa chamado I2C Scanner (http://playground.arduino.cc/Main/I2cScanner) para efetuar um rastreamento no barramento I2C e garantir que o módulo esteja adequadamente ligado ao Arduino. Carregue o I2C Scanner :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
// --------------------------------------
// i2c_scanner
//
// Version 1
//    This program (or code that looks like it)
//    can be found in many places.
//    For example on the Arduino.cc forum.
//    The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
//     Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26  2013
//    V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
//    by Arduino.cc user Krodal.
//    Changes by louarnold removed.
//    Scanning addresses changed from 0...127 to 1...119,
//    according to the i2c scanner by Nick Gammon
//    http://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
//    As version 4, but address scans now to 127.
//    A sensor seems to use address 120.
// 
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//

#include <Wire.h>


void setup()
{
  Wire.begin();

  Serial.begin(9600);
  Serial.println("\nI2C Scanner");
}


void loop()
{
  byte error, address;
  int nDevices;

  Serial.println("Scanning...");

  nDevices = 0;
  for(address = 1; address < 127; address++ ) 
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire.beginTransmission(address);
    error = Wire.endTransmission();

    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");

      nDevices++;
    }
    else if (error==4) 
    {
      Serial.print("Unknow error at address 0x");
      if (address<16) 
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");

  delay(5000);           // wait 5 seconds for next scan
}

Se as conexões estiverem corretas, ao abrir o serial monitor você terá a seguinte tela, mostrando os endereços dos dispositivos detectados :

I2C Scanner - Serial Monitor

O I2C Scanner é um programa que serve não apenas para este módulo, mas também para qualquer outro dispositivo I2C conectado ao barramento.  Tenha este programa sempre à mão para descobrir o endereço do dispositivo ou simplesmente para verificar se ele está se comunicando com o Arduino.

L3G4200D - Giroscópio 3 eixos

O primeiro programa é para o L3G4200D (datasheet), ou seja, o Giroscópio de 3 eixos do GY-80, cujo endereço I2C é 0x69 (ou 150 em decimal). Carregue o seguinte programa no Arduino :

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
// Programa : Teste Giroscopio L3G4200D
// Adaptacoes : Arduino e Cia

#include <Wire.h>

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
#define CTRL_REG5 0x24

//Endereco I2C do L3G4200D
int L3G4200D_Address = 105;

int x;
int y;
int z;

void setup()
{
  Wire.begin();
  Serial.begin(9600);

  Serial.println("Inicializando o L3G4200D");
  // Configura o L3G4200 para 200, 500 ou 2000 graus/seg
  setupL3G4200D(2000); 

  // Aguarda a resposta do sensor
  delay(1500); 
}

void loop()
{
  // Atualiza os valores de X, Y e Z
  getGyroValues();  

  // Mostra os valores no serial monitor
  Serial.print("X:");
  Serial.print(x);

  Serial.print(" Y:");
  Serial.print(y);

  Serial.print(" Z:");
  Serial.println(z);

  // Aguarda 100ms e reinicia o processo
  delay(100);
}

void getGyroValues()
{
  // Rotina para leitura dos valores de X, Y e Z
  byte xMSB = readRegister(L3G4200D_Address, 0x29);
  byte xLSB = readRegister(L3G4200D_Address, 0x28);
  x = ((xMSB << 8) | xLSB);

  byte yMSB = readRegister(L3G4200D_Address, 0x2B);
  byte yLSB = readRegister(L3G4200D_Address, 0x2A);
  y = ((yMSB << 8) | yLSB);

  byte zMSB = readRegister(L3G4200D_Address, 0x2D);
  byte zLSB = readRegister(L3G4200D_Address, 0x2C);
  z = ((zMSB << 8) | zLSB);
}

int setupL3G4200D(int scale)
{
  //From  Jim Lindblom of Sparkfun's code

  // Enable x, y, z and turn off power down:
  writeRegister(L3G4200D_Address, CTRL_REG1, 0b00001111);

  // If you'd like to adjust/use the HPF, you can edit the line below to configure CTRL_REG2:
  writeRegister(L3G4200D_Address, CTRL_REG2, 0b00000000);

  // Configure CTRL_REG3 to generate data ready interrupt on INT2
  // No interrupts used on INT1, if you'd like to configure INT1
  // or INT2 otherwise, consult the datasheet:
  writeRegister(L3G4200D_Address, CTRL_REG3, 0b00001000);

  // CTRL_REG4 controls the full-scale range, among other things:
  if(scale == 250){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0b00000000);
  }else if(scale == 500){
    writeRegister(L3G4200D_Address, CTRL_REG4, 0b00010000);
  }else{
    writeRegister(L3G4200D_Address, CTRL_REG4, 0b00110000);
  }

  // CTRL_REG5 controls high-pass filtering of outputs, use it
  // if you'd like:
  writeRegister(L3G4200D_Address, CTRL_REG5, 0b00000000);
}

void writeRegister(int deviceAddress, byte address, byte val) 
{
    Wire.beginTransmission(deviceAddress); // start transmission to device 
    Wire.write(address);       // send register address
    Wire.write(val);         // send value to write
    Wire.endTransmission();     // end transmission
}

int readRegister(int deviceAddress, byte address)
{
    int v;
    Wire.beginTransmission(deviceAddress);
    Wire.write(address); // register to read
    Wire.endTransmission();

    Wire.requestFrom(deviceAddress, 1); // read a byte

    while(!Wire.available()) 
    {
        // waiting
    }
    v = Wire.read();
    return v;
}

Abra o serial monitor para verificar a velocidade angular dos eixos X, Y e Z (em graus/s). Os valores são atualizados a cada 100ms :

Dados L3G4200D - Serial Monitor


ADXL345 - Acelerômetro 3 eixos

O acelerômetro é muito popular hoje em dia graças à sua utilização nos telefones celulares. É através do acelerômetro que o seu celular detecta a posição do aparelho e permite que você passe horas naquele joguinho de corrida sem apertar nenhum botão, apenas movimentando o aparelho. :)

Utilize o programa abaixo para testar o ADXL345 (datasheet), cujo endereço I2C é 0x53 (ou 83 em decimal) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// Programa : Teste acelerometro ADXL345
// Adaptacoes : Arduino e Cia

#include <Wire.h>

#define Register_ID 0
#define Register_2D 0x2D
#define Register_X0 0x32
#define Register_X1 0x33
#define Register_Y0 0x34
#define Register_Y1 0x35
#define Register_Z0 0x36
#define Register_Z1 0x37

// Endereco I2C do sensor : 83 em decimal ou 0x53
int ADXAddress = 0x53;  // the default 7-bit slave address
int reading = 0;
int val=0;
int X0,X1,X_out;
int Y0,Y1,Y_out;
int Z1,Z0,Z_out;
double Xg,Yg,Zg;

void setup()
{
  Wire.begin();                
  Serial.begin(9600);    
  delay(100);
  // enable to measute g data
  Wire.beginTransmission(ADXAddress);
  Wire.write(Register_2D);
  Wire.write(8);                //measuring enable
  Wire.endTransmission();     // stop transmitting
}

void loop()
{
  //--------------X
  Wire.beginTransmission(ADXAddress); // transmit to device
  Wire.write(Register_X0);
  Wire.write(Register_X1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress,2); 
  if(Wire.available()<=2)   
  {
    X0 = Wire.read();
    X1 = Wire.read(); 
    X1=X1<<8;
    X_out=X0+X1;   
  }

  //------------------Y
  Wire.beginTransmission(ADXAddress); // transmit to device
  Wire.write(Register_Y0);
  Wire.write(Register_Y1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress,2); 
  if(Wire.available()<=2)   
  {
    Y0 = Wire.read();
    Y1 = Wire.read(); 
    Y1=Y1<<8;
    Y_out=Y0+Y1;
  }
  //------------------Z
  Wire.beginTransmission(ADXAddress); // transmit to device
  Wire.write(Register_Z0);
  Wire.write(Register_Z1);
  Wire.endTransmission();
  Wire.requestFrom(ADXAddress,2); 
  if(Wire.available()<=2)   
  {
    Z0 = Wire.read();
    Z1 = Wire.read(); 
    Z1=Z1<<8;
    Z_out=Z0+Z1;
  }
  //
  Xg=X_out/256.0;
  Yg=Y_out/256.0;
  Zg=Z_out/256.0;
  Serial.print("X= ");
  Serial.print(Xg);
  Serial.print("       ");
  Serial.print("Y= ");
  Serial.print(Yg);
  Serial.print("       ");
  Serial.print("Z= ");
  Serial.print(Zg);
  Serial.println("  ");
  delay(200);
}

Movimente o sensor e observe a variação dos eixos X, Y e Z no serial monitor :

Dados ADXL345 - Serial Monitor


HMC5883L - Bússola digital

O HMC5883L (datasheet) é o nosso magnetômetro de 3 eixos, um instrumento usado para mediar a intensidade, direção e sentido de campos magnéticos. É com ele que podemos montar uma bússola com o Arduino, utilizando como base o programa abaixo, que mostra os valores correspondentes aos eixos X, Y e Z. O endereço I2C do sensor é 0x1E (30 em decimal) :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// Programa : Teste HMC5883L - Bussola
// Adaptacoes : Arduino e Cia

#include <Wire.h>

// Define o endereco do HMC5883 - 0x1E ou 30 em decimal
#define address 0x1E 

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  
  // Inicializa o HMC5883
  Wire.beginTransmission(address);
  // Seleciona o modo
  Wire.write(0x02); 
  // Modo de medicao continuo
  Wire.write(0x00); 
  Wire.endTransmission();
}

void loop()
{
  int x,y,z; //triple axis data
  
  // Indica ao HMC5883 para iniciar a leitura
  Wire.beginTransmission(address);
  Wire.write(0x03); //select register 3, X MSB register
  Wire.endTransmission();
 
  // Le os dados de cada eixo, 2 registradores por eixo
  Wire.requestFrom(address, 6);
  if(6<=Wire.available())
  {
    x = Wire.read()<<8; //X msb
    x |= Wire.read(); //X lsb
    z = Wire.read()<<8; //Z msb
    z |= Wire.read(); //Z lsb
    y = Wire.read()<<8; //Y msb
    y |= Wire.read(); //Y lsb
  }
  
  // Imprime os vaores no serial monitor
  Serial.print("x: ");
  Serial.print(x);
  Serial.print("  y: ");
  Serial.print(y);
  Serial.print("  z: ");
  Serial.println(z);
  
  delay(250);
}

Da mesma forma que o acelerometro e o giroscópio, os valores são mostrados no serial :

Dados HMC5883L - Serial Monitor


BMP085 - Sensor de temperatura e pressão

O último sensor é o BMP085 (datasheet), do qual já falamos nesse artigo aqui no Arduino e Cia. Com ele podemos obter os valores da temperatura ambiente e da pressão, entre outras informações:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
// Programa : Teste BMP085 - Barometro / temperatura
// Adaptacoes : Arduino e Cia

/*Based largely on code by  Jim Lindblom
 Get pressure, altitude, and temperature from the BMP085.
 Serial.print it out at 9600 baud to serial monitor.
*/

#include <Wire.h>

//Define o endereco I2C do BMP085 - 0x77 ou 119 em decimal
#define BMP085_ADDRESS 0x77  

const unsigned char OSS = 0;  // Oversampling Setting

// Calibration values
int ac1;
int ac2;
int ac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
int b2;
int mb;
int mc;
int md;

// b5 is calculated in bmp085GetTemperature(...), this 
// variable is also used in bmp085GetPressure(...)
// so ...Temperature(...) must be called before ...Pressure(...).
long b5; 

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  // Inicializa o BMP085
  bmp085Calibration();
}

void loop()
{
  // Chama a rotina que calcula a temperatura
  // Esta rotina DEVE ser executada primeiro
  float temperature = bmp085GetTemperature(bmp085ReadUT());
  // Chama a rotina que calcula a pressao
  float pressure = bmp085GetPressure(bmp085ReadUP());
  // Chama a rotina que calcula atmosfera
  float atm = pressure / 101325; 
  // Chama a rotina que calcula a altitude
  float altitude = calcAltitude(pressure); 

  Serial.print("Temperatura: ");
  // Mostra a temperatura com 2 casas decimais
  Serial.print(temperature, 2); 
  Serial.println(" C");

  Serial.print("Pressao: ");
  Serial.print(pressure, 0); 
  Serial.println(" Pa");

  Serial.print("Atmosfera padrao : ");
  // Mostra o valor com 4 casas decimais
  Serial.println(atm, 4); //display 4 decimal places

  Serial.print("Altitude: ");
  // Mostra o valor com 2 casas decimais
  Serial.print(altitude, 2); 
  Serial.println(" M");

  Serial.println();

  //Aguarda 5 segundos e reinicia o processo
  delay(5000);
}

// Armazena todos os valores de calibracao do BMP085 em 
// variaveis globais. Valores de calibracao sao exigidos para
// calcular temperatura e pressao
// Esta funcao deve ser chamada/acionada no inicio do programa
void bmp085Calibration()
{
  ac1 = bmp085ReadInt(0xAA);
  ac2 = bmp085ReadInt(0xAC);
  ac3 = bmp085ReadInt(0xAE);
  ac4 = bmp085ReadInt(0xB0);
  ac5 = bmp085ReadInt(0xB2);
  ac6 = bmp085ReadInt(0xB4);
  b1 = bmp085ReadInt(0xB6);
  b2 = bmp085ReadInt(0xB8);
  mb = bmp085ReadInt(0xBA);
  mc = bmp085ReadInt(0xBC);
  md = bmp085ReadInt(0xBE);
}

// Calcula a temperatura em graus C
float bmp085GetTemperature(unsigned int ut)
{
  long x1, x2;

  x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
  x2 = ((long)mc << 11)/(x1 + md);
  b5 = x1 + x2;

  float temp = ((b5 + 8)>>4);
  temp = temp /10;

  return temp;
}

// Calcula a pressao. Os valores de calibracao devem ser conhecidos
// b5 tambem eh exigido, logo a funcao bmp085GetTemperature(...) deve
// ser executada primeiro.
// Funcao retorna pressao em unidades de Pa
long bmp085GetPressure(unsigned long up){
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;

  b6 = b5 - 4000;
  // Calcula B3
  x1 = (b2 * (b6 * b6)>>12)>>11;
  x2 = (ac2 * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;

  // Calcula B4
  x1 = (ac3 * b6)>>13;
  x2 = (b1 * ((b6 * b6)>>12))>>16;
  x3 = ((x1 + x2) + 2)>>2;
  b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;

  b7 = ((unsigned long)(up - b3) * (50000>>OSS));
  if (b7 < 0x80000000)
    p = (b7<<1)/b4;
  else
    p = (b7/b4)<<1;

  x1 = (p>>8) * (p>>8);
  x1 = (x1 * 3038)>>16;
  x2 = (-7357 * p)>>16;
  p += (x1 + x2 + 3791)>>4;

  long temp = p;
  return temp;
}

// Read 1 byte from the BMP085 at 'address'
char bmp085Read(unsigned char address)
{
  unsigned char data;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 1);
  while(!Wire.available())
    ;

  return Wire.read();
}

// Read 2 bytes from the BMP085
// First byte will be from 'address'
// Second byte will be from 'address'+1
int bmp085ReadInt(unsigned char address)
{
  unsigned char msb, lsb;

  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 2);
  while(Wire.available()<2)
    ;
  msb = Wire.read();
  lsb = Wire.read();

  return (int) msb<<8 | lsb;
}

// Read the uncompensated temperature value
unsigned int bmp085ReadUT(){
  unsigned int ut;

  // Write 0x2E into Register 0xF4
  // This requests a temperature reading
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x2E);
  Wire.endTransmission();

  // Wait at least 4.5ms
  delay(5);

  // Read two bytes from registers 0xF6 and 0xF7
  ut = bmp085ReadInt(0xF6);
  return ut;
}

// Read the uncompensated pressure value
unsigned long bmp085ReadUP(){

  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;

  // Write 0x34+(OSS<<6) into register 0xF4
  // Request a pressure reading w/ oversampling setting
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x34 + (OSS<<6));
  Wire.endTransmission();

  // Wait for conversion, delay time dependent on OSS
  delay(2 + (3<<OSS));

  // Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
  msb = bmp085Read(0xF6);
  lsb = bmp085Read(0xF7);
  xlsb = bmp085Read(0xF8);

  up = (((unsigned long) msb << 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);

  return up;
}

void writeRegister(int deviceAddress, byte address, byte val) {
  Wire.beginTransmission(deviceAddress); // start transmission to device 
  Wire.write(address);       // send register address
  Wire.write(val);         // send value to write
  Wire.endTransmission();     // end transmission
}

int readRegister(int deviceAddress, byte address){

  int v;
  Wire.beginTransmission(deviceAddress);
  Wire.write(address); // register to read
  Wire.endTransmission();

  Wire.requestFrom(deviceAddress, 1); // read a byte

  while(!Wire.available()) {
    // waiting
  }

  v = Wire.read();
  return v;
}

float calcAltitude(float pressure)
{
  float A = pressure/101325;
  float B = 1/5.25588;
  float C = pow(A,B);
  C = 1 - C;
  C = C /0.0000225577;

  return C;
}

No serial monitor, as informações são atualizadas a cada 5 segundos :

Dados BMP085 - Serial Monitor

 
Um bom exercício é utilizar esses programas e realizar a integração com o Processing (veja o post Processing : mostre as informações do Arduino no seu computador), mostrando as informações do sensor de forma gráfica ou até mesmo por meio de animações.


49 comentários:

  1. Amigo, seria possível usar esse sensor juntamente com o Arduino para controlar um quadricoptero?

    ResponderExcluir
  2. Obrigado pelo excelente tutorial. Gostaria apenas de perguntar se os valores do acelerómetro estão em m/s. Se não é o caso, de que forma podemos converte-los. Obrigado.

    Nuno Teixeira

    ResponderExcluir
    Respostas
    1. Bom dia Nuno,

      Se não me engano, os valores estão em "g", mas no final do código há uma divisão por 256 que eu sinceramente não consegui descobrir ainda pra que serve.

      Vou ter que pesquisar um pouco mais para não passar nenhuma informação errada. Qualquer ajuda será bem vinda. :-)

      Abraço !

      Excluir
    2. Os valores estão em g, ou seja m/(s^2).... Sobre a divisão por 256, é devido ao sensor ter precisão alta e a cada 256 unidades serem equivalentes a 1g.

      Excluir
  3. Daria para usar o sensor de giroscópio, acelerometro, bussola e o sensor de temperatura e pressão ao mesmo tempo ?

    ResponderExcluir
    Respostas
    1. Oi Rafael,

      Sem problemas. Eu separei os programas para ficar mais fácil de entender como cada um se comporta, mas cada componente tem um endereço diferente, e você pode utiliza-los no mesmo programa.

      Abraço !

      Excluir
  4. Grato! Ótimo artigo! No meu caso, tenho IME GY-85 (da Dx), e meu gyro é o ITG 3205 (0x68). Usei outro sketch da http://www.geeetech.com/wiki/index.php/ITG3205_Triple_Axis_Gyroscope_Breakout.
    Agora, próxima parada: processing.

    ResponderExcluir
  5. Olá, eu comprei o sensor para usar como um PIC, a alimentação dele eu sei que pode ser tanto em 3,3V quanto em 5V, mas a comunicação i2C dele pode ser feita em 5V, ou tenho que usar um conversor de sinal lógico, para baixar a tensão de 5V para 3,3V e vice-versa???

    ResponderExcluir
  6. Como posso conectar o sensor na breadboard com segurança? A conexão entre os pinos e a placa fica com uma folga e eu tenho que "calçar" o mesmo para que haja contato.

    ResponderExcluir
    Respostas
    1. Bom dia,

      Creio que o mais simples seja trocar de breadboard, já que o tamanho/espessura desses pinos é padrão.

      Abraço !

      Excluir
  7. É POSSÍVEL COLOCAR GPS NESSA PLACA?

    ResponderExcluir
    Respostas
    1. Boa noite,

      Até onde eu sei, não é possível. O que você pode fazer é interligar essa placa com um gps, por exemplo, mas tudo vai depender do seu projeto.

      Abraço!

      Excluir
  8. Olá, como faço pra trocar o "range" do acelerômetro? Atualmente ele está setado para 2g, mas preciso de mais, por exemplo, 8g. Vi no datasheet quais são os "bits" relacionados a isso, mas não descobri como implementar no código do arduíno. Obrigado

    ResponderExcluir
    Respostas
    1. Boa noite Gabriel,

      Tente essa biblioteca da Adafruit, feita para a placa deles com o ADXL345: https://learn.adafruit.com/adxl345-digital-accelerometer/programming

      Abraço!

      Excluir
    2. Você deve setar os dois últimos bits registrador 0x31 DATA FORMAT como 01 para obter a resolução de 8g.
      00 = 2g
      01 = 4g
      10 = 8g
      11 = 16g

      Os outros 6 bits vc deve setar de acordocom sua necessidade. Todas estas informações estão no data sheet do acelerômetro

      Excluir
    3. No setup, vc tem que usar o beginTransmission,
      BeginTransmission (endereço acelerômetro)
      Write (registrador)
      Write (valor a ser escrito neste registrador com o range requerido)
      endTransmission

      Basicamente isso

      Excluir
  9. Excelente texto. MUITO OBRIGADO!

    Queria saber se posso usar os três sensores ao mesmo tempo. Na verdade, eu só quero os sinais do giroscópio e do acelerômetro. É possível?

    Como faço? Só usar os código acima de cada tipo em um texto só?

    Obrigado!

    A propósito, se não houver problema, meu e-mail é mic_robs@yahoo.com caso você precise ou queira mandar algum conteúdo que preciso saber pra responder a minha pergunta caso não tenha no texto acima

    VALEUU!!!

    ResponderExcluir
    Respostas
    1. Boa noite Michael,

      Exato, use apenas o programa para cada tipo de sensor que você precisa. Você também pode juntar vários programas em um só, dependendo do seu projeto.

      Abraço!

      Excluir
    2. Muito obrigado mesmo! Ajudou bastante. Contudo, estou usando o GY-85. A única diferença que notei com relação a esse sensor apresentado no texto é o giroscópio. No lugar de usar esse citado aqui, o GY-85 usa o giroscópio modelo ITG3205. Você sabe qual seria a diferença? Altera algo no código/programa mostrado acima?

      Obrigado!

      Excluir
  10. A I2C precisa resistores de pull up?

    ResponderExcluir
    Respostas
    1. Boa tarde,

      Depende do módulo, alguns tem sensores pull-up embutidos.

      Abraço!

      Excluir
  11. ola gostaria de saber a diferença entre o gy80 e o gy88

    ResponderExcluir
    Respostas
    1. Boa tarde,

      O GY-80 tem:

      L3G4200D - Giroscópio
      ADXL345 - Acelerômetro 3 eixos
      HMC5883L - Bússola digital / Magnetômetro
      BMP085 - Sensor de temperatura e pressão

      O GY-88 tem:

      MPU6050 - Acelerômetro e Giroscópio
      HMC5883L - Magnetômetro
      GMP085 - Sensor de temperatura e pressão

      Resumindo: tiraram o L3G4200D e o ADXL345 e colocaram o MPU6050, que tem as duas funções no mesmo CI.

      Abraço!

      Excluir
  12. Hola!
    Quiero implementar los sensores del IMU GY 80 L3G4200D, ADXL345, BMP085 , en un mismo bus de datos i2c, tendra el codigo o podria ayudarme a implementarlo.
    Gracias y Saludos desde Mexico

    ResponderExcluir
  13. Olá, obrigado por compartilhar!

    Estou testando o seu codigo, entretanto estou tendo alguns problemas na hora de recuperar o valor do eixo Z do acelerometro

    quando abro o serial monitor, tenho estes valores de retorno.

    ACC_X= -0.17 ACC_Y= 0.11 ACC_Z= 1.00
    ACC_X= -0.25 ACC_Y= 0.16 ACC_Z= 1.50
    ACC_X= -0.29 ACC_Y= 0.19 ACC_Z= 1.75
    ACC_X= -0.32 ACC_Y= 0.20 ACC_Z= 1.87
    ACC_X= -0.33 ACC_Y= 0.21 ACC_Z= 1.93
    ACC_X= -0.33 ACC_Y= 0.21 ACC_Z= 1.96
    ACC_X= -0.34 ACC_Y= 0.21 ACC_Z= 1.98
    ACC_X= -0.34 ACC_Y= 0.22 ACC_Z= 1.99
    ACC_X= -0.34 ACC_Y= 0.22 ACC_Z= 1.99
    ACC_X= -0.34 ACC_Y= 0.22 ACC_Z= 1.99
    ACC_X= -0.34 ACC_Y= 0.21 ACC_Z= 2.00

    Obrigado e att

    ResponderExcluir
  14. Boa Noite! Estou começando as pesquisas para a montagem de um drone quadrimotor, tanto pelo aprendizado quanto pela economia propiciada, usando como base os firmwares das controladoras MultiWii e/ou ArduPilot (APM) instalados numa placa Arduino Mega 2560. Tenho dúvidas sobre qual melhor modelo de placa Arduino usar e qual módulo de sensores entre os modelos GY-80, GY-87, GY-88, MPU-9250 e etc. Você teria alguma sugestão para otimizar o desempenho do drone em função do peso e sensibilidade/eficiência das placas?

    ResponderExcluir
    Respostas
    1. Bom dia,

      Realmente eu vejo projetos com os mais diferentes tipos de sensores e acelerômetros, mas um que eu tenho visto com muita frequência nesses projetos é o MPU-6050, que tem acelerômetro e giroscópio. Quanto ao Arduino, eu acho que o Uno seria mais apropriado, não só por ser mais compacto, como também pelo consumo de energia. Estou assumindo que, além dos motores, vc também vai precisar de outros sensores e módulos wifi ou RF, por exemplo.

      Mas é um projeto interessante, um dia eu chego lá também. :)

      Abraço!

      Excluir
  15. Esqueci do principal. Parabéns e obrigado pela publicação do artigo. Muito esclarecedor e motivador. Solicito ainda sugestão de módulo de satélite.

    ResponderExcluir
  16. eu tive problemas

    Scanning...
    No I2C devices found

    Scanning...
    No I2C devices found

    Scanning...
    No I2C devices found

    Scanning...
    No I2C devices found

    Scanning...
    No I2C devices found

    o que pode ter acontecido?

    ResponderExcluir
    Respostas
    1. Boa tarde,

      O Arduino não está se comunicando com nenhum dos sensores. Reveja as ligações e a alimentação do módulo.

      Abraço!

      Excluir
  17. Boa tarde, não entendo nada disso, mas tenho uma idéia, e nela precisaria controlar com um arduino e um acelerômetro, um motor de 36v 250w. é possível e se for como faço, já que o arduíno trabalha em 3,3v ou 5v.
    grato pela atenção.

    ResponderExcluir
    Respostas
    1. Oi Lucas,

      Que tipo de motor é esse ? CC ? De passo ?

      Abraço!

      Excluir
  18. Boa tarde, vi no datasheet de cada sensor que eles possuem uma certa velocidade de aquisicao (output data rate) como por exemplo no acelerômetro e de até 3200 medicoes por segundo e no giroscópio 800 medicoes por segundo.
    Assim gostaria de saber como que escolho qual vai ser a velocidade que o sensor vai pegar esses dados.
    Desde já agradeco pela atencao.

    ResponderExcluir
  19. boa noite eu tenho que construir um bb 8 do star wars e essa placa emgloba quase td que preciso vc teria alguma pra 4 eixos pois vou ter q usar 4 motores

    ResponderExcluir
  20. Boa tarde, esse sensor poderia ser usado para coletar os dados (pressão por exemplo) num determinado intervalo de tempo? Algo como dde segundo em segundo. Estou fazendo um projeto e preciso de um sensor que possa fazer a coleta de dados da pressão que ocorre sobre o capô do carro numa determinada velocidade durante 2 minutos

    ResponderExcluir
  21. Referente ao video.
    O código faz com que o eixo do motor de passo gire o mesmo angulo do acelerômetro.
    Preciso saber aonde mudar o código para que o motor de passo gire MAIS angulo do que o acelerômetro.
    obrigado.
    Segue o link do vídeo que tem o código.

    https://www.youtube.com/watch?v=KOfuubvrtRw

    ResponderExcluir
  22. Boa noite. Vocês poderiam me ajudar a refazer a programação do exemplo referente ao giroscópio para ler os valores em angulos?

    ResponderExcluir
  23. Ola . Vocês poderiam me ajudar . Estou com um projeto com um sensor barométrico onde está aparecendo somente isso no serial monitor

    Setting up BMP085
    Reading Calibration Data
    AC1: 7768
    AC2: -1097
    AC3: -14561
    AC4: 34080
    AC5: 25194
    AC6: 16268
    B1: 6515
    B2: 40
    MB: -32768
    MC: -11786
    MD: 2702
    p0 = 101989.00

    Esses valores devem ser informado em algum lugar do programa para um calibração?

    Grato.

    ResponderExcluir
  24. Bom dia, eu estou com um robô omidirecioal, e preciso fazer ele rotacionar perfeitamente em 90º. Eu já tentei com o MPU6050, só que ele para de fazer as medias após um tempo e além disso perde o 0º dele (ele é definido na posição em que o programa começa a rodar). Gostaria de saber se com esse sensor tem como eu fazer meu robô rodar os 90º perfeitamente, e quando ele estiver andando reto, e gerar o erro dos motores ele corrigir a trajetória. Desde já obrigado.

    ResponderExcluir
    Respostas
    1. Oi Arthur,

      Acho que você pode usar tanto o MPU6050 como o GY-80... Será que o seu problema com o MPU6050 não foi uma placa defeituosa ? Ele é bem preciso.

      Abraço!

      Excluir
  25. Iniciei um projeto com o MPU6050, entretanto as leituras apresentam bastante variação quando o sensor está parado. Já tentei utilizar um filtro Kalman, mas ainda assim não tive muito sucesso. Alguma dica?

    ResponderExcluir
  26. boa tarde onde eu baixo a biblioteca wire.h da gy80

    ResponderExcluir
    Respostas
    1. Oi Glauco,

      Se não me engano a IDE já vem com essa biblioteca.. que versão de IDE vc está usando ?

      Abraço!

      Excluir
  27. Boa noite,
    tenho uma IMU gy87,quando rodo o programa aparece isso
    Scanning...
    I2C device found at address 0x68 !
    I2C device found at address 0x77 !
    done
    Tem algum problema na minha IMU? Não deveriam aparecer mais address?

    ResponderExcluir
    Respostas
    1. Boa noite,

      Não tenho o GY-87 para testar, mas sei que ele tem o giroscópio e o acelerômetro em um mesmo CI (MPU4050). Deve ser um dos motivos dessa diferença na detecção de endereços.

      Abraço!

      Excluir