Water Wise: LoRaWAN Enabled Water Level Monitoring

Part 1

Ashley Woods

Issue 51, October 2021

An advanced tank level sensing and pump control system that uses LoRaWAN technology to monitor and maintain water tank levels, keeping livestock watered across the farm.


A Note from the Editor

This project was developed by one of our readers, Ashley Woods from regional Queensland. Like most of DIYODE readers, Ashley is a hobbyist who started out dabbling with an Arduino and graduated to other microcontrollers and on to the Raspberry Pi. Along the way, he discovered the fantastic MQTT protocol and has now used it in several projects. We are impressed with Ashley’s project and are really excited to share it with you.

Keep in mind, even though Ashley’s project has been designed for operating multiple water pumps on a farm, you could adapt the project to suit your own needs where long distance monitoring is required. It could be, say, used to operate a gate at the end of your long driveway or operating your outdoor hydroponics garden, for example. You can choose to just build the sensor, and/or the pump control system.

This project is published in two parts, with part 2 to follow next month.

Rather than a single project, this is actually a system where several modules all communicate via MQTT to monitor the water level in a tank and to control a pump to keep the tank full. The pump controller also integrates with a solar inverter to ensure the pump runs when electricity is available from the solar array.

The Broad Overview

My family and I live on a farm in Queensland and this project is born from the necessity to monitor the presence of water in several remote water tanks on the farm. The tanks are located at strategic cattle watering points around the farm, and it is important that water be available for these animals. Cattle consume an average of 40 litres per animal per day, so it is important that water levels are checked regularly. Automated monitoring and reporting of water levels saves the time needed to drive to each tank every few days and check the water level.


LoRaWAN technology is used as the communications technology to connect the monitor on each tank to the network. The end-to-end solution consists of several modules; specifically, the LoRaWAN enabled water level sensors and back end server setup to receive, process and graph the data. Most of the tanks are filled by windmills so while the wind blows, water can be pumped from underground. One of the water tanks is serviced by an electric pump which needs to be switched on and off as needed to maintain the water supply. This electric pump can consume power generated by the local solar panels, so our desire was to optimise the pump to run when the sun shines.

The various elements of this project will be presented in two parts, providing the overall design of the solution as well as the operation of the LoRaWAN enabled tank sensors. While this project started out rather simplistically to remotely control the electric pump, it has evolved into a complete system. Readers wishing to build this project may build just the sensor component or just the pump control component and operate these independently. The basic design of the tank sensor also lends itself to any kind of environmental monitor such as a weather station. Let’s get started!

Diagram 1 shows the overall block diagram of the system.

At this stage, the first of seven tanks has been fitted with the water level sensor. This is a second generation sensor build, which now uses a submerged pressure sensor. The first-generation build used an ultrasonic sensor mounted in the top of the tank. While this proved the use of LoRaWAN communications, unfortunately, the overall solution lacked the required resilience for the outdoor environment. Read about the first generation build below.

The water tanks to be monitored are cylindrical fully enclosed tanks made from moulded polyethylene and are filled by a windmill or electric pump from an underground aquifer or other water source. Tanks range in size but are typically about two metres high and four metres in diameter and hold about 20000 – 25000 litres of water.

First Generation Build

The abandoned first generation project that used ultrasonics.

The first generation water level sensor used an ultrasonic sensor mounted in the top of the tank. This device was oriented so it pointed straight at the water surface. Ultrasonics measured the time of flight for a pulse to be emitted and bounce off the water surface. The sensor calculated this distance and presented the data on a serial interface.

About two thirds of the measurements received were accurate but the remainder were at one extreme or the other of the sensor range. The actual reason for this condition was difficult to diagnose, but it may have been due to condensation forming water droplets on the face of the transducer.

The tanks are fully enclosed polyethylene enclosures and when sitting in the Australian sun, the humidity level in the air space above the water is very high. This design also placed the electronics and the sensor in the same enclosure. Despite the electronics being somewhat sealed from the sensor, some humidity was detected in the electronics enclosure. This caused minor corrosion after about a year of operation.

The solution was powered by three AA batteries which only provided a life of about four months. For these reasons, this design was abandoned, and the more robust submerged sensor and separate solar powered electronics enclosure was pursued.

