DIY bottom timer / dive computer

Please register or login

Welcome to ScubaBoard, the world's largest scuba diving community. Registration is not required to read the forums, but we encourage you to join. Joining has its benefits and enables you to participate in the discussions.

Benefits of registering include

  • Ability to post and comment on topics and discussions.
  • A Free photo gallery to share your dive photos with the world.
  • You can make this box go away

Joining is quick and easy. Log in or Register now!

tongl

Registered
Messages
8
Reaction score
17
Location
UK
# of dives
200 - 499
Wanted to have a console for DPV, only one requirement which is having a biiiiig display for depth. Don't want to invest to much in another large screen dive computer, and the old Aladins don't have constant backlight, hence this project.


First step is to build a pressure tester for validation, which is just RO water filter housing with OPV and needle valve, many people have done this before.
pressure chamber.jpg



First version, MCU is a Seeed Xiao SAMD21, power by 3.7v LiPo battery on a boost converrter to 5V, display is a 1.54 inch OLED, pressure sensor is just an analog fuel line pressure transducer, dirt cheap. I took out the press button of a DJI action 4 housing (go pro housing should do as well), the hole only needs to be enlarged slightly to tap a M10 thread, which fits the 1/8 NPT transducer snugly, watertight by PTFE tape and epoxy.
This works but the depth variation is too large to my liking, perhaps the 12bit ADC built in Xiao board is not high enough for this, could add a ADS1115 16bit ADC, but I don't have much physical room to play around, that transducer is massive.
analog.jpg



Second version, going digital. Found a ROV depth sensor using MS5837 digital depth sensor board on Aliexpress (search 'ROV M10 High Precision Depth Transducer MS5837-30BA'). Again, take out the press button, drill and tap M10, thread in the sensor and seal with PTFE tape. Both Xiao and the sensor run on 3.3V so I can get rid of the boost converter, and power Xiao directly from battery to the Vcc pin, which should drop out at around 3.5V, did a burn test, fully charged battery runs for about 20 hours.
digital.jpg



Testing, very consistent and stable reading compared to Shearwater.
test.jpg



Display: depth, run time (which starts automatically passing 1 meter), and battery voltage
display.jpg



I have also made a version with dive computer function, ZHL-16c (fixed GF of 99/99, I mean if all of my dive computers failed I'll take my chance...)
Plenty of the algorithm code on github. But implementing it means sacrificing the size of depth which is my priority. Plus the housing only has 2 buttons, one is used by depth sensor, another by power button. So no button to switch gas, which makes it useless to me.

The BT code is very simple:

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "MS5837.h"
#define BATTERY_PIN A8 // Battery monitoring pin
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
MS5837 sensor;
float depth = 0.0;
unsigned long prevDisplayTime = 0;
unsigned long timerStartTime = 0;
bool timerStarted = false;
int minutes = 0, seconds = 0;
float batteryVoltage = 0.0;
const int numSamples = 20; // Battery voltage oversampling
void setup() {
Wire.begin();
Wire.setClock(100000); // I2C clock speed 100 kHz
analogReadResolution(12); // Internal ADC resolution 12-bit
sensor.init();
sensor.setModel(MS5837::MS5837_30BA); // 30 bar model
sensor.setFluidDensity(1020); // EN13319 density
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
display.display();
}
void loop() {
unsigned long currentTime = millis();
if (currentTime - prevDisplayTime >= 500) { // 2Hz refresh rate
sensor.read();
depth = sensor.depth();
if (depth < 0) depth = 0; // Minimum depth 0 meter
if (depth > 99.9) depth = 99.9; // Maximum depth 99.9 meters
updateTimer(depth);
batteryVoltage = getAverageBatteryVoltage();
updateDisplay(depth, minutes, batteryVoltage);
prevDisplayTime = currentTime;
}
}
// Timer starts at 1 meter
void updateTimer(float depth) {
if (depth >= 1.0 && !timerStarted) {
timerStartTime = millis();
timerStarted = true;
}
if (timerStarted) {
unsigned long elapsedTime = millis() - timerStartTime;
minutes = elapsedTime / 60000;
seconds = (elapsedTime % 60000) / 1000;
}
}
// Battery voltage averaging
float getAverageBatteryVoltage() {
long total = 0;
for (int i = 0; i < numSamples; i++) {
total += analogRead(BATTERY_PIN);
}
float averageReading = total / numSamples;
return averageReading * (3.3 / 4095.0) * 2; // 1:1 voltage divider
}
// OLED display
void updateDisplay(float depth, int minutes, float batteryVoltage) {
display.clearDisplay();
// Depth
char depthString[5];
if (depth < 10) {
snprintf(depthString, sizeof(depthString), " %.1f", depth);
} else {
snprintf(depthString, sizeof(depthString), "%.1f", depth);
}
display.setTextColor(SSD1306_WHITE);
display.setTextSize(5);
display.setCursor(6, 0);
display.print(depthString);
// Timer
char timerString[7];
snprintf(timerString, sizeof(timerString), "%3d:%02d", minutes, seconds);
display.setTextSize(2);
display.setCursor(0, 48);
display.print(timerString);
// Battery voltage
char batteryString[6];
snprintf(batteryString, sizeof(batteryString), "%.2fV", batteryVoltage);
display.setTextSize(1);
display.setCursor(SCREEN_WIDTH - 6 * strlen(batteryString), 56);
display.print(batteryString);
display.display();
}
 
I have also made a version with dive computer function, ZHL-16c (fixed GF of 99/99, I mean if all of my dive computers failed I'll take my chance...)

If I had to settle on one setting for gradient factors it would be GF 50/70 or GF 50/75, but that debate is a deep rabbit hole …
 
Brilliant work trying with that fuel pressure sensor and great to find those proper sensors in the little housing adapter! I had seen those on bluerobotics site some years ago but were a bit pricey at the time if I recall. Looks like they are cheaper now, but even cheaper options on AliExpress. Thanks for bringing it to my attention!
 
If I had to settle on one setting for gradient factors it would be GF 50/70 or GF 50/75, but that debate is a deep rabbit hole …
My (not so informed) choice is 75/75; but I wanna look down that rabbit hole, any resources to look at? (Don’t wanna hijack this thread; but all I know is deepstops is a NoNo so nothing lower than ~50 🤷🏽‍♀️)
 
My (not so informed) choice is 75/75; but I wanna look down that rabbit hole, any resources to look at? (Don’t wanna hijack this thread; but all I know is deepstops is a NoNo so nothing lower than ~50 🤷🏽‍♀️)

This presentation is worth watching. A bit old now, but I’m not aware of anything contradictory yet.

 
Thanks for sharing this, I have had a similar idea for a while now but haven’t implemented it yet. I’ll definitely be using your work as a starting point!
 

Back
Top Bottom