Here is my code…
bmp180.h
#ifndef _BMP180_H_
#define _BMP180_H_
#define BMP180_I2C_DEV "/dev/i2c-1"
#define BMP180_I2C_ADDR 0x77
// hardware registers
#define BMP180_REG_CTRL_MEAS 0xF4
#define BMP180_REG_SOFT_RESET 0xE0
#define BMP180_CHIP_ID 0xD0
#define BMP180_READ 1
#define BMP180_WRITE 0
#define BMP180_READ_ADDR 0xEF
#define BMP180_WRITE_ADDR 0xEE
#define BMP180_ULTRALOWPOWER 0 // 00b 1x read | Ultra low power mode
#define BMP180_STANDARD 1 // 01b 2x read | Standard mode
#define BMP180_HIGHRES 2 // 10b 4x read | High-res mode
#define BMP180_ULTRAHIGHRES 3 // 11b 8x read | Ultra high-res mode
#define BMP180_CTRL_TEMP 0x2E
#define BMP180_CTRL_PRESSURE_0 0x34
#define BMP180_CTRL_PRESSURE_1 0x74
#define BMP180_CTRL_PRESSURE_2 0xB4
#define BMP180_CTRL_PRESSURE_3 0xF4
#define BMP180_REG_OUT_XLSB 0xF8
#define BMP180_REG_OUT_LSB 0xF7
#define BMP180_REG_OUT_MSB 0xF6
// calibration registers
#define BMP180_REG_AC1_MSB 0xAA
#define BMP180_REG_AC1_LSB 0xAB
#define BMP180_REG_AC2_MSB 0xAC
#define BMP180_REG_AC2_LSB 0xAD
#define BMP180_REG_AC3_MSB 0xAE
#define BMP180_REG_AC3_LSB 0xAF
#define BMP180_REG_AC4_MSB 0xB0
#define BMP180_REG_AC4_LSB 0xB1
#define BMP180_REG_AC5_MSB 0xB2
#define BMP180_REG_AC5_LSB 0xB3
#define BMP180_REG_AC6_MSB 0xB4
#define BMP180_REG_AC6_LSB 0xB5
#define BMP180_REG_B1_MSB 0xB6
#define BMP180_REG_B1_LSB 0xB7
#define BMP180_REG_B2_MSB 0xB8
#define BMP180_REG_B2_LSB 0xB9
#define BMP180_REG_MB_MSB 0xBA
#define BMP180_REG_MB_LSB 0xBB
#define BMP180_REG_MC_MSB 0xBC
#define BMP180_REG_MC_LSB 0xBD
#define BMP180_REG_MD_MSB 0xBE
#define BMP180_REG_MD_LSB 0xBF
static int oss;
/*
* Immutable calibration data read from bmp180
*/
struct bmp180_calib_param {
int16_t ac1;
int16_t ac2;
int16_t ac3;
uint16_t ac4;
uint16_t ac5;
uint16_t ac6;
int16_t b1;
int16_t b2;
int16_t mb;
int16_t mc;
int16_t md;
};
int bmp180_setup(int oversampling);
void bmp180_init(int fd);
void bmp180_get_calib_params(int fd, struct bmp180_calib_param* params);
int32_t bmp180_get_ut(int fd);
int32_t bmp180_get_up(int fd);
int32_t bmp180_get_B5(int fd, const struct bmp180_calib_param params);
int32_t bmp180_get_temperature(int fd, const struct bmp180_calib_param params);
int32_t bmp180_get_pressure(int fd, const struct bmp180_calib_param params);
#endif
bmp180.c
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <wiringx.h>
#include <bmp180.h>
#include <math.h>
int bmp180_setup(int oversampling)
{
printf("wiringXI2CSetup(%s, 0x%x)\n", BMP180_I2C_DEV, BMP180_I2C_ADDR);
int fd_i2c = wiringXI2CSetup(BMP180_I2C_DEV, BMP180_I2C_ADDR);
printf("fd_i2c: 0x%x\n", fd_i2c);
if (fd_i2c < 0) {
printf("I2C Setup failed: 0x%x\n", fd_i2c);
wiringXGC();
return -1;
}
// bmp180_init(fd_i2c);
printf("wiringXI2CReadReg8(0x%x, 0x%x)\n", fd_i2c, BMP180_CHIP_ID);
int8_t chip_id = wiringXI2CReadReg8(fd_i2c, BMP180_CHIP_ID);
if (chip_id != 0x55){
printf("BMP180 wrong chip ID. Got %xd, expected 0x55\n", chip_id);
return -1;
}
oss = oversampling;
return fd_i2c;
}
void bmp180_init(int fd)
{
// use the "handheld device dynamic" optimal setting (see datasheet)
// 500ms sampling time, x16 filter
// const uint8_t reg_config_val = ((0x04 << 5) | (0x05 << 2)) & 0xFC;
// wiringXI2CWriteReg8(fd, BMP180_REG_CTRL_MEAS, reg_config_val);
// osrs_t x1, osrs_p x4, normal mode operation
// const uint8_t reg_ctrl_meas_val = (0x00 << 5) | (0x03 << 2) | (0x03);
// wiringXI2CWriteReg8(fd, BMP180_REG_CTRL_MEAS, reg_ctrl_meas_val);
}
void bmp180_get_calib_params(int fd, struct bmp180_calib_param* params)
{
printf("function bmp180_get_calib_params(0x%x, 0x%x)\n", fd, ¶ms);
int8_t ac1_msb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC1_MSB);
int8_t ac1_lsb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC1_LSB);
params->ac1 = ac1_msb << 8 + ac1_lsb;
// printf("reading calibration parameter AC1\n");
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC1_MSB);
// printf("%d\n", ac1_msb);
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC1_LSB);
// printf("%d\n", ac1_lsb);
printf("AC1: %d\n", params->ac1);
int8_t ac2_msb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC2_MSB);
int8_t ac2_lsb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC2_LSB);
params->ac2 = ac2_msb << 8 + ac2_lsb;
// printf("reading calibration parameter AC2\n");
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC2_MSB);
// printf("%d\n", ac2_msb);
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC2_LSB);
// printf("%d\n", ac2_lsb);
printf("AC2: %d\n", params->ac2);
int8_t ac3_msb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC3_MSB);
int8_t ac3_lsb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC3_LSB);
params->ac3 = ac3_msb << 8 + ac3_lsb;
// printf("reading calibration parameter AC3\n");
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC3_MSB);
// printf("%d\n", ac3_msb);
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC3_LSB);
// printf("%d\n", ac3_lsb);
printf("AC3: %d\n", params->ac3);
uint8_t ac4_msb = (uint8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC4_MSB);
uint8_t ac4_lsb = (uint8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC4_LSB);
params->ac4 = ac4_msb << 8 + ac4_lsb;
// printf("reading calibration parameter AC4\n");
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC4_MSB);
// printf("%d\n", ac4_msb);
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC4_LSB);
// printf("%d\n", ac4_lsb);
printf("AC4: %d\n", params->ac4);
uint8_t ac5_msb = (uint8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC5_MSB);
uint8_t ac5_lsb = (uint8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC5_LSB);
params->ac5 = ac5_msb << 8 + ac5_lsb;
// printf("reading calibration parameter AC5\n");
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC5_MSB);
// printf("%d\n", ac5_msb);
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC5_LSB);
// printf("%d\n", ac5_lsb);
printf("AC5: %d\n", params->ac5);
uint8_t ac6_msb = (uint8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC6_MSB);
uint8_t ac6_lsb = (uint8_t)wiringXI2CReadReg8(fd, BMP180_REG_AC6_LSB);
params->ac6 = ac6_msb << 8 + ac6_lsb;
// printf("reading calibration parameter AC6\n");
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC6_MSB);
// printf("%d\n", ac6_msb);
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_AC6_LSB);
// printf("%d\n", ac6_lsb);
printf("AC6: %d\n", params->ac6);
int8_t b1_msb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_B1_MSB);
int8_t b1_lsb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_B1_LSB);
params->b1 = b1_msb << 8 + b1_lsb;
// printf("reading calibration parameter B1\n");
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_B1_MSB);
// printf("%d\n", b1_msb);
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_B1_LSB);
// printf("%d\n", b1_lsb);
printf("B1: %d\n", params->b1);
int8_t b2_msb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_B2_MSB);
int8_t b2_lsb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_B2_LSB);
params->b2 = b2_msb << 8 + b2_lsb;
// printf("reading calibration parameter B2\n");
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_B2_MSB);
// printf("%d\n", b2_msb);
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_B2_LSB);
// printf("%d\n", b2_lsb);
printf("B2: %d\n", params->b2);
int8_t mb_msb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_MB_MSB);
int8_t mb_lsb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_MB_LSB);
params->mb = mb_msb << 8 + mb_lsb;
// printf("reading calibration parameter MB\n");
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_MB_MSB);
// printf("%d\n", mb_msb);
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_MB_LSB);
// printf("%d\n", mb_lsb);
printf("MB: %d\n", params->mb);
int8_t mc_msb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_MC_MSB);
int8_t mc_lsb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_MC_LSB);
params->mc = mc_msb << 8 + mc_lsb;
// printf("reading calibration parameter MC\n");
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_MC_MSB);
// printf("%d\n", mc_msb);
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_MC_LSB);
// printf("%d\n", mc_lsb);
printf("MC: %d\n", params->mc);
int8_t md_msb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_MD_MSB);
int8_t md_lsb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_MD_LSB);
params->md = md_msb << 8 + md_lsb;
// printf("reading calibration parameter MD\n");
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_MD_MSB);
// printf("%d\n", md_msb);
// printf("wiringXI2CReadReg8(0x%x, 0x%X) = ", fd, BMP180_REG_MD_LSB);
// printf("%d\n", md_lsb);
printf("MD: %d\n", params->md);
}
int32_t bmp180_get_ut(int fd)
{
printf("bmp180_get_ut\n");
wiringXI2CWriteReg8(fd, BMP180_REG_CTRL_MEAS, BMP180_CTRL_TEMP);
if (oss == BMP180_ULTRALOWPOWER)
delayMicroseconds(5000);
else if (oss == BMP180_STANDARD)
delayMicroseconds(8000);
else if (oss == BMP180_HIGHRES)
delayMicroseconds(14000);
else
delayMicroseconds(26000);
int8_t out_msb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_OUT_MSB);
int8_t out_lsb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_OUT_LSB);
int32_t ut = out_msb << 8 + out_lsb;
printf("out_msb: %d\n",out_msb);
printf("out_lsb: %d\n",out_lsb);
printf("ut: %d\n",ut);
return ut;
}
int32_t bmp180_get_up(int fd)
{
printf("bmp180_get_up\n");
wiringXI2CWriteReg8(fd, BMP180_REG_CTRL_MEAS, BMP180_CTRL_PRESSURE_0 + (oss << 6));
if (oss == BMP180_ULTRALOWPOWER)
delayMicroseconds(5000);
else if (oss == BMP180_STANDARD)
delayMicroseconds(8000);
else if (oss == BMP180_HIGHRES)
delayMicroseconds(14000);
else
delayMicroseconds(26000);
int8_t out_msb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_OUT_MSB);
int8_t out_lsb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_OUT_LSB);
int8_t out_xlsb = (int8_t)wiringXI2CReadReg8(fd, BMP180_REG_OUT_XLSB);
int32_t up = (out_msb << 16 + out_lsb << 8 + out_xlsb) >> (8-oss);
printf("out_msb: %d | ",out_msb);
printf("out_lsb: %d | ",out_lsb);
printf("out_xlsb: %d\n",out_xlsb);
printf("up: %d | oversampling: %d\n",up, oss);
return up;
}
int32_t bmp180_get_B5(int fd, const struct bmp180_calib_param params)
{
printf("bmp180_get_B5\n");
int32_t UT = bmp180_get_ut(fd);
printf("UT: %u | ", UT);
printf("AC5: %u | ", params.ac5);
printf("AC6: %u | ", params.ac6);
printf("MC: %d | ", params.mc);
printf("MD: %d\n", params.md);
int32_t X1 = (UT - (int32_t)params.ac6) * ((int32_t)params.ac5) >> 15;
printf("X1: %d | ", X1);
int32_t X2 = ((int32_t)params.mc << 11) / (X1 + (int32_t)params.md);
printf("X2: %d\n", X2);
return X1 + X2;
}
int32_t bmp180_get_temperature(int fd, const struct bmp180_calib_param params)
{
printf("bmp180_get_temperature\n");
int32_t B5 = bmp180_get_B5(fd, params);
// return (B5 + 8) >> 4;
return ((B5 + 8) >> 4) / 10;
}
int32_t bmp180_get_pressure(int fd, const struct bmp180_calib_param params)
{
printf("bmp180_get_pressure\n");
int32_t UP = bmp180_get_up(fd);
printf("UP: %d | ", UP);
int32_t B5 = bmp180_get_B5(fd, params);
printf("B5: %d | ", B5);
int32_t B6 = B5 - 4000;
printf("B6: %d\n", B6);
int32_t X1 = ((params.b2 * B6 * B6) >> 12) >> 11;
printf("X1: %d | ", X1);
int32_t X2 = (params.ac2 * B6) >> 11;
printf("X2: %d | ", X2);
int32_t X3 = X1 + X2;
printf("X3: %d\n", X3);
int32_t B3 = (((params.ac1 * 4 + X3) << oss) + 2) >> 2;
printf("B3: %d | ", B3);
X1 = (params.ac3 * B6) >> 13;
printf("X1: %d | ", X1);
X2 = ((params.b1 * B6 * B6) >> 12) >> 16;
printf("X2: %d | ", X2);
X3 = ((X1 + X2) + 2) >> 2;
printf("X3: %d\n", X3);
uint32_t B4 = ((uint32_t)params.ac4 * (uint32_t)(X3 + 32768)) >> 15;
printf("B4: %d | ", B4);
uint32_t B7 = ((uint32_t)UP - B3) * (uint32_t)(50000UL >> oss);
printf("B7: %d\n ", B7);
int32_t p;
if (B7 < 0x80000000)
p = (B7 * 2) / B4;
else
p = (B7 / B4) * 2;
X1 = (p >> 8) * (p >> 8);
printf("X1: %d | ", X1);
X1 = (X1 * 3038) >> 16;
printf("X1: %d | ", X1);
X2 = (-7357 * p) >> 16;
printf("X2: %d\n", X1);
p = p + ((X1 + X2 + (int32_t)3791) >> 2);
printf("p: %d\n", p);
return p;
}
main.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <unistd.h>
#include <math.h>
#include <wiringx.h>
#include <bmp180.h>
/*
this part is required for compiler on duo with ubuntu
as I'm compiling it directly on the duo dev board.
*/
unsigned long __stack_chk_guard;
void __stack_chk_guard_setup(void)
{
__stack_chk_guard = 0xBAAAAAAD;//provide some magic numbers
}
void __stack_chk_fail(void)
{
printf("variable corrupted");
}// will be called when guard variable is corrupted
int bmp180_i2c;
struct bmp180_calib_param bmp180_calib_params;
int setup()
{
// wiringx setup to duo
printf("wiringXSetup duo\n");
if (wiringXSetup("duo", NULL) == -1)
{
wiringXGC();
return -1;
}
// bmp180 setup
printf("bmp180_setup\n");
bmp180_i2c = bmp180_setup(BMP180_ULTRALOWPOWER);
if (bmp180_i2c == -1)
exit(-1);
printf("bmp180 setup completed\n");
printf("reading bmp180 calibration parameters...\n");
bmp180_get_calib_params(bmp180_i2c, &bmp180_calib_params);
}
void loop()
{
int32_t temp = bmp180_get_temperature(bmp180_i2c, bmp180_calib_params);
int32_t pressure = bmp180_get_pressure(bmp180_i2c, bmp180_calib_params);
//long altitude_meters = 101325;
int32_t altitude_meters = 101500;
float sea_level_pressure = (int32_t) (pressure / pow(1.0 - altitude_meters / 44330, 5.255));
printf("sea_level_pressure: %f\n", sea_level_pressure);
float altitude = 44330 * (1.0 - pow(pressure / sea_level_pressure, 0.1903));
printf("Temperature: %d | ", temp);
printf("Pressure: %d | ", pressure);
printf("Altitude: %f ", altitude);
printf("\n");
}
int main()
{
if (setup() == -1)
{
printf("Setup failed\n");
return 0;
}
while(1)
{
loop();
delayMicroseconds(1500000);
}
}