Schematic for Tank Sensor

TOP TANK SENSOR SCHEMATIC Also downloadable via resources.

The equipment must operate unattended 24/7 for long periods in a harsh and remote environment, so good environmental protection is required. This is achieved by enclosing all electronics in a weatherproof polycarbonate enclosure. The sensor is connected to the electronics module by a cable and lowered to the bottom of the tank. This separation of electronics and sensor avoids the corrosion issues seen with the Gen 1 solution.

The electronics can be powered by solar so minimising power consumption is not critical. A small SLA battery is used to power the device at night or for periods of up to three days with no solar charging. The 10 Watt solar panel is slightly larger than the electronics enclosure and effectively doubles as a shade for the electronics.

The microcontroller will wake up about every hour, take measurements, transmit the data and go back to sleep.

The LoRaWAN connectivity used for the wireless uplink constrains the actual payload based on the duty cycle of LoRaWAN but provides the range needed. Connection is to The Things Network (TTN) via a local LoRaWAN gateway. As there were no gateways in range, a new LoRaWAN gateway was implemented specifically for this project.

The sensor data is then received from The Things Network; also via an Internet connection. The data is logged and graphed, and also used as an input to the system used to control the electric underground pump.

Related metadata such as enclosure temperature, humidity, atmospheric pressure, light level and battery voltage are also reported.

The Build - Part 1: Tank Water Level Sensor

Overall Build and Operation

Parts Required:JaycarAltronicsPakronics
1 x PyCom LoPy4 Microcontroller--SS102991025
1 x Submersible Pressure Sensor See text 
1 x BME280 Environmental Sensor Pimoroni: PIM472 
1 x Ambient Light Sensor (LDR) See text 
1 x Battery Voltage Sensor See text 
1 x ADS1115 Analog to Digital Converter Module--ADA1085
1 x 12V 1.3Ah Sealed Lead Acid BatterySB2480S4517-
1 x SLA Battery Charge Module (SDLA12TA) See text 
1 x 12V 10W Solar Panel See text 
1 x Boost Converter for 24 Volt Supply See text 
1 x LoRaWAN Antenna See text 
1 x Polycarbonate EnclosureHB6132--
1 x 3D Printed Mounting Plate See text 
1 x Custom PCB See text 
3 x 4-pin Mini-Fit Jr 5566 series MOLEX Connectors We purchased from RS Components 
3 x 4-pin Mini-Fit Jr 5566 series MOLEX PCB Mount Connectors We purchased from RS Components 
2 x 3-pin IP68 Waterproof Connectors We used SZJELEN SY1710/SY1711 from Ali Express 
2 x 3-pin Panel Mount IP68 Waterproof Panel Mount Connectors We used SZJELEN SY1710/SY1711 from Ali Express 
1 x BS170 N-Channel MOSFETs (Relay Driver) RS Components: 671-4736 
1 x 12VDC DPDT PCB Mount Relay (Kemet EC2) RS Components: 870-5380 
1 x TRACO 5V Voltage Regulator (TSR 1-2450) RS Components: 666-4379 
Wiring harness and connectors See Text 
1 x Remote Console for Debugging Purposes See Text 

Note: Various generic resistors, diodes, LED and PCB headers required. Refer to schematic, photos and PCB overlay.

This project utilises several client nodes all communicating using MQTT to a cloud based Mosquitto message broker to form a complete system. Nodes operate as publishers or subscribers, or both depending on their role.

This is an excellent model as it allows many different clients to subscribe to messages and each provides different services such as dashboard or status alerting. It also allows authorised clients to publish command messages to stop and start the electric pump based on status received from a different client. Some of the clients are straightforward Python scripts running on the cloud server, and others are Raspberry Pi or PyCom microcontrollers. All of the programming for scripts, Raspberry Pi units and microcontrollers is done in Python or MicroPython. Configuration parameters are generally placed in an associated YAML configuration file.

Most of the development was done using VSCode with the Remote Plugin. This uses a SSH connection to the Linux server or Raspberry Pi, so code is stored and run on the remote target, but the editor runs locally under Windows. This proved to be a very efficient development setup.

Tank Sensor PCB

