High resolution barometer and altimeter using i2c mode

Dependents:   mbed_5637_test Weather_Station_Ofiicial

Fork of ms5611 by Kevin Braun

Committer:
loopsva
Date:
Tue May 07 18:44:06 2013 +0000
Revision:
0:f97f410d4a21
Child:
2:05804ed70748
Initial Release.  High resolution Barometer / Altimeter

Who changed what in which revision?

UserRevisionLine numberNew contents of line
loopsva 0:f97f410d4a21 1 //!
loopsva 0:f97f410d4a21 2 //! @file an520_I2C.c,v
loopsva 0:f97f410d4a21 3 //!
loopsva 0:f97f410d4a21 4 //! Copyright (c) 2009 MEAS Switzerland
loopsva 0:f97f410d4a21 5 //!
loopsva 0:f97f410d4a21 6 //!
loopsva 0:f97f410d4a21 7 //!
loopsva 0:f97f410d4a21 8 //! @brief This C code is for starter reference only. It is written for the
loopsva 0:f97f410d4a21 9 //! MEAS Switzerland MS56xx pressure sensor modules and Atmel Atmega644p
loopsva 0:f97f410d4a21 10 //! microcontroller.
loopsva 0:f97f410d4a21 11 //!
loopsva 0:f97f410d4a21 12 //! @version 1.0 $Id: an520_I2C.c,v 1.0
loopsva 0:f97f410d4a21 13 //!
loopsva 0:f97f410d4a21 14 //! @todo
loopsva 0:f97f410d4a21 15
loopsva 0:f97f410d4a21 16 #include "mbed.h"
loopsva 0:f97f410d4a21 17 #include "ms5611.h"
loopsva 0:f97f410d4a21 18
loopsva 0:f97f410d4a21 19 //--------------------------------------------------------------------------------------------------------------------------------------//
loopsva 0:f97f410d4a21 20 // Constructor and destructor
loopsva 0:f97f410d4a21 21
loopsva 0:f97f410d4a21 22 ms5611::ms5611(PinName sda, PinName scl) : _i2c(sda, scl) {
loopsva 0:f97f410d4a21 23
loopsva 0:f97f410d4a21 24 }
loopsva 0:f97f410d4a21 25
loopsva 0:f97f410d4a21 26 //********************************************************
loopsva 0:f97f410d4a21 27 //! @brief send I2C start condition and the address byte
loopsva 0:f97f410d4a21 28 //!
loopsva 0:f97f410d4a21 29 //! @return 0
loopsva 0:f97f410d4a21 30 //********************************************************
loopsva 0:f97f410d4a21 31
loopsva 0:f97f410d4a21 32 int ms5611::m_i2c_start(bool readMode) {
loopsva 0:f97f410d4a21 33 int twst;
loopsva 0:f97f410d4a21 34 _i2c.start();
loopsva 0:f97f410d4a21 35 if(readMode == true) {
loopsva 0:f97f410d4a21 36 twst = m_i2c_write(MS5611_ADDR_R);
loopsva 0:f97f410d4a21 37 } else {
loopsva 0:f97f410d4a21 38 twst = m_i2c_write(MS5611_ADDR_W);
loopsva 0:f97f410d4a21 39 }
loopsva 0:f97f410d4a21 40 return(twst);
loopsva 0:f97f410d4a21 41 }
loopsva 0:f97f410d4a21 42
loopsva 0:f97f410d4a21 43 //********************************************************
loopsva 0:f97f410d4a21 44 //! @brief send I2C stop condition
loopsva 0:f97f410d4a21 45 //!
loopsva 0:f97f410d4a21 46 //! @return none
loopsva 0:f97f410d4a21 47 //********************************************************
loopsva 0:f97f410d4a21 48
loopsva 0:f97f410d4a21 49 void ms5611::m_i2c_stop(void) {
loopsva 0:f97f410d4a21 50 _i2c.stop();
loopsva 0:f97f410d4a21 51 }
loopsva 0:f97f410d4a21 52
loopsva 0:f97f410d4a21 53 //********************************************************
loopsva 0:f97f410d4a21 54 //! @brief send I2C stop condition
loopsva 0:f97f410d4a21 55 //!
loopsva 0:f97f410d4a21 56 //! @return remote ack status
loopsva 0:f97f410d4a21 57 //********************************************************
loopsva 0:f97f410d4a21 58
loopsva 0:f97f410d4a21 59 unsigned char ms5611::m_i2c_write(unsigned char data) {
loopsva 0:f97f410d4a21 60 int twst = _i2c.write(data);
loopsva 0:f97f410d4a21 61 return(twst);
loopsva 0:f97f410d4a21 62 }
loopsva 0:f97f410d4a21 63
loopsva 0:f97f410d4a21 64 //********************************************************
loopsva 0:f97f410d4a21 65 //! @brief read I2C byte with acknowledgment
loopsva 0:f97f410d4a21 66 //!
loopsva 0:f97f410d4a21 67 //! @return read byte
loopsva 0:f97f410d4a21 68 //********************************************************
loopsva 0:f97f410d4a21 69
loopsva 0:f97f410d4a21 70 unsigned char ms5611::m_i2c_readAck(void) {
loopsva 0:f97f410d4a21 71 int twst = _i2c.read(1);
loopsva 0:f97f410d4a21 72 return(twst);
loopsva 0:f97f410d4a21 73 }
loopsva 0:f97f410d4a21 74
loopsva 0:f97f410d4a21 75 //********************************************************
loopsva 0:f97f410d4a21 76 //! @brief read I2C byte without acknowledgment
loopsva 0:f97f410d4a21 77 //!
loopsva 0:f97f410d4a21 78 //! @return read byte
loopsva 0:f97f410d4a21 79 //********************************************************
loopsva 0:f97f410d4a21 80
loopsva 0:f97f410d4a21 81 unsigned char ms5611::m_i2c_readNak(void) {
loopsva 0:f97f410d4a21 82 int twst = _i2c.read(0);
loopsva 0:f97f410d4a21 83 return(twst);
loopsva 0:f97f410d4a21 84 }
loopsva 0:f97f410d4a21 85
loopsva 0:f97f410d4a21 86 //********************************************************
loopsva 0:f97f410d4a21 87 //! @brief send command using I2C hardware interface
loopsva 0:f97f410d4a21 88 //!
loopsva 0:f97f410d4a21 89 //! @return none
loopsva 0:f97f410d4a21 90 //********************************************************
loopsva 0:f97f410d4a21 91
loopsva 0:f97f410d4a21 92 void ms5611::m_i2c_send(char cmd) {
loopsva 0:f97f410d4a21 93 unsigned char ret;
loopsva 0:f97f410d4a21 94 ret = m_i2c_start(false); // set device address and write mode
loopsva 0:f97f410d4a21 95 if(!(ret)) {//failed to issue start condition, possibly no device found */
loopsva 0:f97f410d4a21 96 m_i2c_stop();
loopsva 0:f97f410d4a21 97 } else {// issuing start condition ok, device accessible
loopsva 0:f97f410d4a21 98 ret = m_i2c_write(cmd);
loopsva 0:f97f410d4a21 99 m_i2c_stop();
loopsva 0:f97f410d4a21 100 }
loopsva 0:f97f410d4a21 101 }
loopsva 0:f97f410d4a21 102
loopsva 0:f97f410d4a21 103 //********************************************************
loopsva 0:f97f410d4a21 104 //! @brief send reset sequence
loopsva 0:f97f410d4a21 105 //!
loopsva 0:f97f410d4a21 106 //! @return none
loopsva 0:f97f410d4a21 107 //********************************************************
loopsva 0:f97f410d4a21 108
loopsva 0:f97f410d4a21 109 void ms5611::cmd_reset() {
loopsva 0:f97f410d4a21 110 m_i2c_send(MS5611_CMD_RESET); // send reset sequence
loopsva 0:f97f410d4a21 111 wait_ms(4); // wait for the reset sequence timing
loopsva 0:f97f410d4a21 112 loadCoefs();
loopsva 0:f97f410d4a21 113 }
loopsva 0:f97f410d4a21 114
loopsva 0:f97f410d4a21 115 //********************************************************
loopsva 0:f97f410d4a21 116 //! @brief preform adc conversion
loopsva 0:f97f410d4a21 117 //!
loopsva 0:f97f410d4a21 118 //! @return 24bit result
loopsva 0:f97f410d4a21 119 //********************************************************
loopsva 0:f97f410d4a21 120
loopsva 0:f97f410d4a21 121 unsigned long ms5611::cmd_adc(char cmd) {
loopsva 0:f97f410d4a21 122 char cobuf[3];
loopsva 0:f97f410d4a21 123 cobuf[0] = 0;
loopsva 0:f97f410d4a21 124 cobuf[1] = 0;
loopsva 0:f97f410d4a21 125 cobuf[2] = 0;
loopsva 0:f97f410d4a21 126 unsigned int ret;
loopsva 0:f97f410d4a21 127 unsigned long temp = 0;
loopsva 0:f97f410d4a21 128 m_i2c_send(MS5611_CMD_ADC_CONV + cmd); // send conversion command
loopsva 0:f97f410d4a21 129 switch (cmd & 0x0f) { // wait necessary conversion time
loopsva 0:f97f410d4a21 130 case MS5611_CMD_ADC_256 : wait_us(900); break;
loopsva 0:f97f410d4a21 131 case MS5611_CMD_ADC_512 : wait_ms(3); break;
loopsva 0:f97f410d4a21 132 case MS5611_CMD_ADC_1024: wait_ms(4); break;
loopsva 0:f97f410d4a21 133 case MS5611_CMD_ADC_2048: wait_ms(6); break;
loopsva 0:f97f410d4a21 134 case MS5611_CMD_ADC_4096: wait_ms(10); break;
loopsva 0:f97f410d4a21 135 }
loopsva 0:f97f410d4a21 136 m_i2c_send(MS5611_CMD_ADC_READ);
loopsva 0:f97f410d4a21 137
loopsva 0:f97f410d4a21 138 ret = _i2c.read(MS5611_ADDR_R, cobuf, 3, false);
loopsva 0:f97f410d4a21 139 if(ret) printf("\n*** ms5611 ADC Read Error ");
loopsva 0:f97f410d4a21 140 temp = (cobuf[0] << 16) + (cobuf[1] << 8) + cobuf[2];
loopsva 0:f97f410d4a21 141 return temp;
loopsva 0:f97f410d4a21 142 }
loopsva 0:f97f410d4a21 143
loopsva 0:f97f410d4a21 144 //********************************************************
loopsva 0:f97f410d4a21 145 //! @brief Read calibration coefficients
loopsva 0:f97f410d4a21 146 //!
loopsva 0:f97f410d4a21 147 //! @return coefficient
loopsva 0:f97f410d4a21 148 //********************************************************
loopsva 0:f97f410d4a21 149
loopsva 0:f97f410d4a21 150 unsigned int ms5611::cmd_prom(char coef_num) {
loopsva 0:f97f410d4a21 151 char cobuf[2];
loopsva 0:f97f410d4a21 152 unsigned int ret;
loopsva 0:f97f410d4a21 153 unsigned int rC = 0;
loopsva 0:f97f410d4a21 154 cobuf[0] = 0;
loopsva 0:f97f410d4a21 155 cobuf[1] = 0;
loopsva 0:f97f410d4a21 156 m_i2c_send(MS5611_CMD_PROM_RD + coef_num * 2); // send PROM READ command
loopsva 0:f97f410d4a21 157 ret = _i2c.read(MS5611_ADDR_R, cobuf, 2, false);
loopsva 0:f97f410d4a21 158 if(ret) printf("\n*** ms5611 PROM Read Error ");
loopsva 0:f97f410d4a21 159 rC = cobuf[0] * 256 + cobuf[1];
loopsva 0:f97f410d4a21 160 return rC;
loopsva 0:f97f410d4a21 161 }
loopsva 0:f97f410d4a21 162
loopsva 0:f97f410d4a21 163 //********************************************************
loopsva 0:f97f410d4a21 164 //! @brief calculate the CRC code
loopsva 0:f97f410d4a21 165 //!
loopsva 0:f97f410d4a21 166 //! @return crc code
loopsva 0:f97f410d4a21 167 //********************************************************
loopsva 0:f97f410d4a21 168
loopsva 0:f97f410d4a21 169 unsigned char ms5611::crc4(unsigned int n_prom[]) {
loopsva 0:f97f410d4a21 170 //int cnt; // simple counter
loopsva 0:f97f410d4a21 171 unsigned int n_rem; // crc reminder
loopsva 0:f97f410d4a21 172 unsigned int crc_read; // original value of the crc
loopsva 0:f97f410d4a21 173 unsigned char n_bit;
loopsva 0:f97f410d4a21 174 n_rem = 0x00;
loopsva 0:f97f410d4a21 175 crc_read = n_prom[7]; //save read CRC
loopsva 0:f97f410d4a21 176 n_prom[7]=(0xFF00 & (n_prom[7])); //CRC byte is replaced by 0
loopsva 0:f97f410d4a21 177 for (int cnt = 0; cnt < 16; cnt++) {// operation is performed on bytes // choose LSB or MSB
loopsva 0:f97f410d4a21 178 if (cnt%2 == 1) {
loopsva 0:f97f410d4a21 179 n_rem ^= (unsigned short) ((n_prom[cnt>>1]) & 0x00FF);
loopsva 0:f97f410d4a21 180 } else {
loopsva 0:f97f410d4a21 181 n_rem ^= (unsigned short) (n_prom[cnt>>1]>>8);
loopsva 0:f97f410d4a21 182 }
loopsva 0:f97f410d4a21 183 for (n_bit = 8; n_bit > 0; n_bit--) {
loopsva 0:f97f410d4a21 184 if (n_rem & (0x8000)) {
loopsva 0:f97f410d4a21 185 n_rem = (n_rem << 1) ^ 0x3000;
loopsva 0:f97f410d4a21 186 } else {
loopsva 0:f97f410d4a21 187 n_rem = (n_rem << 1);
loopsva 0:f97f410d4a21 188 }
loopsva 0:f97f410d4a21 189 }
loopsva 0:f97f410d4a21 190 }
loopsva 0:f97f410d4a21 191 n_rem= (0x000F & (n_rem >> 12)); // final 4-bit reminder is CRC code
loopsva 0:f97f410d4a21 192 // printf("n_rem: %x crc_read: %x n_prom[7]: %x\n", n_rem, crc_read, n_prom[7]);
loopsva 0:f97f410d4a21 193
loopsva 0:f97f410d4a21 194 n_prom[7]=crc_read; // restore the crc_read to its original place
loopsva 0:f97f410d4a21 195 return (n_rem ^ 0x0);
loopsva 0:f97f410d4a21 196 /*
loopsva 0:f97f410d4a21 197 The CRC code is calculated and written in factory with the LSB byte in the prom n_prom[7] set to 0x00 (see
loopsva 0:f97f410d4a21 198 Coefficient table below). It is thus important to clear those bytes from the calculation buffer before proceeding
loopsva 0:f97f410d4a21 199 with the CRC calculation itself:
loopsva 0:f97f410d4a21 200 n_prom[7]=(0xFF00 & (n_prom[7])); //CRC byte is replaced by 0
loopsva 0:f97f410d4a21 201 As a simple test of the CRC code, the following coefficient table could be used:
loopsva 0:f97f410d4a21 202 unsigned int nprom[] = {0x3132,0x3334,0x3536,0x3738,0x3940,0x4142,0x4344,0x4500};
loopsva 0:f97f410d4a21 203 the resulting calculated CRC should be 0xB.
loopsva 0:f97f410d4a21 204
loopsva 0:f97f410d4a21 205 DB 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
loopsva 0:f97f410d4a21 206 Addr
loopsva 0:f97f410d4a21 207 0 16 bit reserved for manufacturer
loopsva 0:f97f410d4a21 208 1 Coefficient 1 (16 bit unsigned)
loopsva 0:f97f410d4a21 209 2 Coefficient 2 (16 bit unsigned)
loopsva 0:f97f410d4a21 210 3 Coefficient 3 (16 bit unsigned)
loopsva 0:f97f410d4a21 211 4 Coefficient 4 (16 bit unsigned)
loopsva 0:f97f410d4a21 212 5 Coefficient 5 (16 bit unsigned)
loopsva 0:f97f410d4a21 213 6 Coefficient 6 (16 bit unsigned)
loopsva 0:f97f410d4a21 214 7 0 0 0 0 CRC(0x0)
loopsva 0:f97f410d4a21 215 */
loopsva 0:f97f410d4a21 216 /*
loopsva 0:f97f410d4a21 217 //Returns 0x0b as per AP520_004
loopsva 0:f97f410d4a21 218 PTbuffer[0] = 0x3132;
loopsva 0:f97f410d4a21 219 PTbuffer[1] = 0x3334;
loopsva 0:f97f410d4a21 220 PTbuffer[2] = 0x3536;
loopsva 0:f97f410d4a21 221 PTbuffer[3] = 0x3738;
loopsva 0:f97f410d4a21 222 PTbuffer[4] = 0x3940;
loopsva 0:f97f410d4a21 223 PTbuffer[5] = 0x4142;
loopsva 0:f97f410d4a21 224 PTbuffer[6] = 0x4344;
loopsva 0:f97f410d4a21 225 PTbuffer[7] = 0x4546;
loopsva 0:f97f410d4a21 226 n_crc = ms.crc4(C); // calculate the CRC
loopsva 0:f97f410d4a21 227 pc.printf("testing CRC: 0x%x\n", n_crc);
loopsva 0:f97f410d4a21 228 */
loopsva 0:f97f410d4a21 229
loopsva 0:f97f410d4a21 230 }
loopsva 0:f97f410d4a21 231 //********************************************************
loopsva 0:f97f410d4a21 232 //! @brief load all calibration coefficients
loopsva 0:f97f410d4a21 233 //!
loopsva 0:f97f410d4a21 234 //! @return none
loopsva 0:f97f410d4a21 235 //********************************************************
loopsva 0:f97f410d4a21 236
loopsva 0:f97f410d4a21 237 unsigned int PTbuffer[8]; // calibration coefficients
loopsva 0:f97f410d4a21 238
loopsva 0:f97f410d4a21 239 void ms5611::loadCoefs() {
loopsva 0:f97f410d4a21 240 // printf("Getting coefficients... ");
loopsva 0:f97f410d4a21 241 for (int i = 0; i < 8; i++){
loopsva 0:f97f410d4a21 242 wait_ms(50);
loopsva 0:f97f410d4a21 243 PTbuffer[i] = cmd_prom(i); // read coefficients
loopsva 0:f97f410d4a21 244 // printf("0x%04x ", PTbuffer[i]);
loopsva 0:f97f410d4a21 245 }
loopsva 0:f97f410d4a21 246 // printf("\nCalculate CRC4: ");
loopsva 0:f97f410d4a21 247 unsigned char n_crc = crc4(PTbuffer); // calculate the CRC
loopsva 0:f97f410d4a21 248 // printf(" 0x%02x\n", n_crc);
loopsva 0:f97f410d4a21 249 }
loopsva 0:f97f410d4a21 250
loopsva 0:f97f410d4a21 251 double P; // compensated pressure value
loopsva 0:f97f410d4a21 252 double T; // compensated temperature value
loopsva 0:f97f410d4a21 253
loopsva 0:f97f410d4a21 254 //********************************************************
loopsva 0:f97f410d4a21 255 //! @brief calculate temperature and pressure
loopsva 0:f97f410d4a21 256 //!
loopsva 0:f97f410d4a21 257 //! @return none
loopsva 0:f97f410d4a21 258 //********************************************************
loopsva 0:f97f410d4a21 259
loopsva 0:f97f410d4a21 260 void ms5611::calcPT() {
loopsva 0:f97f410d4a21 261 unsigned long D2 = cmd_adc(MS5611_CMD_ADC_D2 + MS5611_CMD_ADC_4096); // read D2
loopsva 0:f97f410d4a21 262 unsigned long D1 = cmd_adc(MS5611_CMD_ADC_D1 + MS5611_CMD_ADC_4096); // read D1
loopsva 0:f97f410d4a21 263 // calculate 1st order pressure and temperature (MS5607 1st order algorithm)
loopsva 0:f97f410d4a21 264
loopsva 0:f97f410d4a21 265 double dT = D2 - (PTbuffer[5] << 8);
loopsva 0:f97f410d4a21 266 //change OFF and SENS scaling factor for ms5611
loopsva 0:f97f410d4a21 267 double OFF = (PTbuffer[2] << 16) + dT * PTbuffer[4] / (1 << 6); //was OFF = (PTbuffer[2] << 17) + dT * PTbuffer[4] / (1 << 6);
loopsva 0:f97f410d4a21 268 double SENS = (PTbuffer[1] << 15) + dT * PTbuffer[3] / (1 << 7); //was SENS = (PTbuffer[1] << 16) + dT * PTbuffer[3] / (1 << 7);
loopsva 0:f97f410d4a21 269 T = (2000 + (dT * PTbuffer[6]) / (1 << 23)) / 100;
loopsva 0:f97f410d4a21 270 P = (((D1*SENS) / (1 << 21) - OFF) / (1 << 15)) / 100;
loopsva 0:f97f410d4a21 271
loopsva 0:f97f410d4a21 272 // dT = D2 - PTbuffer[5] * pow(2,8);
loopsva 0:f97f410d4a21 273 // OFF = PTbuffer[2] * pow(2,17) + dT * PTbuffer[4] / pow(2,6);
loopsva 0:f97f410d4a21 274 // SENS = PTbuffer[1] * pow(2,16) + dT * PTbuffer[3] / pow(2,7);
loopsva 0:f97f410d4a21 275 // T = (2000 + (dT * PTbuffer[6]) / pow(2,23)) / 100;
loopsva 0:f97f410d4a21 276 // P = (((D1*SENS) / pow(2,21) - OFF) / pow(2,15)) / 100;
loopsva 0:f97f410d4a21 277 // place to use P, T, put them on LCD, send them trough RS232 interface...
loopsva 0:f97f410d4a21 278 }
loopsva 0:f97f410d4a21 279
loopsva 0:f97f410d4a21 280 //********************************************************
loopsva 0:f97f410d4a21 281 //! @brief calculate temperature
loopsva 0:f97f410d4a21 282 //!
loopsva 0:f97f410d4a21 283 //! @return double temperature degC
loopsva 0:f97f410d4a21 284 //********************************************************
loopsva 0:f97f410d4a21 285
loopsva 0:f97f410d4a21 286 double ms5611::calcTemp() {
loopsva 0:f97f410d4a21 287 calcPT();
loopsva 0:f97f410d4a21 288 return(T);
loopsva 0:f97f410d4a21 289 }
loopsva 0:f97f410d4a21 290
loopsva 0:f97f410d4a21 291 //********************************************************
loopsva 0:f97f410d4a21 292 //! @brief calculate prssure
loopsva 0:f97f410d4a21 293 //!
loopsva 0:f97f410d4a21 294 //! @return double barometric pressure millibar
loopsva 0:f97f410d4a21 295 //********************************************************
loopsva 0:f97f410d4a21 296
loopsva 0:f97f410d4a21 297 double ms5611::calcPressure() {
loopsva 0:f97f410d4a21 298 calcPT();
loopsva 0:f97f410d4a21 299 return(P);
loopsva 0:f97f410d4a21 300 }