MS5837 Sensor recording depth incorrectly (Help! I need this for a competition)

Hello, I have a sensor problem and I don’t know how to fix it. My sensor is reading the depth of the shallow end of our pool (~4ft deep) as 200m, and it’s not even all the way down. The calibration thing won’t work either because at the surface it reads 193m. I’m using the sensor.depth() function to read it, but its giving me all these nonsense numbers with no correlation except the number gets smaller as you go towards the surface. I’ve found no other people with a problem like this, and I have the density of the water set to the appropriate value for freshwater, as our pool is a chlorine pool. I was hoping someone may know how to fix this.

Hi @QDaCoder -
Have you powered up the ArduSub system using the pressure sensor in air? That should “calibrate” the sensor to read 0 depth. If this isn’t the case, either the unit is damaged (left too long immersed in water?) or is sharing garbled data - have the wires going to the sensor been modified, extended, etc.?

No, I haven’t. I’m using an Arduino to control it. I’ve been mostly testing it in air. It thinks that its around 192m on a table. As for modified or extended wires I’m unsure, I’ll ask the part of my team that built the thing, I’m just the coder. We haven’t left it in water, we’ve only tested it in water 3 or so times and it lasts about a minute each time. Is there a specific way I have to manually calibrate it? I saw something about sensor calibration on here but it didn’t make too much sense. Thank you by the way.

Update: The wires are not extended or modified.

Hi @QDaCoder -
You will have success if you modify your code so that whatever the initial reading on startup is, it is subtracted from all subsequent readings, “zeroing-out” the sensor. From here, the relative depth should be measured very accurately as the sensor is submerged and the pressure increases. Best of luck!

Hi @QDaCoder,

The MS5837 is available in multiple different variants (for different pressure ranges, and extra environmental protection features), and you need to know which pressure range you’re using to be able to apply the correct calculations to estimate pressure.

  1. Do you know which sensor you have?
    • e.g. MS5837-30BA, like used in our Bar30, or MS5837-02BA, like in our Bar02
  2. What code are you using to determine the pressure from its readings?

Beyond that, as @tony-white described depth readings are generally relative to surface pressure, which should be zeroed out (like the ‘tare’ function on a scale) before meaningful depth estimates are provided. In case it’s relevant, our libraries currently just assume standard air pressure as the reference, which I’ve raised a GitHub Issue about previously, because it’s annoying for users to need to do that kind of offsetting external to the functionality the libraries provide.

I think I figured out the problem. I have a bar 02, and I’ve been initializing it as a bar 30, because I couldn’t get the bar 02 code to work. I’ll try to get the 02 bar code to work, but if it doesn’t, is there a conversion rate?

Hi @QDaCoder

There is no “conversion factor” - the correct sensor type just needs to be specified.

I tried it today but couldn’t figure it out. It seemed to break all my other code when I changed it from a 30 to an 02 in my code. Does it work in a 115200 baud rate serial monitor? I need that rate so my two esps can communicate. If I forgot to mention, I’m running this on an esp, not an arduino. I don’t know if that would change anything.

Hi @QDaCoder -
If you can share your sketch, that would be best! It should have sensor.setModel(MS5837::MS5837_30BA);
replaced with
sensor.setModel(MS5837::MS5837_02BA);

ESP32 vs. arduino shouldn’t be an issue, as long as the I2C communications are working OK…

My code is kind of crazy, as the depth detection is just a very small part. I’ll try to specify the depth stuff.

#include <SPIFFS.h>
#include <FS.h>
#include <Wire.h>
#include "MS5837.h"
#include <esp_now.h>
#include <WiFi.h>
#include "CytronMotorDriver.h"

// Motor setup
CytronMD motor(PWM_DIR, 14, 12);  // PWM = Pin 14, DIR = Pin 12.

// Limit switch pins
const int limitSwitch_1 = 26; // Pin for the microswitch at the bottom.
const int limitSwitch_2 = 27; // Pin for the microswitch at the top.

