Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1993 | - | 1 | /* |
2 | MS5611-01BA.cpp - Interfaces a Measurement Specialities MS5611-01BA with Arduino |
||
3 | See http://www.meas-spec.com/downloads/MS5611-01BA01.pdf for the device datasheet |
||
4 | |||
5 | Copyright (C) 2011 Fabio Varesano <fvaresano@yahoo.it> |
||
6 | |||
7 | Development of this code has been supported by the Department of Computer Science, |
||
8 | Universita' degli Studi di Torino, Italy within the Piemonte Project |
||
9 | http://www.piemonte.di.unito.it/ |
||
10 | |||
11 | |||
12 | This program is free software: you can redistribute it and/or modify |
||
13 | it under the terms of the version 3 GNU General Public License as |
||
14 | published by the Free Software Foundation. |
||
15 | |||
16 | This program is distributed in the hope that it will be useful, |
||
17 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
18 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
19 | GNU General Public License for more details. |
||
20 | |||
21 | You should have received a copy of the GNU General Public License |
||
22 | along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
23 | |||
24 | */ |
||
25 | |||
26 | #include "MS561101BA.h" |
||
27 | #define EXTRA_PRECISION 5 // trick to add more precision to the pressure and temp readings |
||
28 | |||
29 | MS561101BA::MS561101BA() { |
||
30 | ; |
||
31 | } |
||
32 | |||
33 | void MS561101BA::init(uint8_t address) { |
||
34 | _addr = address; |
||
35 | |||
36 | // disable internal pullups of the ATMEGA which Wire enable by default |
||
37 | #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega8__) || defined(__AVR_ATmega328P__) |
||
38 | // deactivate internal pull-ups for twi |
||
39 | // as per note from atmega8 manual pg167 |
||
40 | cbi(PORTC, 4); |
||
41 | cbi(PORTC, 5); |
||
42 | #else |
||
43 | // deactivate internal pull-ups for twi |
||
44 | // as per note from atmega128 manual pg204 |
||
45 | cbi(PORTD, 0); |
||
46 | cbi(PORTD, 1); |
||
47 | #endif |
||
48 | |||
49 | reset(); // reset the device to populate its internal PROM registers |
||
50 | delay(1000); // some safety time |
||
51 | readPROM(); // reads the PROM into object variables for later use |
||
52 | } |
||
53 | |||
54 | float MS561101BA::getPressure(uint8_t OSR) { |
||
55 | // see datasheet page 7 for formulas |
||
56 | int64_t dT = getDeltaTemp(OSR); |
||
57 | int64_t off = (((int64_t)_C[1]) << 16) + ((_C[3] * dT) >> 7); |
||
58 | int64_t sens = (((int64_t)_C[0]) << 15) + ((_C[2] * dT) >> 8); |
||
59 | return ((((rawPressure(OSR) * sens) >> 21) - off) >> (15-EXTRA_PRECISION)) / ((1<<EXTRA_PRECISION) * 100.0); |
||
60 | } |
||
61 | |||
62 | float MS561101BA::getTemperature(uint8_t OSR) { |
||
63 | // see datasheet page 7 for formulas |
||
64 | return ((1<<EXTRA_PRECISION)*2000l + ((getDeltaTemp(OSR) * _C[5]) >> (23-EXTRA_PRECISION))) / ((1<<EXTRA_PRECISION) * 100.0); |
||
65 | } |
||
66 | |||
67 | int64_t MS561101BA::getDeltaTemp(uint8_t OSR) { |
||
68 | return rawTemperature(OSR) - (((int32_t)_C[4]) << 8); |
||
69 | } |
||
70 | |||
71 | int32_t MS561101BA::rawPressure(uint8_t OSR) { |
||
72 | return doConversion(MS561101BA_D1 + OSR); |
||
73 | } |
||
74 | |||
75 | int32_t MS561101BA::rawTemperature(uint8_t OSR) { |
||
76 | return doConversion(MS561101BA_D2 + OSR); |
||
77 | } |
||
78 | |||
79 | |||
80 | unsigned long MS561101BA::doConversion(uint8_t command) { |
||
81 | unsigned long conversion = 0; |
||
82 | |||
83 | // see page 11 of the datasheet |
||
84 | |||
85 | // initialize pressure conversion |
||
86 | Wire.beginTransmission(_addr); |
||
87 | Wire.send(command); |
||
88 | Wire.endTransmission(); |
||
89 | |||
90 | delay(10); // the conversion will take a time <= 9.04 ms to have the output ready |
||
91 | // TODO: make the delay dependant on the OSR requested in the command |
||
92 | |||
93 | // start read sequence |
||
94 | Wire.beginTransmission(_addr); |
||
95 | Wire.send(0); |
||
96 | Wire.endTransmission(); |
||
97 | |||
98 | Wire.beginTransmission(_addr); |
||
99 | Wire.requestFrom(_addr, (uint8_t) MS561101BA_D1D2_SIZE); |
||
100 | if(Wire.available()) { |
||
101 | conversion = Wire.receive() * 65536 + Wire.receive() * 256 + Wire.receive(); |
||
102 | } |
||
103 | else { |
||
104 | conversion = -1; |
||
105 | } |
||
106 | |||
107 | return conversion; |
||
108 | } |
||
109 | |||
110 | |||
111 | /** |
||
112 | * Reads factory calibration and store it into object variables. |
||
113 | */ |
||
114 | int MS561101BA::readPROM() { |
||
115 | for (int i=0;i<MS561101BA_PROM_REG_COUNT;i++) { |
||
116 | Wire.beginTransmission(_addr); |
||
117 | Wire.send(MS561101BA_PROM_BASE_ADDR + (i * MS561101BA_PROM_REG_SIZE)); |
||
118 | Wire.endTransmission(); |
||
119 | |||
120 | Wire.beginTransmission(_addr); |
||
121 | Wire.requestFrom(_addr, (uint8_t) MS561101BA_PROM_REG_SIZE); |
||
122 | if(Wire.available()) { |
||
123 | _C[i] = Wire.receive() << 8 | Wire.receive(); |
||
124 | |||
125 | //DEBUG_PRINT(_C[i]); |
||
126 | } |
||
127 | else { |
||
128 | return -1; // error reading the PROM or communicating with the device |
||
129 | } |
||
130 | } |
||
131 | return 0; |
||
132 | } |
||
133 | |||
134 | |||
135 | /** |
||
136 | * Send a reset command to the device. With the reset command the device |
||
137 | * populates its internal registers with the values read from the PROM. |
||
138 | */ |
||
139 | void MS561101BA::reset() { |
||
140 | Wire.beginTransmission(_addr); |
||
141 | Wire.send(MS561101BA_RESET); |
||
142 | Wire.endTransmission(); |
||
143 | } |