Tank Level options

Jump to Arduino application

Boats have many places where liquids are kept and it is important to monitor the level. Low tech solutions: dipstick, sight gauge, looking inside,.. are traditional.

For fuel storage, it is convenient to have an accurate readout - to monitor usage and to plan refuelling. Here I focus on options.

My experience of fuel tanks on motor boats: my first boat had a resistive sender (float that slid up and down two wires so varying resistance with a display as a moving needle gauge). This gave very imprecise readings and then malfunctioned completely. My second boat had a tank with an access cap that could be unscrewed and a dipstick inserted. This was failsafe and reliable when in flat calm but rather time consuming to operate.

So I decided to update the system - ideally with a cheap and reliable system that conveniently displayed an accurate reading.

Technical options

An added complication is that some fuel tanks may not be cuboid - so the level is not directly proportional to the volume remaining. Also because of fuel sloshing around, some means of determining an average level is needed. Another factor is that, if a boat heels, the reading should be taken in the centre of the tank to minimize bias.


I looked into capacitative senders: they require quite sophisticated electronics to analyse the signal, so are expensive (about £200). Some can output a signal as NMEA2000 which means that a MFD can display it (so no need for a separate display, but with cost of extra NMEA cabling and connectors). Some have the option to calibrate a tank of irregular shape also. This is the system now used on top-end power boats. The senders are claimed to be accurate to a few mm. Another advantage is that they can be cut to length as needed.
  One issue is that water has a very different dielectric constant from fuel (or air) - which means the reading becomes modified if some water is stirred into the fuel - this is claimed to be a useful "feature" that enables fuel contamination to be detected.

A cheaper option is a resistive sender. Car senders are "swinging arm" mostly and are not very reliable or accurate. The marine environment (salty air) degrades the surface of the variable resistor element.
  A more reliable resistive sender uses a sealed vertical column with a series of reed switches inside, connected to resistors. The reed switch is activated (closed) by a magnetic field and a float with magnets inside it can activate the switches without any marine air getting at them. These are available with a typical separation of switches of 20mm in level. An option of smaller (10mm) separation also is available. For my tank with a 450mm vertical extension, 20mm separation gives 4.5% increments - so a volume reading with maximum relative error of 2.2%. That is about the precision that I got with a dipstick.

Resistive senders are mostly designed for cars and there are two different conventions in use (values in ohms): European 10(empty) 190(full); US 240(empty) 30(full). Also the fitting to the hole in the top of the tank can be (i) traditional SAE 5-hole fitting or (ii) 1.25 inch BSP.


I have a 1.25 inch BSP fitting on my tank for the tank inspection cap. So a reed-switch resistive sender with that top fitting would fit directly in place of the cap. This is less commonly available than the standard 5-hole fitting, but can be ordered. Manufacturers include WEMA (Europe-based) and KUS (Chinese). I ordered a Chinese 400mm long (length options every 50 mm and recommended 50mm gap below bottom of sender to bottom of tank) sender with US-style resistance range (eBay cost £23 in 2017).

On the bench, I then measured the resistance (with a multimeter) while moving the float to different positions. There is some hysteresis: the reading changes at a different position when moving up than when moving down. Overall there were 18 different readings in the 350 mm range of travel of the float with average separation 20.5 mm. These resistance readings are not quite linear - possibly to emulate traditional swinging-arm senders and/or to expand the scale near empty.

My plot of level (mm)[with 70mm ullage addded] versus resistance (ohms).

Armed with this calibration information, I could then relate each of the 18 possible resistance readings to a level and hence a volume of fuel stored.


(1) In my spirit of economy, I connected a cheap multimeter across the leads to read resistance. This could then be converted to a volume reading using a table I printed out. Cost of a multimeter is a few pounds, but I had a spare, that had some functions no longer working, but which showed resistance accurately. This was much more convenient than raising the floorboards, unscrewing the tank-cap, inserting the dipstick, holding the dripping dipstick to read the level, cleaning up drips of fuel and putting cap and floor back in place. It did, however, still have to be done in calm conditions to get a steady reading.

How to do better?
  Automobile (moving needle) displays are cheap but are fairly inaccurate. Automotive bar-graph displays also exist but typically have a resolution of 12% or worse.
  (2) I drew up a plan to use a simple circuit to convert the resistance value into a voltage proportional to the fuel volume: this is illustrated as a curve on the figure above. Voltage can be displayed by a small LCD/LED block (cost few £) which could be mounted on the engine diagnostic panel.
  This seemed to be a rather sub-optimal approach: the curve does not track the data exactly - so extra error would be introduced. A better solution would be to have the option to translate the resistance values accurately to volume values.
Cruzpro make such a device, but it is rather expensive (FU60: £200).

Given my computing and electronics expertise, I took up the challenge to achieve this myself. A promising way forward was to use an Arduino computer board. These are designed to take voltage input and to give a voltage output after processing. Introducing "damping" would also be easy to achieve. An Arduino Uno R3 board is about £10 depending on manufacturer.