MQTT is a great protocol for these connections as it can operate when devices are behind firewalls and on cellular connections. As long as every client has connectivity to the broker, messages can effectively flow between clients without the clients even knowing about each other.

The tank sensor uses a PyCom LoPy4 microcontroller module which publishes the measurements via the LoRaWAN gateway to TTN. Data is retrieved from TTN via MQTT and processed by a Python script running on a cloud server. This script logs data and republishes the water level measurement for the selected tank.

The pump controller module (running on a Raspberry Pi) subscribes to tank level measurements and uses this as an input to control the electric pump. When the water level sensor detects a low water level in the tank, the pump will be switched on, and when the sensor reports the tank as full the pump will be switched off. The pump controller also monitors solar power availability, so the pump preferentially runs during times of surplus solar power generation. The detailed design and operation of the pump controller will be covered in Part 2 of this project.

The completed electronics module for the tank top sensor is shown in the following photograph.

The completed electronics module for the tank top sensor

The tank water level sensor uses the submerged pressure sensor to determine the height of the column of water above the sensor. The sensor is supported by a stainless steel mounting frame (thank you Bill Armstrong) which supports the sensor about 110mm off the bottom of the tank. This helps prevent the sensor from being contaminated with any algae or detritus in the bottom of the tank. It also places the sensor close to the level of the water outlet.

The pressure reported by the sensor is proportional to the height of the water column above it. The sensor has an exposure to the atmosphere to compensate for variations in atmospheric pressure. This ensures changes in air pressure do not change the measured water pressure. This compensation is achieved via a small air tube running from the sensor itself inside the electrical cable and vented to the atmosphere.

The following photograph shows the pressure sensor supported by the mount and ready to deploy inside the tank.

Pressure sensor mounted into a frame.
Pressure sensor sits 110mm off the tank bottom.

The sensor uses the old but robust 4-20 mA current loop technology to report the measured pressure. When no water pressure is applied to the sensor, it will pass 4 mA of current, and when the sensor is at maximum range, it will pass 20 mA of current. A power source is needed to drive the sensor, and this is usually 24 VDC. Some sensors will pass 25 mA (or more) to indicate an error condition so the power supply must be capable of at least this range. These sensors are available to support various water depths and we chose the five-metre version as this was the best to suit our water depth of about two metres.

The 4-20 mA current loop technology is a very robust technology used widely in industrial automation. As it uses current rather than voltage, the cable length is not critical. Unlike voltage which drops off over distance, the current flowing around this circuit will be the same at any point in the loop.

In order to determine the current flow in the circuit, we simply measure the voltage drop across a 100 Ω shunt resistor in the circuit. This shunt resistor is inserted in series on the low side of the circuit so one end of the resistor is at ground. The other side of the shunt resistor will register an increasing voltage as the current flowing in the circuit increases. This linear relationship converts current to a measurable voltage which is converted from analogue to digital to provide a water level.

The 24 VDC to the pressure sensor is provided by a XL6009E1 DC-DC boost converter. The boost converter is adjusted to produce the required 24V output. This is best done by installing the “offline” jumper on the PCB. This modifies the flow of code to bypass the LoRaWAN join and subsequent communication and to extend the time that the 24V supply is enabled. This allows plenty of time to adjust the boost converter and to measure the voltage from the shunt resistor.

As this sensor may consume up to 20 mA (at 24 VDC), it will only be powered up when readings are needed. A single N Channel MOSFET drives a small PCB mounted relay, which is used to supply battery voltage to the boost converter. This is simply powered on when a reading is needed and allowed to stabilise for several seconds. Multiple readings are then taken and averaged.

Readings are converted from analogue to digital via the ADS1115. This is a 16 bit ADC. This resolution is not required but this converter was chosen in preference to the onboard ADC because the LoPy4 MicroPython only supports one of the two A-D inputs on the microcontroller. The external A-D converter is also less likely to be influenced by a drift in the power supply as it uses an internal reference voltage.

The size of the shunt resistor will vary based on the input range on the analogue input. The actual value of the shunt resistor can be calculated as follows. This is based on the use of the ADS1115 analogue to digital converter chip. The one used in this project is an Adafruit Product ID 1085 (ADS1115 16-Bit ADC - 4 Channel with Programmable Gain Amplifier). It is powered from the 3.3 VDC regulator onboard the LoPy4 module.

