Home Heating Hacking Part 1 or How to Measure an Oil Tank

Cross posted from Blogger


Oil Tank

not our tank, but a reasonable facsimile

For a while now, I have had this plan to monitor the energy use of our house–primarily the fuel oil for our furnace.  Unless I go out to the tank regularly and check it with a dipstick, I have no idea how fast or slow we are using up the tank.  The above ground tank holds 570 gallons and it lasts us around a year.  Since we live in a temperate rainforest (and the water heater uses the furnace), the furnace is running year round.  I only have a very rough idea of the difference between summer and winter usage.  Last winter we decided it might save some oil to use a space heater, but I could not determine how much of a difference it made.
With this in mind, I made the following mental list of requirements for the first stage of this project:

  • oil tank level sensing
  • enough granularity to see daily usage
  • data logging
  • ability to compare oil usage to outside temperature


I looked into several potential methods to measure the tank level.

The Rocket

There is really only one product already on the market that is similar to what I want: The Rocket.  It is $120, only reads in 10% increments and just displays on the receiver.  Without hacking the wireless protocol that is being used, there is no way to do automatic data logging and a 60 gallon granularity is not optimal for the analysis I want to be able to do.


Here is a summary of the various sensors I considered:
  • Mechanical – while this style of sensor should be very simple and reliable, I didn’t come across any that could be read digitally or were able to read a range of 4 feet.  One may exist, but I suspect they would be fairly expensive.
  • Resistive – While strips exist and provides continuous range, they are not even close to being long enough.
  • Capacitive – There are also capacitance based strips, but they are also too short so I would have to build and calibrate my own.  I also had some concern about a capacitive sensing in fuel oil, but I later learned that this type of gauge is used in some aircraft so it should be safe.  Probably better safe than sorry.
  • Gravitational – Strain gauges are solid state devices that measure weight and are used in scales of all sizes.  I was not sure how hard it would be to get them placed under the tank, so I did not research them very much.
  • Optical – Infrared distance sensors seemed like a simple option, but I didn’t find one that covers a broad enough range for my purpose.  They all seemed to be designed for close range or far range
  • Ultrasonic sensors – there are a lot of different ultrasonic sensors.  There are expensive industrial models and cheap ones that are often used in hobby robotics.  After looking at several different sensors, I picked up a Maxbotix EZ4 (more on these later).
  • Others – I considered a sensor based on light diffraction, but I don’t know how one would work on a tank like this.  There may also be some sort of resonance type that could read from the outside of the tank, but I would guess these would need a bit of calibration if something does exist.
  • I also thought about putting a flow meter on the intake line, but I would also have to have one on the return line and it would not really tell when the tank was getting empty.
  • Thanks to hackaday.com comments, I was pointed to the Jaycar and the Centroid sensors.  The Jaycar needs a half meter of head space–I think it is intended for upright tanks.  Like the Rocket, it uses its own receiver.  The Centroid is hard to find a lot of information on (especially price), but I believe it is a capacitive sensor that can be cut to length.


I started out with the EZ4 sensor mentioned above.  This sensor is versatile and simple to use.  It has circuitry onboard that does most of the work and communicates the results as an analog voltage, PWM or RS232 signal.  The down side of this sensor is that it only offers 1-inch resolution which is about 15 gallons in the middle of the tank, but something that works is better than nothing and I can swap it out later.
I hooked it up to an Arduino Uno board with a 9V battery and tried aiming it down the fill tube which is maybe 8 inches long.  Even holding the sensor an inch or so into the tube, it would only read a small number of inches (can’t remember the exact number) when the tank was clearly under half full.  I realized it was getting interference off of the fill tube and looked up the datasheet again.  It turned out that I got the sensor versions backwards and what I really meant to get was the narrow beam Maxbotix EZ0.
for it’s 0 to 255 inch range and narrow beam so it could be spaced up far enough off of the top of the tank to avoid getting wet from splash back.

The LCD contrast was too a bit low
for the picture, but it says 116

Before I got around to mounting the EZ0, I came across a cheap version of the Ping))) sensor on eBay (2 for about $5 shipped).  These sensors claim centimeter accuracy (about 6.5 gallons in the middle of the tank) and also cover the required range, so they were worth a try.  I hooked one up on a breadboard and brought it out to the tank.  I had to hold it most of the way in the whole, but it gave a reasonable reading: 116cm (about 46″ or almost empty; it was filled the next day).  Once I verified that it would read properly aimed through a PVC adapter, I decided to go forward with this sensor.
The simplicity of this sensor is actually a bit of a strength.  To use it, you pulse a trigger pin and wait for the echo on another pin.  Even though its rated accuracy is a centimeter, accurate timing (and a bit of algorithmic cleanup) can allow for even better precision.  More on the output later on in the software section.






