I can give you the unit I have developed, but not sure it's correct.
I have stopped dev because the chip I was using had the Temperature sensor broken...
Ordered a newone on Sparkfun; then I will verify if my translation from C routines is good.
Code
Unit BMP085;
||| library for Barometric sensor. chip Bosch BMP085
(*
Sensor on I2C bus as Slave.
xMega su TWI_E ovvero pins PE0, PE1
Get pressure, altitude, and temperature from the BMP085.
*)
interface
// global part
Uses Vars in 'Vars.pas';
{--------------------------------------------------------------}
{ Const Declarations }
const
{$IDATA}
{--------------------------------------------------------------}
{ Type Declarations }
type
{--------------------------------------------------------------}
{ Var Declarations }
var
vTemperature : integer;
vPressure : longint;
vAltitude : float;
fTemperature: float;
Pressure: integer;
vertSpeed: integer;
{--------------------------------------------------------------}
{ functions }
// Public API
procedure BMP085_init; // configura accel settings
procedure BMP085_calibration;
procedure BMP085_ReadUT; // read uncompensated Temperature value
procedure BMP085_ReadUP;
procedure BMP085_CalcTemperature;
procedure BMP085_CalcPressure;
procedure BMP085_CalcAltitude;
// Local functions
implementation
// local part
{--------------------------------------------------------------}
{ Type Declarations }
type
st14 = string[14];
TPtext = pointer to st14;
{--------------------------------------------------------------}
{ Const Declarations }
const
// -- BMP085 addresses --
BMP085_ADDRESS : byte = $77; // I2C address of BMP085
BMP085_R : byte = $EF;
BMP085_W : byte = $EE;
oversampling_setting : byte = 0;
pressure_conversiontime : array [ 0..3 ] of byte = ( 5, 8, 14, 26 ); // delays for oversampling settings 0, 1, 2 and 3
// ------- Calibration Register names -------
addr_AC1 : byte = $AA;
addr_AC2 : byte = $AC;
addr_AC3 : byte = $AE;
addr_AC4 : byte = $B0;
addr_AC5 : byte = $B2;
addr_AC6 : byte = $B4;
addr_B1 : byte = $B6;
addr_B2 : byte = $B8;
addr_MB : byte = $BA;
addr_MC : byte = $BC;
addr_MD : byte = $BE;
BMP085_OK : byte = 1; // no error
BMP085_ERROR : byte = 0; // indicates error is predent
BMP085_NO_ERROR : byte = 2; // initial state
{--------------------------------------------------------------}
{ Var Declarations }
{$IDATA}
var
dev_address : integer;
error_code : byte; // Initial state
UTemp : integer;
arrUP : array [ 0..3 ] of byte;
intUP [@arrUP] : longint; // 4bytes, used max 3.
UncompPress : longint;
mswUP [@UncompPress+2] : word;
lswUP [@UncompPress] : word;
vAC1 : integer;
vAC2 : integer;
vAC3 : integer;
vAC4 : word;
vAC5 : word;
vAC6 : word;
vB1 : integer;
vB2 : integer;
vMB : integer;
vMC : integer;
vMD : integer;
altA : float;
altB : float;
altC : float;
{--------------------------------------------------------------}
{ functions }
procedure BMP085_init;
begin
// BMP085 r/w address $EF,$EE diventano $77 BMP085_ADDRESS !
if TWIstatE(BMP085_ADDRESS) then
Writeln(SerOutF0, 'Sensor OK !');
Cmd_Result := True;
else
Writeln(SerOutF0, 'no response...');
endif;
end;
procedure BMP085_CalcTemperature; //calculate true temperature
var
ctX1, ctX2, ctB5 : longint;
begin
ctX1 := longint(UTemp - vAC6);
ctX1 := (ctX1 * longint(vAC5)) shr 15;
ctX2 := (longint(vMC shl 11)) div (ctX1 + longint(vMD));
ctB5 := ctX1 + ctX2;
vTemperature := integer((ctB5 + 8) shr 4);
(*
int ut= readUT();
long up = readUP();
long x1, x2, x3, b3, b5, b6, p;
unsigned long b4, b7;
//calculate true temperature
x1 = ((long)ut - ac6) * ac5 >> 15;
x2 = ((long) mc << 11) / (x1 + md);
b5 = x1 + x2;
vTemperature = (b5 + 8) >> 4;
*)
end;
procedure BMP085_CalcPressure; //calculate true pressure
var
cpX1, cpX2, cpX3, cpB3, cpB5, cpB6, p : longint;
cpB4, cpB7 : longword;
begin
cpB6 := cpB5 - 4000;
// Calculate cpB3
cpX1 := (longint(vB2) * (cpB6 * cpB6 shr 12)) shr 11;
cpX2 := longint(vAC2) * cpB6 shr 11;
cpX3 := cpX1 + cpX2;
cpB3 := ((longint(vAC1) * 4 + cpX3) shl oversampling_setting + 2) shr 2;
// Calculate cpB4
cpX1 := longint(vAC3) * cpB6 shr 13;
cpX2 := (longint(vB1) * (cpB6 * cpB6 shr 12)) shr 16;
cpX3 := ((cpX1 + cpX2) + 2) shr 2;
cpB4 := (longword(vAC4) * longword(cpX3 + 32768)) shr 15;
cpB7 := (longword(UncompPress) - cpB3) * (50000 shr oversampling_setting);
if cpB7 < $80000000 then
p := longint((cpB7 shl 1) div cpB4);
else
p := longint((cpB7 div cpB4) shl 1);
endif;
cpX1 := (p shr 8) * (p shr 8);
cpX1 := (cpX1 * 3038) shr 16;
cpX2 := (-7357 * p) shr 16;
vPressure := p + ((cpX1 + cpX2 + 3791) shr 4);
(*
int ut= readUT();
long up = readUP();
long x1, x2, x3, b3, b5, b6, p;
unsigned long b4, b7;
//calculate true pressure
b6 = b5 - 4000;
// Calculate B3
x1 = (b2 * (b6 * b6 >> 12)) >> 11;
x2 = ac2 * b6 >> 11;
x3 = x1 + x2;
b3 = (((int32_t) ac1 * 4 + x3)<<oversampling_setting + 2) >> 2;
// Calculate B4
x1 = ac3 * b6 >> 13;
x2 = (b1 * (b6 * b6 >> 12)) >> 16;
x3 = ((x1 + x2) + 2) >> 2;
b4 = (ac4 * (uint32_t) (x3 + 32768)) >> 15;
b7 = ((uint32_t) up - b3) * (50000 >> oversampling_setting);
p = b7 < 0x80000000 ? (b7 * 2) / b4 : (b7 / b4) * 2;
x1 = (p >> 8) * (p >> 8);
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;
pressure = p + ((x1 + x2 + 3791) >> 4);
*)
end;
procedure BMP085_CalcAltitude;
begin
altA := float(vPressure) / 101325;
altB := 1 / 5.25588;
altC := pow(altA, altB);
altC := 1 - altC;
vAltitude := altC / 0.0000225577;
(*
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;
*)
end;
procedure BMP085_ReadUT; // read Uncompensated Temperature value
begin
TWIOutE(BMP085_ADDRESS, $F4, $2E ); // read temper reg.
mDelay( 5 );
TWIOutE(BMP085_ADDRESS, $F6); // $F6, F7
TWIinpE(BMP085_ADDRESS, iTmp); // 2 bytes only: msb, lsb
array2consolle(ptrB(@iTmp), 2); // input recFrame 1:2 output su consolle $C0+$B4 -> 'C0B4'
UTemp := swap(iTmp); // serve ?
Writeln(SerOutF0, 'uncomp. Temper = '+ IntToHex(UTemp)+' '+ IntToStr(UTemp));
end;
procedure BMP085_ReadUP; // read Uncompensated Pressure value
begin
TWIOutE(BMP085_ADDRESS, $F4, $34 + (oversampling_setting shl 6)); // var Res
// TWIOutE(BMP085_ADDRESS, $F4, $F4 ); // fixed HiRes
// TWIOutE(BMP085_ADDRESS, $F4, $34 ); // fixed LowRes
mDelay( word(pressure_conversiontime[oversampling_setting]) );
TWIOutE(BMP085_ADDRESS, $F6); // $F6, F7, F8
TWIinpPE(BMP085_ADDRESS, @arrUP, 3); // 3 bytes sample: msb, lsb, xlsb
//array2consolle(ptrB(@arrUP), 4); // x debug - input recFrame 1:2 output su consolle $C0+$B4 -> 'C0B4'
//Writeln(SerOutF0, 'uncomp. Pressure = '+ longToHex(intUP)+' '+ longToStr(intUP)); // no, map diretto di array su longint non converte correttamente !
HI( mswUP ) := 0;
LO( mswUP ) := arrUP[0];
HI( lswUP ) := arrUP[1];
LO( lswUP ) := arrUP[2];
//Writeln(SerOutF0, 'uncomp. Press2 = '+ longToHex(UncompPress)+' '+ longToStr(UncompPress)); // x debug
UncompPress := UncompPress shr (8 - oversampling_setting);
Writeln(SerOutF0, 'uncomp. Pressure = '+ longToHex(UncompPress)+' '+ longToStr(UncompPress));
end;
procedure BMP085_calibration;
begin
if TWIstatE(BMP085_ADDRESS) then
TWIOutE(BMP085_ADDRESS, addr_AC1);
tBool := TWIinpE (BMP085_ADDRESS, iTmp);
if tBool then
vAC1 := swap(iTmp);
Writeln(SerOutF0, 'word AC1 = '+ IntToHex(vAC1) +' '+ IntToStr(vAC1));
Cmd_Result := True;
else
Writeln(SerOutF0, 'RD error.');
endif;
TWIOutE(BMP085_ADDRESS, addr_AC2);
if TWIinpE (BMP085_ADDRESS, iTmp) then
vAC2 := swap(iTmp);
Writeln(SerOutF0, 'word AC2 = '+ IntToHex(vAC2)+' '+ IntToStr(vAC2));
endif;
TWIOutE(BMP085_ADDRESS, addr_AC3);
if TWIinpE (BMP085_ADDRESS, iTmp) then
vAC3 := swap(iTmp);
Writeln(SerOutF0, 'word AC3 = '+ IntToHex(vAC3)+' '+ IntToStr(vAC3));
endif;
TWIOutE(BMP085_ADDRESS, addr_AC4);
if TWIinpE (BMP085_ADDRESS, wTmp) then
vAC4 := swap(wTmp);
Writeln(SerOutF0, 'word AC4 = '+ IntToHex(vAC4)+' '+ IntToStr(vAC4));
endif;
TWIOutE(BMP085_ADDRESS, addr_AC5);
if TWIinpE (BMP085_ADDRESS, wTmp) then
vAC5 := swap(wTmp);
Writeln(SerOutF0, 'word AC5 = '+ IntToHex(vAC5)+' '+ IntToStr(vAC5));
endif;
TWIOutE(BMP085_ADDRESS, addr_AC6);
if TWIinpE (BMP085_ADDRESS, wTmp) then
vAC6 := swap(wTmp);
Writeln(SerOutF0, 'word AC6 = '+ IntToHex(vAC6)+' '+ IntToStr(vAC6));
endif;
TWIOutE(BMP085_ADDRESS, addr_B1);
if TWIinpE (BMP085_ADDRESS, iTmp) then
vB1 := swap(iTmp);
Writeln(SerOutF0, 'word B1 = '+ IntToHex(vB1)+' '+ IntToStr(vB1));
endif;
TWIOutE(BMP085_ADDRESS, addr_B2);
if TWIinpE (BMP085_ADDRESS, iTmp) then
vB2 := swap(iTmp);
Writeln(SerOutF0, 'word B2 = '+ IntToHex(vB2)+' '+ IntToStr(vB2));
endif;
TWIOutE(BMP085_ADDRESS, addr_MB);
if TWIinpE (BMP085_ADDRESS, iTmp) then
vMB := swap(iTmp);
Writeln(SerOutF0, 'word MB = '+ IntToHex(vMB)+' '+ IntToStr(vMB));
endif;
TWIOutE(BMP085_ADDRESS, addr_MC);
if TWIinpE (BMP085_ADDRESS, iTmp) then
vMC := swap(iTmp);
Writeln(SerOutF0, 'word MC = '+ IntToHex(vMC)+' '+ IntToStr(vMC));
endif;
TWIOutE(BMP085_ADDRESS, addr_MD);
if TWIinpE (BMP085_ADDRESS, iTmp) then
vMD := swap(iTmp);
Writeln(SerOutF0, 'word MD = '+ IntToHex(vMD)+' '+ IntToStr(vMD));
endif;
endif;
end;
initialization // at StartUp
error_code := BMP085_NO_ERROR;
// finalization // optional
// at System_ShutDown
end BMP085.