[How-To] Measure Salt Level in your Water Softener


How-To Measure Salt Level in Your Water Softener Using an Ultrasonic Sensor

by BraveSirRobbin

This How-To will describe how to measure the salt level for your water softener. This has been requested by a number of members. Various techniques have been tried in the past, but all had one common methodology. "Something" had to touch the salt. Be it a weight, string, magnet, etc... all of these methods required a mechanical means that touched the top level of the salt to acquire a "level" reading.

The problem with these methods was it made refilling the softener difficult. These strings had to be manually coiled/lifted/etc... to get them out of the way, then rearranged so they could start measuring the "new" level.

This method uses an "ultrasonic" sensor so nothing touches the salt. Also, with the mounting method used, the sensor can be pivoted out of the way for easy refilling of salt in the water softener.

First, I would like to thank fellow Cocooner roussell for posting about the Maxbotix Ultrasonic Sensor in THIS thread. This sparked an interest for a lot of applications, thus THIS dedicated thread was created.

Also, this How-To was featured as a Home Toys article for their August 2006 issue.

Ultrasonic Sensor Details
HERE is the link for the Maxbotix Ultrasonic Sensor used.
These MaxSonar-EZ1 offers very short to long-range detection and ranging, in an incredibly small package with ultra low power consumption.  The MaxSonar-EZ1 detects objects from 0-inches to 254-inches (6.45-meters) and provides sonar range information from 6-inches out to 254-inches with 1-inch resolution.  Objects between 0-inches and 6-inches range as 6-inches.  The interface output formats included are pulse width output, analog voltage output, and asynchronous serial digital output.
HERE is a detailed data sheet for this sensor.
  • sensor.jpg
Preliminary Testing
Bench testing was first performed to determine what code/methodology was needed for a serial interface as well as power and overall system accuracy. I had a leftover five volt wall wart and since the unit required 4.5 to 5.5 volts DC for power I thought it would make for a good power source.

After plugging in the wall-wart (to check the voltage output level before connecting it to the sensor), I noticed that the voltage was slightly above 5.5 volts DC (a common problem with most wall warts that I use in my home). I therefore placed a diode in-line with the positive lead in order to get the voltage down to a level within specs.

All the unit needs for an RS-232 interface is for pin 2 of the serial port to be connected to the "TX" solder ring and pin 5 to the "GND" solder ring. The wall wart would of course be connected to "+5v" and "GND".

HyperTerminal was used to check for communication. As soon as the unit was powered up and HyperTerminal set for 9600, N, 8, 1 serial port settings (no hardware control) the unit sent an "R" followed by a three digit ASCII number which represented inches. The update was very fast and it was accurate to within one inch.

I found that as long as the "RX" line was high (or disconnected in this case), the unit would just "free run" (i.e. keep transmitting the data). I also noticed that CPU level was significantly increased when the unit was connected and free-running.

Since I wanted to place this unit in a very warm garage environment and since I didn't want to have it free run I decided the easiest way to have the unit interfaced with my automation computer was to turn power to the unit on via an appliance module for just a second whenever data was needed (only once a day in this case).

I would just turn the appliance module on, wait a second, get the distance data to a HomeSeer device, then turn the unit off.

I would like to thank Michael (the Great) McSharry for helping me out with the serial code (in THIS HomeSeer thread) to interface this device via HomeSeer. Though this code is HomeSeer specific it should be easily modified for other HA systems.

Mounting the Sensor

(Click on Picture for Full Sized Image)
The Water Softener

The sensor is very small and is very easy to mount. Care must be taken as to not short out any circuitry on the PC board.

I mounted the unit on a leftover "hinge mount" from an X-10 security motion sensor (I dropped the motion sensor... long story). I used a rubber washer between the mount and the sensor's PC board. I drilled a small hole through the arm of the mount and attached the sensor as shown.

(Click on Picture for Full Sized Image)
Ultrasonic Sensor Mounting

I then attached the mount to the water softener. Make sure you know exactly what you are drilling/screwing into as not to damage the water softener itself!

(Click on Picture for Full Sized Image)
Ultrasonic Sensor Mounting

(Click on Picture for Full Sized Image)
Ultrasonic Sensor Mounting (Overhead View)

