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)
45  ; // wait for chip to power on
46 
49 
50  i2c_->write(0, 0, 0);
51  delay(1);
53  {
54  baro_present_ = false;
55  return false;
56  }
57  else
58  {
59  baro_present_ = true;
60  }
61 
62  delay(3);
63 
64  // Read the PROM (try a couple times if it fails)
65  bool got_valid_prom = false;
66  for (int i = 0; i < 5; i++)
67  {
68  if (read_prom() == true)
69  {
70  if (calc_crc() != 0)
71  continue;
72  else
73  {
74  got_valid_prom = true;
75  break;
76  }
77  }
78  }
79 
80  if (got_valid_prom)
81  {
83  new_data_ = false;
84  baro_present_ = true;
86  return true;
87  }
88  else
89  {
90  return false;
91  }
92 }
93 
95 {
97  baro_present_ = false;
98  return baro_present_;
99 }
100 
102 {
103  uint32_t now_ms = millis();
104 
105  // Sometimes the barometer fails to respond. If this happens, then reset it
106  // the barometer also seems to stop responding after 72 minutes (suspiciously close to a overflow of uint32_t with a
107  // microsecond timer) to avoid that, just reboot periodically
108  if ((waiting_for_cb_ && now_ms) > last_update_ms_ + 20 || (now_ms > next_reboot_ms_))
109  {
110  last_update_ms_ = now_ms;
112  i2c_->write(ADDR, RESET, 1, &cb, false);
113  }
114 
115  else if (now_ms > next_update_ms_)
116  {
117  switch (state_)
118  {
119  case START_TEMP:
120  if (start_temp_meas())
121  next_update_ms_ += 100;
122  break;
123  case READ_TEMP:
124  if (read_temp_mess())
125  next_update_ms_ += 100;
126  break;
127  case START_PRESS:
128  if (start_pres_meas())
129  next_update_ms_ += 100;
130  break;
131  case READ_PRESS:
132  if (read_pres_mess())
133  next_update_ms_ += 100;
134  break;
135  default:
136  state_ = START_TEMP;
137  break;
138  }
139  }
140 
141  if (new_data_)
142  {
143  convert();
144  }
145 }
146 
147 void MS5611::reset() {}
148 
150 {
151  uint8_t buf[2] = {0, 0};
152 
153  // try a few times
154  for (int i = 0; i < 8; i++)
155  {
156  i2c_->write(ADDR, 0xFF, PROM_RD + 2 * i);
157  if (i2c_->read(ADDR, 0xFF, 2, buf, nullptr, true) == I2C::RESULT_SUCCESS)
158  prom[i] = static_cast<uint16_t>(buf[0] << 8 | buf[1]);
159  else
160  {
161  reset();
162  delay(3);
163  i2c_->write(0, 0, 0);
164  delay(3);
165  // didn't work, try again
166  return false;
167  }
168  }
169  return true;
170 }
171 
173 {
174  uint32_t res = 0;
175  uint8_t crc = prom[7] & 0xF;
176  prom[7] &= 0xFF00;
177 
178  bool blank = true;
179 
180  for (int i = 0; i < 16; i++)
181  {
182  if (prom[i >> 1])
183  {
184  blank = false;
185  }
186  if (i & 1)
187  res ^= ((prom[i >> 1]) & 0x00FF);
188  else
189  res ^= (prom[i >> 1] >> 8);
190  for (int j = 8; j > 0; j--)
191  {
192  if (res & 0x8000)
193  res ^= 0x1800;
194  res <<= 1;
195  }
196  }
197  prom[7] |= crc;
198  if (!blank && crc == ((res >> 12) & 0xF))
199  return 0;
200 
201  return -1;
202 }
203 
204 // int8_t MS5611::calc_crc()
205 //{
206 // uint16_t n_rem; // crc reminder
207 // uint16_t crc_read; // original value of the crc
208 // uint8_t n_bit;
209 // n_rem = 0x00;
210 // crc_read=prom[7]; //save read CRC
211 // prom[7]=(0xFF00 & (prom[7])); //CRC byte is replaced by 0
212 // for (uint8_t cnt = 0; cnt < 16; cnt++) // operation is performed on bytes
213 // {// choose LSB or MSB
214 // if (cnt%2==1) n_rem ^= ((prom[cnt>>1]) & 0x00FF);
215 // else n_rem ^= (prom[cnt>>1]>>8);
216 // for (n_bit = 8; n_bit > 0; n_bit--)
217 // {
218 // if (n_rem & (0x8000))
219 // {
220 // n_rem = (n_rem << 1) ^ 0x3000;
221 // }
222 // else
223 // {
224 // n_rem = (n_rem << 1);
225 // }
226 // }
227 // }
228 // n_rem= (0x000F & (n_rem >> 12)); // final 4-bit reminder is CRC code
229 // prom[7]=crc_read; // restore the crc_read to its original place
230 // return (n_rem ^ 0x0);
231 //}
232 
234 {
235  int32_t press = 0;
236  int32_t temp = 0;
237  int64_t delta = 0;
238  temp_raw_ = (temp_buf_[0] << 16) | (temp_buf_[1] << 8) | temp_buf_[2];
239  pres_raw_ = (pres_buf_[0] << 16) | (pres_buf_[1] << 8) | pres_buf_[2];
240  if (pres_raw_ > 9085466 * 2 / 3 && temp_raw_ > 0)
241  {
242  int32_t dT = temp_raw_ - (static_cast<int32_t>(prom[5]) << 8);
243  int64_t off = (static_cast<int64_t>(prom[2]) << 16) + ((static_cast<int64_t>(prom[4]) * dT) >> 7);
244  int64_t sens = (static_cast<int64_t>(prom[1]) << 15) + ((static_cast<int64_t>(prom[3]) * dT) >> 8);
245  temp = 2000 + ((dT * static_cast<int64_t>(prom[6])) >> 23);
246 
247  // temperature lower than 20degC
248  if (temp < 2000)
249  {
250  delta = temp - 2000;
251  delta = 5 * delta * delta;
252  off -= delta >> 1;
253  sens -= delta >> 2;
254 
255  // temperature lower than -15degC
256  if (temp < -1500)
257  {
258  delta = temp + 1500;
259  delta = delta * delta;
260  off -= 7 * delta;
261  sens -= (11 * delta) >> 1;
262  }
263 
264  temp -= ((dT * dT) >> 31);
265  }
266 
267  press = (((static_cast<uint64_t>(pres_raw_) * sens) >> 21) - off) >> 15;
268 
269  pressure_ = static_cast<float>(press); // Pa
270  temperature_ = static_cast<float>(temp) / 100.0 + 273.0; // K
271  }
272  new_data_ = false;
273 }
274 
276 {
277  waiting_for_cb_ = true;
280  return i2c_->write(ADDR, 0xFF, ADC_CONV + ADC_D2 + ADC_4096, &cb) > 0;
281 }
282 
284 {
285  waiting_for_cb_ = true;
288  return i2c_->write(ADDR, 0XFF, ADC_CONV + ADC_D1 + ADC_4096, &cb) > 0;
289 }
290 
292 {
293  waiting_for_cb_ = true;
296  return i2c_->write(ADDR, 0xFF, ADC_READ, &cb) > 0;
297 }
298 
300 {
301  waiting_for_cb_ = true;
304  return (i2c_->write(ADDR, 0xFF, ADC_READ, &cb) > 0);
305 }
306 
307 void MS5611::temp_read_cb1(uint8_t result)
308 {
309  (void)result;
310  waiting_for_cb_ = false;
313  i2c_->read(ADDR, 0xFF, 3, temp_buf_, &cb);
314 }
315 
316 void MS5611::pres_read_cb1(uint8_t result)
317 {
318  (void)result;
319  waiting_for_cb_ = false;
322  i2c_->read(ADDR, 0xFF, 3, pres_buf_, &cb);
323 }
324 
325 void MS5611::temp_read_cb2(uint8_t result)
326 {
327  (void)result;
329  waiting_for_cb_ = false;
332  new_data_ = true;
333 }
334 
335 void MS5611::pres_read_cb2(uint8_t result)
336 {
337  (void)result;
338  state_ = START_TEMP;
339  waiting_for_cb_ = false;
342  new_data_ = true;
343 }
344 
345 void MS5611::temp_start_cb(uint8_t result)
346 {
347  (void)result;
348  state_ = READ_TEMP;
349  waiting_for_cb_ = false;
352 }
353 
354 void MS5611::pres_start_cb(uint8_t result)
355 {
356  (void)result;
357  state_ = READ_PRESS;
358  waiting_for_cb_ = false;
361 }
362 
363 void MS5611::reset_cb(uint8_t result)
364 {
365  (void)result;
369  waiting_for_cb_ = false;
371  i2c_->write(0, 0, 0, &cb, false);
372 }
373 
374 void MS5611::write_zero_cb(uint8_t result)
375 {
376  (void)result;
380  waiting_for_cb_ = false;
381  state_ = START_TEMP;
382 }
383 
384 void MS5611::read(float* press, float* temp)
385 {
386  (*press) = pressure_;
387  (*temp) = temperature_;
388 }
389 
390 void MS5611::master_cb(uint8_t result)
391 {
392  if (result == I2C::RESULT_SUCCESS)
393  baro_present_ = true;
394  switch (callback_type_)
395  {
396  case CB_TEMP_READ1:
397  temp_read_cb1(result);
398  break;
399  case CB_TEMP_READ2:
400  temp_read_cb2(result);
401  break;
402  case CB_PRES_READ1:
403  pres_read_cb1(result);
404  break;
405  case CB_PRES_READ2:
406  pres_read_cb2(result);
407  break;
408  case CB_TEMP_START:
409  temp_start_cb(result);
410  break;
411  case CB_PRES_START:
412  pres_start_cb(result);
413  break;
414  case CB_RESET:
415  reset_cb(result);
416  break;
417  case CB_WRITE_ZERO:
418  write_zero_cb(result);
419  break;
420  }
421 }
422 
423 void cb(uint8_t result)
424 {
425  baro_ptr->master_cb(result);
426 }
bool start_temp_meas()
Definition: ms5611.cpp:275
bool new_data_
Definition: ms5611.h:100
float temperature_
Definition: ms5611.h:94
void temp_start_cb(uint8_t result)
Definition: ms5611.cpp:345
#define REBOOT_PERIOD_MS
Definition: ms5611.cpp:37
volatile uint32_t millis(void)
Definition: system.c:50
int8_t calc_crc()
Definition: ms5611.cpp:172
bool waiting_for_cb_
Definition: ms5611.h:99
uint32_t last_update_ms_
Definition: ms5611.h:98
float pressure_
Definition: ms5611.h:93
int32_t pres_raw_
Definition: ms5611.h:91
bool read_prom()
Definition: ms5611.cpp:149
callback_type_t callback_type_
Definition: ms5611.h:103
Definition: ms5611.h:38
uint32_t next_reboot_ms_
Definition: ms5611.h:97
void temp_read_cb2(uint8_t result)
Definition: ms5611.cpp:325
void reset()
Definition: ms5611.cpp:147
void pres_read_cb2(uint8_t result)
Definition: ms5611.cpp:335
static void cb(uint8_t result)
Definition: ms5611.cpp:423
void pres_read_cb1(uint8_t result)
Definition: ms5611.cpp:316
bool read_temp_mess()
Definition: ms5611.cpp:299
state_t state_
Definition: ms5611.h:63
void reset_cb(uint8_t result)
Definition: ms5611.cpp:363
bool init(I2C *_i2c)
Definition: ms5611.cpp:39
void convert()
Definition: ms5611.cpp:233
bool read_pres_mess()
Definition: ms5611.cpp:291
static volatile int16_t temp
Definition: drv_mpu6050.c:278
void temp_read_cb1(uint8_t result)
Definition: ms5611.cpp:307
void master_cb(uint8_t result)
Definition: ms5611.cpp:390
void update()
Definition: ms5611.cpp:101
uint32_t next_update_ms_
Definition: ms5611.h:96
int8_t write(uint8_t addr, uint8_t reg, uint8_t data, void(*callback)(uint8_t), bool blocking=false)
Definition: i2c.cpp:297
Definition: i2c.h:39
int32_t temp_raw_
Definition: ms5611.h:92
bool present()
Definition: ms5611.cpp:94
void pres_start_cb(uint8_t result)
Definition: ms5611.cpp:354
I2C * i2c_
Definition: ms5611.h:88
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:177
bool baro_present_
Definition: ms5611.h:101
uint8_t temp_buf_[3]
Definition: ms5611.h:90
void write_zero_cb(uint8_t result)
Definition: ms5611.cpp:374
void read(float *press, float *temp)
Definition: ms5611.cpp:384
void delay(uint32_t ms)
Definition: system.c:101
MS5611 * baro_ptr
Definition: ms5611.cpp:34
uint8_t pres_buf_[3]
Definition: ms5611.h:89
uint16_t prom[8]
Definition: ms5611.h:95
bool start_pres_meas()
Definition: ms5611.cpp:283
static const uint8_t ADDR
Definition: ms5611.h:77


rosflight_firmware
Author(s): Daniel Koch , James Jackson
autogenerated on Fri Oct 9 2020 03:17:16