GithubHelp home page GithubHelp logo

ms5611's Introduction

Arduino CI Arduino-lint JSON check GitHub issues

License: MIT GitHub release PlatformIO Registry

MS5611

Arduino library for MS5611 temperature and pressure sensor.

Description

The MS5611-01BA03 is a high resolution pressure (and temperature) sensor a.k.a GY-63. The high resolution is made possible by oversampling many times.

The device address is 0x76 or 0x77 depending on the CSB/CSO pin.

This library only implements the I2C interface.

An experimental SPI version of the library can be found here

Compatibility

The library should be compatible with MS56XX, MS57xx and MS58xx devices (to be tested). Some device types will returns only 50% of the pressure value. This is solved in 0.3.9 by calling reset(1) to select the math used.

Self heating

In some configurations especially when using SPI the sensor showed a self heating. First this was approached as a problem, so investigations were done to understand the cause and how to solve it. During this process the view changed of seeing the higher temperature as a problem to being the solution.

The sensor is primary a pressure sensor and if it is heated by a cause (don't care) it needs compensation. For that the temperature sensor is build in the device. Depending on the configuration self heating can be as low as 0.1°C to as high as 10++ °C.

WARNING One should NOT use 5V to control I2C address line, SPI select, or the protocol select line. This causes extreme heat build up > 10°C.

One should only use 3V3 lines for these "selection lines".

See also - RobTillaart/MS5611_SPI#3

Note: the self heating offset can be compensated with setTemperatureOffset(offset) which allows you to match the temperature with the ambient temperature again. As the self heating effect is not expected to be linear over the full range of the temperature sensor the offset might work only in a smaller range. To have a reliable ambient temperature it is advised to use an dedicated temperature sensor for this (e.g. DS18B20).

Breakout GY-63

//
//  BREAKOUT  MS5611  aka  GY63 - see datasheet
//
//  SPI    I2C
//              +--------+
//  VCC    VCC  | o      |
//  GND    GND  | o      |
//         SCL  | o      |
//  SDI    SDA  | o      |
//  CSO         | o      |
//  SDO         | o L    |   L = led
//          PS  | o    O |   O = opening  PS = protocol select
//              +--------+
//
//  PS to VCC  ==>  I2C  (GY-63 board has internal pull up, so not needed)
//  PS to GND  ==>  SPI
//  CS to VCC  ==>  0x76
//  CS to GND  ==>  0x77
//

Related libraries

For pressure conversions see - https://github.com/RobTillaart/pressure

For temperature conversions see - https://github.com/RobTillaart/Temperature

Release Notes (major)

0.3.0 breaking change

  • fixed math error so previous versions are obsolete.
  • temperature is a float expressed in degrees Celsius.
  • pressure is a float expressed in mBar.

0.3.5 NANO 33 BLE

The I2C/Wire library of the NANO 33 BLE does not see the device on the I2C bus. After hours of testing it looks like that the I2C/Wire library of the NANO 33 BLE does not handle isConnected() like other platforms do. Adding a wire->write(0x00) in isConnected() fixes the problem, however more investigation is needed to understand the root cause.

0.3.9 pressure math

There are MS5611 compatibles for which the math for the pressure is different. See AN520__004: C-code example for MS56xx, MS57xx (except analog sensor), and MS58xx series pressure sensors The difference is in the constants (powers of 2) used to calculate the pressure.

The library implements reset(uint8_t mathMode = 0) to select the mathMode.

  • mathMode = 0 ==> datasheet type math (default)
  • mathMode = 1 ==> Application notes type math.
  • other values will act as 0

See issue #33.

0.4.0 breaking change

refactored the Wire dependency. Affected are:

  • constructor
  • begin()

User has to call Wire.begin() (or equivalent) before calling ms5611.begin()

Interface

#include "MS5611.h"

Base

  • MS5611(uint8_t deviceAddress = MS5611_DEFAULT_ADDRESS, TwoWire *wire = &Wire) constructor. Since 0.3.7 a default address 0x77 is added. Optionally set Wire interface.
  • bool begin() Initializes internals by calling reset(). Return false indicates either isConnected() error or reset() error.
    One must call Wire.begin() (or equivalent) before calling begin().
  • bool isConnected() checks availability of device address on the I2C bus. (see note above NANO 33 BLE).
  • bool reset(uint8_t mathMode = 0) resets the chip and loads constants from its ROM. Returns false if ROM could not be read.
    • mathMode = 0 follows the datasheet math (default).
    • mathMode = 1 will adjust for a factor 2 in the pressure math.
  • int read(uint8_t bits) the actual reading of the sensor. Number of bits determines the oversampling factor. Returns MS5611_READ_OK upon success.
  • int read() wraps the read() above, uses the preset oversampling (see below). Returns MS5611_READ_OK upon success.
  • float getTemperature() returns temperature in °C. Subsequent calls will return the same value until a new read() is called.
  • float getPressure() pressure is in mBar. Subsequent calls will return the same value until a new read() is called.

Oversampling

  • void setOversampling(osr_t samplingRate) sets the amount of oversampling. See table below and test example how to use.
  • osr_t getOversampling() returns amount of oversampling.

Some numbers from datasheet, page 3 MAX column rounded up. (see #23) (actual read time differs - see performance sketch)

definition value oversampling ratio resolution (mbar) time (us) notes
OSR_ULTRA_HIGH 12 4096 0.012 9100
OSR_HIGH 11 2048 0.018 4600
OSR_STANDARD 10 1024 0.027 2300
OSR_LOW 9 512 0.042 1200
OSR_ULTRA_LOW 8 256 0.065 600 Default = backwards compatible

Offset

The offset functions are added (0.3.6) to calibrate the sensor against e.g. a local weather station. This calibration can only be done runtime.

  • void setPressureOffset(float offset = 0) Set an offset to calibrate the pressure. Can be used to get the pressure relative to e.g. 1 Atm. Set the offset to -1013 HPa/mBar and you get a sort of relative pressure. Default the offset is set to 0.
  • float getPressureOffset() returns the current pressure offset.
  • void setTemperatureOffset(float offset = 0) Set an offset to calibrate the temperature. Can be used to get the temperature in degrees Kelvin, just set the offset to +273.15. Default the offset is set to 0.
  • float getTemperatureOffset() returns the current temperature offset.

Misc

  • int getLastResult() checks last I2C communication. Replace with more informative error handling?
  • uint32_t lastRead() last time when read() was called in milliseconds since startup.

DeviceID

  • uint32_t getDeviceID() returns the hashed values of the calibration PROM. As these calibration are set in the factory and differ (enough) per sensor these can serve as an unique deviceID.

Having a device-ID can be used in many ways:

  • use known offsets for each sensor automatically,
  • work as an identification of that specific copy of the project (customer specific tracking).
  • ID in a mesh network
  • etc.

Note: this is not an official ID from the device / datasheet, it is made up from calibration data.

getManufacturer

The meaning of the manufacturer and serialCode value is unclear.

  • uint16_t getManufacturer() returns manufacturer private info.
  • uint16_t getSerialCode() returns serialCode from the PROM[6].

2nd order pressure compensation

  • setCompensation(bool flag = true) to enable/desirable the 2nd order compensation. The default = true. Disabling the compensation will be slightly faster but you loose precision.
  • getCompensation() returns flag set above.

Future

Must

  • update documentation

Should

  • proper error handling.
  • move all code to .cpp

Could

  • redo lower level functions?
  • handle the read + math of temperature first?

Wont

Support

If you appreciate my libraries, you can support the development and maintenance. Improve the quality of the libraries by providing issues and Pull Requests, or donate through PayPal or GitHub sponsors.

Thank you,

ms5611's People

Contributors

lberrymage avatar lyricpants66133 avatar robtillaart avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

ms5611's Issues

Bias between different oversampling levels

Hello! thanks a lot for your work here!

I'm trying to filter out this high frequency noise and, while analizing the data, ultra_low oversampling consistently sheds 20mBar less than ultra_high. I wonder whether this is normal.
image

Also, it's hard to characterise this noise. There's no spike in the spectrum (fourier transform) for any of the sampling methods. Only the band-base signal.

I'm thinking of the best way to filter out the noise. If you had some ideas (IIR/FIR/Kalman...) and also, maybe the reset(1) method can include this oversampling aware compensation

NANO 33 BLE can not see device on I2C bus - isConnected()

(this is a summary of an earlier discussion by e-mail, better to archive the essence here)
The NANO 33 BLE is an processor using MBED toolchain.

Problem

The MS5611 cannot be seen on the I2C bus

  • not with the isConnected() call
  • not by I2C scanners

This prevents to check if the device is connected in the device.begin() call during the setup of the project.
Note that the device will work as it should if one ignores the return value of begin().

Analysis

The isConnected() call and I2C scanners just put addresses on the I2C bus and expect an ACK when a device recognizes its address. The MS5611 does this well on AVR and ESP but not on MBED.

Note that on the internet there were similar an related problems mentioned without a solution.

(many tests and mails later a possible cause is found in the endTransmission() code of MBED
....Arduino15\packages\arduino\hardware\mbed_nano\2.7.2\libraries\Wire\Wire.cpp

uint8_t arduino::MbedI2C::endTransmission(bool stopBit) {
  #ifndef TARGET_PORTENTA_H7
  if (usedTxBuffer == 0) {
    // we are scanning, return 0 if the addresed device responds with an ACK
    char buf[1];
    int ret = master->read(_address, buf, 1, !stopBit);
    return ret;
  }
  #endif
  if (master->write(_address, (const char *) txBuffer, usedTxBuffer, !stopBit) == 0) return 0;
  return 2;
}

If there are no bytes in the transmitBuffer the MBED returns the value of read()
If there are bytes in the transmitBuffer the MBED returns the value of write()

Other endTransmission() implementations known - AVR / ESP - always use the write()
even if the transmitBuffer is empty (usedTxBuffer == 0)

The rationale why MBED does this differently is unknown.

Patch / workaround

The library is patched so if an NANO 33 BLE is addressed it adds an write(0) in the isConnected() code (0.3.5)

https://github.com/RobTillaart/MS5611/blob/master/MS5611.cpp

bool MS5611::isConnected()
{
  _wire->beginTransmission(_address);
   #ifdef ARDUINO_ARCH_NRF52840
   //  needed for NANO 33 BLE
  _wire->write(0);                            // <<< extra byte forces code to select the write path in endTransmission()
   #endif
  return (_wire->endTransmission() == 0);
}

This forces the write path in endTransmission() and the device returns the ACK expected.

WARNING: Although this works it is not a solution as it is unknown how devices in general will react on this extra byte,

Thoughts about a solution

The patch above is a workaround that is not the right solution so more investigations / discussions are needed to solve this.

  • why does MBED use a master->read() when the buffer is empty?
  • what does the master->read() return ? is that correct? (apparently not)
  • can the endTransmission() function be simplified to always using write()?
    a test shows this works well for the MS5611 but unknown if this causes any problems with other devices.

A generic solution could be that the Wire library is extended with a call, which returns if the address exist on the I2C bus.

  • bool exist(address)

Set 0x77 as default address in example scripts

As stated in the MS5611 documentation and in the example sketches, MS5611's address can be configured by wiring CSB pin to VCC (0x76) or to GND (0x77). MS5611's documentation suggests not to leave CSB pin unconnected/unwired. However, if unconnected/unwired, 0x77 is the default address.

Currently all example sketches are configured to use 0x76 address. This should be changed to 0x77.

Problems reading two barometers from version 0.3.3 onwards.

Thank you for this library, it is of good use to me. I am using it in a DIY airspeed indicator based on two GY63 ms5611 breakouts. The pressures from the pitot tube are read in succession and their values are compared, compensated for the offset between them.

Using version 0.3.2 this all worked fine. But with versions 0.3.3 to 0.3.5 I get corrupted values from the first baro that is read; that is the one with address 0x76.

Possible calculation error on MS5611.cpp line 128

Hey,

For a project, I'm trying to rewrite your library (which looks great by the way) to STM32. During the rewrite, I found a possible calculation error in MS5611.cpp on line 128.

float sens2 = 1.25 * t * t * t;

Here, you take t to the third power, while the datasheet (page 9) takes t to the second power.

SENS2 = 5 * (TEMP – 2000)^2 / 4

Looking at all the math in the diagram, it might be even better to assign
t = (_temperature - 2000) * (_temperature - 2000)

MS5611 compilation error: lvalue required as left operand of assignment uint32_t D1 = readADC();

Testing with the minimal example at master/examples/MS5611_minimal/MS5611_minimal.ino.
During sketch compilation I get following error:

c:\...\Arduino\libraries\MS5611\MS5611.cpp: In member function 'int MS5611::read(uint8_t)':
c:\...\Arduino\libraries\MS5611\MS5611.cpp:141:25: error: lvalue required as left operand of assignment
   uint32_t D1 = readADC();
                         ^
c:\...\Arduino\libraries\MS5611\MS5611.cpp:146:25: error: lvalue required as left operand of assignment
   uint32_t D2 = readADC();
                         ^
Compilation error: exit status 1}

Tested with MS5611 library versions 0.3.1, 0.3.2 and 0.3.3.
Tested with Arduino IDE v1.8.19 and v2.0.0-rc3.

Verify formulas for different mathModi

During development for MS5837 I noticed a significant difference in the compensation code for pressure.

To verify and clarify.
(idem for SPI based class, not making a separate issue for now, first solve here)

Error compiling MS5611cpp

Received this error when compiling MS5611.cpp Version 0.2:

C:\Users\User1\.platformio\lib\MS5611_ID1351\MS5611.cpp:150:19: note: deduced conflicting types for parameter 'const _Tp' ('unsigned char' and 'int') reg = min(reg, 7); // constrain(reg, 0, 7) but reg is an uint so...

My fix was to assign a variable the line before with the same type (uint8_t) as 'reg', ie:

uint8_t maxNum = 7; reg = min(reg, maxNum); // constrain(reg, 0, 7) but reg is an uint so...

Reading temperature compensated values

Hello,

in your examples you not use the ms5611.reset function… while is the only one that read the calibration tables on the ms5611 memory.

can you tell me how to simple get temperature compensated pressure values?

For that we need to code this below?

in the setup:
Ms5611.begin
Ms5611.reset

in the main loop:
Ms5611.read
Ms5611.get temperature
Ms5611.get pressure

?

Does I forgot one thing?

thank you for for help.

rgds

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.