/* Copyright 2012, Sebastian Reichel * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ public class BMP085 : I2CDevice, Barometer { public uint8 oversampling_setting = 0x03; private Calibration cal = Calibration(); private int64 next_temp_measurement; private int raw_temp; private int raw_pressure; private int64 temp_correction_coefficient; struct Calibration { int16 AC1; int16 AC2; int16 AC3; uint16 AC4; uint16 AC5; uint16 AC6; int16 B1; int16 B2; int16 MB; int16 MC; int16 MD; } public BMP085(uint8 dev, uint8 addr = 0x77) throws I2CError { base(dev, addr); read_calibration_values(); } private void read_calibration_values() throws I2CError { var data = get_block(0xaa, 22); cal.AC1 = data[0] << 8 | data[1]; cal.AC2 = data[2] << 8 | data[3]; cal.AC3 = data[4] << 8 | data[5]; cal.AC4 = data[6] << 8 | data[7]; cal.AC5 = data[8] << 8 | data[9]; cal.AC6 = data[10] << 8 | data[11]; cal.B1 = data[12] << 8 | data[13]; cal.B2 = data[14] << 8 | data[15]; cal.MB = data[16] << 8 | data[17]; cal.MC = data[18] << 8 | data[19]; cal.MD = data[20] << 8 | data[21]; } private void msleep(uint msecs) { Posix.usleep(msecs*1000); } private void update_raw_temperature() throws I2CError { set_byte(0xf4, 0x2e); msleep(5); var data = get_block(0xf6, 2); raw_temp = data[0] << 8 | data[1]; next_temp_measurement = time_t() + 1; } private void update_raw_pressure() throws I2CError { set_byte(0xf4, 0x34 + (oversampling_setting<<6)); msleep(2+(3 << oversampling_setting<<1)); var data = get_block(0xf6, 3); raw_pressure = data[0] << 16 | data[1] << 8 | data[2]; raw_pressure >>= 8-oversampling_setting; } public int32 get_temperature() throws I2CError { if(next_temp_measurement+1 < time_t()) update_raw_temperature(); int64 x1 = ((raw_temp - cal.AC6) * cal.AC5) >> 15; int64 x2 = (cal.MC << 11) / (x1 + cal.MD); temp_correction_coefficient = x1 + x2 - 4000; return (int32) (x1+x2+8) >> 4; } public int32 get_pressure() throws I2CError { int64 x1, x2, x3, b3, p; uint64 b4, b7; if(next_temp_measurement+1 < time_t()) get_temperature(); update_raw_pressure(); x1 = (temp_correction_coefficient * temp_correction_coefficient) >> 12; x1 *= cal.B2; x1 >>= 11; x2 = cal.AC2 * temp_correction_coefficient; x2 >>= 11; x3 = x1 + x2; b3 = (((((int64)cal.AC1) * 4 + x3) << oversampling_setting) + 2) >> 2; x1 = (cal.AC3 * temp_correction_coefficient) >> 13; x2 = (cal.B1 * ((temp_correction_coefficient * temp_correction_coefficient) >> 12)) >> 16; x3 = (x1 + x2 + 2) >> 2; b4 = (cal.AC4 * (uint64)(x3 + 32768)) >> 15; b7 = ((uint64)raw_pressure - b3) * (50000 >> oversampling_setting); p = (int64) ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2)); x1 = p >> 8; x1 *= x1; x1 = (x1 * 3038) >> 16; x2 = (-7357 * p) >> 16; p += (x1 + x2 + 3791) >> 4; return (int32) p; } }