Skip to content
experience

Stopped driving round checking troughs. LoRa, an ultrasonic sensor and far too much silicone

Hamish Turner@hamish_on_the_farm

July 16, 2026 · 3 min read

Kia ora. Been lurking a while, figured I owe the place a build post since half my setup came from people here and YouTube.

Background: 400 cows on about 160 ha just out of Matamata. Water is everything. A trough that runs dry on a hot day in January is a proper problem, and a leaking one wastes thousands of litres and turns a paddock into a swamp. For years the job was: ute, every morning, every trough. About 45 minutes I didn't have.

Last winter I decided to fix it. I'm not a programmer. I'm a farmer who watched a lot of videos and swore a lot.

Arduino board with resistors, LEDs and a relay (stock photo, mine is far grubbier)

What's out there now

  • Sensors: 9 nodes on the troughs and the two big tanks. Each one is an ESP32 LoRa board (the Heltec style ones, about NZ$45 each landed) and a JSN-SR04T waterproof ultrasonic sensor looking down at the water.
  • Power: one 18650 cell and a little 1 W solar panel per node. The ESP32 wakes every 15 minutes, takes 5 readings, sends the median, goes back to deep sleep. Batteries haven't dropped below about 70% even through winter.
  • Gateway: one LoRaWAN gateway on the dairy shed roof, up a 6 m pole made from an old irrigation pipe. Furthest trough is about 2.3 km away over a small hill and it still gets through most of the time.
  • Back end: ChirpStack and Home Assistant on an old Dell desktop in the shed office. Home Assistant sends a phone alert if a trough drops below 30% or falls faster than it should (leak), and the missus gets the same alerts so it's not only me.

Things I learnt the hard way

  1. Cows lick everything. First enclosure was a nice grey box with cable glands. Gone in a week. Now the box sits inside a bit of 100 mm PVC pipe with an end cap, bolted to a waratah, and the cable runs down inside the pipe. Ugly as. Works.
  2. The ultrasonic sensor hates condensation. Readings went mental on cold mornings. A little hood over the sensor and taking the median of 5 readings sorted most of it.
  3. The sensor has a dead zone. The JSN-SR04T can't read much closer than 20-25 cm, so mount it high enough above the full water level or a full trough reads as garbage.
  4. Deep sleep is everything. First version stayed awake and flattened the battery in two days. The trick is making sure the sensor is powered off too, I switch it through a little MOSFET.
  5. Silicone, cable ties and more silicone. No apologies.

The bit of the code that took me longest, for anyone doing the same (Arduino IDE, cut down):

#define uS_TO_S 1000000ULL
#define SLEEP_SECS 900   // 15 min

void setup() {
  pinMode(SENSOR_PWR, OUTPUT);
  digitalWrite(SENSOR_PWR, HIGH);   // sensor on
  delay(300);                       // let it settle
  int cm = medianOf5();             // 5 pings, sorted, take the middle
  digitalWrite(SENSOR_PWR, LOW);    // sensor off before we sleep

  sendLora(cm);                     // see the LMIC examples
  esp_sleep_enable_timer_wakeup(SLEEP_SECS * uS_TO_S);
  esp_deep_sleep_start();
}

void loop() {}  // never gets here, deep sleep restarts from setup()

It's not pretty but it's saved me the 45 minute drive every morning since spring. Last summer it caught a broken ballcock at 2 am that would have drained the main tank by milking. Paid for the whole thing that one night, eh.

Happy to answer questions. Not a programmer, just stubborn.

Get the best of Dynamo Geeks weekly

One email each Monday with the most useful posts. No spam; unsubscribe in one click.

Comments

10

Sign in to join the conversation.

Sign in to comment
Matt O'Brien@pi_tinker_matt
Hamish you legend, finally! the PVC pipe enclosure is genius, cows are worse than possums and I say that as a man who lost a weather station to a possum 😅 one q: what's the gateway backhaul, 4G or does the shed have fibre?
4 net votes
Hamish Turner@hamish_on_the_farm
cheers mate. shed's got a fixed wireless link off the house, rural internet being what it is. and at least our cows don't follow the Wallabies 🏉
4 net votes
Matt O'Brien@pi_tinker_matt
low blow. accurate, but low
5 net votes
Leo Chen 陈立@szhw_leo
Good build. One problem: if you do OTAA join every wake up, you send join request every 15 min. Use more battery and network don't like it. Save session in RTC memory (RTC_DATA_ATTR) and only join again after power loss. Can, very easy.
2 net votes
Hamish Turner@hamish_on_the_farm
yeah nah you're right, the code above is cut down. learnt that one the hard way too, first week the battery drain was way worse than it should've been. it keeps the session in RTC memory now. chur Leo
2 net votes
Daan Visser@daan_fpga
The MOSFET to cut the sensor power is the detail most people miss. Those JSN boards draw a few mA even idle, a little bit annoying with an 18650 budget. Which MOSFET? A logic level P-channel on the high side?
3 net votes
Hamish Turner@hamish_on_the_farm
AO3401 I think, Leo sent a bag of them with the last order. high side yeah
3 net votes
Karthikeyan S@karthik_embedded
Machi this is proper field engineering. Condensation and median filter, exactly what we see on borewell level sensors in Tamil Nadu farms. One more tip: check battery voltage before transmit. When the 18650 is low, the radio TX pulls the voltage down and the ESP32 brown-out resets in a loop.
5 net votes
Hamish Turner@hamish_on_the_farm
good tip, will add. sweet as
2 net votes
Gwen Albright@gwenprints
Cows licking everything is my new favourite engineering requirement (right up there with "must survive a toddler"). If you ever want a printed sensor hood I'd happily send STLs (print it in ASA, not PLA, PLA will warp in your summer sun (ask me how I know)).
1 net votes