Skip to content

Commit e462bc2

Browse files
committed
Added libraries for SPI flash, BMP180 and Si7021
1 parent 08221e6 commit e462bc2

File tree

16 files changed

+2028
-0
lines changed

16 files changed

+2028
-0
lines changed

libraries/SFE_BMP180/SFE_BMP180.cpp

Lines changed: 387 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,387 @@
1+
/*
2+
SFE_BMP180.cpp
3+
Bosch BMP180 pressure sensor library for the Arduino microcontroller
4+
Mike Grusin, SparkFun Electronics
5+
6+
Uses floating-point equations from the Weather Station Data Logger project
7+
http://wmrx00.sourceforge.net/
8+
http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf
9+
10+
Forked from BMP085 library by M.Grusin
11+
12+
version 1.0 2013/09/20 initial version
13+
14+
Our example code uses the "beerware" license. You can do anything
15+
you like with this code. No really, anything. If you find it useful,
16+
buy me a (root) beer someday.
17+
*/
18+
19+
#include <SFE_BMP180.h>
20+
#include <Wire.h>
21+
#include <stdio.h>
22+
#include <math.h>
23+
24+
25+
SFE_BMP180::SFE_BMP180()
26+
// Base library type
27+
{
28+
}
29+
30+
31+
char SFE_BMP180::begin()
32+
// Initialize library for subsequent pressure measurements
33+
{
34+
double c3,c4,b1;
35+
36+
// Start up the Arduino's "wire" (I2C) library:
37+
38+
Wire.begin();
39+
40+
// The BMP180 includes factory calibration data stored on the device.
41+
// Each device has different numbers, these must be retrieved and
42+
// used in the calculations when taking pressure measurements.
43+
44+
// Retrieve calibration data from device:
45+
46+
if (readInt(0xAA,AC1) &&
47+
readInt(0xAC,AC2) &&
48+
readInt(0xAE,AC3) &&
49+
readUInt(0xB0,AC4) &&
50+
readUInt(0xB2,AC5) &&
51+
readUInt(0xB4,AC6) &&
52+
readInt(0xB6,VB1) &&
53+
readInt(0xB8,VB2) &&
54+
readInt(0xBA,MB) &&
55+
readInt(0xBC,MC) &&
56+
readInt(0xBE,MD))
57+
{
58+
59+
// All reads completed successfully!
60+
61+
// If you need to check your math using known numbers,
62+
// you can uncomment one of these examples.
63+
// (The correct results are commented in the below functions.)
64+
65+
// Example from Bosch datasheet
66+
// AC1 = 408; AC2 = -72; AC3 = -14383; AC4 = 32741; AC5 = 32757; AC6 = 23153;
67+
// B1 = 6190; B2 = 4; MB = -32768; MC = -8711; MD = 2868;
68+
69+
// Example from http://wmrx00.sourceforge.net/Arduino/BMP180-Calcs.pdf
70+
// AC1 = 7911; AC2 = -934; AC3 = -14306; AC4 = 31567; AC5 = 25671; AC6 = 18974;
71+
// VB1 = 5498; VB2 = 46; MB = -32768; MC = -11075; MD = 2432;
72+
73+
/*
74+
Serial.print("AC1: "); Serial.println(AC1);
75+
Serial.print("AC2: "); Serial.println(AC2);
76+
Serial.print("AC3: "); Serial.println(AC3);
77+
Serial.print("AC4: "); Serial.println(AC4);
78+
Serial.print("AC5: "); Serial.println(AC5);
79+
Serial.print("AC6: "); Serial.println(AC6);
80+
Serial.print("VB1: "); Serial.println(VB1);
81+
Serial.print("VB2: "); Serial.println(VB2);
82+
Serial.print("MB: "); Serial.println(MB);
83+
Serial.print("MC: "); Serial.println(MC);
84+
Serial.print("MD: "); Serial.println(MD);
85+
*/
86+
87+
// Compute floating-point polynominals:
88+
89+
c3 = 160.0 * pow(2,-15) * AC3;
90+
c4 = pow(10,-3) * pow(2,-15) * AC4;
91+
b1 = pow(160,2) * pow(2,-30) * VB1;
92+
c5 = (pow(2,-15) / 160) * AC5;
93+
c6 = AC6;
94+
mc = (pow(2,11) / pow(160,2)) * MC;
95+
md = MD / 160.0;
96+
x0 = AC1;
97+
x1 = 160.0 * pow(2,-13) * AC2;
98+
x2 = pow(160,2) * pow(2,-25) * VB2;
99+
y0 = c4 * pow(2,15);
100+
y1 = c4 * c3;
101+
y2 = c4 * b1;
102+
p0 = (3791.0 - 8.0) / 1600.0;
103+
p1 = 1.0 - 7357.0 * pow(2,-20);
104+
p2 = 3038.0 * 100.0 * pow(2,-36);
105+
106+
/*
107+
Serial.println();
108+
Serial.print("c3: "); Serial.println(c3);
109+
Serial.print("c4: "); Serial.println(c4);
110+
Serial.print("c5: "); Serial.println(c5);
111+
Serial.print("c6: "); Serial.println(c6);
112+
Serial.print("b1: "); Serial.println(b1);
113+
Serial.print("mc: "); Serial.println(mc);
114+
Serial.print("md: "); Serial.println(md);
115+
Serial.print("x0: "); Serial.println(x0);
116+
Serial.print("x1: "); Serial.println(x1);
117+
Serial.print("x2: "); Serial.println(x2);
118+
Serial.print("y0: "); Serial.println(y0);
119+
Serial.print("y1: "); Serial.println(y1);
120+
Serial.print("y2: "); Serial.println(y2);
121+
Serial.print("p0: "); Serial.println(p0);
122+
Serial.print("p1: "); Serial.println(p1);
123+
Serial.print("p2: "); Serial.println(p2);
124+
*/
125+
126+
// Success!
127+
return(1);
128+
}
129+
else
130+
{
131+
// Error reading calibration data; bad component or connection?
132+
return(0);
133+
}
134+
}
135+
136+
137+
char SFE_BMP180::readInt(char address, int &value)
138+
// Read a signed integer (two bytes) from device
139+
// address: register to start reading (plus subsequent register)
140+
// value: external variable to store data (function modifies value)
141+
{
142+
unsigned char data[2];
143+
144+
data[0] = address;
145+
if (readBytes(data,2))
146+
{
147+
value = (((int)data[0]<<8)|(int)data[1]);
148+
//if (*value & 0x8000) *value |= 0xFFFF0000; // sign extend if negative
149+
return(1);
150+
}
151+
value = 0;
152+
return(0);
153+
}
154+
155+
156+
char SFE_BMP180::readUInt(char address, unsigned int &value)
157+
// Read an unsigned integer (two bytes) from device
158+
// address: register to start reading (plus subsequent register)
159+
// value: external variable to store data (function modifies value)
160+
{
161+
unsigned char data[2];
162+
163+
data[0] = address;
164+
if (readBytes(data,2))
165+
{
166+
value = (((unsigned int)data[0]<<8)|(unsigned int)data[1]);
167+
return(1);
168+
}
169+
value = 0;
170+
return(0);
171+
}
172+
173+
174+
char SFE_BMP180::readBytes(unsigned char *values, char length)
175+
// Read an array of bytes from device
176+
// values: external array to hold data. Put starting register in values[0].
177+
// length: number of bytes to read
178+
{
179+
char x;
180+
181+
Wire.beginTransmission(BMP180_ADDR);
182+
Wire.write(values[0]);
183+
_error = Wire.endTransmission();
184+
if (_error == 0)
185+
{
186+
Wire.requestFrom(BMP180_ADDR,length);
187+
while(Wire.available() != length) ; // wait until bytes are ready
188+
for(x=0;x<length;x++)
189+
{
190+
values[x] = Wire.read();
191+
}
192+
return(1);
193+
}
194+
return(0);
195+
}
196+
197+
198+
char SFE_BMP180::writeBytes(unsigned char *values, char length)
199+
// Write an array of bytes to device
200+
// values: external array of data to write. Put starting register in values[0].
201+
// length: number of bytes to write
202+
{
203+
char x;
204+
205+
Wire.beginTransmission(BMP180_ADDR);
206+
Wire.write(values,length);
207+
_error = Wire.endTransmission();
208+
if (_error == 0)
209+
return(1);
210+
else
211+
return(0);
212+
}
213+
214+
215+
char SFE_BMP180::startTemperature(void)
216+
// Begin a temperature reading.
217+
// Will return delay in ms to wait, or 0 if I2C error
218+
{
219+
unsigned char data[2], result;
220+
221+
data[0] = BMP180_REG_CONTROL;
222+
data[1] = BMP180_COMMAND_TEMPERATURE;
223+
result = writeBytes(data, 2);
224+
if (result) // good write?
225+
return(5); // return the delay in ms (rounded up) to wait before retrieving data
226+
else
227+
return(0); // or return 0 if there was a problem communicating with the BMP
228+
}
229+
230+
231+
char SFE_BMP180::getTemperature(double &T)
232+
// Retrieve a previously-started temperature reading.
233+
// Requires begin() to be called once prior to retrieve calibration parameters.
234+
// Requires startTemperature() to have been called prior and sufficient time elapsed.
235+
// T: external variable to hold result.
236+
// Returns 1 if successful, 0 if I2C error.
237+
{
238+
unsigned char data[2];
239+
char result;
240+
double tu, a;
241+
242+
data[0] = BMP180_REG_RESULT;
243+
244+
result = readBytes(data, 2);
245+
if (result) // good read, calculate temperature
246+
{
247+
tu = (data[0] * 256.0) + data[1];
248+
249+
//example from Bosch datasheet
250+
//tu = 27898;
251+
252+
//example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf
253+
//tu = 0x69EC;
254+
255+
a = c5 * (tu - c6);
256+
T = a + (mc / (a + md));
257+
258+
/*
259+
Serial.println();
260+
Serial.print("tu: "); Serial.println(tu);
261+
Serial.print("a: "); Serial.println(a);
262+
Serial.print("T: "); Serial.println(*T);
263+
*/
264+
}
265+
return(result);
266+
}
267+
268+
269+
char SFE_BMP180::startPressure(char oversampling)
270+
// Begin a pressure reading.
271+
// Oversampling: 0 to 3, higher numbers are slower, higher-res outputs.
272+
// Will return delay in ms to wait, or 0 if I2C error.
273+
{
274+
unsigned char data[2], result, delay;
275+
276+
data[0] = BMP180_REG_CONTROL;
277+
278+
switch (oversampling)
279+
{
280+
case 0:
281+
data[1] = BMP180_COMMAND_PRESSURE0;
282+
delay = 5;
283+
break;
284+
case 1:
285+
data[1] = BMP180_COMMAND_PRESSURE1;
286+
delay = 8;
287+
break;
288+
case 2:
289+
data[1] = BMP180_COMMAND_PRESSURE2;
290+
delay = 14;
291+
break;
292+
case 3:
293+
data[1] = BMP180_COMMAND_PRESSURE3;
294+
delay = 26;
295+
break;
296+
default:
297+
data[1] = BMP180_COMMAND_PRESSURE0;
298+
delay = 5;
299+
break;
300+
}
301+
result = writeBytes(data, 2);
302+
if (result) // good write?
303+
return(delay); // return the delay in ms (rounded up) to wait before retrieving data
304+
else
305+
return(0); // or return 0 if there was a problem communicating with the BMP
306+
}
307+
308+
309+
char SFE_BMP180::getPressure(double &P, double &T)
310+
// Retrieve a previously started pressure reading, calculate abolute pressure in mbars.
311+
// Requires begin() to be called once prior to retrieve calibration parameters.
312+
// Requires startPressure() to have been called prior and sufficient time elapsed.
313+
// Requires recent temperature reading to accurately calculate pressure.
314+
315+
// P: external variable to hold pressure.
316+
// T: previously-calculated temperature.
317+
// Returns 1 for success, 0 for I2C error.
318+
319+
// Note that calculated pressure value is absolute mbars, to compensate for altitude call sealevel().
320+
{
321+
unsigned char data[3];
322+
char result;
323+
double pu,s,x,y,z;
324+
325+
data[0] = BMP180_REG_RESULT;
326+
327+
result = readBytes(data, 3);
328+
if (result) // good read, calculate pressure
329+
{
330+
pu = (data[0] * 256.0) + data[1] + (data[2]/256.0);
331+
332+
//example from Bosch datasheet
333+
//pu = 23843;
334+
335+
//example from http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf, pu = 0x982FC0;
336+
//pu = (0x98 * 256.0) + 0x2F + (0xC0/256.0);
337+
338+
s = T - 25.0;
339+
x = (x2 * pow(s,2)) + (x1 * s) + x0;
340+
y = (y2 * pow(s,2)) + (y1 * s) + y0;
341+
z = (pu - x) / y;
342+
P = (p2 * pow(z,2)) + (p1 * z) + p0;
343+
344+
/*
345+
Serial.println();
346+
Serial.print("pu: "); Serial.println(pu);
347+
Serial.print("T: "); Serial.println(*T);
348+
Serial.print("s: "); Serial.println(s);
349+
Serial.print("x: "); Serial.println(x);
350+
Serial.print("y: "); Serial.println(y);
351+
Serial.print("z: "); Serial.println(z);
352+
Serial.print("P: "); Serial.println(*P);
353+
*/
354+
}
355+
return(result);
356+
}
357+
358+
359+
double SFE_BMP180::sealevel(double P, double A)
360+
// Given a pressure P (mb) taken at a specific altitude (meters),
361+
// return the equivalent pressure (mb) at sea level.
362+
// This produces pressure readings that can be used for weather measurements.
363+
{
364+
return(P/pow(1-(A/44330.0),5.255));
365+
}
366+
367+
368+
double SFE_BMP180::altitude(double P, double P0)
369+
// Given a pressure measurement P (mb) and the pressure at a baseline P0 (mb),
370+
// return altitude (meters) above baseline.
371+
{
372+
return(44330.0*(1-pow(P/P0,1/5.255)));
373+
}
374+
375+
376+
char SFE_BMP180::getError(void)
377+
// If any library command fails, you can retrieve an extended
378+
// error code using this command. Errors are from the wire library:
379+
// 0 = Success
380+
// 1 = Data too long to fit in transmit buffer
381+
// 2 = Received NACK on transmit of address
382+
// 3 = Received NACK on transmit of data
383+
// 4 = Other error
384+
{
385+
return(_error);
386+
}
387+

0 commit comments

Comments
 (0)