bmp085.c


1
/*
2
bmp085 lib 0x01
3
4
copyright (c) Davide Gironi, 2012
5
6
Released under GPLv3.
7
Please refer to LICENSE file for licensing information.
8
*/
9
10
11
#include <stdio.h>
12
#include <stdlib.h>
13
#include <string.h>
14
#include <math.h>
15
#include <avr/io.h>
16
#include <util/delay.h>
17
18
#include "bmp085.h"
19
20
//path to i2c fleury lib
21
#include BMP085_I2CFLEURYPATH
22
23
/*
24
 * i2c write
25
 */
26
void bmp085_writemem(uint8_t reg, uint8_t value) {
27
  i2c_start_wait(BMP085_ADDR | I2C_WRITE);
28
  i2c_write(reg);
29
  i2c_write(value);
30
  i2c_stop();
31
}
32
33
/*
34
 * i2c read
35
 */
36
void bmp085_readmem(uint8_t reg, uint8_t buff[], uint8_t bytes) {
37
  uint8_t i =0;
38
  i2c_start_wait(BMP085_ADDR | I2C_WRITE);
39
  i2c_write(reg);
40
  i2c_rep_start(BMP085_ADDR | I2C_READ);
41
  for(i=0; i<bytes; i++) {
42
    if(i==bytes-1)
43
      buff[i] = i2c_readNak();
44
    else
45
      buff[i] = i2c_readAck();
46
  }
47
  i2c_stop();
48
}
49
50
51
#if BMP085_FILTERPRESSURE == 1
52
#define BMP085_AVARAGECOEF 21
53
static long k[BMP085_AVARAGECOEF];
54
long bmp085_avaragefilter(long input) {
55
  uint8_t i=0;
56
  long sum=0;
57
  for (i=0; i<BMP085_AVARAGECOEF; i++) {
58
    k[i] = k[i+1];
59
  }
60
  k[BMP085_AVARAGECOEF-1] = input;
61
  for (i=0; i<BMP085_AVARAGECOEF; i++) {
62
    sum += k[i];
63
  }
64
  return (sum /BMP085_AVARAGECOEF) ;
65
}
66
#endif
67
68
/*
69
 * read calibration registers
70
 */
71
void bmp085_getcalibration() {
72
  uint8_t buff[2];
73
  memset(buff, 0, sizeof(buff));
74
75
  bmp085_readmem(BMP085_REGAC1, buff, 2);
76
  bmp085_regac1 = ((int)buff[0] <<8 | ((int)buff[1]));
77
  bmp085_readmem(BMP085_REGAC2, buff, 2);
78
  bmp085_regac2 = ((int)buff[0] <<8 | ((int)buff[1]));
79
  bmp085_readmem(BMP085_REGAC3, buff, 2);
80
  bmp085_regac3 = ((int)buff[0] <<8 | ((int)buff[1]));
81
  bmp085_readmem(BMP085_REGAC4, buff, 2);
82
  bmp085_regac4 = ((unsigned int)buff[0] <<8 | ((unsigned int)buff[1]));
83
  bmp085_readmem(BMP085_REGAC5, buff, 2);
84
  bmp085_regac5 = ((unsigned int)buff[0] <<8 | ((unsigned int)buff[1]));
85
  bmp085_readmem(BMP085_REGAC6, buff, 2);
86
  bmp085_regac6 = ((unsigned int)buff[0] <<8 | ((unsigned int)buff[1]));
87
  bmp085_readmem(BMP085_REGB1, buff, 2);
88
  bmp085_regb1 = ((int)buff[0] <<8 | ((int)buff[1]));
89
  bmp085_readmem(BMP085_REGB2, buff, 2);
90
  bmp085_regb2 = ((int)buff[0] <<8 | ((int)buff[1]));
91
  bmp085_readmem(BMP085_REGMB, buff, 2);
92
  bmp085_regmb = ((int)buff[0] <<8 | ((int)buff[1]));
93
  bmp085_readmem(BMP085_REGMC, buff, 2);
94
  bmp085_regmc = ((int)buff[0] <<8 | ((int)buff[1]));
95
  bmp085_readmem(BMP085_REGMD, buff, 2);
96
  bmp085_regmd = ((int)buff[0] <<8 | ((int)buff[1]));
97
}
98
99
/*
100
 * get raw temperature as read by registers, and do some calculation to convert it
101
 */
