Building a wireless plant soil moisture monitoring system using ESP-IDF and ESP32-C3
If you have have house plants, you probably have some issues with them. For example, ours seem to get brown and perish after a couple months. If you look online, they most common reason for brown leaves is either overwatering or underwatering (!).
So, to understand what’s the issue, I decided that I want to monitor the soil moisture more scientifically. I looked into commercial soil moisture sensors, but they are either a) unreliable or poorly made, or b) way too expensive (around 25–35 euros per sensor). Since we have about 10 plants, the cost would be quite high.
The hardware
So what’s the solution? Rolling your own of course! A friend of mine linked me to a new ESP32-C3 from Seeed Studio which seemed to contain all the bits I wanted: WiFi, a few ADC GPIOs and last but not the least, a battery charging controller (I wanted the sensor pods to work on battery power to facilitate easier placement).
I also scoured AliExpress for the sensors and found a simple soil moisture sensor for 77 cents a piece. I also bought a few 1200 mAh lithium polymer batteries that seemed a reasonable compromise between capacity and size.
The firmware
Finally, the ESP32 needs software. I had some previous experience with ESP-IDF so I figured out it’s a good start (I wanted something that’s easy to build and compile without extensive IDE setup and Git repository friendly).
I already had in mind where I wanted to store the moisture information in: InfluxDB. Home Assistant comes with an InfluxDB server add-on, so getting it up and running is extremely simple. All you need is an InfluxDB database, username and password.
In fact, cobbling together some ESP-IDF example codes resulted in getting something that’s able to read the analog sensors easily and send the data via HTTP to a local InfluxDB:
So, next it was up to build some sensors. The ESP32 has two AD controllers, 1 and 2. The first controller is connected to D0-D2 and the second to D2. In this case, to make it easier, I opted to connect three sensors per sensor pod.
Putting it together
It was time to start building. I decided to use a bit of prototyping board to mount JST-XH connectors (the same as on the sensor side) so I can disconnect and reconnect the sensors. The sensors take in 3.3V and ground and output 0–3.3V through the third connector. The 3.3V and GND are connected between all the sensors and the third pin is connector to the D0-D2 pins.
I also used 2 pin JST-XH connectors for the batteries so they can be unplugged.
I ordered quite small cases (63 x 57 x 35mm) in the beginning, guessing that everything fits in. But unfortunately they turned out to be too small to accommodate the short USB extension cables (for recharging). So slightly larger cases needed to be ordered (115 x 90 x 55mm).
The sensors themselves are connected via 26 AWG wire and wrapped in a braided cable sheath (4mm).
While waiting for the new cases, I decided to update the code by adding MAC-based station configuration via a configuration URL. Home Assistant was able to host the configuration text file without much trouble.
Finishing the build
After the new cases, all was needed is to put the hardware inside the box and charge the batteries. I also did some fixes to the firmware, including UDP syslog, improving the NTP time sync and updating ESP-IDF from 5.0 to 5.1.
Now every unit sleeps for an hour in deep sleep, wakes up, reads the ADCs and submits the information to InfluxDB via a HTTP request. I opted to send raw numbers to InfluxDB, since I can do the dry-moist mapping there. No need to involve the firmware in that. This is how my dashboard looks like:
Bill of Materials
Build your own
I’ve placed the code here alongside with the instructions if you want to build your own: https://github.com/rosmo/plant-monitoring