Subversion Repositories FlightCtrl

Rev

Go to most recent revision | 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
}