102
void bmp085_getrawtemperature() {
103
  uint8_t buff[2];
104
  memset(buff, 0, sizeof(buff));
105
  long ut,x1,x2;
106
107
  //read raw temperature
108
  bmp085_writemem(BMP085_REGCONTROL, BMP085_REGREADTEMPERATURE);
109
  _delay_ms(5); // min. 4.5ms read Temp delay
110
  bmp085_readmem(BMP085_REGCONTROLOUTPUT, buff, 2);
111
  ut = ((long)buff[0] << 8 | ((long)buff[1])); //uncompensated temperature value
112
113
  //calculate raw temperature
114
  x1 = ((long)ut - bmp085_regac6) * bmp085_regac5 >> 15;
115
  x2 = ((long)bmp085_regmc << 11) / (x1 + bmp085_regmd);
116
  bmp085_rawtemperature = x1 + x2;
117
}
118
119
/*
120
 * get raw pressure as read by registers, and do some calculation to convert it
121
 */
122
void bmp085_getrawpressure() {
123
  uint8_t buff[3];
124
  memset(buff, 0, sizeof(buff));
125
  long up,x1,x2,x3,b3,b6,p;
126
  unsigned long b4,b7;
127
128
  #if BMP085_AUTOUPDATETEMP == 1
129
  bmp085_getrawtemperature();
130
  #endif
131
132
  //read raw pressure
133
  bmp085_writemem(BMP085_REGCONTROL, BMP085_REGREADPRESSURE+(BMP085_MODE << 6));
134
  _delay_ms(2 + (3<<BMP085_MODE));
135
  bmp085_readmem(BMP085_REGCONTROLOUTPUT, buff, 3);
136
  up = ((((long)buff[0] <<16) | ((long)buff[1] <<8) | ((long)buff[2])) >> (8-BMP085_MODE)); // uncompensated pressure value
137
138
  //calculate raw pressure
139
  b6 = bmp085_rawtemperature - 4000;
140
  x1 = (bmp085_regb2* (b6 * b6) >> 12) >> 11;
141
  x2 = (bmp085_regac2 * b6) >> 11;
142
  x3 = x1 + x2;
143
  b3 = (((((long)bmp085_regac1) * 4 + x3) << BMP085_MODE) + 2) >> 2;
144
  x1 = (bmp085_regac3 * b6) >> 13;
145
  x2 = (bmp085_regb1 * ((b6 * b6) >> 12)) >> 16;
146
  x3 = ((x1 + x2) + 2) >> 2;
147
  b4 = (bmp085_regac4 * (uint32_t)(x3 + 32768)) >> 15;
148
  b7 = ((uint32_t)up - b3) * (50000 >> BMP085_MODE);
149
  p = b7 < 0x80000000 ? (b7 << 1) / b4 : (b7 / b4) << 1;
150
  x1 = (p >> 8) * (p >> 8);
151
  x1 = (x1 * 3038) >> 16;
152
  x2 = (-7357 * p) >> 16;
153
  bmp085_rawpressure = p + ((x1 + x2 + 3791) >> 4);
154
155
  #if BMP085_FILTERPRESSURE == 1
156
  bmp085_rawpressure = bmp085_avaragefilter(bmp085_rawpressure);
157
  #endif
158
}
159
160
/*
161
 * get celsius temperature
162
 */
163
double bmp085_gettemperature() {
164
  bmp085_getrawtemperature();
165
  double temperature = ((bmp085_rawtemperature + 8)>>4);
166
  temperature = temperature /10;
167
  return temperature;
168
}
169
170
/*
171
 * get pressure
172
 */
173
int32_t bmp085_getpressure() {
174
  bmp085_getrawpressure();
175
  return bmp085_rawpressure + BMP085_UNITPAOFFSET;
176
}
177
178
/*
179
 * get altitude
180
 */
181
double bmp085_getaltitude() {
182
  bmp085_getrawpressure();
183
  return ((1 - pow(bmp085_rawpressure/(double)101325, 0.1903 )) / 0.0000225577) + BMP085_UNITMOFFSET;
184
}
185
186
/*
187
 * init bmp085
188
 */
189
void bmp085_init() {
190
  #if BMP085_I2CINIT == 1
191
  //init i2c
192
  i2c_init();
193
  _delay_us(10);
194
  #endif
195
196
  bmp085_getcalibration(); //get calibration data
197
  bmp085_getrawtemperature(); //update raw temperature, at least the first time
198
199
  #if BMP085_FILTERPRESSURE == 1
200
  //initialize the avarage filter
201
  uint8_t i=0;
202
  for (i=0; i<BMP085_AVARAGECOEF; i++) {
203
    bmp085_getrawpressure();
204
  }
205
  #endif
206
}