The input to the ADS1115 must not significantly exceed VCC, so a target maximum analogue input of 3VDC was chosen. With a maximum current flow in the circuit of 30 mA, the shunt resistor may be calculated using Ohm’s law.

Resistance = Voltage / Current

Resistance = 3 Volts / 0.03 Amps = 100 Ω

Therefore, at different pressure readings, the following readings will be present on the shunt resistor.

No pressure (tank empty) 4mA 0.4 V

Maximum pressure (5 m of water head) 20mA 2.0 V

While the tanks we will use will only exercise about half the range of the 5 metre sensor, this value of shunt resistor provides a useful range of input to the ADS1115, while allowing for an adequate safety margin.

Any reading below 0.4 V or above 2.0 V suggests something is disconnected or faulty as such a reading should never occur and must be considered an error condition.

A number of test points were designed into the PCB and conveniently placed on the lower right corner so the various power supply voltages and analogue sensor readings can be checked during operation or troubleshooting. The calibration of the sensor and the conversion to a 0% - 100% reading is all handled in the script on the server. A LED is provided on the PCB which illuminates when the 24 VDC supply is present.

The battery voltage is measured in a similar way using a typical voltage divider to present a suitable voltage to the analogue to digital converter. A sealed lead acid (SLA) battery is used as the required energy density is low and SLA chemistry is potentially more stable under high temperatures. The battery voltage calibration is done locally at the sensor itself.

The system also contains a light dependent resistor (LDR) which is a simple way to monitor the integrity of the enclosure. The entire project is housed in a polycarbonate enclosure which is rather dark inside. If the LDR reports light levels above a threshold then it is likely the enclosure has been compromised and the electronics are now exposed to the elements. The LDR also uses a voltage divider to present a controlled analogue voltage into the A-D converter.

All analogue to digital conversion is done using a Texas Instruments ADS1115 four channel Analog to Digital converter (conveniently mounted on a breakout module by Adafruit). This uses I2C for communications with the microcontroller. These analogue readings (for pressure, battery voltage and light level) occupy three of the four channels on the ADS1115. The fourth channel is unused.

Environmental readings are made using a Bosch BME280 sensor (also conveniently mounted on a breakout module by Pimoroni). This is an I2C module which reports the temperature, humidity and atmospheric pressure.

The ADS1115 Analogue to Digital converter and the BME280 environmental sensor as well as various power supplies are all used on modules and mounted along with the PyCom module and IO connectors on a custom PCB.

The microcontroller is powered by 5 VDC. The environmental sensors are powered from the PyCom 3.3 VDC output. The submerged pressure sensor uses a dedicated boost converter to supply 24 VDC.

The enclosure and the separate solar panel are mounted on top of the tank with the panel facing roughly towards the North. The enclosure is mounted underneath the panel so the panel also serves to shade the electronics.

The following photograph shows the installation of the electronics module and solar panel on top of the tank.

Installation in progress

The sensor electronics were designed to fit in a Jaycar HB6132 weatherproof enclosure. The photo shown here is a preliminary fit of the PCB and battery in the enclosure. This shows the custom PCB with the various sockets for microcontroller, power modules, A-D converter and environment sensor.

Preliminary fit into sealed ABS enclosure.

Note the LDR located at the top of the PCB is used to measure ambient light inside the enclosure.

The connectors for the solar panel, sensor and battery are all identical 4 pin Molex connectors which we found excellent to use as they fit securely into the PCB and provide a strong mechanical connection. We used different pins on each so no incorrect connection is ever made if a plug is inserted into the incorrect socket. External connections to the solar panel and the sensor are made using IP68 rated connectors.

Waterproof connectors help keep moisture out.

Our custom PCBs are all designed using KiCad and fabricated in China. We had to design our own KiCad schematic symbol and PCB footprints for some of these generic modules such as charge controllers and boost converters. This is a straightforward exercise in KiCad but it does require careful measurement with a digital vernier to correctly locate pin connections and mounting holes. This is a one-off task as these library symbols and footprints can be used in subsequent PCB designs. The footprint measurements are available for modules such as the ADS1115 A-D converter or the BME280 breakout module as these are well documented by suppliers such as Adafruit or Pimoroni.

