ms5611.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, James Jackson
3  *
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * * Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  *
12  * * Redistributions in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * * Neither the name of the copyright holder nor the names of its
17  * contributors may be used to endorse or promote products derived from
18  * this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "ms5611.h"
33 
35 static void cb(uint8_t result);
36 
37 #define REBOOT_PERIOD_MS 1000 * 60 * 30 // reboot the device every 30 minutes
38 
39 bool MS5611::init(I2C *_i2c)
40 {
41  baro_ptr = this;
42  i2c_ = _i2c;
43  baro_present_ = false;
44  while (millis() < 10); // wait for chip to power on
45 
48 
49  i2c_->write(0, 0, 0);
50  delay(1);
52  {
53  baro_present_ = false;
54  return false;
55  }
56  else
57  {
58  baro_present_ = true;
59  }
60 
61  delay(3);
62 
63  // Read the PROM (try a couple times if it fails)
64  bool got_valid_prom = false;
65  for (int i = 0; i < 5; i++)
66  {
67  if (read_prom() == true)
68  {
69  if (calc_crc() != 0)
70  continue;
71  else
72  {
73  got_valid_prom = true;
74  break;
75  }
76  }
77  }
78 
79  if (got_valid_prom)
80  {
82  new_data_ = false;
83  baro_present_ = true;
85  return true;
86  }
87  else
88  {
89  return false;
90  }
91 }
92 
94 {
96  baro_present_ = false;
97  return baro_present_;
98 }
99 
101 {
102  uint32_t now_ms = millis();
103 
104  // Sometimes the barometer fails to respond. If this happens, then reset it
105  // the barometer also seems to stop responding after 72 minutes (suspiciously close to a overflow of uint32_t with a microsecond timer)
106  // to avoid that, just reboot periodically
107  if ((waiting_for_cb_ && now_ms) > last_update_ms_ + 20 || (now_ms > next_reboot_ms_))
108  {
109  last_update_ms_ = now_ms;
111  i2c_->write(ADDR, RESET, 1, &cb, false);
112  }
113 
114  else if (now_ms > next_update_ms_)
115  {
116  switch (state_)
117  {
118  case START_TEMP:
119  if (start_temp_meas())
120  next_update_ms_ += 100;
121  break;
122  case READ_TEMP:
123  if (read_temp_mess())
124  next_update_ms_ += 100;
125  break;
126  case START_PRESS:
127  if (start_pres_meas())
128  next_update_ms_ += 100;
129  break;
130  case READ_PRESS:
131  if (read_pres_mess())
132  next_update_ms_ += 100;
133  break;
134  default:
135  state_ = START_TEMP;
136  break;
137  }
138  }
139 
140  if (new_data_)
141  {
142  convert();
143  }
144 }
145 
146 
148 {
149 
150 }
151 
153 {
154  uint8_t buf[2] = {0, 0};
155 
156  // try a few times
157  for (int i = 0; i < 8; i++)
158  {
159  i2c_->write(ADDR, 0xFF, PROM_RD + 2* i);
160  if (i2c_->read(ADDR, 0xFF, 2, buf, nullptr, true) == I2C::RESULT_SUCCESS)
161  prom[i] = static_cast<uint16_t>(buf[0] << 8 | buf[1]);
162  else
163  {
164  reset();
165  delay(3);
166  i2c_->write(0, 0, 0);
167  delay(3);
168  // didn't work, try again
169  return false;
170  }
171  }
172  return true;
173 }
174 
176 {
177  uint32_t res = 0;
178  uint8_t crc = prom[7] & 0xF;
179  prom[7] &= 0xFF00;
180 
181  bool blank = true;
182 
183  for (int i = 0; i < 16; i++)
184  {
185  if (prom[i >> 1])
186  {
187  blank = false;
188  }
189  if (i & 1)
190  res ^= ((prom[i >> 1]) & 0x00FF);
191  else
192  res ^= (prom[i >> 1] >> 8);
193  for (int j = 8; j > 0; j--)
194  {
195  if (res & 0x8000)
196  res ^= 0x1800;
197  res <<= 1;
198  }
199  }
200  prom[7] |= crc;
201  if (!blank && crc == ((res >> 12) & 0xF))
202  return 0;
203 
204  return -1;
205 }
206 
207 //int8_t MS5611::calc_crc()
208 //{
209 // uint16_t n_rem; // crc reminder
210 // uint16_t crc_read; // original value of the crc
211 // uint8_t n_bit;
212 // n_rem = 0x00;
213 // crc_read=prom[7]; //save read CRC
214 // prom[7]=(0xFF00 & (prom[7])); //CRC byte is replaced by 0
215 // for (uint8_t cnt = 0; cnt < 16; cnt++) // operation is performed on bytes
216 // {// choose LSB or MSB
217 // if (cnt%2==1) n_rem ^= ((prom[cnt>>1]) & 0x00FF);
218 // else n_rem ^= (prom[cnt>>1]>>8);
219 // for (n_bit = 8; n_bit > 0; n_bit--)
220 // {
221 // if (n_rem & (0x8000))
222 // {
223 // n_rem = (n_rem << 1) ^ 0x3000;
224 // }
225 // else
226 // {
227 // n_rem = (n_rem << 1);
228 // }
229 // }
230 // }
231 // n_rem= (0x000F & (n_rem >> 12)); // final 4-bit reminder is CRC code
232 // prom[7]=crc_read; // restore the crc_read to its original place
233 // return (n_rem ^ 0x0);
234 //}
235 
237 {
238  int32_t press = 0;
239  int32_t temp = 0;
240  int64_t delta = 0;
241  temp_raw_ = (temp_buf_[0] << 16) | (temp_buf_[1] << 8) | temp_buf_[2];
242  pres_raw_ = (pres_buf_[0] << 16) | (pres_buf_[1] << 8) | pres_buf_[2];
243  if (pres_raw_ > 9085466 * 2 / 3 && temp_raw_ > 0)
244  {
245  int32_t dT = temp_raw_ - (static_cast<int32_t>(prom[5]) << 8);
246  int64_t off = (static_cast<int64_t>(prom[2]) << 16) + ((static_cast<int64_t>(prom[4]) * dT) >> 7);
247  int64_t sens = (static_cast<int64_t>(prom[1]) << 15) + ((static_cast<int64_t>(prom[3]) * dT) >> 8);
248  temp = 2000 + ((dT * static_cast<int64_t>(prom[6])) >> 23);
249 
250  // temperature lower than 20degC
251  if (temp < 2000)
252  {
253  delta = temp - 2000;
254  delta = 5 * delta * delta;
255  off -= delta >> 1;
256  sens -= delta >> 2;
257 
258  // temperature lower than -15degC
259  if (temp < -1500)
260  {
261  delta = temp + 1500;
262  delta = delta * delta;
263  off -= 7 * delta;
264  sens -= (11 * delta) >> 1;
265  }
266 
267  temp -= ((dT * dT) >> 31);
268  }
269 
270  press = (((static_cast<uint64_t>(pres_raw_) * sens) >> 21) - off) >> 15;
271 
272  pressure_ = static_cast<float>(press); // Pa
273  temperature_ = static_cast<float>(temp) / 100.0 + 273.0; // K
274  }
275  new_data_ = false;
276 }
277 
279 {
280  waiting_for_cb_ = true;
283  return i2c_->write(ADDR, 0xFF, ADC_CONV + ADC_D2 + ADC_4096, &cb) > 0;
284 }
285 
287 {
288  waiting_for_cb_ = true;
291  return i2c_->write(ADDR, 0XFF, ADC_CONV + ADC_D1 + ADC_4096, &cb) > 0;
292 }
293 
295 {
296  waiting_for_cb_ = true;
299  return i2c_->write(ADDR, 0xFF, ADC_READ, &cb) > 0;
300 }
301 
303 {
304  waiting_for_cb_ = true;
307  return (i2c_->write(ADDR, 0xFF, ADC_READ, &cb) > 0);
308 }
309 
310 void MS5611::temp_read_cb1(uint8_t result)
311 {
312  (void) result;
313  waiting_for_cb_ = false;
316  i2c_->read(ADDR, 0xFF, 3, temp_buf_, &cb);
317 }
318 
319 void MS5611::pres_read_cb1(uint8_t result)
320 {
321  (void) result;
322  waiting_for_cb_ = false;
325  i2c_->read(ADDR, 0xFF, 3, pres_buf_, &cb);
326 }
327 
328 
329 void MS5611::temp_read_cb2(uint8_t result)
330 {
331  (void) result;
333  waiting_for_cb_ = false;
336  new_data_ = true;
337 }
338 
339 void MS5611::pres_read_cb2(uint8_t result)
340 {
341  (void) result;
342  state_ = START_TEMP;
343  waiting_for_cb_ = false;
346  new_data_ = true;
347 }
348 
349 void MS5611::temp_start_cb(uint8_t result)
350 {
351  (void) result;
352  state_ = READ_TEMP;
353  waiting_for_cb_ = false;
356 }
357 
358 void MS5611::pres_start_cb(uint8_t result)
359 {
360  (void) result;
361  state_ = READ_PRESS;
362  waiting_for_cb_ = false;
365 }
366 
367 void MS5611::reset_cb(uint8_t result)
368 {
369  (void) result;
373  waiting_for_cb_ = false;
375  i2c_->write(0, 0, 0, &cb, false);
376 }
377 
378 void MS5611::write_zero_cb(uint8_t result)
379 {
380  (void) result;
384  waiting_for_cb_ = false;
385  state_ = START_TEMP;
386 }
387 
388 void MS5611::read(float *press, float *temp)
389 {
390  (*press) = pressure_;
391  (*temp) = temperature_;
392 }
393 
394 void MS5611::master_cb(uint8_t result)
395 {
396  if (result == I2C::RESULT_SUCCESS)
397  baro_present_ = true;
398  switch (callback_type_)
399  {
400  case CB_TEMP_READ1:
401  temp_read_cb1(result);
402  break;
403  case CB_TEMP_READ2:
404  temp_read_cb2(result);
405  break;
406  case CB_PRES_READ1:
407  pres_read_cb1(result);
408  break;
409  case CB_PRES_READ2:
410  pres_read_cb2(result);
411  break;
412  case CB_TEMP_START:
413  temp_start_cb(result);
414  break;
415  case CB_PRES_START:
416  pres_start_cb(result);
417  break;
418  case CB_RESET:
419  reset_cb(result);
420  break;
421  case CB_WRITE_ZERO:
422  write_zero_cb(result);
423  break;
424  }
425 }
426 
427 void cb(uint8_t result)
428 {
429  baro_ptr->master_cb(result);
430 }
bool start_temp_meas()
Definition: ms5611.cpp:278
bool new_data_
Definition: ms5611.h:102
float temperature_
Definition: ms5611.h:96
void temp_start_cb(uint8_t result)
Definition: ms5611.cpp:349
#define REBOOT_PERIOD_MS
Definition: ms5611.cpp:37
volatile uint32_t millis(void)
Definition: system.c:50
int8_t calc_crc()
Definition: ms5611.cpp:175
bool waiting_for_cb_
Definition: ms5611.h:101
uint32_t last_update_ms_
Definition: ms5611.h:100
float pressure_
Definition: ms5611.h:95
int32_t pres_raw_
Definition: ms5611.h:93
bool read_prom()
Definition: ms5611.cpp:152
callback_type_t callback_type_
Definition: ms5611.h:105
Definition: ms5611.h:39
uint32_t next_reboot_ms_
Definition: ms5611.h:99
void temp_read_cb2(uint8_t result)
Definition: ms5611.cpp:329
void reset()
Definition: ms5611.cpp:147
void pres_read_cb2(uint8_t result)
Definition: ms5611.cpp:339
static void cb(uint8_t result)
Definition: ms5611.cpp:427
void pres_read_cb1(uint8_t result)
Definition: ms5611.cpp:319
bool read_temp_mess()
Definition: ms5611.cpp:302
state_t state_
Definition: ms5611.h:65
void reset_cb(uint8_t result)
Definition: ms5611.cpp:367
bool init(I2C *_i2c)
Definition: ms5611.cpp:39
void convert()
Definition: ms5611.cpp:236
bool read_pres_mess()
Definition: ms5611.cpp:294
static volatile int16_t temp
Definition: drv_mpu6050.c:278
void temp_read_cb1(uint8_t result)
Definition: ms5611.cpp:310
void master_cb(uint8_t result)
Definition: ms5611.cpp:394
void update()
Definition: ms5611.cpp:100
uint32_t next_update_ms_
Definition: ms5611.h:98
int8_t write(uint8_t addr, uint8_t reg, uint8_t data, void(*callback)(uint8_t), bool blocking=false)
Definition: i2c.cpp:298
Definition: i2c.h:40
int32_t temp_raw_
Definition: ms5611.h:94
bool present()
Definition: ms5611.cpp:93
void pres_start_cb(uint8_t result)
Definition: ms5611.cpp:358
I2C * i2c_
Definition: ms5611.h:90
int8_t read(uint8_t addr, uint8_t reg, uint8_t num_bytes, uint8_t *data, void(*callback)(uint8_t)=nullptr, bool blocking=false)
Definition: i2c.cpp:179
bool baro_present_
Definition: ms5611.h:103
uint8_t temp_buf_[3]
Definition: ms5611.h:92
void write_zero_cb(uint8_t result)
Definition: ms5611.cpp:378
void read(float *press, float *temp)
Definition: ms5611.cpp:388
void delay(uint32_t ms)
Definition: system.c:98
MS5611 * baro_ptr
Definition: ms5611.cpp:34
uint8_t pres_buf_[3]
Definition: ms5611.h:91
uint16_t prom[8]
Definition: ms5611.h:97
bool start_pres_meas()
Definition: ms5611.cpp:286
static const uint8_t ADDR
Definition: ms5611.h:79


rosflight_firmware
Author(s): Daniel Koch , James Jackson
autogenerated on Wed Jul 3 2019 19:59:25