I saw an excellent write-up on how to monitor fuel levels in an oil tank using ultrasonic sensors over on hackaday. In his blog, alaskanshade details how he used Arduino and an ultrasonic sensor to log the data and measure fuel levels. I really like the idea of monitoring fuel levels using this setup, so I had to give it a try. I also wanted to incorporate the following design goals:
- Perform all-wireless data acquisition
- Ability to see current fuel level on the internet/web-page
- Log all data to a sql database/web-server using deviceLogger
- Battery life should last a long time, at least six months without having to change batteries
Forgive my lack of drawing skills, here is a diagram of the whole system:
In a nutshell, the process works like this:
- The sending unit pings the tank with the ultrasonic sensor and calculates the gallons (see attached gist for code, I found some code online that I adapted for use here. I’d give credit, but I can’t remember which site(s?) I found it on anymore)
- The entire system shuts down using the excellent LowPower library for Arduino. After about one minute, it wakes back up and does another measurement. After 15 measurements/minutes we send the current running median (another great Arduino Library) of the measurements. At this point, the whole process repeats.
- On the receiving end, there is an Arduino with an nrf24l01 module and ethernet shield (see my previous post on getting these two to work together if needed). The receiver publishes some text/xml to a web page.
- The deviceLogger reader script periodically checks this page for new data. It then writes the data to a mySQL database. The deviceLogger php application then serves up the graphs and current data.
I ended up using one of my protoBoard pcbs on this project, and it worked out very well. It fit perfectly in the 2″ pvc that I used to build the sensor housing. Here’s some images from the build:
One thing that I noticed in the course of this project was that I was getting some strange readings from time to time, and sometimes readings would just be completely off from what I knew to be the current tank depth. I had a theory that some of the erroneous readings may have been caused by multiple echoes bouncing off of the many internal facets of the tank (multipathing). I decided to try adding a ‘snoot’ of 1/2″ pvc pipe to the end of the ultrasonic sensor to better guide the send signal towards the surface I actually wanted to measure (the fuel sitting at rest in the tank). This seems to work very well. Once I placed the snoot on the sensor, I immediately began receiving good readings without error. I do still have some bad-value rejection and median-smoothing in the Arduino sketch though. And as you can see from the screenshots, I still get fluctuations in the ultrasonic readings that work out to about a +/- 1 gallon level of accuracy over the course of a day:
I also made a few modifications to the newPing library settings that changed the amount of time delay between pings on the ping_median() method. This was done because the aforementioned multipathing/echo issues seem to present themselves once again if you don’t wait long enough between pings. I adjusted the time from 29ms up to 1000ms.
As mentioned above, the sketch also uses the excellent LowPower library. I used LowPower to power down the Atmega328 for about a minute at a time between readings. This should allow the three AAA batteries to last about one year before needing to be replaced.
If you want to use this code, but have a different sized tank, you should be able to adjust the values for variables ‘tankHeight, tankWidth, and tankLength’. As long as your tank maintains standard ob-round dimensions/shape, it should work fine.
Here’s the sketches: