ddr4s / fw / wiringPi / wiringPi / bmp180.c @ 32:cadb9025f1e0
History  View  Annotate  Download (6 KB)
1 
/*


2 
* bmp180.c:

3 
* Extend wiringPi with the BMP180 I2C Pressure and Temperature

4 
* sensor. This is used in the Pi Weather Station

5 
* Copyright (c) 2016 Gordon Henderson

6 
*

7 
* Information from the document held at:

8 
* http://wmrx00.sourceforge.net/Arduino/BMP085Calcs.pdf

9 
* was very useful when building this code.

10 
*

11 
***********************************************************************

12 
* This file is part of wiringPi:

13 
* https://projects.drogon.net/raspberrypi/wiringpi/

14 
*

15 
* wiringPi is free software: you can redistribute it and/or modify

16 
* it under the terms of the GNU Lesser General Public License as

17 
* published by the Free Software Foundation, either version 3 of the

18 
* License, or (at your option) any later version.

19 
*

20 
* wiringPi is distributed in the hope that it will be useful,

21 
* but WITHOUT ANY WARRANTY; without even the implied warranty of

22 
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the

23 
* GNU Lesser General Public License for more details.

24 
*

25 
* You should have received a copy of the GNU Lesser General Public

26 
* License along with wiringPi.

27 
* If not, see <http://www.gnu.org/licenses/>.

28 
***********************************************************************

29 
*/

30  
31 
#include <unistd.h> 
32 
#include <stdint.h> 
33 
#include <stdio.h> 
34 
#include <math.h> 
35  
36 
#include "wiringPi.h" 
37 
#include "wiringPiI2C.h" 
38  
39 
#include "bmp180.h" 
40  
41 
#undef DEBUG

42  
43 
#define I2C_ADDRESS 0x77 
44 
#define BMP180_OSS 0 
45  
46  
47 
// Static calibration data

48 
// The downside of this is that there can only be one BMP180 in

49 
// a system  which is practice isn't an issue as it's I2C

50 
// address is fixed.

51  
52 
static int16_t AC1, AC2, AC3 ;

53 
static uint16_t AC4, AC5, AC6 ;

54 
static int16_t VB1, VB2 ;

55 
static int16_t MB, MC, MD ;

56  
57 
static double c5, c6, mc, md, x0, x1, x2, yy0, yy1, yy2, p0, p1, p2 ; 
58  
59 
// Pressure & Temp variables

60  
61 
uint32_t cPress, cTemp ; 
62  
63 
static int altitude ; 
64  
65 
/*

66 
* read16:

67 
* Quick hack to read the 16bit data with the correct endian

68 
*********************************************************************************

69 
*/

70  
71 
uint16_t read16 (int fd, int reg) 
72 
{ 
73 
return (wiringPiI2CReadReg8 (fd, reg) << 8)  wiringPiI2CReadReg8 (fd, reg + 1) ; 
74  
75 
} 
76  
77  
78 
/*

79 
* bmp180ReadTempPress:

80 
* Does the hard work of reading the sensor

81 
*********************************************************************************

82 
*/

83  
84 
static void bmp180ReadTempPress (int fd) 
85 
{ 
86 
double fTemp, fPress ;

87 
double tu, a ;

88 
double pu, s, x, y, z ;

89  
90 
uint8_t data [4] ;

91  
92 
// Start a temperature sensor reading

93  
94 
wiringPiI2CWriteReg8 (fd, 0xF4, 0x2E) ; 
95 
delay (5) ;

96  
97 
// Read the raw data

98  
99 
data [0] = wiringPiI2CReadReg8 (fd, 0xF6) ; 
100 
data [1] = wiringPiI2CReadReg8 (fd, 0xF7) ; 
101  
102 
// And calculate...

103  
104 
tu = (data [0] * 256.0) + data [1] ; 
105  
106 
a = c5 * (tu  c6) ; 
107 
fTemp = a + (mc / (a + md)) ; 
108 
cTemp = (int)rint (((100.0 * fTemp) + 0.5) / 10.0) ; 
109  
110 
#ifdef DEBUG

111 
printf ("fTemp: %f, cTemp: %6d\n", fTemp, cTemp) ;

112 
#endif

113  
114 
// Start a pressure snsor reading

115  
116 
wiringPiI2CWriteReg8 (fd, 0xF4, 0x34  (BMP180_OSS << 6)) ; 
117 
delay (5) ;

118  
119 
// Read the raw data

120  
121 
data [0] = wiringPiI2CReadReg8 (fd, 0xF6) ; 
122 
data [1] = wiringPiI2CReadReg8 (fd, 0xF7) ; 
123 
data [2] = wiringPiI2CReadReg8 (fd, 0xF8) ; 
124  
125 
// And calculate...

126  
127 
pu = ((double)data [0] * 256.0) + (double)data [1] + ((double)data [2] / 256.0) ; 
128 
s = fTemp  25.0 ; 
129 
x = (x2 * pow (s, 2.0)) + (x1 * s) + x0 ; 
130 
y = (yy2 * pow (s, 2.0)) + (yy1 * s) + yy0 ; 
131 
z = (pu  x) / y ; 
132 
fPress = (p2 * pow (z, 2.0)) + (p1 * z) + p0 ; 
133 
cPress = (int)rint (((100.0 * fPress) + 0.5) / 10.0) ; 
134  
135 
#ifdef DEBUG

136 
printf ("fPress: %f, cPress: %6d\n", fPress, cPress) ;

137 
#endif

138 
} 
139  
140  
141 
/*

142 
* myAnalogWrite:

143 
* Write to a fake register to represent the height above sea level

144 
* so that the peudo millibar register can read the pressure in mB

145 
*********************************************************************************

146 
*/