Arduino A clone of an Arduino board (Uno R3) is readily available. You will need a USB cable (with printer-type termination: USB-B) and a computer (Windows, Mac or Linux) to program the board. The board has analogue voltage input pins (returning integer 0,..1023 as voltage is 0,..5 volts). Since the board has a 5V output pin (low current only), one can determine resistance using a divider: connect R0 between +5V and analogue pin and connect sender resistance R between the same analogue pin and ground (GRD).
  Then voltage at pin will be R/(R+R0) times 5 volts. This can be solved to give the unknown R in terms of R0 and the voltage ratio at pin / 5 volts. It is sensible to choose a value of R0 similar to the values covered by R: I used 257 ohms since I had such a resistor handy (resistance measured by same multimeter used to calibrate the sender). A larger value of R0 will mean less current flows (current is 5/(R+R0) Amp so 19mA maximum in my case) which can help battery life (see below).
  In my case, since there are only 18 possible resistance values, I select the one nearest to the measured value of R. This then gives the corresponding depth of the float above its bottom position from my bench measurements. From the tank geometry the depth can be converted into volume of fuel (in litres and/or gallons).
  If you have a tank with complicated geometry - just add fuel 10 litres at a time (say), measuring the level with a dipstick to calibrate the relationship between depth and volume.

How to display the result? (it is actually shown on the computer screen used to program and set up the board - useful for checking, but not for boat use). The most accurate method would be to get an LCD/LED display that can be driven by the Arduino. These are readily available (for instance some "starter packs" include them) but are quite fiddly to connect and of unknown reliability on board a boat.
  (3) A much cheaper option, with very much simpler wiring, is to use the option to output a variable voltage (0,..5V) from one of the Arduino PWM pins. This can then be read by a cheap digital voltmeter (for instance a 3 digit LED voltage display 0-30V with separate power input line of more than 3V costs a few pounds only). Such a display only has three leads so is easy to fit to a boat console and it appears quite robust. So one arranges to send out a voltage (between 0 and 5V) that carries the volume message required: for example 3.01V for 301 litres or 0.66V for 66 gallons.
  There is one catch: PWM means Pulse Width Modulation and the output pin has output varying regularly from 0V to 5V with the average voltage representing the "output voltage". This is specified as an integer 0,...255 representing the fraction of maximum. If the voltmeter has a suitable averaging circuit built in, it will read this average correctly. If not, one can either calibrate it and correct for any shift or use an RC filter to average the signal before sending it to the voltmeter. I found that, in my case, the shift needed for correction was small, so applied it in the program.

My program is here .
Image of prototype setup.

A further issue is providing power to the Arduino and to the voltmeter. When programming it, with USB connection to a computer, power is provided by the USB. For the eventual stand-alone use, power needs to come from somewhere else. Options are a 9V battery with suitable plug (there is an input jack on the Arduino that optimally should be provided with 7 to 9V); a USB plug from a USB charger if you have one onboard; or a DC to DC drop-down board to reduce the boat electricity supply (12v or 24v nominal) down to about 8v which can be applied to the power input socket.

So what is needed: Arduino Uno R3, USB cable, a resistor (R0), an LED voltmeter and some wire to connect. Plus a source of power (7-9v if a USB input is not available) and maybe an on/off power switch too.

An Arduino board is designed for prototyping and wires have push-in connections. I am experimenting with a more "rugged" way of connecting. I am happy to solder, heat-shrink, etc.

I also explored other display options from the Arduino:
  (4) Using a 3-digit 7-segment LED (cost few £). This is accurate but needs lots of wires to connect up (even if using a shift register to transfer the 7-segments serially). image of spaghetti here.
  (5) A 2 line by 16 character LCD display is also inexpensive(£2-3). Using I2C serial interface, this only needs 4 wires. It is not clear to me how "marine air tolerant" this display is. This can display both the gallons and litres available.
  (6) Since I only need a number output (tank volume available), I explored using speech to output this to a speaker. Using the "talkie" library on an Arduino, one can have a "cultured voice" (actually Kenneth Kendall ) read out the value on one of the Arduino pins as an audio file. I used a surplus landline telephone earpiece as a speaker - this should be more marine tolerant. To protect the Arduino which can only source about 20 mA, I put a 100Ω resistor and a 0.5μF capacitor (to remove any DC component) in series with the earpiece (which had a DC resistance of about 100Ω). This method uses only two leads to carry the signal.
  (7) Getting the hang of this now - I used a 128x64 OLED dot matrix display with an I2C serial driver (so 4 leads)(costing £2-3). This can be arranged to give a nice accurate graphical display (to 1%) of the tank level - as well as accurate numbers.
  (8) Another option would be to generate NMEA2000 output (effectively CANBUS) from the board - this is tricky (most probably needs a board such as Arduino Due with more memory, etc, as well as a suitable transceiver chip). Display would be the MFD (chart plotter). Work in progress.
  (9) As I wanted to display other information (
exhaust temperature - since my Vetus sender died), I decided to use a display screen: Nextion NX4024T032_011. This model is 400 x 240 pixels, colour and touch-screen., and has its own computing power inbuilt. It can be driven from an Arduino by a serial line (2 wires - just sending numbers to display) once the display is set up using a dedicated Nextion editor (then loaded using a SD card). My implementation is here:

The slider at the bottom allows the screen to be dimmed - essential on a boat at night.

"Ruggedised" set up on test bench: thermistor probe (£2, mounted in brass screw fitting at centre), 12/24 to 7v dropper (switch-mode, £4.31), Arduino nano (cost just over £2) with pins and board soldered on (also with active 5V buzzer), nextion display (£16).

Arduino code.

Finally: installed on boat. Here is display (bezel 3D-printed thanks to Julian). It was a cold day: 8°C.

Return to Boat Pages.