Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: mbed_5637_test Weather_Station_Ofiicial
Fork of ms5611 by
Revision 0:f97f410d4a21, committed 2013-05-07
- Comitter:
- loopsva
- Date:
- Tue May 07 18:44:06 2013 +0000
- Child:
- 1:94a46b4fed9d
- Commit message:
- Initial Release. High resolution Barometer / Altimeter
Changed in this revision
| ms5611.cpp | Show annotated file Show diff for this revision Revisions of this file |
| ms5611.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ms5611.cpp Tue May 07 18:44:06 2013 +0000
@@ -0,0 +1,300 @@
+//!
+//! @file an520_I2C.c,v
+//!
+//! Copyright (c) 2009 MEAS Switzerland
+//!
+//!
+//!
+//! @brief This C code is for starter reference only. It is written for the
+//! MEAS Switzerland MS56xx pressure sensor modules and Atmel Atmega644p
+//! microcontroller.
+//!
+//! @version 1.0 $Id: an520_I2C.c,v 1.0
+//!
+//! @todo
+
+#include "mbed.h"
+#include "ms5611.h"
+
+//--------------------------------------------------------------------------------------------------------------------------------------//
+// Constructor and destructor
+
+ms5611::ms5611(PinName sda, PinName scl) : _i2c(sda, scl) {
+
+}
+
+//********************************************************
+//! @brief send I2C start condition and the address byte
+//!
+//! @return 0
+//********************************************************
+
+int ms5611::m_i2c_start(bool readMode) {
+ int twst;
+ _i2c.start();
+ if(readMode == true) {
+ twst = m_i2c_write(MS5611_ADDR_R);
+ } else {
+ twst = m_i2c_write(MS5611_ADDR_W);
+ }
+ return(twst);
+}
+
+//********************************************************
+//! @brief send I2C stop condition
+//!
+//! @return none
+//********************************************************
+
+void ms5611::m_i2c_stop(void) {
+ _i2c.stop();
+}
+
+//********************************************************
+//! @brief send I2C stop condition
+//!
+//! @return remote ack status
+//********************************************************
+
+unsigned char ms5611::m_i2c_write(unsigned char data) {
+ int twst = _i2c.write(data);
+ return(twst);
+}
+
+//********************************************************
+//! @brief read I2C byte with acknowledgment
+//!
+//! @return read byte
+//********************************************************
+
+unsigned char ms5611::m_i2c_readAck(void) {
+ int twst = _i2c.read(1);
+ return(twst);
+}
+
+//********************************************************
+//! @brief read I2C byte without acknowledgment
+//!
+//! @return read byte
+//********************************************************
+
+unsigned char ms5611::m_i2c_readNak(void) {
+ int twst = _i2c.read(0);
+ return(twst);
+}
+
+//********************************************************
+//! @brief send command using I2C hardware interface
+//!
+//! @return none
+//********************************************************
+
+void ms5611::m_i2c_send(char cmd) {
+ unsigned char ret;
+ ret = m_i2c_start(false); // set device address and write mode
+ if(!(ret)) {//failed to issue start condition, possibly no device found */
+ m_i2c_stop();
+ } else {// issuing start condition ok, device accessible
+ ret = m_i2c_write(cmd);
+ m_i2c_stop();
+ }
+}
+
+//********************************************************
+//! @brief send reset sequence
+//!
+//! @return none
+//********************************************************
+
+void ms5611::cmd_reset() {
+ m_i2c_send(MS5611_CMD_RESET); // send reset sequence
+ wait_ms(4); // wait for the reset sequence timing
+ loadCoefs();
+}
+
+//********************************************************
+//! @brief preform adc conversion
+//!
+//! @return 24bit result
+//********************************************************
+
+unsigned long ms5611::cmd_adc(char cmd) {
+ char cobuf[3];
+ cobuf[0] = 0;
+ cobuf[1] = 0;
+ cobuf[2] = 0;
+ unsigned int ret;
+ unsigned long temp = 0;
+ m_i2c_send(MS5611_CMD_ADC_CONV + cmd); // send conversion command
+ switch (cmd & 0x0f) { // wait necessary conversion time
+ case MS5611_CMD_ADC_256 : wait_us(900); break;
+ case MS5611_CMD_ADC_512 : wait_ms(3); break;
+ case MS5611_CMD_ADC_1024: wait_ms(4); break;
+ case MS5611_CMD_ADC_2048: wait_ms(6); break;
+ case MS5611_CMD_ADC_4096: wait_ms(10); break;
+ }
+ m_i2c_send(MS5611_CMD_ADC_READ);
+
+ ret = _i2c.read(MS5611_ADDR_R, cobuf, 3, false);
+ if(ret) printf("\n*** ms5611 ADC Read Error ");
+ temp = (cobuf[0] << 16) + (cobuf[1] << 8) + cobuf[2];
+ return temp;
+}
+
+//********************************************************
+//! @brief Read calibration coefficients
+//!
+//! @return coefficient
+//********************************************************
+
+unsigned int ms5611::cmd_prom(char coef_num) {
+ char cobuf[2];
+ unsigned int ret;
+ unsigned int rC = 0;
+ cobuf[0] = 0;
+ cobuf[1] = 0;
+ m_i2c_send(MS5611_CMD_PROM_RD + coef_num * 2); // send PROM READ command
+ ret = _i2c.read(MS5611_ADDR_R, cobuf, 2, false);
+ if(ret) printf("\n*** ms5611 PROM Read Error ");
+ rC = cobuf[0] * 256 + cobuf[1];
+ return rC;
+}
+
+//********************************************************
+//! @brief calculate the CRC code
+//!
+//! @return crc code
+//********************************************************
+
+unsigned char ms5611::crc4(unsigned int n_prom[]) {
+ //int cnt; // simple counter
+ unsigned int n_rem; // crc reminder
+ unsigned int crc_read; // original value of the crc
+ unsigned char n_bit;
+ n_rem = 0x00;
+ crc_read = n_prom[7]; //save read CRC
+ n_prom[7]=(0xFF00 & (n_prom[7])); //CRC byte is replaced by 0
+ for (int cnt = 0; cnt < 16; cnt++) {// operation is performed on bytes // choose LSB or MSB
+ if (cnt%2 == 1) {
+ n_rem ^= (unsigned short) ((n_prom[cnt>>1]) & 0x00FF);
+ } else {
+ n_rem ^= (unsigned short) (n_prom[cnt>>1]>>8);
+ }
+ for (n_bit = 8; n_bit > 0; n_bit--) {
+ if (n_rem & (0x8000)) {
+ n_rem = (n_rem << 1) ^ 0x3000;
+ } else {
+ n_rem = (n_rem << 1);
+ }
+ }
+ }
+ n_rem= (0x000F & (n_rem >> 12)); // final 4-bit reminder is CRC code
+// printf("n_rem: %x crc_read: %x n_prom[7]: %x\n", n_rem, crc_read, n_prom[7]);
+
+ n_prom[7]=crc_read; // restore the crc_read to its original place
+ return (n_rem ^ 0x0);
+/*
+The CRC code is calculated and written in factory with the LSB byte in the prom n_prom[7] set to 0x00 (see
+Coefficient table below). It is thus important to clear those bytes from the calculation buffer before proceeding
+with the CRC calculation itself:
+n_prom[7]=(0xFF00 & (n_prom[7])); //CRC byte is replaced by 0
+As a simple test of the CRC code, the following coefficient table could be used:
+unsigned int nprom[] = {0x3132,0x3334,0x3536,0x3738,0x3940,0x4142,0x4344,0x4500};
+the resulting calculated CRC should be 0xB.
+
+DB 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+Addr
+0 16 bit reserved for manufacturer
+1 Coefficient 1 (16 bit unsigned)
+2 Coefficient 2 (16 bit unsigned)
+3 Coefficient 3 (16 bit unsigned)
+4 Coefficient 4 (16 bit unsigned)
+5 Coefficient 5 (16 bit unsigned)
+6 Coefficient 6 (16 bit unsigned)
+7 0 0 0 0 CRC(0x0)
+*/
+/*
+ //Returns 0x0b as per AP520_004
+ PTbuffer[0] = 0x3132;
+ PTbuffer[1] = 0x3334;
+ PTbuffer[2] = 0x3536;
+ PTbuffer[3] = 0x3738;
+ PTbuffer[4] = 0x3940;
+ PTbuffer[5] = 0x4142;
+ PTbuffer[6] = 0x4344;
+ PTbuffer[7] = 0x4546;
+ n_crc = ms.crc4(C); // calculate the CRC
+ pc.printf("testing CRC: 0x%x\n", n_crc);
+*/
+
+}
+//********************************************************
+//! @brief load all calibration coefficients
+//!
+//! @return none
+//********************************************************
+
+unsigned int PTbuffer[8]; // calibration coefficients
+
+void ms5611::loadCoefs() {
+ // printf("Getting coefficients... ");
+ for (int i = 0; i < 8; i++){
+ wait_ms(50);
+ PTbuffer[i] = cmd_prom(i); // read coefficients
+ // printf("0x%04x ", PTbuffer[i]);
+ }
+ // printf("\nCalculate CRC4: ");
+ unsigned char n_crc = crc4(PTbuffer); // calculate the CRC
+ // printf(" 0x%02x\n", n_crc);
+}
+
+double P; // compensated pressure value
+double T; // compensated temperature value
+
+//********************************************************
+//! @brief calculate temperature and pressure
+//!
+//! @return none
+//********************************************************
+
+void ms5611::calcPT() {
+ unsigned long D2 = cmd_adc(MS5611_CMD_ADC_D2 + MS5611_CMD_ADC_4096); // read D2
+ unsigned long D1 = cmd_adc(MS5611_CMD_ADC_D1 + MS5611_CMD_ADC_4096); // read D1
+ // calculate 1st order pressure and temperature (MS5607 1st order algorithm)
+
+ double dT = D2 - (PTbuffer[5] << 8);
+ //change OFF and SENS scaling factor for ms5611
+ double OFF = (PTbuffer[2] << 16) + dT * PTbuffer[4] / (1 << 6); //was OFF = (PTbuffer[2] << 17) + dT * PTbuffer[4] / (1 << 6);
+ double SENS = (PTbuffer[1] << 15) + dT * PTbuffer[3] / (1 << 7); //was SENS = (PTbuffer[1] << 16) + dT * PTbuffer[3] / (1 << 7);
+ T = (2000 + (dT * PTbuffer[6]) / (1 << 23)) / 100;
+ P = (((D1*SENS) / (1 << 21) - OFF) / (1 << 15)) / 100;
+
+// dT = D2 - PTbuffer[5] * pow(2,8);
+// OFF = PTbuffer[2] * pow(2,17) + dT * PTbuffer[4] / pow(2,6);
+// SENS = PTbuffer[1] * pow(2,16) + dT * PTbuffer[3] / pow(2,7);
+// T = (2000 + (dT * PTbuffer[6]) / pow(2,23)) / 100;
+// P = (((D1*SENS) / pow(2,21) - OFF) / pow(2,15)) / 100;
+ // place to use P, T, put them on LCD, send them trough RS232 interface...
+}
+
+//********************************************************
+//! @brief calculate temperature
+//!
+//! @return double temperature degC
+//********************************************************
+
+double ms5611::calcTemp() {
+ calcPT();
+ return(T);
+}
+
+//********************************************************
+//! @brief calculate prssure
+//!
+//! @return double barometric pressure millibar
+//********************************************************
+
+double ms5611::calcPressure() {
+ calcPT();
+ return(P);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/ms5611.h Tue May 07 18:44:06 2013 +0000
@@ -0,0 +1,127 @@
+#ifndef MS5611_H
+#define MS5611_H
+
+#include "mbed.h"
+
+/** Software routines to access the Measurement Specialties' MS5611-01BA03
+ * Variometer Module using the I2C bus option. The MS5611 is a 24 bit
+ * temperature and pressure transducer for high accuracy Barometer and
+ * Altimeter applications. It also includes compensation coefficients
+ * stored within the device.
+ *
+ * Code adapted from Measurement Specialties:
+ * "AN520 C-code example for MS56xx, MS57xx (except analog sensor), and
+ * MS58xx series pressure sensors"
+ *
+ * Note: AN520 has not been updated for use with the MS5611. Changes
+ * were necessary to "calcPT()" in order to correct scaling of
+ * pressure readings.
+ *
+ * Features:
+ * Altitude resolution to 10cm
+ * Fast conversion down to 1 ms
+ * Low power, 1 μA (standby < 0.15 μA)
+ * QFN package 5.0 x 3.0 x 1.0 mm^3
+ * Supply voltage 1.8 to 3.6 V
+ * Integrated digital pressure sensor (24 bit DeltaSigma ADC)
+ * Operating range: 10 to 1200 mbar, -40 to +85 °C
+ * I2C and SPI interface up to 20 MHz
+ * No external components (Internal oscillator)
+ * Excellent long term stability
+ *
+ * @code
+ * #include "mbed.h"
+ * #include "ms5611.h"
+ *
+ * ms5611 ms(p9, p10); // i2c pins used
+ * Serial pc(USBTX, USBRX); // local terminal interface
+ *
+ *
+ * int main (void) {
+ * pc.baud(921600); // set up USB serial speed
+ * i2c.frequency(400000); // set up i2c speed
+ *
+ * // set up the ms5611
+ * pc.printf("\n\nInitializing the MS5611..\n");
+ * ms.cmd_reset();
+ * pc.printf("Ready\n");
+ *
+ * while(1) {
+ * double Temp = ms.calcTemp();
+ * double Press = ms.calcPressure();
+ * pc.printf("Temp: %.2f degC Barometer: %.1f mB %.3f in/Hg\n", Temp, Press, Press * 0.0295301);
+ * wait(2.0);
+ * }
+ * }
+ *
+ * @endcode
+ */
+
+//_____ M A C R O S
+
+#define MS5611_ADDR_W 0xEE // Module address write mode
+#define MS5611_ADDR_R 0xEF // Module address read mode
+#define MS5611_CMD_RESET 0x1E // ADC reset command
+#define MS5611_CMD_ADC_READ 0x00 // ADC read command
+#define MS5611_CMD_ADC_CONV 0x40 // ADC conversion command
+#define MS5611_CMD_ADC_D1 0x00 // ADC D1 conversion
+#define MS5611_CMD_ADC_D2 0x10 // ADC D2 conversion
+#define MS5611_CMD_ADC_256 0x00 // ADC OSR=256
+#define MS5611_CMD_ADC_512 0x02 // ADC OSR=512
+#define MS5611_CMD_ADC_1024 0x04 // ADC OSR=1024
+#define MS5611_CMD_ADC_2048 0x06 // ADC OSR=2048
+#define MS5611_CMD_ADC_4096 0x08 // ADC OSR=4096
+#define MS5611_CMD_PROM_RD 0xA0 // Prom read command
+
+/* MS5611 controller class
+ */
+class ms5611{
+
+public:
+ /** Create a MS5611 object using the specified I2C object
+ *
+ * @param constructor, - the I2C object to communicate with
+ */
+ ms5611(PinName sda, PinName scl);
+ /** Initialize the MS5611 and set up the coefficients
+ * First - reset the MS5611
+ * Second - load coefficient values from the MS5611 PROM
+ * Third - calculate coefficient checksum
+ * This routine only needs to be run once at boot up
+ *
+ * @param NONE
+ */
+ void cmd_reset();
+ /** Calculate and return compensated temperature
+ * Returns double temperature in degC
+ *
+ * @param NONE
+ */
+ double calcTemp();
+ /** Calculate and return compensated barometric pressure
+ * Returns double pressure in millibars
+ *
+ * @param NONE
+ */
+ double calcPressure();
+
+private:
+ int m_i2c_start(bool readMode);
+ void m_i2c_stop(void);
+ unsigned char m_i2c_write(unsigned char data);
+ unsigned char m_i2c_readAck(void);
+ unsigned char m_i2c_readNak(void);
+ void m_i2c_send(char cmd);
+ void loadCoefs();
+ unsigned long cmd_adc(char cmd);
+ unsigned int cmd_prom(char coef_num);
+ unsigned char crc4(unsigned int n_prom[]);
+ void calcPT();
+ unsigned int PTbuffer[8]; // calibration coefficients
+
+protected:
+ I2C _i2c;
+
+
+};
+#endif
