4 min
Building a Little Soil-Moisture Sensor, from Wiring to the Cloud
The steps I followed to build a small soil-moisture sensor with a Wemos board: wiring it up, reading the sensor through the ADC, turning the value into a percentage in firmware, and sending it to ThingSpeak.

These are the steps I followed to build my little soil-moisture sensor, from the hardware all the way to the cloud.
Hardware
I used a jumper cable (three wires) to connect the sensor to the Wemos. The jumper has to be the male-to-male type.

Then I connected the wires following this logic:
| Wemos | Sensor |
|---|---|
3V3 | VCC |
GND | GND |
A0 | AOUT |

Once everything was connected, I took a cable with a micro-USB-B connector for the Wemos, with the USB-A end going to the laptop. This way the laptop both powers and manages the sensor over USB.
The 3.3 V supplied by the Wemos powers the sensor, and GND closes the circuit
both for the power and for the sensor's AOUT output. GND is what closes the
circuit (ground, the common return).
The sensor generates a voltage proportional to the moisture in the soil. Soil is
a conductor, and its electrical conductivity changes with how wet it is. As the
moisture changes, so does the conductivity, and the sensor's electronics turn
that variation into an analog voltage on the AOUT pin.
For developing and calibrating it, the laptop is enough. In the finished build I later moved the Wemos into a small weatherproof box powered by a USB power bank.

From analog to digital: the ADC
AOUT is connected to the A0 pin of the Wemos. Behind that pin sits an
analog-to-digital converter (ADC) that converts the voltage (a binary
sequence) into a whole number, for example:
633

A0 pin feeds the onboard ADC.Firmware
At this point the values coming out of the ADC are processed by the firmware, code written in C++ that converts the voltage into a percentage through a linear transformation. These are the tests I ran:
- 270 → maximum moisture. I got this value by putting the sensor in water
(100 % humidity). With wet soil the resistance is low, and
A0reads a voltage close to 0 V. - 633 → maximum dryness. I got this value with the sensor dry (0 % humidity).
With dry soil the resistance is high, and
A0reads a voltage close to VCC.
From these two points the percentage comes out of a simple linear formula:
633 − reading
humidity % = ─────────────────── × 100
633 − 270
A reading of 270 gives 100 %, a reading of 633 gives 0 %, and everything in between falls on a straight line. In C++ it is just a few lines:
const int WET = 270; // sensor in water → 100%
const int DRY = 633; // sensor dry → 0%
float readMoisture() {
int raw = analogRead(A0);
return (float)(DRY - raw) / (DRY - WET) * 100.0;
}
Network and cloud
Once the percentage is ready, the firmware makes an HTTP call to the ThingSpeak API, which shows the percentage values on a line chart in its dashboard.

And that is the whole path: the soil changes the sensor's reading, the ADC turns it into a number, the firmware turns that number into a percentage, and ThingSpeak turns the percentage into something I can watch from anywhere.