Accueil > Arduino, Matériel > Capteur de pression barométrique pour Arduino

Capteur de pression barométrique pour Arduino

J’ai commandé, il y a peu de temps, une platine équipé d’un capteur de pression barométrique BMP085 de chez Sparkfun. Il permet d’effectuer des mesures de 300 à 1100 hPa (Hecto Pascal) avec une précision de 0.03 hPa et en bonus il permet également de mesurer des températures de -40 à +85°C avec une précision de +/- 2°C.

Le schéma de cette platine est le suivant :

image

 

Ce capteur utilise le bus I2C pour la communication. Attention l’alimentation de ce module s’effectue en 3.3 V. Ce module est équipé de 6 sorties :

BMP085 Pin

Pin Function

VCC

Power (1.8V-3.6V)

GND

Ground

EOC

End of conversion output

XCLR

Master Clear (low-active)

SCL

Serial Clock I/O

SDA

Serial Data I/O

La broche XCLR permet de réinitialiser le module et la broche EOC permet de générer un signal lorsque la conversion est effectuée. Nous n’utiliserons pas ces broches. SCL et SDA sont les broches de communication I2C. L’adresse 0x77 permet d’accéder au module sur le bus I2C.

Le schéma de câblage avec l’Arduino sera le suivant :

image

Après quelques recherches sur internet (oui je suis un peu paresseux aujourd’hui), voici le programme :

/* Ce programme permet d’obtenir la pression, la température et l’altitude
*/
#include <Wire.h>
#define BMP085_ADDRESS 0x77  // adresse I2C capteur BMP085
const unsigned char OSS = 3;  // échantillonage
/* Echantillonage | Mode échantillonage       | Temps de conversion
        0         | basse consommation        | 4.5 ms
        1         | standard                  | 7.5 ms
        2         | haute résolution          | 13.5 ms
        3         | ultra haute résolution    | 25.5 ms
*/
// valeurs calibrées
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;
long b5;
// Pour connaitre l’altitude et le temps annoncé
// il faut indiquer la pression en Pascal au niveau de la mer
float pressure_sea = 102500;

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

void loop()
{
  float temperature = bmp085GetTemperature(bmp085ReadUT()); //doit être exécuté en premier
  float pressure = bmp085GetPressure(bmp085ReadUP());
  float altitude = calcAltitude(pressure); 
  const float ePressure = pressure_sea * pow((1-altitude/44330), 5.255);  // pression attendue en Pascal, selon l’altitude
  float weatherDiff;
  Serial.print("Temperature: ");
  Serial.print(temperature, 2);
  Serial.println(" deg C");
  Serial.print("Pression: ");
  Serial.print(pressure / 100, 0);
  Serial.println(" hPa");
  Serial.print("Altitude: ");
  Serial.print(altitude, 2);
  Serial.println(" M");
  Serial.println();
  weatherDiff = pressure – ePressure;
  if(weatherDiff > 250)
    Serial.println("Ensoleillé");
  else if ((weatherDiff <= 250) || (weatherDiff >= -250))
    Serial.println("Nuageux");
  else if (weatherDiff > -250)
    Serial.println("Pluie");
  Serial.println();
  delay(1000);
}

/* Lit les valeurs calibrées en usine
   ces valeurs sont nécessaires pour calculer la température et la pression
*/
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);
}

// Calcule la température en °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;
}

// Calcule la pression
long bmp085GetPressure(unsigned long up){
  long x1, x2, x3, b3, b6, p;
  unsigned long b4, b7;
  b6 = b5 – 4000;
  x1 = (b2 * (b6 * b6)>>12)>>11;
  x2 = (ac2 * b6)>>11;
  x3 = x1 + x2;
  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;
  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;
}

// Lit un octet à l’adresse du BMP085
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();
}

// Lit 2 octets du BMP085
// le premier octet à ‘addresse’
// le second octet à  ‘addresse’+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;
}

// Lit la valeur de température non compensée
unsigned int bmp085ReadUT(){
  unsigned int ut;
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x2E);
  Wire.endTransmission();
  delay(5); // 26ms car on a choisit le mode d’échantillonage ultra haute résolution
  ut = bmp085ReadInt(0xF6);
  return ut;
}

// Lit la valeur de pression non compensée
unsigned long bmp085ReadUP(){
  unsigned char msb, lsb, xlsb;
  unsigned long up = 0;
  Wire.beginTransmission(BMP085_ADDRESS);
  Wire.write(0xF4);
  Wire.write(0x34 + (OSS<<6));
  Wire.endTransmission();
  // on a choisit le mode d’échantillonage ultra haute résolution
  delay(2 + (3<<OSS));
  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); 
  Wire.write(address);      
  Wire.write(val);        
  Wire.endTransmission();   
}

int readRegister(int deviceAddress, byte address){
  int v;
  Wire.beginTransmission(deviceAddress);
  Wire.write(address);
  Wire.endTransmission();
  Wire.requestFrom(deviceAddress, 1);
  while(!Wire.available()) {
  }
  v = Wire.read();
  return v;
}

// Calcul de l’altitude
float calcAltitude(float pressure){
  float A = pressure/pressure_sea;
  float B = 1/5.25588;
  float C = pow(A,B);
  C = 1 – C;
  C = C /0.0000225577;
  return C;
}

Celui-ci permet d’afficher la pression, la température, l’altitude et la tendance du temps. Attention de bien renseigner la pression actuelle au niveau de la mer afin de pouvoir calculer l’altitude et la tendance du temps (variable pressure_sea).

Publicités
Catégories :Arduino, Matériel Étiquettes : ,
  1. Aucun commentaire pour l’instant.
  1. No trackbacks yet.

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :