Arduino-TWI
Two-Wire Interface (TWI) library for Arduino
BMP085.h
Go to the documentation of this file.
1 
19 #ifndef BMP085_H
20 #define BMP085_H
21 
22 #include "TWI.h"
23 
50 class BMP085 : protected TWI::Device {
51 public:
55  enum Mode {
57  STANDARD = 1,
60  } __attribute__((packed));
61 
67  TWI::Device(twi, 0x77),
69  m_cmd(0),
70  m_start(0),
71  B5(0),
72  m_pressure(0)
73  {}
74 
81  bool begin(Mode mode = ULTRA_LOW_POWER)
82  {
83  // Set the operation mode
84  m_mode = mode;
85 
86  // Read coefficients from the device
87  if (!acquire()) return (false);
88  uint8_t reg = COEFF_REG;
89  write(&reg, sizeof(reg));
90  int res = read(&m_param, sizeof(m_param));
91  if (!release()) return (false);
92  if (res != sizeof(m_param)) return (false);
93 
94  // Adjust coefficients to little endian
95  uint16_t* p = (uint16_t*) &m_param;
96  for (size_t i = 0; i < sizeof(param_t) / sizeof(uint16_t); i++, p++)
97  *p = bswap16(*p);
98 
99  return (true);
100  }
101 
108  {
109  // Check that a conversion request is not in process
110  if (m_cmd != 0) return (false);
111 
112  // Start a temperature measurement and wait
114  uint8_t req[2] = { CMD_REG, m_cmd };
115  if (!acquire()) return (false);
116  write(req, sizeof(req));
117  if (!release()) return (false);
118 
119  // Set start time for completion
120  m_start = millis();
121  return (true);
122  }
123 
130  {
131  // Check that a temperature conversion request was issued
132  if (m_cmd != TEMP_CONV_CMD) return (false);
133  m_cmd = 0;
134 
135  // Check if we need to wait for the conversion to complete
136  uint16_t run = millis() - m_start;
137  if (run < TEMP_CONV_MS) delay(TEMP_CONV_MS - run);
138 
139  // Read the raw temperature sensor data
140  uint8_t reg = RES_REG;
141  int16_t UT;
142  if (!acquire()) return (false);
143  write(&reg, sizeof(reg));
144  read(&UT, sizeof(UT));
145  if (!release()) return (false);
146 
147  // Adjust for little-endian
148  UT = bswap16(UT);
149 
150  // Temperature calculation
151  int32_t X1 = ((((int32_t) UT) - m_param.ac6) * m_param.ac5) >> 15;
152  int32_t X2 = (((int32_t) m_param.mc) << 11) / (X1 + m_param.md);
153  B5 = X1 + X2;
154  return (true);
155  }
156 
163  {
165  }
166 
173  {
174  // Check that a conversion request is not in process
175  if (m_cmd != 0) return (false);
176 
177  // Start a pressure measurement
178  if (!acquire()) return (false);
179  m_cmd = PRESSURE_CONV_CMD + (m_mode << 6);
180  uint8_t req[2] = { CMD_REG, m_cmd };
181  write(&req, sizeof(req));
182  if (!release()) return (false);
183 
184  // Set start time for completion
185  m_start = millis();
186  return (true);
187  }
188 
195  {
197  static const uint8_t PRESSURE_CONV_MS[] PROGMEM = {
198  5, 8, 14, 26
199  };
200 
201  // Check that a conversion request was issued
202  if (m_cmd != (PRESSURE_CONV_CMD + (m_mode << 6))) return (false);
203  m_cmd = 0;
204 
205  // Check if we need to wait for the conversion to complete
206  uint16_t run = millis() - m_start;
207  uint16_t ms = pgm_read_byte(&PRESSURE_CONV_MS[m_mode]);
208  if (run < ms) delay(ms - run);
209 
210  // Read the raw pressure sensor data
211  union {
212  uint32_t as_int32;
213  uint8_t as_uint8[4];
214  } res;
215  res.as_uint8[0] = 0;
216  uint8_t reg = RES_REG;
217  if (!acquire()) return (false);
218  write(&reg, sizeof(reg));
219  read(&res.as_uint8[1], 3);
220  if (!release()) return (false);
221 
222  // Adjust for little endian and resolution (oversampling mode)
223  int32_t UP = bswap32(res.as_int32) >> (8 - m_mode);
224  int32_t B3, B6, X1, X2, X3;
225  uint32_t B4, B7;
226 
227  // Pressure calculation
228  B6 = B5 - 4000;
229  X1 = (m_param.b2 * ((B6 * B6) >> 12)) >> 11;
230  X2 = (m_param.ac2 * B6) >> 11;
231  X3 = X1 + X2;
232  B3 = ((((((int32_t) m_param.ac1) << 2) + X3) << m_mode) + 2) >> 2;
233  X1 = (m_param.ac3 * B6) >> 13;
234  X2 = (m_param.b1 * ((B6 * B6) >> 12)) >> 16;
235  X3 = ((X1 + X2) + 2) >> 2;
236  B4 = (m_param.ac4 * (uint32_t) (X3 + 32768)) >> 15;
237  B7 = ((uint32_t) UP - B3) * (50000 >> m_mode);
238  m_pressure = (B7 < 0x80000000) ? (B7 << 1) / B4 : (B7 / B4) << 1;
239  X1 = (m_pressure >> 8) * (m_pressure >> 8);
240  X1 = (X1 * 3038) >> 16;
241  X2 = (-7357 * m_pressure) >> 16;
242  m_pressure += (X1 + X2 + 3791) >> 4;
243 
244  return (true);
245  }
246 
253  __attribute__((always_inline))
254  {
255  return (sample_pressure_request() && read_pressure());
256  }
257 
264  bool sample()
265  __attribute__((always_inline))
266  {
267  return (sample_temperature() && sample_pressure());
268  }
269 
274  int16_t temperature() const
275  __attribute__((always_inline))
276  {
277  return ((B5 + 8) >> 4);
278  }
279 
285  int32_t pressure() const
286  {
287  return (m_pressure);
288  }
289 
290 protected:
292  static const uint16_t TEMP_CONV_MS = 5;
293 
298  struct param_t {
299  int16_t ac1;
300  int16_t ac2;
301  int16_t ac3;
302  uint16_t ac4;
303  uint16_t ac5;
304  uint16_t ac6;
305  int16_t b1;
306  int16_t b2;
307  int16_t mb;
308  int16_t mc;
309  int16_t md;
310  } __attribute__((packed));
311 
316  enum reg_t {
317  COEFF_REG = 0xAA,
318  CMD_REG = 0xF4,
319  RES_REG = 0xF6
320  } __attribute__((packed));
321 
325  enum cmd_t {
326  TEMP_CONV_CMD = 0x2E,
328  } __attribute__((packed));
329 
332 
335 
337  uint8_t m_cmd;
338 
340  uint16_t m_start;
341 
343  int32_t B5;
344 
346  int32_t m_pressure;
347 };
348 
349 #endif
Definition: TWI.h:28
uint16_t ac4
Definition: BMP085.h:302
BMP085(TWI &twi)
Definition: BMP085.h:66
uint16_t m_start
Definition: BMP085.h:340
static const uint16_t TEMP_CONV_MS
Definition: BMP085.h:292
int16_t ac3
Definition: BMP085.h:301
bool release()
Definition: TWI.h:62
uint8_t m_cmd
Definition: BMP085.h:337
int32_t B5
Definition: BMP085.h:343
Temperature conversion command.
Definition: BMP085.h:326
bool sample_pressure_request()
Definition: BMP085.h:172
bool sample_temperature()
Definition: BMP085.h:162
Result register address (16-bit).
Definition: BMP085.h:319
bool begin(Mode mode=ULTRA_LOW_POWER)
Definition: BMP085.h:81
bool read_pressure()
Definition: BMP085.h:194
int16_t mc
Definition: BMP085.h:308
int32_t pressure() const
Definition: BMP085.h:285
param_t m_param
Definition: BMP085.h:331
int32_t m_pressure
Definition: BMP085.h:346
int16_t md
Definition: BMP085.h:309
cmd_t
Definition: BMP085.h:325
Mode
Definition: BMP085.h:55
Pressure conversion command.
Definition: BMP085.h:327
int16_t ac2
Definition: BMP085.h:300
Hardware::TWI twi(100000UL)
int16_t ac1
Definition: BMP085.h:299
Command register address (8-bit).
Definition: BMP085.h:318
bool sample_pressure()
Definition: BMP085.h:252
reg_t
Definition: BMP085.h:316
bool sample_temperature_request()
Definition: BMP085.h:107
Mode m_mode
Definition: BMP085.h:334
bool sample()
Definition: BMP085.h:264
uint16_t ac5
Definition: BMP085.h:303
int write(const void *buf, size_t count)
Definition: TWI.h:84
Device(TWI &twi, uint8_t addr)
Definition: TWI.h:41
int16_t temperature() const
Definition: BMP085.h:274
bool acquire()
Definition: TWI.h:52
uint16_t ac6
Definition: BMP085.h:304
int read(void *buf, size_t count)
Definition: TWI.h:73
bool read_temperature()
Definition: BMP085.h:129
Calibration coefficients register address.
Definition: BMP085.h:317
int16_t b2
Definition: BMP085.h:306
Definition: BMP085.h:50
int16_t b1
Definition: BMP085.h:305
int16_t mb
Definition: BMP085.h:307