Contiki-Inga 3.x
bmp085.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2012, TU Braunschweig.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the Institute nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29 
30 /**
31  * \file
32  * Bosch BMP085 Digital Pressure Sensor driver implementation
33  * \author
34  * Ulf Kulau <kulau@ibr.cs.tu-bs.de>
35  */
36 
37 /**
38  * \addtogroup bmp085_interface BMP085 Digital Pressure Sensor
39  */
40 
41 #include "bmp085.h"
42 
43 /*!
44  * I2C address to read data
45  */
46 #define BMP085_DEV_ADDR_R 0xEF
47 /*!
48  * I2C address to write data
49  */
50 #define BMP085_DEV_ADDR_W 0xEE
51 /*Control register address*/
52 /*!
53  * Basic control register address
54  */
55 #define BMP085_CTRL_REG_ADDR 0xF4
56 /*!
57  * Control register value for temperature
58  */
59 #define BMP085_CTRL_REG_TEMP 0x2E
60 /*!
61  * Control register value for oversampling mode 0
62  */
63 #define BMP085_CTRL_REG_PRESS_0 0x34
64 /*!
65  * Control register value for oversampling mode 1
66  */
67 #define BMP085_CTRL_REG_PRESS_1 0x74
68 /*!
69  * Control register value for oversampling mode 2
70  */
71 #define BMP085_CTRL_REG_PRESS_2 0xB4
72 /*!
73  * Control register value for oversampling mode 3
74  */
75 #define BMP085_CTRL_REG_PRESS_3 0xF4
76 /*Data register*/
77 /*!
78  * Main data register address
79  */
80 #define BMP085_DATA_REG_N 0xF6
81 /*!
82  * Extended data register address for 19bit
83  * resolution
84  */
85 #define BMP085_DATA_REG_X 0xF8
86 /*EEPROM Register addresses for calibration data*/
87 /*!
88  * Coefficient AC1 eeprom address
89  */
90 #define BMP085_AC1_ADDR 0xAA
91 /*!
92  * Coefficient AC2 eeprom address
93  */
94 #define BMP085_AC2_ADDR 0xAC
95 /*!
96  * Coefficient AC3 eeprom address
97  */
98 #define BMP085_AC3_ADDR 0xAE
99 /*!
100  * Coefficient AC4 eeprom address
101  */
102 #define BMP085_AC4_ADDR 0xB0
103 /*!
104  * Coefficient AC5 eeprom address
105  */
106 #define BMP085_AC5_ADDR 0xB2
107 /*!
108  * Coefficient AC6 eeprom address
109  */
110 #define BMP085_AC6_ADDR 0xB4
111 /*!
112  * Coefficient B1 eeprom address
113  */
114 #define BMP085_B1_ADDR 0xB6
115 /*!
116  * Coefficient B2 eeprom address
117  */
118 #define BMP085_B2_ADDR 0xB8
119 /*!
120  * Coefficient MB eeprom address
121  */
122 #define BMP085_MB_ADDR 0xBA
123 /*!
124  * Coefficient MC eeprom address
125  */
126 #define BMP085_MC_ADDR 0xBC
127 /*!
128  * Coefficient MD eeprom address
129  */
130 #define BMP085_MD_ADDR 0xBE
131 
132 /*!
133  * Hold all coefficients
134  */
135 typedef struct {
136  volatile int16_t ac1;
137  volatile int16_t ac2;
138  volatile int16_t ac3;
139  volatile uint16_t ac4;
140  volatile uint16_t ac5;
141  volatile uint16_t ac6;
142  volatile int16_t b1;
143  volatile int16_t b2;
144  volatile int16_t mb;
145  volatile int16_t mc;
146  volatile int16_t md;
147 } bmp085_calib_data;
148 
149 /*!
150  * Hold all coefficients
151  */
152 static bmp085_calib_data bmp085_coeff;
153 
154 static uint8_t bmp085_read8bit_data(uint8_t addr);
155 static uint16_t bmp085_read16bit_data(uint8_t addr);
156 static void bmp085_read_calib_data(void);
157 static int32_t bmp085_read_uncomp_pressure(uint8_t mode);
158 static int32_t bmp085_read_uncomp_temperature(void);
159 /*---------------------------------------------------------------------------*/
160 int8_t
162 {
163  uint8_t i = 0;
164 
165  i2c_init();
166  while (bmp085_read16bit_data(BMP085_AC1_ADDR) == 0x00) {
167  _delay_ms(10);
168  if (i++ > 10) {
169  return 0;
170  }
171  }
172  return 1;
173 }
174 /*---------------------------------------------------------------------------*/
175 int8_t
177 {
178  if (!bmp085_available()) {
179  return -1;
180  }
181  bmp085_read_calib_data();
182  return 0;
183 }
184 /*---------------------------------------------------------------------------*/
185 int8_t
187 {
188  return 0;
189 }
190 /*---------------------------------------------------------------------------*/
191 static int32_t
192 bmp085_read_uncomp_temperature(void)
193 {
194  i2c_start(BMP085_DEV_ADDR_W);
197  i2c_stop();
198  _delay_ms(5);
199  return (int32_t) (bmp085_read16bit_data(BMP085_DATA_REG_N));
200 }
201 /*---------------------------------------------------------------------------*/
202 static int32_t
203 bmp085_read_uncomp_pressure(uint8_t mode)
204 {
205  int32_t pressure;
206  i2c_start(BMP085_DEV_ADDR_W);
208  switch (mode) {
211  i2c_stop();
212  _delay_ms(5);
213  break;
214  case BMP085_STANDARD:
216  i2c_stop();
217  _delay_ms(8);
218  break;
221  i2c_stop();
222  _delay_ms(14);
223  break;
226  i2c_stop();
227  _delay_ms(26);
228  break;
229  }
230  pressure = (int32_t) bmp085_read16bit_data(BMP085_DATA_REG_N) << 8;
231  pressure += bmp085_read8bit_data(BMP085_DATA_REG_X);
232  return (pressure >> (8 - mode));
233 }
234 /*---------------------------------------------------------------------------*/
235 int16_t
237 {
238  int32_t ut = 0;
239  int32_t x1, x2, b5;
240 
241  ut = bmp085_read_uncomp_temperature();
242 
243  x1 = ((int32_t) ut - (int32_t) bmp085_coeff.ac6)
244  * (int32_t) bmp085_coeff.ac5 >> 15;
245  x2 = ((int32_t) bmp085_coeff.mc << 11) / (x1 + bmp085_coeff.md);
246  b5 = x1 + x2;
247 
248  return (int16_t) ((b5 + 8) >> 4);
249 }
250 /*---------------------------------------------------------------------------*/
251 int32_t
252 bmp085_read_pressure(uint8_t mode)
253 {
254  int32_t ut = 0, compt = 0;
255  int32_t up = 0, compp = 0;
256 
257  int32_t x1, x2, b5, b6, x3, b3, p;
258  uint32_t b4, b7;
259 
260  ut = bmp085_read_uncomp_temperature();
261  up = bmp085_read_uncomp_pressure(mode);
262 
263  x1 = ((int32_t) ut - (int32_t) bmp085_coeff.ac6)
264  * (int32_t) bmp085_coeff.ac5 >> 15;
265  x2 = ((int32_t) bmp085_coeff.mc << 11) / (x1 + bmp085_coeff.md);
266  b5 = x1 + x2;
267  compt = (b5 + 8) >> 4;
268 
269  b6 = b5 - 4000;
270  x1 = (bmp085_coeff.b2 * ((b6 * b6) >> 12)) >> 11;
271  x2 = (bmp085_coeff.ac2 * b6) >> 11;
272  x3 = x1 + x2;
273  b3 = (((((int32_t) bmp085_coeff.ac1) * 4 + x3) << mode) + 2) >> 2;
274  x1 = (bmp085_coeff.ac3 * b6) >> 13;
275  x2 = (bmp085_coeff.b1 * ((b6 * b6) >> 12)) >> 16;
276  x3 = ((x1 + x2) + 2) >> 2;
277  b4 = (bmp085_coeff.ac4 * (uint32_t) (x3 + 32768)) >> 15;
278  b7 = ((uint32_t) (up - b3) * (50000 >> mode));
279 
280  if (b7 < 0x80000000) {
281  p = (b7 << 1) / b4;
282  } else {
283  p = (b7 / b4) << 1;
284  }
285 
286  x1 = (p >> 8) * (p >> 8);
287  x1 = (x1 * 3038) >> 16;
288  x2 = (-7357 * p) >> 16;
289  compp = p + ((x1 + x2 + 3791) >> 4);
290  return compp;
291 }
292 /*---------------------------------------------------------------------------*/
293 static void
294 bmp085_read_calib_data(void)
295 {
296  bmp085_coeff.ac1 = bmp085_read16bit_data(BMP085_AC1_ADDR);
297  bmp085_coeff.ac2 = bmp085_read16bit_data(BMP085_AC2_ADDR);
298  bmp085_coeff.ac3 = bmp085_read16bit_data(BMP085_AC3_ADDR);
299  bmp085_coeff.ac4 = bmp085_read16bit_data(BMP085_AC4_ADDR);
300  bmp085_coeff.ac5 = bmp085_read16bit_data(BMP085_AC5_ADDR);
301  bmp085_coeff.ac6 = bmp085_read16bit_data(BMP085_AC6_ADDR);
302  bmp085_coeff.b1 = bmp085_read16bit_data(BMP085_B1_ADDR);
303  bmp085_coeff.b2 = bmp085_read16bit_data(BMP085_B2_ADDR);
304  bmp085_coeff.mb = bmp085_read16bit_data(BMP085_MB_ADDR);
305  bmp085_coeff.mc = bmp085_read16bit_data(BMP085_MC_ADDR);
306  bmp085_coeff.md = bmp085_read16bit_data(BMP085_MD_ADDR);
307 }
308 /*---------------------------------------------------------------------------*/
309 static uint16_t
310 bmp085_read16bit_data(uint8_t addr)
311 {
312  uint8_t msb = 0, lsb = 0;
313  i2c_start(BMP085_DEV_ADDR_W);
314  i2c_write(addr);
315  i2c_rep_start(BMP085_DEV_ADDR_R);
316  i2c_read_ack(&msb);
317  i2c_read_nack(&lsb);
318  i2c_stop();
319  return (uint16_t) ((msb << 8) | lsb);
320 }
321 /*---------------------------------------------------------------------------*/
322 static uint8_t
323 bmp085_read8bit_data(uint8_t addr)
324 {
325  uint8_t lsb = 0;
326  i2c_start(BMP085_DEV_ADDR_W);
327  i2c_write(addr);
328  i2c_rep_start(BMP085_DEV_ADDR_R);
329  i2c_read_nack(&lsb);
330  i2c_stop();
331  return lsb;
332 }