To hold the sensor in place, I cut a disc out of a plastic container and made holes to fit the sender and receiver through.  I started with a #5 plastic container which was quite soft and flexible and then changed out for a more rigid #7 plastic.  Once I determined the sensor would not pick up the sides of the PVC, I started putting everything together.
I used CAT5 to run into the crawl space of the house so there are minimal components outside to weatherproof.  I added an LED for a visual indication that the system had power (and perhaps to ward off anyone who comes by with the idea of siphoning the tank).

soldered up using CAT5

Everything in place

Final test setup

Final test setup

I tested out the system over the full 100′ spool to make sure that it wouldn’t suffer from any issues due to distance.  Ultimately, I used closer to 20′ to get into the house and it would have been shorter but I already had a hole around the corner to use.  I added in a temperature sensor, but I had to use an LM35 I had sitting around because I broke the leads on my TMP36.  I don’t expect most people will know the difference, but basically the LM35 requires a negative voltage in order to read below freezing.  I don’t have any parts around to produce the proper voltage, but I left the sensor in anyway.  Even above freezing, I am getting erratic results, so I intend to replace it (when the weather is a bit warmer) or use a separate temperature sensor.  I have tinkered with intercepting the signal from our Oregon Scientific weather station, but I haven’t had any luck yet (possibly, I need to add an antenna but that is for a different post).

Installed and functioning

Installed and functioning


I tried to keep things simple on the Arduino end since it would not be really easy to access in the crawl space.  Initially, it was coded to take 10 consecutive readings each time and return the total.  This essentially gives an average in millimeters.  This seemed to work great inside, but after a bit of time on the tank it was clear that it wasn’t reading correctly.  The distance returned would often be lower than it should be.  It is possible that I didn’t have the proper delay between readings (supposed to be at least 29 microseconds and I forgot to add in a delay).

sample output

I decided to go down to the crawl space to update the code and made a few changes while I was at it: increased the number of readings each time to 100, return the sum of the 10 median values, also send the min and max values.  The output is simply passed over serial using the XBee to a computer with another XBee on a USB adapter.  I wrote a simple application to allow me to select the COM port and it starts reading the data and inserting it into a simple database.  I put together a basic webpage to output the data by hour and graph the results to visualize daily trends.
16 days of data so far

Oil sensor chart


For those that are interested, there are charts and formulas available for the calculations so I won’t reproduce them here.  The tank has rounded ends, but it would be difficult to account for and accounts for a small enough portion of the volume that I ignore it for now.


All in all, I am very happy with this progress.  There are a few issues that have come up during the process:
  • As I mentioned already, it is not very convenient to bring the laptop down to the crawl space to update the Arduino code.  In addition to that, the jumpers on the XBee shield are not working for me, so I have to disconnect power, carefully remove the shield, plug in the USB to upload, disconnect USB, reattach the shield and plug the power in again.
  • The XBees (at least series 1) are simple to use, but they don’t quite operate the way I had planned.  My hope was to use one receiving module with several senders, but they are designed to be one to one communication.  There may be a way to set one to promiscuous mode, but my current plan is to change out the Uno board for a Spark Core which should be arriving soon.  These boards have integrated wifi and can be programmed over the Internet.
  • The XBees also don’t have the range I had hoped.  I had to move the receiving end as far from the computer as possible to get them somewhat reliable.
  • Sometimes the data jumps around a bit which can be seen on the graph image above.  There are also times that the sensor gets a drop of liquid on it causing misreads.  I have done some cleanup of outlying values, but the moisture problem is not apparent yet.  It could be a bit of condensation, but I suspect it is a stray drop that splashed from the return line.  To fix the problem, I have pulled the sensor off and blown it clear each time.  If the problem goes away as the tank gets lower, I will assume it is splash back, but I haven’t formulated a permanent solution yet.
  • As I mentioned above, the temperature sensor I included doesn’t provide any benefits as it is.  I won’t change it out until the weather is warmer, but if I come up with an easy way to generate a -5V, I may do some more testing in the meantime.
  • I forgot to do a manual measurement to calibrate the distance from the sensor to the top of the tank, so I made a rough guess.  This could make the values off, but I can adjust the head space on the database side if I decide to.  In the future, I may make this a setting on the Arduino side that I can modify over serial communication.

While this project is in stable operation, it is not yet complete.  Besides the improvements just mentioned, I would like to add active anti-theft of some sort.  A couple ideas I have are a tilt switch on the fill cap and a motion sensor and there may be other features I come up with later so I will revisit this part of the system after I get some of the other systems functioning and have some more parts.

