Hello, not yet.
Basically the sensor is not initializing correctly and I’m getting this message on the monitor:
Init failed!
Are SDA/SCL connected correctly?
Blue Robotics Bar30: White=SDA, Green=SCL
This is the code I’m using:
bar30.uno
#include <Wire.h>
#include “MS5837.h”
MS5837 sensor;
void setup() {
Serial.begin(9600);
Serial.println(“Starting”);
Wire.begin();
// Initialize pressure sensor
// Returns true if initialization was successful
// We can’t continue with the rest of the program unless we can initialize the sensor
while (!sensor.init()) {
Serial.println(“Init failed!”);
Serial.println(“Are SDA/SCL connected correctly?”);
Serial.println(“Blue Robotics Bar30: White=SDA, Green=SCL”);
Serial.println(“\n\n\n”);
delay(5000);
}
sensor.setModel(MS5837::MS5837_30BA);
sensor.setFluidDensity(997); // kg/m^3 (freshwater, 1029 for seawater)
}
void loop() {
// Update pressure and temperature readings
sensor.read();
Serial.print(“Pressure: “);
Serial.print(sensor.pressure());
Serial.println(” mbar”);
Serial.print(“Temperature: “);
Serial.print(sensor.temperature());
Serial.println(” deg C”);
Serial.print(“Depth: “);
Serial.print(sensor.depth());
Serial.println(” m”);
Serial.print(“Altitude: “);
Serial.print(sensor.altitude());
Serial.println(” m above mean sea level”);
delay(1000);
}
MS5837.cpp
#include “MS5837.h”
#include <Wire.h>
#define MS5837_ADDR 0x76
#define MS5837_RESET 0x1E
#define MS5837_ADC_READ 0x00
#define MS5837_PROM_READ 0xA0
#define MS5837_CONVERT_D1_8192 0x4A
#define MS5837_CONVERT_D2_8192 0x5A
const float MS5837::Pa = 100.0f;
const float MS5837::bar = 0.001f;
const float MS5837::mbar = 1.0f;
const uint8_t MS5837::MS5837_30BA = 0;
const uint8_t MS5837::MS5837_02BA = 1;
MS5837::MS5837() {
fluidDensity = 1029;
}
bool MS5837::init() {
// Reset the MS5837, per datasheet
Wire.beginTransmission(MS5837_ADDR);
Wire.write(MS5837_RESET);
Wire.endTransmission();
// Wait for reset to complete
delay(10);
// Read calibration values and CRC
for ( uint8_t i = 0 ; i < 7 ; i++ ) {
Wire.beginTransmission(MS5837_ADDR);
Wire.write(MS5837_PROM_READ+i*2);
Wire.endTransmission();
Wire.requestFrom(MS5837_ADDR,2);
C[i] = (Wire.read() << 8) | Wire.read();
}
// Verify that data is correct with CRC
uint8_t crcRead = C[0] >> 12;
uint8_t crcCalculated = crc4(C);
if ( crcCalculated == crcRead ) {
return true; // Initialization success
}
return false; // CRC fail
}
void MS5837::setModel(uint8_t model) {
_model = model;
}
void MS5837::setFluidDensity(float density) {
fluidDensity = density;
}
void MS5837::read() {
// Request D1 conversion
Wire.beginTransmission(MS5837_ADDR);
Wire.write(MS5837_CONVERT_D1_8192);
Wire.endTransmission();
delay(20); // Max conversion time per datasheet
Wire.beginTransmission(MS5837_ADDR);
Wire.write(MS5837_ADC_READ);
Wire.endTransmission();
Wire.requestFrom(MS5837_ADDR,3);
P1 = 0;
P1 = Wire.read();
P1 = (P1 << 8) | Wire.read();
P1 = (P1 << 8) | Wire.read();
// Request D2 conversion
Wire.beginTransmission(MS5837_ADDR);
Wire.write(MS5837_CONVERT_D2_8192);
Wire.endTransmission();
delay(20); // Max conversion time per datasheet
Wire.beginTransmission(MS5837_ADDR);
Wire.write(MS5837_ADC_READ);
Wire.endTransmission();
Wire.requestFrom(MS5837_ADDR,3);
P2 = 0;
P2 = Wire.read();
P2 = (P2 << 8) | Wire.read();
P2 = (P2 << 8) | Wire.read();
calculate();
}
void MS5837::calculate() {
// Given C1-C6 and D1, D2, calculated TEMP and P
// Do conversion first and then second order temp compensation
int32_t dT = 0;
int64_t SENS = 0;
int64_t OFF = 0;
int32_t SENSi = 0;
int32_t OFFi = 0;
int32_t Ti = 0;
int64_t OFF2 = 0;
int64_t SENS2 = 0;
// Terms called
dT = P2-uint32_t(C[5])*256l;
if ( _model == MS5837_02BA ) {
SENS = int64_t(C[1])*65536l+(int64_t(C[3])*dT)/128l;
OFF = int64_t(C[2])*131072l+(int64_t(C[4])*dT)/64l;
P = (P1*SENS/(2097152l)-OFF)/(32768l);
} else {
SENS = int64_t(C[1])*32768l+(int64_t(C[3])*dT)/256l;
OFF = int64_t(C[2])*65536l+(int64_t(C[4])*dT)/128l;
P = (P1*SENS/(2097152l)-OFF)/(8192l);
}
// Temp conversion
TEMP = 2000l+int64_t(dT)*C[6]/8388608LL;
//Second order compensation
if ( _model == MS5837_02BA ) {
if((TEMP/100)<20){ //Low temp
Serial.println("here");
Ti = (11*int64_t(dT)*int64_t(dT))/(34359738368LL);
OFFi = (31*(TEMP-2000)*(TEMP-2000))/8;
SENSi = (63*(TEMP-2000)*(TEMP-2000))/32;
}
} else {
if((TEMP/100)<20){ //Low temp
Ti = (3*int64_t(dT)*int64_t(dT))/(8589934592LL);
OFFi = (3*(TEMP-2000)*(TEMP-2000))/2;
SENSi = (5*(TEMP-2000)*(TEMP-2000))/8;
if((TEMP/100)<-15){ //Very low temp
OFFi = OFFi+7*(TEMP+1500l)*(TEMP+1500l);
SENSi = SENSi+4*(TEMP+1500l)*(TEMP+1500l);
}
}
else if((TEMP/100)>=20){ //High temp
Ti = 2*(dT*dT)/(137438953472LL);
OFFi = (1*(TEMP-2000)*(TEMP-2000))/16;
SENSi = 0;
}
}
OFF2 = OFF-OFFi; //Calculate pressure and temp second order
SENS2 = SENS-SENSi;
if ( _model == MS5837_02BA ) {
TEMP = (TEMP-Ti);
P = (((P1*SENS2)/2097152l-OFF2)/32768l)/100;
} else {
TEMP = (TEMP-Ti);
P = (((P1*SENS2)/2097152l-OFF2)/8192l)/10;
}
}
float MS5837::pressure(float conversion) {
return P*conversion;
}
float MS5837::temperature() {
return TEMP/100.0f;
}
float MS5837::depth() {
return (pressure(MS5837::Pa)-101300)/(fluidDensity*9.80665);
}
float MS5837::altitude() {
return (1-pow((pressure()/1013.25),.190284))145366.45.3048;
}
uint8_t MS5837::crc4(uint16_t n_prom) {
uint16_t n_rem = 0;
n_prom[0] = ((n_prom[0]) & 0x0FFF);
n_prom[7] = 0;
for ( uint8_t i = 0 ; i < 16; i++ ) {
if ( i%2 == 1 ) {
n_rem ^= (uint16_t)((n_prom[i>>1]) & 0x00FF);
} else {
n_rem ^= (uint16_t)(n_prom[i>>1] >> 8);
}
for ( uint8_t 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 = ((n_rem >> 12) & 0x000F);
return n_rem ^ 0x00;
}
MS5837.h
#ifndef MS5837_H_BLUEROBOTICS
#define MS5837_H_BLUEROBOTICS
#include “Arduino.h”
class MS5837 {
public:
static const float Pa;
static const float bar;
static const float mbar;
static const uint8_t MS5837_30BA;
static const uint8_t MS5837_02BA;
MS5837();
bool init();
/** Set model of MS5837 sensor. Valid options are MS5837::MS5837_30BA (default)
* and MS5837::MS5837_02BA.
*/
void setModel(uint8_t model);
/** Provide the density of the working fluid in kg/m^3. Default is for
* seawater. Should be 997 for freshwater.
*/
void setFluidDensity(float density);
/** The read from I2C takes up to 40 ms, so use sparingly is possible.
*/
void read();
/** Pressure returned in mbar or mbar*conversion rate.
*/
float pressure(float conversion = 1.0f);
/** Temperature returned in deg C.
*/
float temperature();
/** Depth returned in meters (valid for operation in incompressible
* liquids only. Uses density that is set for fresh or seawater.
*/
float depth();
/** Altitude returned in meters (valid for operation in air only).
*/
float altitude();
private:
uint16_t C[8];
uint32_t P1, P2;
int32_t TEMP;
int32_t P;
uint8_t _model;
float fluidDensity;
/** Performs calculations per the sensor data sheet for conversion and
* second order compensation.
*/
void calculate();
uint8_t crc4(uint16_t n_prom[]);
};
#endif