summaryrefslogtreecommitdiffstats
path: root/sensors/barometer/bmp085.vala
diff options
context:
space:
mode:
Diffstat (limited to 'sensors/barometer/bmp085.vala')
-rw-r--r--sensors/barometer/bmp085.vala140
1 files changed, 140 insertions, 0 deletions
diff --git a/sensors/barometer/bmp085.vala b/sensors/barometer/bmp085.vala
new file mode 100644
index 0000000..f0da790
--- /dev/null
+++ b/sensors/barometer/bmp085.vala
@@ -0,0 +1,140 @@
+/* Copyright 2012, Sebastian Reichel <sre@ring0.de>
+ *
+ * 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 {
+ setup(dev, addr);
+ read_calibration_values();
+ }
+
+ public void init(KeyFile cfg) throws KeyFileError, I2CError {
+ var adapter = cfg.get_uint64("BMP085", "i2c-adapter");
+ var address = cfg.get_uint64("BMP085", "i2c-address");
+ setup((uint8) adapter, (uint8) address);
+ 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;
+ }
+}
+
+public Type register_plugin (Module module) {
+ // types are registered automatically
+ return typeof(BMP085);
+}