Coming soon: Part 2 – How to Audit a Furnace

Update: added a couple commercial sensors to the list.

Update #2: Here is a snippet of messy data before purging.  The values jump all over the place, but the maximum distance read is often in line with what it should be.  Once I removed the sensor and blew it clean, it continues to read fine for a while.  This time I couldn’t see anything on the sensor.

2 weeks


Posted on December 2, 2013, in Electronics and tagged , , . Bookmark the permalink. 13 Comments.

  1. Hi – this is fantastic! I am thinking about doing something similar, as I just ran out of fuel oil this weekend!
    I would be worried about the moisture / oil and the unprotected ultrasonic sensor. Are you planning on doing anything about sealing the sensor?

    • Since this sensor is really cheap and I have a second one, I decided to just try it out as is. I put it on the tank the day after it was filled and it sits a couple inches away from the surface. I think I have had a bit of splash back from the return line (that is only a few inches down the tank), but it only seems to cause interference and hasn’t killed it yet in the almost 2 months it has been operating. I am not yet sure if it is possible to seal it off without blocking the ultrasonic signal. It would be nice to use a sensor from an aftermarket automotive backup sensor, but I haven’t found any details on how the communicate.

  2. Hi! I had been working on the very same idea (which has sat on my bench for a while). I have the same/similar idea for a brine tank for a water softener. In reference to the threaded hole on the tank, you said you used a 2″ PVC? Is that a standard tank opening? I’m only asking because the one I have is 2.36″ (60 mm). Well, that’s the measurement with a caliper of thread diameter.

    I like the LED idea a lot. It helps make sure you’re getting power to the sensor, that you can see without having to find the Arduino! Great idea! Might even be worth adding a segmented LED to show the fill level.

    For a sensor, have you considered the XL-MaxSonar -WR (MB7060), from Maxbotix? Weather resistant and has a 1cm resolution.

    • I am not sure if that is a standard or not, but all the openings on the top of my tank are that size. I haven’t measured the opening, but a regular 2″ galvanized threaded pipe will fit since that is what the fill tube is. For the sensor mount, I found a PVC adapter with the same threads as the galvanized piping (most seem to have finer threads). I would take the caliper to a hardware store and see what matches.

      The LED was one of those last minute additions, which is why it isn’t in the early pics. The tank is behind our house and the LED is just visible from our back window. I considered adding some sort of level display, but I don’t think it would quite be readable from inside and it could give other people an idea of how much oil is in my tank (oil theft can be a problem).

      I did see that sensor, but it was a bit too expensive (at least for my first version). Since this version has been relatively successful, I will expand my search (and budget) for the next prototype. My ultimate goal is to create something reliable and affordable to function as a security system for oil tanks, but I have a ways to go yet.

  3. Any chance of viewing your code? Github? I want to improve my readings(oscillating values) using the averaging as you’ve used. And how about temperature compensation?

  4. Thanks for sharing your project! It’s inspired me to do something similar.. that and my wife does not want to go down into our dirty, scary basement to check the tank.
    I ended up using a hc-sr04 ultrasonic sensor on an Arduino Nano as the sending unit. It pushes the values over 2.4GHz link to a raspi that writes those values to a mysql database and serves up a webpage with a javascript gauge on it.
    I’m also finding that my ultrasonic sensor is acting kinda wonky at times, showing my tank as almost full when I know it’s only halfway full…
    anyway, thanks again

  5. You really should get the temperature sensor working, because otherwise you can’t correct for the change in the speed of sound with temperature.

    At +25°C, the time of flight over 1 meter is 2.88 msec. At -25°C, that increases to 3.16 msec.

    So, some of the strange readings you’re seeing may just be temperature changes.

  6. I’m also working on an HC-SR04-based oil tank system. My tank is buried, so I’m using a hard-wired interface. One issue I’ve seen is HC-SR04 failure after a few months of use. I suspect that condensation in the tank is killing the sensor. Need to solve this since digging up the sensor every few months is not an option.

    How have you made out, long term, using the HC-SR04 in an oil tank environment?

    • I had some issues with it misreading as a really short distance which I attributed to droplets getting on the front mesh. I could get it working for a while by removing it and blowing it out, but that fix has stopped working now. I need to find some time to experiment some more to see what is going on, but I have been too busy. If it is a dead sensor like yours, I may have to track down a better sensor. I considered a backup sensor from a car, but I doubt they have any decent resolution. There are some sealed ones, but they are not as easy to come by and find information on.

  1. Pingback: Home Heating Hacking with the Raspberry Pi (Links) » TechNotes

  2. Pingback: A wireless Fuel Tank monitor | shanes.net

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: