0.1.0 MS5837

This commit is contained in:
Rob Tillaart 2023-12-24 11:16:46 +01:00
parent cb75f28139
commit 39dc12113d
15 changed files with 855 additions and 0 deletions

View File

@ -0,0 +1,28 @@
platforms:
rpipico:
board: rp2040:rp2040:rpipico
package: rp2040:rp2040
gcc:
features:
defines:
- ARDUINO_ARCH_RP2040
warnings:
flags:
packages:
rp2040:rp2040:
url: https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json
compile:
# Choosing to run compilation tests on 2 different Arduino platforms
platforms:
- uno
# - due
# - zero
# - leonardo
- m4
- esp32
- esp8266
# - mega2560
- rpipico

4
libraries/MS5837/.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,4 @@
# These are supported funding model platforms
github: RobTillaart

View File

@ -0,0 +1,13 @@
name: Arduino-lint
on: [push, pull_request]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: arduino/arduino-lint-action@v1
with:
library-manager: update
compliance: strict

View File

@ -0,0 +1,17 @@
---
name: Arduino CI
on: [push, pull_request]
jobs:
runTest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: ruby/setup-ruby@v1
with:
ruby-version: 2.6
- run: |
gem install arduino_ci
arduino_ci.rb

View File

@ -0,0 +1,18 @@
name: JSON check
on:
push:
paths:
- '**.json'
pull_request:
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: json-syntax-check
uses: limitusus/json-syntax-check@v1
with:
pattern: "\\.json$"

View File

