You have a soil sensor working on the bench. Then someone asks a reasonable question: "When should it tell me to water my plant?" For a team developing a smart planter or an educational kit, this is where the prototype needs more than a changing number. The person using it has to understand the reading, set a reminder and recognize when the sensor is not ready.
We built a small device that puts those decisions on the device itself: a soil probe supplies the reading, a physical slider sets the threshold, and a small screen shows both, with an LED and a buzzer to prompt the user. The assembly is a useful integration example. Our recorded run also exposed a calibration failure that has to be handled before the device goes to anyone else.
It is a watering reminder; there is no pump. And because of that failure, our run does not establish reliable plant-care performance. What it does show is how to work through the interface between a sensor and the person making the decision.
Start with the decision, then give the number a meaning
A slider is easy to understand when its effect is visible. Raising the threshold should make the reminder trigger at a higher displayed moisture level; lowering it should make the device wait longer. Showing the current reading next to the threshold lets the user see why the light came on.
This is a real source of confusion beyond prototypes. A Home Assistant community thread about a Zigbee soil moisture sensor includes a March 2026 question about a dry flag not following the warning threshold, and a September follow-up about telling soil moisture apart from air humidity. Those reports are about a different device, but they show why the meaning of a value matters as much as displaying it.
Our build combines an NE555-based capacitive soil probe, a slider potentiometer, an SSD1306 OLED, a passive buzzer and an LED module on a Raspberry Pi Pico (RP2040) GraftPort carrier. The probe's two calibration references define a relative scale. A value of 40 on that scale is not proof that the pot holds 40% water by volume, and it is not a universal watering instruction for every plant.
Keep the controls visible while you assemble
The carrier's labeled connectors let us build the interaction from modules before designing a dedicated board:
| Module | Carrier connector | Role |
|---|---|---|
| Soil probe | AIN0 | Analog sensor input |
| Slider | AIN1 | Adjustable reminder threshold |
| OLED | I2C0 | Reading, threshold and state |
| Passive buzzer | DIO1 | Audible reminder |
| LED | DIO0 | Visible reminder |
These are carrier connector names, not RP2040 GPIO numbers. Use the matching board configuration and module pin labels when reproducing it. Our OLED answered at 0x3c; confirm the address on your own module.
The probe has to reach the growing medium without making the display or the slider awkward to use. Keep the slider on a separate module and cable during layout trials, until the preferred control position has been tried with a user. Light and sound give two ways to notice a reminder, and they raise their own question: will the device sit on a desk, in a classroom or next to someone sleeping? Acceptable brightness and sound need a trial in that setting.
The parts sit on a perforated base inside an acrylic case held with M3 screws. Keep the slider, the button, the charging connection and the probe lead reachable. An open assembly that works says nothing about whether the final enclosure tolerates splashes from watering. Two practical details: on one of our power cables red was ground and black was positive, so check polarity at the connector, never by color; and on this carrier, RUN switch 2 must be on when no external watchdog module is fitted. The battery module's charge indicator does not tell you how long the device runs between charges.
Make calibration an understandable part of startup
At startup the firmware enters dry-reference calibration and collects five samples. Holding the button for at least two seconds and releasing it confirms that stage. The wet-reference stage then collects its own five samples, and a second confirmation starts normal monitoring.
The prompts refer to dry air and to water or moist soil. Protect the probe electronics and connectors; the prompt is not permission to submerge the whole board. More importantly, those two endpoints define only the relative scale. The watering threshold still has to be chosen for the intended pot, medium and use.
Two implementation details matter for anyone reading the code. The five samples belong to each calibration stage; normal readings are not averaged over five samples. And the moisture check runs every two seconds, while shorter task intervals serve the button and display. A short button press pauses or resumes monitoring and turns the alarm off while paused. The long press confirms calibration on release; it is not a "recalibrate any time" command.
Read the failure message before trusting the percentage
The most useful record from our run is the console log. It shows both the dry and the wet references recorded as 65535, followed by "divide by zero" errors on every moisture calculation. Completing the calibration screens did not establish a valid scale.
The driver divides by the distance between the two reference values, and when they are equal that distance is zero. That explains the arithmetic error. It does not explain why both readings sat at 65535, the top of the ADC range. We have not established whether wiring, configuration, input range or something else caused it.
For a user-facing version, an invalid reading needs its own visible state. Our task prints the read error and carries on, and it can keep showing the previous moisture value. A reassuring "Normal" on screen, based on stale data, would be misleading. The fix we would make is to reject calibration when the two references are equal or implausibly close, and to show a calibration or sensor error instead. We have not tested that change yet.
Run the interaction test in small steps
Before testing thresholds, log the probe's raw readings in the two reference conditions. Confirm that they change and that the endpoints differ. If both stay at the same extreme, investigate the input path first; no slider setting can repair an invalid scale.
Once calibration works, move the slider through the current reading and watch the OLED, LED and buzzer together. The comparison in our code is simply "moisture below threshold", with no separate clearing threshold. If the alert chatters near the boundary, a small dead band or a persistence delay is a reasonable next revision, to be tested rather than assumed.
Then ask someone unfamiliar with the build to explain the displayed value, adjust the reminder and recognize an invalid reading. Note where their explanation differs from the intended behavior, and repeat with the probe installed the same way in the target pot each time.
Before a user handoff, make the relationship between sensor, threshold, display and alerts dependable: reject invalid calibration, make sensor faults visible, check behavior after a restart, and keep water away from the electronics while leaving the control reachable. A person should be able to tell whether the device wants attention because the pot seems dry, because the threshold changed, or because the sensor needs checking.