We used the PyCom LoPy4 module which supports Wi-Fi, Bluetooth, Sigfox and LoRaWAN. This project utilises only the LoRaWAN stack and the other communications stacks are deliberately disabled to conserve battery power.

The LoPy4 module is mounted on the custom PCB along with environmental sensors and power supply components. The PCB is then mounted on a backing board before being mounted in the polycarbonate enclosure. The backing board is 3D printed using PLA and sized to fit inside the Jaycar enclosure which is IP65 rated.

Several different 915MHz antenna types were tested. The 170mm rubber ducky antenna provided the best performance but was impractical to fit within the enclosure. The “wire” antenna ultimately selected provides reliable performance and fits easily within the enclosure. The backing board has been designed to accommodate a vertically mounted stubby antenna should better range be needed at subsequent tank locations. Antenna options are discussed later.

The software generates detailed status messages via the serial console but if the console is not connected, basic status information can be determined by the activity of the RGB LED on the microcontroller itself. The LED will cycle through various colours and patterns depending on the operation. It also reports error conditions via numerous red flashes.

Power Management

This sensor module operates from an internal 12 Volt 1.3 Amp Hour sealed Lead Acid (SLA) battery. The battery is charged by an external solar panel via the SLA charge module. The LoPy4 microcontroller is placed in deep sleep mode between each reading. This reduces the power consumption from 120-150 mA to below 1 mA.

The battery has been tested to run the system for several days with no charging. There is no low voltage disconnect so it is preferable to keep the battery topped up to prolong the life of the battery.

The sealed lead acid battery was chosen over other chemistries (such as LiPo or LiFePo4) as SLA is potentially more stable in the high temperature environment produced by direct exposure to the sun. Lead acid is also cheaper than the Lithium options.

PyCom LoPy4 Module Connections

The following pin connections are used on the LoPy4 module. This shows all external connections as used by the sensors, the power supply and the serial console (which may be connected for debug purposes).

Console Connection

A serial console connects to UART 1 on the LoPy4 module. This is used as debug output. The console port presents in a three pin socket on the outside of the enclosure. The pin numbers on the console port (J2) are as follows.

The console cable which connects to this port must crossover pins 2 and 3. The serial device (typically USB to Serial) must use 3.3 Volts. This serial connection is best made to a USB to serial adapter.

The PyCom microcontroller code does not use RX so this connection is optional. If the USB to serial module uses 5V (as would be used to connect to an Arduino) then the TX line should not be connected to avoid damaging the 3.3 V RX input to the PyCom module.

In a future build, we plan to use a Bluetooth serial module rather than a cable as it is inconvenient to connect a cable to the module located on top of the tank. A Bluetooth connection will allow for a more relaxed laptop location when any monitoring is needed at the sensor itself!

The serial console simply outputs debug messages and other status information as the LoPy4 module wakes up, connects to the network, takes the readings, transmits data and goes back to sleep.

Pressure Sensor External Connections

The following table shows the connections to the pressure sensor. This is the external three pin connection on the enclosure.

The pressure sensor air pressure equalisation tube opens inside this connector.

The LoRaWAN Data Payload

As well as the water level measurement, some local metadata and several environmental measurements are taken and reported. All the measurement data is packed into a byte array for transmission. The first character is a format identifier which details the composition of the subsequent structured data. Readings are typically taken in decimal and then processed by the microcontroller to produce a fixed length zero filled string. The various measurements are then simply concatenated before transmission.

Some of the measurements are mapped to a range suitable for transmission so the raw data may not instantly show temperature, water level or other measurements. These values must be processed by the receiver to extract the actual temperature, battery voltage, etc.

Table 2

The table [2] defines the structure of Protocol Format 2 data. Protocol Format 1 was used on the Gen 1 version of the sensor. As the Gen 1 sensor used a different data structure, the use of this Protocol Identifier ensures correct decode of the data by the receiver. It also allows for future changes without having to update any existing receivers.

The following shows the breakdown of a sample Format 2 message. The message payload as received from The Things Network and decoded is "219870C7D120732101011330E". This is 25 characters and is broken down as follows.

