top of page

Baromètre et température en NMEA

Montage permettant d'envoyer la pression atmosphérique et la température ambiante sur un port série ( ici le port usb de la carte UNO )

 

Pour transmettre en Bluetooth, brancher le module HC-05 sur RX0 et TX1 ou modifier le programme.

 

 

 

 

 

 

Le branchement Arduino uno :

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Le programme qui créé la phrase NMEA  XDR et qui l’envoie sur le port série.

 

#include <Wire.h>

//les variables

 

 String laphrasebaro;

 String baro;

String temp;

String baroini;

String baromilieu;

String barofin;

int checkbaro;

 

 

 

 

 

//L'adresse I2C du BMP085

#define BMP085_ADDRESS 0x77

 

// Lit 1 byte du BMP085 à 'address'

char bmp085ReadChar(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 bytes sur le BMP085

// Le premier byte vient de 'address'

// Le second byte vient de 'address'+1

int bmp085ReadInt(unsigned char address)

{

  unsigned char msb, lsb;

 

  Wire.beginTransmission(BMP085_ADDRESS);

  Wire.write(address);

  Wire.endTransmission();

 

  //on va lire 2 bytes, correspondant à un integer

  Wire.requestFrom(BMP085_ADDRESS, 2);

 

  //Attendons que les 2 bytes soient arrivés...

  while(Wire.available()<2);

  msb = Wire.read();

  lsb = Wire.read();

 

  return (int) msb<<8 | lsb;

}

// paramètre d'oversampling 0 à 3,

//qui permet d'avoir plus de précision dans les mesures

const unsigned char OSS = 0;

 

// Valeurs de calibration

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 est calculé dans bmp085GetTemperature(...),

// et est aussi utilisée dans bmp085GetPressure(...)

// donc ...Temperature(...) doit être appelée avant ...Pressure(...).

long b5;

 

short temperature;

long pressure;

 

// Stocke toutes les valeurs de calibration du BMP085 dans des variables globales.

// Ces valeurs sont nécessaires pour calculer la température et la pression.

// Cette fonction doit être appelée au début du programme.

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);

}

 

 

 

 

void setup()

{

// initialise la connection série ( broches 0 et 1 )

  Serial.begin(9600);

  Wire.begin();

  bmp085Calibration();

}

 

 

// Lit la température non compensée

unsigned int bmp085ReadUT()

{

  unsigned int ut;

 

  // Ecrit 0x2E dans le registre 0xF4.

  // Cela demande une lecture de température.

  Wire.beginTransmission(BMP085_ADDRESS);

  Wire.write(0xF4);

  Wire.write(0x2E);

  Wire.endTransmission();

 

  // Attendons au moins 4.5ms

  delay(5);

 

  // Lit les 2 octets des registres 0xF6 et 0xF7

  ut = bmp085ReadInt(0xF6);

  return ut;

}

 

// Lit la pression non compensée

unsigned long bmp085ReadUP()

{

  unsigned char msb, lsb, xlsb;

  unsigned long up = 0;

 

  // Ecrit 0x34 + (OSS<<6) dans le registre 0xF4 pour

  // demander une lecture de la pression avec le paramètre d'oversampling

  Wire.beginTransmission(BMP085_ADDRESS);

  Wire.write(0xF4);

  Wire.write(0x34 + (OSS<<6));

  Wire.endTransmission();

 

  // Attend la fin de conversion, le délai dépend de OSS

  delay(2 + (3 << OSS));

 

  // Lit la réponse dans les registres :

  // 0xF6 (MSB), 0xF7 (LSB), et 0xF8 (XLSB)

  Wire.beginTransmission(BMP085_ADDRESS);

  Wire.write(0xF6);

  Wire.endTransmission();

  Wire.requestFrom(BMP085_ADDRESS, 3);

 

  // Attend aue les données soient dispo (3 bytes)

  while(Wire.available() < 3);

 

  msb = Wire.read();

  lsb = Wire.read();

  xlsb = Wire.read();

 

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

 

  return up;

}

// Calcule la température à partir de ut.

// La valeur de sortie est exprimée en dixièmes de degrés.

short bmp085GetTemperature(unsigned int ut)

{

  long x1, x2;

 

  x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;

  x2 = ((long)mc << 11)/(x1 + md);

  b5 = x1 + x2;

 

  return ((b5 + 8)>>4);

}

 

// Calcule la pression à partir de up.

// Les valeurs de calibration doivent être initialisées.

// b5 est aussi requise, donc bmp085GetTemperature(...) doit être appelée en premier.

// La valeur de sortie est exprimée en hPascals.

long bmp085GetPressure(unsigned long up)

{

  long x1, x2, x3, b3, b6, p;

  unsigned long b4, b7;

 

  b6 = b5 - 4000;

  // Calcule B3

  x1 = (b2 * (b6 * b6)>>12)>>11;

  x2 = (ac2 * b6)>>11;

  x3 = x1 + x2;

  b3 = (((((long)ac1)*4 + x3)<<OSS) + 2)>>2;

 

  // Calcule 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;

 

  return p;

}

 

//Le programme principale

 

void loop()

 

{

  temperature = bmp085GetTemperature(bmp085ReadUT());

  pressure = bmp085GetPressure(bmp085ReadUP());

  baroini = "$ERXDR,pression,";

  baromilieu = ",pa,BMP085,temperature,";

  barofin = ",C,BMP085," ;

  temp = String(temperature);

  //temperature en dixiemes de degres

  baro = String(pressure);

 laphrasebaro = baroini + baro + baromilieu + temp + barofin;

 checkbaro = getCheckSum(laphrasebaro);

 barofin = "*";

// la phrase nmea transmise au port série

  laphrasebaro = laphrasebaro + barofin;

 Serial.print(laphrasebaro);

 Serial.println(checkbaro,HEX);

  delay(500);   

}

 

//la fonction qui calcule le checksum

int getCheckSum(String phrase) {

int checksum = 0;

int longueur = 0;

longueur = phrase.length();

for(int i = 1; i < longueur; i++)

{

checksum = checksum ^ int(phrase[i]);

}

 

return checksum; 

}

 

Avec Livre de Bord et ce montage, on peut Avoir la pression atmosphérique et la température de l'air, mais aussi une courbe baromètrique sur trois jours qui peut être enregistrée et relue.

De plus les hauteurs de marée peuvent alors être ajustées en tennant compte de la pression atmosphérique.

 

bottom of page