Rev Author Line No. Line
2773 kaklik 1 /* mbed MPL115A1 (Barometric Pressure Sensor) Library
2 *
3 * This code is based on application notes and
4 * Sparkfun example code, written by Jim Lindblom <jim at sparkfun.com>
5 *
6 * Copyright (c) 2012 Mitja Kleider
7 *
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * http://www.apache.org/licenses/LICENSE-2.0
13 *
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
19 */
20  
21 // TODO: support shutdown pin
22  
23  
24 #include "MPL115A1.h"
25  
26 MPL115A1::MPL115A1(SPI& spi, PinName ncs) : _spi(spi), _cs(ncs)
27 {
28 _cs = 1;
29 // sdn = 1; // sensor on
30  
31 // SCL idle low, sample data on rising edge
32 _spi.format(8, 0); // 8bit, POL 0, PHA 0
33 _spi.frequency(1000000); // 1MHz
34 }
35  
36 void MPL115A1::write_register(uint8_t address, char data)
37 {
38 //write any data byte to any single address
39 //adds a 0 to the MSB of the address byte (WRITE mode)
40  
41 address &= 0x7F;
42  
43 _cs = 0;
44 wait_ms(1);
45 _spi.write(address);
46 wait_ms(1);
47 _spi.write(data);
48 wait_ms(1);
49 _cs = 1;
50 }
51  
52 char MPL115A1::read_register(uint8_t address)
53 {
54 // returns the contents of any 1 byte register from any address
55 // sets the MSB for every address byte (READ mode)
56  
57 char byte;
58  
59 address |= 0x80;
60  
61 _cs = 0;
62 _spi.write(address);
63 byte = _spi.write(0x00);
64 _cs = 1;
65  
66 return byte;
67 }
68  
69 float MPL115A1::readPressure()
70 {
71 // read pressure, temperature and coefficients, calculate and return absolute pressure [kPa]
72  
73 write_register(MPL115A1_STARTBOTH, 0x00); // start temperature and pressure conversions
74 wait_ms(10); // AN: data is typically ready after 3ms, DS for both: max. 1ms
75  
76 // read raw pressure
77 uiPH = read_register(MPL115A1_PRESH);
78 uiPL = read_register(MPL115A1_PRESL);
79 uiTH = read_register(MPL115A1_TEMPH);
80 uiTL = read_register(MPL115A1_TEMPL);
81  
82 uiPadc = (unsigned int) uiPH << 8;
83 uiPadc += (unsigned int) uiPL & 0x00FF;
84 uiTadc = (unsigned int) uiTH << 8;
85 uiTadc += (unsigned int) uiTL & 0x00FF;
86  
87 // read coefficients, put into 16-bit Variables
88 // a0, pressure offset coefficient
89 sia0MSB = read_register(MPL115A1_A0MSB);
90 sia0LSB = read_register(MPL115A1_A0LSB);
91 sia0 = (signed int) sia0MSB << 8;
92 sia0 += (signed int) sia0LSB & 0x00FF;
93  
94 // b1, pressure sensitivity coefficient
95 sib1MSB = read_register(MPL115A1_B1MSB);
96 sib1LSB = read_register(MPL115A1_B1LSB);
97 sib1 = (signed int) sib1MSB << 8;
98 sib1 += (signed int) sib1LSB & 0x00FF;
99  
100 // b2, 1st order temperature offset coefficient (TCO)
101 sib2MSB = read_register(MPL115A1_B2MSB);
102 sib2LSB = read_register(MPL115A1_B2LSB);
103 sib2 = (signed int) sib2MSB << 8;
104 sib2 += (signed int) sib2LSB & 0x00FF;
105  
106 // c12, temperature sensitivity coefficient (TCS)
107 sic12MSB = read_register(MPL115A1_C12MSB);
108 sic12LSB = read_register(MPL115A1_C12LSB);
109 sic12 = (signed int) sic12MSB << 8;
110 sic12 += (signed int) sic12LSB & 0x00FF;
111  
112 // c11, pressure linearity (2nd order) coefficient
113 sic11MSB = read_register(MPL115A1_C11MSB);
114 sic11LSB = read_register(MPL115A1_C11LSB);
115 sic11 = (signed int) sic11MSB << 8;
116 sic11 += (signed int) sic11LSB & 0x00FF;
117  
118 // c22, 2nd order temperature offset coefficient
119 sic22MSB = read_register(MPL115A1_C22MSB);
120 sic22LSB = read_register(MPL115A1_C22LSB);
121 sic22 = (signed int) sic22MSB << 8;
122 sic22 += (signed int) sic22LSB & 0x00FF;
123  
124 // Coefficient 9 equation compensation
125  
126 // 10bit stored in 16bit, shift right
127 uiPadc = uiPadc >> 6;
128 uiTadc = uiTadc >> 6;
129  
130 // Step 1: c11x1 = c11 * Padc
131 lt1 = (signed long) sic11;
132 lt2 = (signed long) uiPadc;
133 lt3 = lt1*lt2;
134 si_c11x1 = (signed long) lt3;
135  
136 // Step 2: a11 = b1 + c11x1
137 lt1 = ((signed long)sib1)<<14;
138 lt2 = (signed long) si_c11x1;
139 lt3 = lt1 + lt2;
140 si_a11 = (signed long)(lt3>>14);
141  
142 // Step 3: c12x2 = c12 * Tadc
143 lt1 = (signed long) sic12;
144 lt2 = (signed long) uiTadc;
145 lt3 = lt1*lt2;
146 si_c12x2 = (signed long)lt3;
147  
148 // Step 4: a1 = a11 + c12x2
149 lt1 = ((signed long)si_a11<<11);
150 lt2 = (signed long)si_c12x2;
151 lt3 = lt1 + lt2;
152 si_a1 = (signed long) lt3>>11;
153  
154 // Step 5: c22x2 = c22*Tadc
155 lt1 = (signed long)sic22;
156 lt2 = (signed long)uiTadc;
157 lt3 = lt1 * lt2;
158 si_c22x2 = (signed long)(lt3);
159  
160 // Step 6: a2 = b2 + c22x2
161 lt1 = ((signed long)sib2<<15);
162 lt2 = ((signed long)si_c22x2>1);
163 lt3 = lt1+lt2;
164 si_a2 = ((signed long)lt3>>16);
165  
166 // Step 7: a1x1 = a1 * Padc
167 lt1 = (signed long)si_a1;
168 lt2 = (signed long)uiPadc;
169 lt3 = lt1*lt2;
170 si_a1x1 = (signed long)(lt3);
171  
172 // Step 8: y1 = a0 + a1x1
173 lt1 = ((signed long)sia0<<10);
174 lt2 = (signed long)si_a1x1;
175 lt3 = lt1+lt2;
176 si_y1 = ((signed long)lt3>>10);
177  
178 // Step 9: a2x2 = a2 * Tadc
179 lt1 = (signed long)si_a2;
180 lt2 = (signed long)uiTadc;
181 lt3 = lt1*lt2;
182 si_a2x2 = (signed long)(lt3);
183  
184 // Step 10: pComp = y1 + a2x2
185 lt1 = ((signed long)si_y1<<10);
186 lt2 = (signed long)si_a2x2;
187 lt3 = lt1+lt2;
188  
189 // Fixed point result with rounding
190 //siPcomp = ((signed int)lt3>>13);
191 siPcomp = lt3/8192;
192  
193 // decPcomp is defined as a floating point number
194 // Conversion to decimal value from 1023 ADC count value
195 // ADC counts are 0 to 1023, pressure is 50 to 115kPa respectively
196 decPcomp = ((65.0/1023.0)*siPcomp)+50;
197  
198 return decPcomp;
199 }
200  
201 float MPL115A1::readTemperature()
202 {
203 // read, calculate and return temperature
204  
205 write_register(MPL115A1_STARTTEMP, 0x00); // start temperature conversion
206 wait_ms(10); // AN: data is typically ready after 3ms, DS for temp: max. 0.7ms
207  
208 // read raw temperature
209 uiTH = read_register(MPL115A1_TEMPH);
210 uiTL = read_register(MPL115A1_TEMPL);
211  
212 uiTadc = (unsigned int) uiTH << 8;
213 uiTadc += (unsigned int) uiTL & 0x00FF;
214  
215 // 10bit stored in 16bit, shift right
216 uiTadc = uiTadc >> 6;
217  
218 // Tadc is 472 counts at 25degC, -5.35 counts/degC
219 // return ((float)uiTadc - 472.0)/(-5.35) + 25
220 return (605.75-uiTadc)*0.186916;
221 }