Les logiciels Windows de Tiercelin
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.