147  
148 
static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) 
149 
{ 
150 
int chan = pin  node>pinBase ;

151  
152 
if (chan == 0) 
153 
altitude = value ; 
154 
} 
155  
156 
/*

157 
* myAnalogRead:

158 
*********************************************************************************

159 
*/

160  
161 
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) 
162 
{ 
163 
int chan = pin  node>pinBase ;

164  
165 
bmp180ReadTempPress (node>fd) ; 
166  
167 
/**/ if (chan == 0) // Read Temperature 
168 
return cTemp ;

169 
else if (chan == 1) // Pressure 
170 
return cPress ;

171 
else if (chan == 2) // Pressure in mB 
172 
return cPress / pow (1  ((double)altitude / 44330.0), 5.255) ; 
173 
else

174 
return 9999 ; 
175  
176 
} 
177  
178  
179 
/*

180 
* bmp180Setup:

181 
* Create a new instance of a PCF8591 I2C GPIO interface. We know it

182 
* has 4 pins, (4 analog inputs and 1 analog output which we'll shadow

183 
* input 0) so all we need to know here is the I2C address and the

184 
* userdefined pin base.

185 
*********************************************************************************

186 
*/

187  
188 
int bmp180Setup (const int pinBase) 
189 
{ 
190 
double c3, c4, b1 ;

191 
int fd ;

192 
struct wiringPiNodeStruct *node ;

193  
194 
if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0) 
195 
return FALSE ;

196  
197 
node = wiringPiNewNode (pinBase, 4) ;

198  
199 
node>fd = fd ; 
200 
node>analogRead = myAnalogRead ; 
201 
node>analogWrite = myAnalogWrite ; 
202  
203 
// Read calibration data

204  
205 
AC1 = read16 (fd, 0xAA) ;

206 
AC2 = read16 (fd, 0xAC) ;

207 
AC3 = read16 (fd, 0xAE) ;

208 
AC4 = read16 (fd, 0xB0) ;

209 
AC5 = read16 (fd, 0xB2) ;

210 
AC6 = read16 (fd, 0xB4) ;

211 
VB1 = read16 (fd, 0xB6) ;

212 
VB2 = read16 (fd, 0xB8) ;

213 
MB = read16 (fd, 0xBA) ;

214 
MC = read16 (fd, 0xBC) ;

215 
MD = read16 (fd, 0xBE) ;

216  
217 
// Calculate coefficients

218  
219 
c3 = 160.0 * pow (2.0, 15.0) * AC3 ; 
220 
c4 = pow (10.0, 3.0) * pow(2.0,15.0) * AC4 ; 
221 
b1 = pow (160.0, 2.0) * pow(2.0,30.0) * VB1 ; 
222 
c5 = (pow (2.0, 15.0) / 160.0) * AC5 ; 
223 
c6 = AC6 ; 
224 
mc = (pow (2.0, 11.0) / pow(160.0,2.0)) * MC ; 
225 
md = MD / 160.0 ; 
226 
x0 = AC1 ; 
227 
x1 = 160.0 * pow (2.0, 13.0) * AC2 ; 
228 
x2 = pow (160.0, 2.0) * pow(2.0,25.0) * VB2 ; 
229 
yy0 = c4 * pow (2.0, 15.0) ; 
230 
yy1 = c4 * c3 ; 
231 
yy2 = c4 * b1 ; 
232 
p0 = (3791.0  8.0) / 1600.0 ; 
233 
p1 = 1.0  7357.0 * pow (2.0, 20.0) ; 
234 
p2 = 3038.0 * 100.0 * pow (2.0, 36.0) ; 
235  
236 
return TRUE ;

237 
} 