// Motor control variables
boolean ForwardState = 0;  // Forward state from limit switches.
boolean BackwardState = 0; // Backward state from limit switches.

#define WIFI_CHANNEL 1
esp_now_peer_info_t master;
uint8_t masterMac[] = {0xxx, 0xxx, 0xxx, 0xxx, 0xxx, 0xxx}; //MAC code of the master ESP32, I took it out for this example because I don't know if that can be used to hack me lol
const int dataSize = 4; // Size of temperature data (float).
float lastTemperature = 0.0;
bool recording = false; //If the esp should be logging info to the logfile, line 27.

const char* sensorData = "/sensor_log.txt"; //Log file for the information recored by the MS5837 sensor, line 29.

MS5837 sensor; //Temp and depth sensor.

//Varibles for recording time
int startTime = 0;
int realTime = 0;
int timeInMinutes = 0;
int timeInSeconds = 0;
int timeInMilliseconds = 0;

//Varibles for avoiding the use of dealys, they interfer with the limit switches, lines 13 and 14.
unsigned long previousMillisLog = 0;
const long logInterval = 5000; //How often the esp logs to the file, 5 seconds.
const long goForward = 15000;
unsigned long currentMillis = 0;
unsigned long backMillis = 0;
unsigned long elapsedTime1 = 0;

bool first = false;
bool goBack = true;
bool finished = false;

void setup() {
  //Initialisation of the comunacation between the esps.
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  if (esp_now_init() != ESP_OK) {
    Serial.println("ESP-NOW init failed");
    return;
  }
  memcpy(master.peer_addr, masterMac, 6);
  master.channel = WIFI_CHANNEL;
  master.encrypt = false;
  esp_now_add_peer(&master);
  esp_now_register_recv_cb(OnDataRecv);

  Wire.begin();

  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);
  }

  //Initialisation of the sensor
  sensor.setModel(MS5837::MS5837_30BA);  //Changing it to 20BA seems to break the program.
  sensor.setFluidDensity(997);

  if (SPIFFS.begin(true)) {
    Serial.println("SPIFFS mounted successfully.");
  } else {
    Serial.println("SPIFFS mount failed. Check your filesystem.");
  }

  //Motor code
  // Initialize limit switches
  pinMode(limitSwitch_1, INPUT_PULLUP);
  pinMode(limitSwitch_2, INPUT_PULLUP);
}

void loop() {

  currentMillis = millis();


  recordData();
  

  //More motor code

  ForwardState = digitalRead(limitSwitch_1);
  BackwardState = digitalRead(limitSwitch_2);

  if(recording)
  {
    if(goBack == true)
    {
      if(first == true)
      {
      SlideForward();
      Serial.println("Moving backwards.");
      }

      if(ForwardState == HIGH && BackwardState == LOW)
      {
        motor.setSpeed(0);
        if(first == true)
        {
          backMillis = millis();
          currentMillis = millis();
          first = false;
          Serial.println("Waiting at bottom");
          Serial.println(backMillis);
          Serial.println(currentMillis);
        }
      }

      if(first == false)
        elapsedTime1 = currentMillis - backMillis;

      if(backMillis != 0 && elapsedTime1 >= goForward)
        {
        SlideBackward();
        Serial.println("Moving forward");
        goBack = false;
        }
    }
    if(goBack == false && finished == false)
    {
      SlideBackward();
    }
    if(goBack == false && ForwardState == LOW && BackwardState == HIGH && finished == false)
    {
      motor.setSpeed(0);
      Serial.println("Stopped moving");
      finished = true;
    }
  }
  else if(!recording)
  {
    motor.setSpeed(0);
  }
}