2 1987 0C7D 1207 32 1010 1133 0E

Analysis of a sample data message from the LoPy4 sensor controller module is shown in table [3].

Table 3

Connecting to TTN and Transmitting the Data

The pressure measurement along with related metadata is transmitted by the LoPy4 module via LoRaWAN. In Australia, LoRaWAN uses either the 915MHz (AU915) or 923MHz (AS923) ISM frequency band. The LoPy4 module uses 915MHz and may operate on any of the eight defined channels within this band.

The LoPy4 module wakes up from deep sleep based on an internal timer and attempts to connect to the LoRaWAN network through the local gateway.

The first time this happens, the security exchange will occur and the network “join” will occur. The LoPy4 module can then retain the negotiated security keys in non volatile storage so the join does not need to be repeated every cycle. Uplink transmission can occur anytime providing the client node does not violate the allowed airtime.

Once the join has occurred, subsequent transmissions are essentially a “fire and forget” approach as there is no guarantee of delivery to TTN. Redundant TTN gateways can be implemented to improve the connection reliability. In this case, the uplink transmission may be seen by multiple gateways; all of which will forward the message to TTN.

Although the LoRaWAN network does support limited downlink communications, this is not presently used. In this mode of operation (Class A) a small receive window is opened by the LoPy4 node following each uplink transmission. The network may transmit to the node only during this limited timeslot.

This was tested during development but the timing was too variable to reliably receive a downlink message during the open window.

Australia has embraced LoRaWAN technology and is now one of the leading adopters of the technology outside Europe. Unlike other IoT networks, TTN is a community network, where gateways can be provided by and used by anyone; essentially free of charge.

Australia even has its own entry point to TTN, thanks to the services provided to the community by Andrew Maggio and his team at Meshed Networks.

Receiving Data from The Things Network

Data transmitted via LoRaWAN from the tank sensor on the tank is received by the local LoRaWAN gateway and forwarded via the Internet to The Things Network (TTN).

Once the application and the client (LoPy4 microcontroller) are registered with TTN, the required API Key is generated. After subscribing to the “application” on TTN, using the API Key, data from any client node registered with that application is received. TTN provides lots of metadata, including the name of the gateway(s) that received this data and the signal strength seen by each gateway. This metric is really useful when comparing the performance of different antenna types on the sensor.

The network metadata and sensor payload is presented from TTN as JSON payload. This JSON format makes it very easy to parse; particularly with Python. A sample of the JSON message is shown here.