@ -0,0 +1,16 @@
# Change Log MS5837
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/)
and this project adheres to [Semantic Versioning](http://semver.org/).
## [0.1.0] - 2023-12-24
- initial release
## [0.0.0] - 2023-11-12
- initial version

21
libraries/MS5837/LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023-2023 Rob Tillaart
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

279
libraries/MS5837/MS5837.cpp Normal file
View File

@ -0,0 +1,279 @@
//
// FILE: MS5837.cpp
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2023-11-12
// PURPOSE: Arduino library for MS5837 temperature and pressure sensor.
// URL: https://github.com/RobTillaart/MS5837
#include "MS5837.h"
// commands (MS5611 alike)
#define MS5837_CMD_READ_ADC 0x00
#define MS5837_CMD_READ_PROM 0xA0
#define MS5837_CMD_RESET 0x1E
#define MS5837_CMD_CONVERT_D1 0x4A // differs from MS5611
#define MS5837_CMD_CONVERT_D2 0x5A // differs from MS5611
// CONSTRUCTOR
MS5837::MS5837(TwoWire *wire)
{
_wire = wire;
}
bool MS5837::begin(uint8_t mathMode)
{
if (! isConnected()) return false;
reset(mathMode);
return true;
}
bool MS5837::isConnected()
{
_wire->beginTransmission(_address);
return ( _wire->endTransmission() == 0);
}
bool MS5837::reset(uint8_t mathMode)
{
command(MS5837_CMD_RESET);
uint32_t start = millis();
// while loop prevents blocking RTOS
while (micros() - start < 10)
{
yield();
delay(1);
}
initConstants(mathMode);
// SKIP CRC check
// derive the type from mathMode instead of the other way around.
// user must
_type = MS5837_TYPE_30;
if (mathMode == 1) _type = MS5837_TYPE_02;
if (mathMode == 2) _type = MS5803_TYPE_01;
return true;
}
uint8_t MS5837::getType()
{
return _type;
}
uint8_t MS5837::getAddress()
{
return _address;
}
//////////////////////////////////////////////////////////////////////
//
// READ
//
bool MS5837::read(uint8_t bits)
{
if (isConnected() == false) return false;
int index = constrain(bits, 8, 13);
index -= 8;
uint8_t waitMillis[6] = { 1, 2, 3, 5, 9, 18 };
uint8_t wait = waitMillis[index];
// D1 conversion
_wire->beginTransmission(_address);
_wire->write(MS5837_CMD_CONVERT_D1 + index * 2);
_wire->endTransmission(); // TODO check all of these
uint32_t start = millis();
// while loop prevents blocking RTOS
while (micros() - start < wait)
{
yield();
delay(1);
}
// NOTE: D1 and D2 are reserved in MBED (NANO BLE)
uint32_t _D1 = readADC();
// D2 conversion
_wire->beginTransmission(_address);
_wire->write(MS5837_CMD_CONVERT_D2 + index * 2);
_wire->endTransmission();
start = millis();
// while loop prevents blocking RTOS
while (micros() - start < wait)
{
yield();
delay(1);
}
// NOTE: D1 and D2 are reserved in MBED (NANO BLE)
uint32_t _D2 = readADC();
float dT = _D2 - C[5];
_temperature = 2000 + dT * C[6];
float offset = C[2] + dT * C[4];
float sens = C[1] + dT * C[3];
_pressure = _D1 * sens + offset;
// Second order compensation
if (_temperature < 20)
{
float ti = dT * dT * (11 * 2.91038304567E-11); // 1 / 2^35
float t = (_temperature - 2000) * (_temperature - 2000);
float offset2 = t * (31 * 0.125); // 1 / 2^3
float sens2 = t * (63 * 0.03125); // 1 / 2^5
offset -= offset2;
sens -= sens2;
_temperature -= ti;
}
// 1 / 2^21 C[7] / 100
_pressure = (_D1 * sens * 4.76837158203E-7 - offset) * C[7] * 0.01;
_temperature *= 0.01;
return true;
}
float MS5837::getPressure()
{
return _pressure;
}
float MS5837::getTemperature()
{
return _temperature;
}
// https://www.mide.com/air-pressure-at-altitude-calculator
// https://community.bosch-sensortec.com/t5/Question-and-answers/How-to-calculate-the-altitude-from-the-pressure-sensor-data/qaq-p/5702
//
float MS5837::getAltitude(float airPressure)
{
float ratio = _pressure / airPressure;
return 44330 * (1 - pow(ratio, 0.190294957));
}
//////////////////////////////////////////////////////////////////////
//
// DENSITY for depth
//
void MS5837::setDensity(float density)
{
_density = density;
}
float MS5837::getDensity()
{
return _density;
}
float MS5837::getDepth(float airPressure)
{
// 9.80665 == Gravity constant.
// 1 / (_density * 9.80665 * 10) can be pre-calculated and cached in setDensity.
//
// delta P = rho * g * h => h = delta P / rho * g
// pressure = mbar, density grams/cm3 => correction factor 0.1 (=1/10)
return (_pressure - airPressure)/(_density * 9.80665 * 10);
}
//////////////////////////////////////////////////////////////////////
//
// PROTECTED
//
int MS5837::command(uint8_t cmd)
{
yield();
_wire->beginTransmission(_address);
_wire->write(cmd);
_result = _wire->endTransmission();
return _result;
}
void MS5837::initConstants(uint8_t mathMode)
{
// Constants that were multiplied in read() - datasheet page 8
// do this once and you save CPU cycles.
//
// datasheet MS5837_30 page 7
//
// mathMode = 0; | = 1
C[0] = 1;
C[1] = 32768L; // SENSt1 = C[1] * 2^15 | * 2^16
C[2] = 65536L; // OFFt1 = C[2] * 2^16 | * 2^17
C[3] = 3.90625E-3; // TCS = C[3] / 2^8 | / 2^7
C[4] = 7.8125E-3; // TCO = C[4] / 2^7 | / 2^6
C[5] = 256; // Tref = C[5] * 2^8 | * 2^8
C[6] = 1.1920928955E-7; // TEMPSENS = C[6] / 2^23 | / 2^23
C[7] = 1.220703125E-4; // compensate uses / 2^13 | / 2^15
// Appnote version for pressure.
// adjustments for MS5837_02
if (mathMode == 1)
{
C[1] *= 2; // SENSt1
C[2] *= 2; // OFFt1
C[3] *= 2; // TCS
C[4] *= 2; // TCO
C[7] /= 4; // compensation code has factor 4.
}
// adjustments for MS5803_01
if (mathMode == 2)
{
C[7] /= 4; // compensation code has factor 4.
}
for (uint8_t i = 0; i < 7 ; i++)
{
_wire->beginTransmission(_address);
_wire->write(MS5837_CMD_READ_PROM + i + i);
_wire->endTransmission();
uint8_t length = 2;
_wire->requestFrom(_address, length);
uint16_t tmp = _wire->read() << 8;
tmp |= _wire->read();
C[i] *= tmp;
}
}
uint32_t MS5837::readADC()
{
command(MS5837_CMD_READ_ADC);
if (_result == 0)
{
uint8_t length = 3;
int bytes = _wire->requestFrom(_address, length);
if (bytes >= length)
{
uint32_t value = _wire->read() * 65536UL;
value += _wire->read() * 256UL;
value += _wire->read();
return value;
}
return 0UL;
}
return 0UL;
}
// -- END OF FILE --

103
libraries/MS5837/MS5837.h Normal file
View File

@ -0,0 +1,103 @@
#pragma once
//
// FILE: MS5837.h
// AUTHOR: Rob Tillaart
// VERSION: 0.1.0
// DATE: 2023-11-12
// PURPOSE: Arduino library for MS5837 temperature and pressure sensor.
// URL: https://github.com/RobTillaart/MS5837
#include "Arduino.h"
#include "Wire.h"
// TODO OSR factor in code?
#define MS5837_LIB_VERSION (F("0.1.0"))
#define MS5803_TYPE_01 1
#define MS5837_TYPE_02 2
#define MS5837_TYPE_30 30
class MS5837
{
public:
MS5837(TwoWire *wire = &Wire);
// MS5837-30bar = 0
// MS5837-02bar = 1
bool begin(uint8_t mathMode);
bool isConnected();
bool reset(uint8_t mathMode);
uint8_t getType();
uint8_t getAddress();
//////////////////////////////////////////////////////////////////////
//
// READ
//
// call will block 3-40 milliseconds, depends on # bits.
// bits = 8-12 (8-13 for the MS5837_02)
bool read(uint8_t bits = 8);
// see https://github.com/RobTillaart/pressure for conversions.
// returns mBar
float getPressure();
// see https://github.com/RobTillaart/temperature for conversions.
// returns Celsius
float getTemperature();
// compensate for actual air pressure if needed
float getAltitude(float airPressure = 1013.25);
//////////////////////////////////////////////////////////////////////
//
// DEPTH
//
// density is temperature dependent, see
// https://www.usgs.gov/special-topics/water-science-school/science/water-density
//
// density water 20°C = 0.99802
// density seawater is
// density in grams / cm3 (so not in grams per liter
void setDensity(float density = 0.99802);
float getDensity();
// returns meters (SI unit)
// compensate for actual air pressure if needed
float getDepth(float airPressure = 1013.25);
protected:
int command(uint8_t cmd);
void initConstants(uint8_t mathMode);
uint32_t readADC();
uint8_t _address = 0x76; // fixed address
TwoWire * _wire = NULL;
float _pressure;
float _temperature;
float C[8];
uint8_t _type;
int _result;
float _density = 0.99802; // water at 20 °C
};
//////////////////////////////////////////////////////////////////////
//
// DERIVED CLASSES
//
// MS5837_30 MS5837_02 etc ?
// -- END OF FILE --

188
libraries/MS5837/README.md Normal file
View File

@ -0,0 +1,188 @@
[![Arduino CI](https://github.com/RobTillaart/MS5837/workflows/Arduino%20CI/badge.svg)](https://github.com/marketplace/actions/arduino_ci)
[![Arduino-lint](https://github.com/RobTillaart/MS5837/actions/workflows/arduino-lint.yml/badge.svg)](https://github.com/RobTillaart/MS5837/actions/workflows/arduino-lint.yml)
[![JSON check](https://github.com/RobTillaart/MS5837/actions/workflows/jsoncheck.yml/badge.svg)](https://github.com/RobTillaart/MS5837/actions/workflows/jsoncheck.yml)
[![GitHub issues](https://img.shields.io/github/issues/RobTillaart/MS5837.svg)](https://github.com/RobTillaart/MS5837/issues)
[![License: MIT](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/RobTillaart/MS5837/blob/master/LICENSE)
[![GitHub release](https://img.shields.io/github/release/RobTillaart/MS5837.svg?maxAge=3600)](https://github.com/RobTillaart/MS5837/releases)
[![PlatformIO Registry](https://badges.registry.platformio.org/packages/robtillaart/library/MS5837.svg)](https://registry.platformio.org/libraries/robtillaart/MS5837)
# MS5837
Library for the MS5837 temperature and pressure sensor and compatibles.
## Description
**Experimental**
The MS5837 is a waterproof device to measure temperature and pressure to a high level
of accuracy.
From the pressure one can calculate the depth or the altitude of the sensor to some extend.
- The MS5837_30 can go to depth of 300 meter (30 Bar).
- The MS5837_02 is meant for altitude measurements as it can as low as 300 mBar.
The library does not use the integer math from the datasheet but float math.
Assumption is that it reduces footprint and increases math speed.
This will have an effect on the accuracy of the results,
although these are expected relative small. (to be investigated)
#### Related
- https://github.com/RobTillaart/pressure Conversions
- https://github.com/RobTillaart/temperature Conversions
- https://github.com/RobTillaart/MS5611 temperature and pressure sensor
See also .h file
#### Compatibles
See mathType notes below.
| Sensor | mathType | Celsius °C | pressure mBar | Notes |
|:---------------|:--------:|:------------:|:---------------:|:-------:|
| MS5837-30bar | 0 | -20 to +85 | 0 to 30000 | for depth
| MS5837-02bar | 1 | -20 to +85 | 300 to 1200 | for altitude
| MS5803-01bar | 2 | -40 to +85 | 10 to 1300 | investigate
#### Pressure mathType
There are MS5837 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 (mostly powers of 2) used to calculate the pressure.
The library implements **reset(uint8_t mathMode = 0)** to select the mathMode.
- mathMode = 0 ==> datasheet MS5837_30 page 7
- mathMode = 1 ==> datasheet MS5837_02 page 7
- mathMode = 2 ==> datasheet MS5803_01 page 7
- other values will act as 0
#### Tests
Library uses similar code as the tested MS5611 library.
TODO: tests with hardware.
The library is tested with the following boards: TODO
As always feedback is welcome.
Please let me know of other working platforms / processors (and failing ones!).
## I2C
User has to call **Wire.begin()** (or equivalent) before calling **ms5611.begin(0)**
#### Performance
The maximum I2C speed is 400 KHz. (TODO verify).
#### Multiplexing
The MS5837 has one fixed address 0x76. So you can have only one per I2C bus.
If one needs to control more MS5837's one need an I2C multiplexer.
- https://github.com/RobTillaart/TCA9548 I2C multiplexer.
## Interface
```cpp
#include MS5837.h
```
#### Constructor
- **MS5837(TwoWire \* wire = &Wire))** constructor, optional
- **bool begin(uint8_t mathMode)** initializes the library.
- **bool isConnected()** returns true if device visible on I2C bus.
- **bool reset(uint8_t mathMode)** resets the sensor and reads its configuration.
The mathMode must match the type of sensor, see table above.
- **uint8_t getType()** type indicates max pressure.
Returns 30 or 2 or zero if unknown.
- **uint8_t getAddress()** returns 0x76 as this is a fixed address.
#### Temperature and Pressure
- **bool read(uint8_t bits = 8)** the actual reading of the sensor.
The bits determines the oversampling factor, see table below.
Returns true upon success.
The call will block for 3 to 40 milliseconds, depending upon number of bits.
- **float getPressure()** returns mBar.
- **float getTemperature()** returns degrees Celsius.
- **float getAltitude(float airPressure = 1013.25)** calculates the altitude, based upon actual pressure and the pressure at sea level.
Returns altitude in meters.
One can compensate for the actual air pressure at sea level.
| type | bits read() |
|:-----------:|:-------------:|
| MS5837_30 | 8..12 |
| MS5837_02 | 8..12, 13 |
| MS5803_01 | 8..12 |
#### Depth
Mainly for the MS5837_30.
Depth calculation depends on the air pressure at sea level, and the density
of the liquid you are submerged in (typical water).
The pressure is in fact the sum of the air pressure and the weight of the liquid above.
If the density is larger the maximum depth of the sensor will decrease.
- **void setDensity(float density)** set liquid density.
- **float getDensity()** returns set liquid density.
- **float getDepth(float airPressure = 1013.25)** calculates the depth,
based upon actual pressure and the pressure at sea level.
Returns depth in meters.
One can compensate for the actual air pressure at sea level.
## Future
#### Must
- documentation
- buy hardware - 30 or 2 bar version ?
- check TODO's in code / documentation
- test
#### Should
- add **lastRead()**
- create derived classes?
- so one does not need to set mathMode.
- for 5803
- can we see conversion ready?
- performance test
- investigate the effects of float math on accuracy / precision.
#### Could
- refactor type & mathMode
- add offset functions
#### Won't (unless requested)
## 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,

View File

@ -0,0 +1,54 @@
// FILE: MS5837_demo.ino
// AUTHOR: Rob Tillaart
// PURPOSE: demo MS5837 library
// URL: https://github.com/RobTillaart/MS5837
#include "Arduino.h"
#include "Wire.h"
#include "MS5837.h"
MS5837 MS(&Wire);
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println(__FILE__);
Serial.print("MS5837_LIB_VERSION: ");
Serial.println(MS5837_LIB_VERSION);
Serial.println();
Wire.begin();
if (MS.begin(0) == true)
{
Serial.println("MS5837 found.");
}
else
{
Serial.println("MS5837 not found. halt.");
// while (1);
}
Serial.println();
}
void loop()
{
MS.read(); // note no error checking => "optimistic".
Serial.print("T:\t");
Serial.print(MS.getTemperature(), 2);
Serial.print("\tP:\t");
Serial.print(MS.getPressure(), 2);
Serial.print("\tA:\t");
Serial.print(MS.getAltitude(), 2);
Serial.print("\tD:\t");
Serial.print(MS.getDepth(), 2);
Serial.println();
delay(10000);
}
// -- END OF FILE --

View File

@ -0,0 +1,29 @@
# Syntax Colouring Map For MS5837
# Data types (KEYWORD1)
MS5837 KEYWORD1
# Methods and Functions (KEYWORD2)
begin KEYWORD2
isConnected KEYWORD2
reset KEYWORD2
getType KEYWORD2
getAddress KEYWORD2
read KEYWORD2
getPressure KEYWORD2
getTemperature KEYWORD2
getAltitude KEYWORD2
setDensity KEYWORD2
getDensity KEYWORD2
getDepth KEYWORD2
# Constants (LITERAL1)
MS5837_LIB_VERSION LITERAL1
MS5837_TYPE_UNKNOWN LITERAL1
MS5837_TYPE_02 LITERAL1
MS5837_TYPE_30 LITERAL1

View File

@ -0,0 +1,23 @@
{
"name": "MS5837",
"keywords": "MS5837, temperature, pressure",
"description": "Arduino library for MS5837 temperature and pressure sensor.",
"authors":
[
{
"name": "Rob Tillaart",
"email": "Rob.Tillaart@gmail.com",
"maintainer": true
}
],
"repository":
{
"type": "git",
"url": "https://github.com/RobTillaart/MS5837.git"
},
"version": "0.1.0",
"license": "MIT",
"frameworks": "*",
"platforms": "*",
"headers": "MS5837.h"
}

View File

@ -0,0 +1,11 @@
name=MS5837
version=0.1.0
author=Rob Tillaart <rob.tillaart@gmail.com>
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
sentence=Arduino library for MS5837 temperature and pressure sensor.
paragraph=
category=Signal Input/Output
url=https://github.com/RobTillaart/MS5837
architectures=*
includes=MS5837.h
depends=

View File

@ -0,0 +1,51 @@
//
// FILE: unit_test_001.cpp
// AUTHOR: Rob Tillaart
// DATE: 2020-12-06
// PURPOSE: unit tests for the MS5837 current sensor
// https://github.com/RobTillaart/MS5837
// https://github.com/Arduino-CI/arduino_ci/blob/master/REFERENCE.md
//
// supported assertions
// ----------------------------
// assertEqual(expected, actual)
// assertNotEqual(expected, actual)
// assertLess(expected, actual)
// assertMore(expected, actual)
// assertLessOrEqual(expected, actual)
// assertMoreOrEqual(expected, actual)
// assertTrue(actual)
// assertFalse(actual)
// assertNull(actual)
#include <ArduinoUnitTests.h>
#include "Arduino.h"
#include "MS5837.h"
#define A0 0
unittest_setup()
{
fprintf(stderr, "MS5837_LIB_VERSION: %s\n", (char *) MS5837_LIB_VERSION);
}
unittest_teardown()
{
}
unittest(test_constants)
{
assertEqual(1,1);
}
unittest_main()
// -- END OF FILE --