I had the luxury of AC Power and Cat5e cable available near the water softener (prior planning before the house was built). I just used a pair of Cat5e wires from that cable (for the RS-232 signal and gnd) and plugged an appliance module and the wall wart in the nearby outlet via a home made short AC extension cord (for the unit's power). This homemade extension cord has a built in small amperage fuse, therefore I didn't place any additional inline fuses in the system.

I then routed the five volt power leads and the Cat5e pair through the water softener's "overfill drain" outlet and soldered the diode and leads to the sonic sensor's PC board.

Making the Connections to the HA Computer
I then wired the HA computer's Com7 port to the appropriate patch socket in my wiring closet via a custom DB-9 to Cat-5e interface cable. As long as you keep track of the color pair (brown/brown-white in my case) that you wired the sensor's TX and GND lines to, this cable will work through multiple patches.

I just wired the brown wire (connected to the TX) to pin #2 of a 9-Pin D Female connector and the brown-white wire (connected to GND) to pin #5 of the D Female connector to one end of a (cut) Cat-5e cable and plugged the other end into the nearby RJ-45 socket. After going through multiple patches I then used a cut piece of a Cat5e jumper and placed the RJ-45 connector end into the outlet near my computer and soldered the brown wire to pin #2 of a 9-Pin D connector, and the brown/white wire to pin #5. I then connected the 9-Pin D connector to Com7 of my Edgeport USB to eight port serial expander which is on my HomeSeer PC.


You can also use a RJ-45 to 9-Pin "D" connector (such as THIS one) for this final connection instead.

(Click on Picture for Full Sized Image)
Final Wiring & Mounting

Testing the System
I again opened HyperTerminal up and looked at Com 7 with the appropriate serial parameters listed above.

I then turned the appliance module on and noticed a reading of R018 on HyperTerminal which of course meant the unit was reading 18 inches.

I took a tape measure and measured from the "tip" of the sensor to the salt level and that reading was over 17 inches. Therefore the unit looked like it was working properly. I took a piece of cardboard and tested other "simulated" salt levels. The unit's readings were always within an inch of the real measurements.

Developing the Code
As mentioned earlier Micheal McSharry helped with the bulk of the serial interface code. Basically when HomeSeer starts, I want to open Com 7 (in my case as I'm using an Edgeport 8 serial to USB interface) in the "StartUp.txt" file and close the Com Port when HomeSeer exits.

Then, whenever a reading is needed, a HomeSeer event will be created and the unit will power on for a second and then power off. During that time a sensor reading will be "stuffed" in a HomeSeer device and a "converted percentage" reading stuffed into another HomeSeer device. This second percentage reading will represent the salt level in "%" (i.e. between 0-100 percent filled).

Code Listing
Here is the HomeSeer (ver 1.7x) code I used to open serial port 7 and is placed in the "startup.txt" entry:

Note that I'm using HomeSeer virtual device "R10" to store the inches data from the sonic sensor and "D12" for the appliance module for controlling power via the wall wart.

'Open Com 7 and have Sonic Sensor "Push" Readings To Device "R10"
e=hs.OpenComPortex(7,"9600,n,8,1",1,"sonic2.txt","sonic", chr(13), 1)
if e<> "" then msgbox "Error opening COM7 (Sonic Sensor): " & e

And here is the code for the "sonic2.txt" file that is referenced by the hs.OpenComPortex command:

sub sonic(data)
    if left(data,1) = "R" and len(data) = 4 then
        sDigits = mid(data,2)
        if isNumeric(sDigits) then
            hs.setdevicestring "r10", cstr(cint(sDigits))
            hs.setdevicevalue "r10", clng(sDigits)
        end if
    end if
end sub

Of course when HomeSeer shuts down the Com7 serial port must be closed. Place this code in your "Shutdown.txt" script:

Doing the Math
Well, I really don't like "inches" and would rather have "percent filled" displayed in another HomeSeer device. In order to do this, some math relationships need to be established.

Notice in the inside water softener picture there is a graduated pipe with measurements starting with "8". I only fill the softener up the the top of the "7" mark, therefore I'm calling this 100% filled. This comes in handy since the way I mounted the sensor that the first reading past six inches was the top of that "7". (Remember this sensor does not start reading at zero, rather it starts at six inches).

I never want my salt level to go below the "top" of the "1" in the graduated pipe so I will call that "zero" percent filled. Now an equation needs to be established with the ultrasonic inches readings and these percent relationship boundaries.

Taking the Data
I first took an ultrasonic reading for the top of the "7" graduated pipe mark by placing a large sheet of cardboard at the top of the "7" mark and, keeping the cardboard level, took a reading with the sensor.

I then took readings at the "6", "5", and "4" marks (since the current salt level was below the "4". At each reading I took the corresponding "inch" reading from the ultrasonic sensor. The results are shown below.

(Click on Picture for Full Sized Image)
Inch Data Measurements at Graduated Pipe Markings

As you can see the data is linear (three inches separates the readings on the graduated pipe's readings). Therefore (as we learned in THIS Guide) we can develop an equation which represents a relationship between the ultrasonic sensor's "inch" reading and "percent" filled.

Since the data is showing a nice linear progression, I just extrapolated the date to the "3", "2", and "1" marks (since the salt was above those numbers, thus prohibiting taking "real" measurements at those levels).

First let’s take a look at the two "extreme" data pairs (for zero and 100 percent filled):




Now we need to calculate the slope intercept formula using those data sets above. For a very detailed explanation on how to do this please see the Analog to Digital Converter Guide.

The equation Y = mX + b will be used where m represents the "slope" and b represents the "Y-intercept".

Calculate 'm':

m = (Y2 - Y1) / (X2 - X1)

m = (100 - 0) / (7 - 24) = -5.882

Calculate 'b':

Now solve for b using one of the data pairs above (24,0 in this case):

Y = mX + b
0 = -5.882X + b
b = 141

Determine the Equation:

Therefore we have an equation which can convert "inches" from the ultrasonic sensor to "percent filled":

%Filled = -5.882 (inches) + 141

You can test this equation using any data pair listed above and see that it is correct. For additional details on how and why this method was used please refer to the Guide listed above.

Implementing the Final Code
Now we have to place all of the above pieces together with an event that will run a program to incorporate all of the above features.

Using HomeSeer set an event to fire once a day (probably in the evening for the voice announcement to be heard) to implement this code (remember the Com port was already opened via the "startup.txt" script):

For my scenario D12 is the appliance module device, R10 is the ultrasonic "inches" data device, and R11 is the "percent filled" device.

sub main()

Dim SaltLevel
Dim SaltPercent
Dim i

hs.ExecX10 "D12", "on", 0, 0  'Power for Sonic Sensor

hs.WaitSecs 1  'Wait One Second

hs.ExecX10 "D12", "off", 0, 0  'Power Off Sonic Sensor 

hs.setdevicestring "r11", (141 - (5.882 * (hs.DeviceString ("R10"))))

hs.WaitSecs 10  'Wait Ten Seconds

'Set virtual device r11 to percent from the inch reading of r10
hs.setdevicestring "r11", (141 - (5.882 * (hs.DeviceString ("R10"))))

If hs.DeviceString ("r11") > 22 then  'Send an Email if salt level (inches) to low
hs.sendemail"[i]yourpop3.com","yoursmtp.com[/i]","Water Softner Salt Level Low", "The Water Softener Needs to be Filled!"

hs.speak "The Water Softener Needs Filled"

end if

end sub

I was having a timing problem where the percent device would not get updated, but the inch device would. I solved this by the hacked fix above of just reading and calculating the percent twice (I know, hack job but I got a little lazy towards the end of this project). Maybe one of you code gurus can figure that problem out for me :( .

When the salt level gets to be more than 22 inches from the sonic sensor (i.e. less filled) you can send an Email so you can remember to fill it.

Putting the Icing on the Cake
I use MainLobby and asked Mario if he could create a flash icon which would visually represent the salt "percentage" filled for my water softener. He made the icon below. Note that the slider uses a value from zero to 100 for it's min and max values. I can associate the "percent" HomeSeer device to this icon, thus having an accurate visualization of how full my water softener is!
  • icons.jpg
***********MainLobby Flash Icon of Water Softener***********

This represents one way to measure salt level for your water softener. One disadvantage is it needs a serial line to the water softener from your HA machine.

One of the many advantages is there is nothing touching the salt and no strings or devices that need to be reset/recoiled when filling the softener. I would recomend covering the sensor with a small baggie though when filling the unit so the salt's dust can not enter into the sensor.
Wow BSR, that is awesome! This just may top your "Ultimate garage door monitor" mod. :( Congratulations on a job well done and another great how-to. BTW, I've found that covering the sensors in that soft, sponge-like open-celled foam that you can get from hobby stores (or leftover from packing containers) works great at keeping most things away from the sensor's face/electronics and does not interfere with the unit's operation.
roussell said:
I've found that covering the sensors in that soft, sponge-like open-celled foam that you can get from hobby stores (or leftover from packing containers) works great at keeping most things away from the sensor's face/electronics and does not interfere with the unit's operation.
That's a good point and I posted one of your pictures of your mounting setup below. If I had a little more time this would have been a better way to go as it would protect the unit also.

I may try to do this later. Smee also had some comments concerning the "salt" environment and if it would pose a problem for the sensor (I'll post his comments after I get his permission). I don't think it would pose a problem as there is not a lot of "salt dust" kicked up inside the unit, but I'm wondering if an area with very high humidity would have a problem??

I honestly don't know. We have very little humidity here so I'm obviously not a good test case for this concern! :(


  • roussell_sensor.jpg
    37.4 KB · Views: 162
Here is a comment that smee had. I also fixed a typo error he caught (thanks smee) and posted the "sonic2.txt" source code (forgot that also :eek: )!

Quote from smee:


Regarding the problem with computing the percentage twice...

When the hs.waitsecs is running (for 1 second), is everything else disabled?  I.e., is HS prevented from reading the data in the serial port buffer until this finishes?  This would explain why the first percentage calculation doesn't work - the data may not have changed yet - it hasn't been given a chance.

If you need to go this route, you might as well remove the first one, anyway.

But, why don't you just compute the percentage in your comm handler function ("sonic" in "sonic2.txt", I think - you didn't include that code in the write-up)?  Is there any reason not to do it at the same time?

I'd probably do the notification as a timed event independent of the measurement event.  It means setting up two events, but you don't need to put in delays.  And it can be 10 minutes or an hour later - or it can check the percentage every time you come home and tell you then.

When I get some time I would like to try out his code suggestions as I think that would be a better way to go! :(

Great Writeup once again !!!! A lot of effort putting this writeup together a project on its own...

TBH I have heard of water softeners but never seen one before and was really curious when you mentioned thats how you were using yours....

And Putting the icing on the cake....Thats nice ;-) Nice work.....

Well Done

FrankMc said:
And Putting the icing on the cake....Thats nice ;-) Nice work.....
Yes, that's the great talented work of Mario Cascio, President of Cinemar! He also did the icon for my garage door opener.

I think MainLobby has some of the most visually impressive displays for interfacing as a front end to my Home Automation system!
Out of curiosity why does one need a water softener? I've never seen one until BSR posted his pictures.
Rupp said:
Out of curiosity why does one need a water softener? I've never seen one until BSR posted his pictures.
We have "hard water" here (heavy calcium and tastes bad, plus it is bad for the pipes/faucets).

I obtained this explanation from a web site, but basically you are swapping out one ion for another (calcium ions for sodium ions).

The idea behind a water softener is simple. The calcium and magnesium ions in the water are replaced with sodium ions. Since sodium does not precipitate out in pipes or react badly with soap, both of the problems of hard water are eliminated. To do the ion replacement, the water in the house runs through a bed of small plastic beads or through a chemical matrix called zeolite . The beads or zeolite are covered with sodium ions. As the water flows past the sodium ions, they swap places with the calcium and magnesium ions. Eventually, the beads or zeolite contain nothing but calcium and magnesium and no sodium, and at this point they stop softening the water. It is then time to regenerate the beads or zeolite.

Regeneration involves soaking the beads or zeolite in a stream of sodium ions. Salt is sodium chloride , so the water softener mixes up a very strong brine solution and flushes it through the zeolite or beads (this is why you load up a ater softener with salt). The strong brine displaces all of the calcium and magnesium that has built up in the zeolite or beads and replaces it again with sodium. The remaining brine plus all of the calcium and magnesium is flushed out through a drain pipe.

This also helps the soap "lather" for the shower and clothes.

Also note that for my drinking water I have a reverse osmosis system (six filtered steps) which can take out any additional non-wanted substances/particles in the water.

You probably have low calcium or spring water so it isn't needed in your area.
Hi Guys

I have heard of areas which have "Hard Water" but i like Rupp have never seen a Water softner......Isnt it neat that it can be monitored by the H.A. System ;-)


How would the water taste if not using the reverse osmisis system? Would it be salty? Also, dont the salty water corrode your washing machine and other ferrous metals in your home?
I'm not an expert but supposedly this doesn't introduce a lot of salt into the water. It still "tastes" bad though.

The high calcium is actually more of a detriment to the plumbing than the sodium ions I believe (again, not an area of my expertise). :(
The salt tank is only half of the water softening system. There is another tank, the filter (Looks like a seteline tank). The salt is mixed with water and used to clean the filter. The salt itself does not go into the drinking water, and if it does it is a VERY small percentage.

Living in South Florida, as anyone that is not on city water here can attest, we have a LOT of iron in the ground water here (Basically...RUST!). It makes terrible yellow stains on walls from the sprinklers, stains the tub, shower, sinks, toilets ect. It will actually give white clothes a slightly orange hue to them when washed in the unfiltered water. Where I grew up, I could never buy white clothes for that very reason. The water softner helps to remove the iron, calcium and other unwanted stuff in the water.

Here is an example of some typical Florida water stains: (Courtesy of a Google Image search :( )
AutomatedOutlet said:

My pool is a salt water pool, I guess it would work for there as well, right?
Hi Martin;

I'm not really sure of your particular situation. Do you have a swimming pool where you need the level sensed? What are the distance ranges?

I guess I'm not really sure if this would be the best methodology for your situation without some more details.


BSR, what is the sensitivity / resolution of the distance sensor? ie: can it detect a 1/4 inch change? Can it detect clear water level? Or does there have to be something floating to bounce off of?
Excellent writeup as usual!