Water Softener Salt Level

First post, sorry if I fail at formatting. As I’m a new user, the forum won’t let me post as many links and pics as I need to. Maybe I can add more later.

I created a simple arduino project to monitor Water Softener salt levels in HA. It works by using an Ultrasonic Sensor an Arduino Nano a Nano ENC28J60 Ethernet Shield a Nano screw-terminal board (not strictly necessary) and some poor-man’s POE to allow me to run only one cable.

The arduino code shamelessly copied from different projects will have to be modified for your IP and MAC address.

 // sensor power connected to 5v
// sensor ground to GND
// sensor trigger connected to pin 2
// sensor echo connected to pin 3

#include <EtherCard.h>
const int trigPin = 2;
const int echoPin = 3;


// ethernet interface mac address, must be unique on the LAN
static byte mymac[] = { 0x74,0x69,0x69,0x2D,0x30,0x01 };
static byte myip[] = { 192,168,1,78 };

byte Ethernet::buffer[500];
BufferFiller bfill;

void setup () {
  // Change 'SS' to your Slave Select pin, if you arn't using the default pin
  if (ether.begin(sizeof Ethernet::buffer, mymac, SS) == 0)
    Serial.println(F("Failed to access Ethernet controller"));
  ether.staticSetup(myip);
}

static word homePage() {

long duration, inches, cm;

pinMode(trigPin, OUTPUT);

digitalWrite(trigPin, LOW);

delayMicroseconds(2);

digitalWrite(trigPin, HIGH);

delayMicroseconds(10);

digitalWrite(trigPin, LOW);

pinMode(echoPin, INPUT);

duration = pulseIn(echoPin, HIGH);

cm = microsecondsToCentimeters(duration);

delay(100);

//map centimeters to percantage full - adjust per your softener tank

int percent = map (cm, 5, 75, 100, 0);

// check if percentage is out of bounds and set to zero if it is
 if (percent < 0) {
    percent = 0;
 }
 if (percent > 200) {
  percent = 0;
 }
  
  bfill = ether.tcpOffset();
  bfill.emit_p(PSTR(
    "HTTP/1.0 200 OK\r\n"
    "Content-Type: text/html\r\n"
    "Pragma: no-cache\r\n"
    "\r\n"
    "$D"), percent);
  return bfill.position();
}

void loop () {
  word len = ether.packetReceive();
  word pos = ether.packetLoop(len);

  if (pos)  // check if valid tcp data is received
    ether.httpServerReply(homePage()); // send web page data
}

long microsecondsToCentimeters(long microseconds)

{return microseconds / 29 / 2;}

I created a rest sensor in my configuration.yaml to receive the data from the nano webserver. It could take much more data with properly formatted templates, but I was planning on using this only for my Softener Salt so just an integer works fine in this case.

- platform: rest
        resource: http://192.168.1.78
        method: GET
        name: Salt
        unit_of_measurement: "%"

by using only the TX and RX wires on the RJ45 plug, I was able to steal the blue and brown wires to send power. The 5v wall plug on one end and a keystone jack on the other to pull the power out and send it to vcc and ground on the arduino.

I also 3d printed a (marginally sealed) box to hold the sensor in a way that will mount in my water softener. Your mileage my vary. Here’s the STL file for those with a 3d printer:

Eventually, I’ll get an enclosure for the arduino as well. I don’t have any pics of it mounted but the results are positive!

5 Likes