The “payload” field is the original data payload from the LoPy4 microcontroller. It is encoded as Base 64. Once unpacked the original payload is available.

  "gw_id": "kel-west",
  "payload": "QLEdBiaAAAACKCxHMJm60y+L/
  "lora": {
    "spreading_factor": 12,
    "bandwidth": 125,
    "air_time": 1810432000
  "coding_rate": "4/5",
  "timestamp": "2021-07-14T02:21:49.920Z",
  "rssi": -83,
  "snr": 10.5,
  "dev_addr": "26061DB1",
  "frequency": 918200000

We used a Python script running on a cloud server to manage all the data connection, unpacking and data logging. This script could run anywhere – even on a Raspberry Pi as long as it has Internet access. We also hosted InfluxDB and Grafana on the same server so the data could be recorded, graphed and presented in a GUI. This Python script is called “TankDataWriter” and does the following.

  • Subscribes to TTN to receive the data. Data arrives about every hour based on the sleep timer in the LoPy4 module.
  • Unpack the Base64 data and recover the original measurements.
  • Write selected data values to the Influx real time database.
  • Examine the water level sensor values received and if within a defined range, republish the water level. This water level message is subscribed to by the pump controller so the pump can be stopped or started as needed. (More on this in Part 2). If the pressure reading falls outside the defined range, it indicates an error with the sensor. This triggers a Telegram Alert message to advise us of a possible problem with the sensor.

Of course, the pump controller itself could subscribe to TTN and directly retrieve the water level messages but this design has a couple of benefits. It reduces the complexity of the pump controller software by removing the need to subscribe to two separate brokers.

It also removes the need to decode the messages, but more importantly, the intermediate script allows several other uses of the sensor data; notably the dashboard and the environment monitoring. The water level data republished by the script is a short JSON message which contains just the data needed by the pump controller.

Rather than use breadboard or other prototyping boards, all of the modules were built using their own custom PCB design. In total there are three separate custom PCB designs. These are the LoPy4 based tank sensor; the Raspberry Pi based pump controller and the PiZero based remote switch.

Each module was prototyped on the bench using breadboard before the schematic and the PCB were finalised. The schematics and PCB designs were all done using KiCad. We sourced all the components and did all assembly in house.

This included some surface mount components on the pump controller. The use of a custom PCB makes for a much more reliable electronics module and is actually much less daunting than many may think.

Hardware and Sensors Used in this Project

The following hardware is used to build the tank top LoRaWAN sensor. The major components are sourced locally from suppliers such as Core Electronics, RS Components and Jaycar. Some of the generic modules are sourced from the usual Chinese suppliers such as Ali Express, Banggood or from eBay.


PyCom LoPy4 microcontroller.

Submersible pressure sensor

This is a generic 24 VDC 4-20 mA submersible pressure sensor with a maximum depth of 5 metres. The sensor is mounted in a custom made stainless steel frame to orient it correctly in the bottom of the tank.

I purchased my sensor from eBay, model number 478526, and a label that states TL-MPM-70G, 0 ~ 5M, 4 ~ 20MA, 24 VDC.

According to the seller, the specifications include:

Measurement Range: 0-5mH2O/50kPa;

Measurement Medium: Water;

Power Supply: 24VDC;

Output Signal: 4-20mA;

Accuracy: ±0.5%FS;

Overload Capacity: Two times full-scale pressure;

Using Temperature: -20°c to 120°c;

Compensation Temperature Range: -10°c to 80°c;

ZTC/STC: (typical): ±0.02%FS/c

Long-term Stability: (typical): ±0.1%FS/year;

Waterproof Class: IP68;

Load Resistance: less than (U-10)/0.02Ω;

Shell Material: 316L stainless steel;

Environmental sensor

Pimoroni (PIM472) BME280 Temperature, humidity, and barometric pressure sensor breakout. This uses an I2C interface.

Ambient light sensor

Generic LDR with a resistance range between about 100 Ω in sunlight and 100 KΩ in darkness. A voltage divider is used to create about 3.0 V under full light.

Battery voltage sensor

This is another simple voltage divider setup to create about 3.0 V when the battery supply is at about 13.2 V. This circuit is permanently connected across the battery. The resistance values used are 15 KΩ + 4.7 KΩ for a total of 19.7K. This suggests a theoretical drain of about 0.5 mA.

The battery discharge has been measured at about 2.3 mA during deep sleep.

Analog to Digital Converter Module

Adafruit (ADA1085) ADS1115 16bit 4 channel Analog to Digital converter module. This also uses an I2C interface.

Sealed Lead Acid Battery

Jaycar (SB2480) Compact 12V 1.3 Amp Hour sealed lead acid battery.

SLA Battery Charge Module

SDLA12TA Solar Charge Controller. This is a generic module.

Solar Panel

Generic 10 Watt solar panel.

Boost converter for 24 Volt supply

Generic XL6009E1 Adjustable DC-DC Boost Converter.

LoRaWAN Antenna

Several different antennas have been tested. Each providing a different gain. The mounting plate inside the enclosure has been designed to mount a short antenna inside the enclosure. The antenna is discussed in more detail below.

Polycarbonate enclosure

Jaycar (HB6132) IP65 rated weatherproof sealed enclosure. This has threaded brass M2.5 inserts so the PCB mounting plate can be screwed into place.

Mounting plate inside the enclosure

This is a custom designed 3D printed (PLA) mounting plate designed to locate the battery, mount the PCB and provide mounting support for a variety of internal 915MHz antennas.

PCB to mount all electronics inside enclosure

This is a custom made PCB designed in KiCad and fabricated in China. It mounts on the mounting plate using PCB standoffs.

Wiring harness and connectors in enclosure

Hand made using generic connectors from RS Components and Jelen SP series connectors.

Remote console

This is a generic USB to Serial module. It must use 3.3 volts on the serial connection to match the LoPy4 module. This is only connected when debug output is needed.

Antenna Options

The following different antenna types were tested during development.

  • 17cm hinged (right angled) rubber ducky omnidirectional antenna. This was an unbranded antenna but appears to be a 2dBi unit. Some of these are identified as dipole antennas.
  • PCB dipole
  • Single wire
  • 4cm rubber ducky

The gateway reports the received signal strength of each received message and this was used to obtain a comparison between different antenna types. The best performing antenna was the 17 cm rubber ducky antenna but this was too large to use inside the enclosure.

The production solution uses the single wire antenna as can be seen in the photograph of the completed enclosure. This provides -83 dbm to the production gateway which is entirely adequate for LoRa. The distance between the tank and the current gateway is about 100 metres, but through several trees and low buildings, so not an optimal line of sight for LoRa.

Writing Data to InfluxDB

InfluxDB is an open source time series database which makes it ideal for logging time based events such as water level, temperature, pressure and such. It is not a relational database and does not need pre-defined fields in the database.

Each record written to the InfluxDB time series database must adhere to a specific format, with “tags” and “fields” and an optional timestamp. We used the metadata such as sensor name for the tag and the actual metrics as the fields. As TTN provides a timestamp in the JSON data we used this as our record timestamp.

The tag is used when selecting records for use in a graph. Rather than use the LoRa EUI of the device or the device name assigned in the TTN application, we use a locally defined “friendly name”. The friendly name can be a simple tank name such as “HouseTank”. This decouples the actual sensor name from the data recorded in InfluxDB which means the sensor hardware can be changed (in the event of a sensor failure) and the data will continue to be recorded against the same tank.

The friendly name is assigned against the TTN assigned Device Name in the YAML configuration file. This allows the script to look up the friendly name and use it as one of the tags when writing influx data. The TTN Device Name and the LoRa EUI are also recorded as tags. These come from the metadata in the message received from TTN. Whenever the sensor is changed by installing new hardware or by a reconfiguration in the TTN application, the YAML file should be edited to ensure the new device carries forward the same friendly name.

While the tag size in InfluxDB can be quite large, we keep the friendly name to about 20 characters (such as “HouseTank”).

The Grafana Dashboard

The water level is shown on a Grafana dashboard, which is an open source graphing tool that runs on various platforms, and integrates well with InfluxDB. We will run it on the same cloud server that hosts InfluxDB and python scripts.

The screenshot shows the dashboard with the various graphs. The most valuable data here are the Water Level and the Historical Water Level and the Battery Voltage. The environmental readings are just of interest.

Future Enhancements

This build is Generation 2 and already a number of improvements are under consideration for the Generation 3 version of the tank level sensor. These include the following.

  • The existing 1.3 Amp Hour SLA battery provides way more capacity than really needed. This may be reduced to a lower capacity battery, along with the subsequent reduction in enclosure volume and solar panel size.
  • A power on reset circuit will be introduced to hold the PyCom module in reset while the power stabilises. This is required as the controller does not always start when power is applied by connecting the battery. This is resolved today by pressing the reset button on the controller if this happens. As it will not occur once initial power is applied this is a low priority.
  • A Bluetooth console will be introduced to save the inconvenience of connecting the console cable during testing. This Bluetooth console may only be powered up when the PyCom module is operating. A more advanced version of the Bluetooth console may be built using an ESP32. This would also double as a watchdog timer and log repository.
  • The fourth channel on the Analog to Digital converter may be used to monitor the 24 VDC to the pressure sensor. This would be checked when the 24 V boost converter is powered up to confirm the power supply does not drift.
  • A more sophisticated dashboard is needed to centralise the water level, pump status and other alarm conditions. The current Grafana dashboard is excellent for presenting water level and environmental readings, but additional information such as pump status, alarms and some log messages should also be displayed. We are optimistic that Home Assistant can provide the framework for this capability.

The first of the tank top sensors has been in production since July 2021 and has performed extremely well. The occasional transmission is missed (about 1 in 30) and the back end code has been written to accommodate this. Apart from missing a dot or two on the graph, this has no impact on the operation.

NEXT MONTH: Part 2 - Pump controller & remote switch

Reading & Resources:

Ashley Woods

Hobbyist, hardware hacker and recently retired IT Network Engineer