void OnDataRecv(const esp_now_recv_info *mac_addr, const uint8_t *data, int data_len) {
  char command = (char)data[0];
  if (command == 'S' || command == 's')
  {
    recording = true;
    first = true;
    goBack = true;
    startTime = millis();
    SPIFFS.remove(sensorData);
    Serial.println("Started recording");
  } else if (command == 'E' || command == 'e') {
    
    recording = false;
    startTime = 0;
    realTime = 0;
    timeInMinutes = 0;
    timeInSeconds = 0;
    timeInMilliseconds = 0;
    previousMillisLog = 0;
    currentMillis = 0;
    backMillis = 0;
    elapsedTime1 = 0;
    first = false;
    goBack = true;
    finished = false;
    lastTemperature = 0.0;
    ForwardState = 0;
    BackwardState = 0;

    Serial.println("Stopped recording");
  } else if (command == 'R' || command == 'r') {
    sendLogFile();
  }
}

void sendLogFile() {
  File logFile = SPIFFS.open(sensorData, "r");
  if (logFile) {
    int fileSize = logFile.size();
    int bytesSent = 0;
    const int chunkSize = 200;

    while (bytesSent < fileSize) {
      int bytesToSend = min(chunkSize, fileSize - bytesSent);
      uint8_t chunk[bytesToSend];
      logFile.read(chunk, bytesToSend);
      esp_now_send(master.peer_addr, chunk, bytesToSend);
      Serial.write(chunk, bytesToSend);
      bytesSent += bytesToSend;
      delay(50);
    }
    logFile.close();
    Serial.println("Log file sent.");
  } else {
    Serial.println("Failed to open log file for sending.");
  }
}

void SlideForward() 
{
  motor.setSpeed(0);
  motor.setSpeed(255);
  motor.setSpeed(255);
}

void SlideBackward() 
{
  motor.setSpeed(0);
  motor.setSpeed(-255);
  motor.setSpeed(-255);
}


void recordData()
{
  if (currentMillis - startTime - previousMillisLog >= logInterval)
  {
    previousMillisLog = currentMillis - startTime;
    if(recording)
    {
      sensor.read(); //reads the sensor
      lastTemperature = sensor.temperature();

      realTime = millis();
      timeInMinutes = (realTime - startTime) / 60000;
      timeInSeconds = ((realTime - startTime) % 60000) / 1000;
      timeInMilliseconds = (realTime - startTime) % 1000;

      File logFile = SPIFFS.open(sensorData, "a");

      if (logFile) 
      {
        logFile.print("Time: ");
        logFile.print(timeInMinutes);
        logFile.print(":");
        logFile.print(timeInSeconds);
        logFile.print(":");
        logFile.println(timeInMilliseconds);
        logFile.print("Temperature: ");
        logFile.print(lastTemperature);
        logFile.println(" deg C");
        logFile.println();
        logFile.print("Depth: ");
        logFile.print(sensor.depth());  //Where it logs the depth
        logFile.println("m");
        logFile.println();
        logFile.close();
        Serial.print("Logged temperature: ");
        Serial.println(lastTemperature);
      } 
      else 
      {
        Serial.println("Failed to open log file.");
      }
    }
  }
}

For some reason, making it a bar 02 breaks the rest of the program. I’m still testing, but I don’t know whats going on.

Hi @QDaCoder -
To clarify, this needs to be set to sensor.setModel(MS5837::MS5837_02BA); , not 20BA

To test the sensor functionality, using a simple example with only code to read and print the sensor values would be a good test. If that works, you then know some other aspect of your code is interefering with the I2C communications.

Sorry, that was a typo. changing it to 02BA breaks it. I’ve tested it with a example code and the sensor does work. My problem is that for the life of me I cannot figure out the issue.

Hi @QDaCoder -
A large language model AI like ChatGPT or Google Gemini may be able to help you hunt the issue down! If you’re talking to other I2C or serial devices, it may be good to add them one at a time and then see when the functionality breaks…

I fixed it! Thank you so much, you guys help me some much. Turned out it didn’t work yesterday because my motor wasn’t pugged in!

2 Likes