Arduino soil moisture data logger for extended remote usage

Tool Concept

Primary problem statement:
I am a farmer and I want a tool to record observations on my farm because a rich recorded history leads to more informed decisions.
Read more about this problem statement


This is a simple soil moisture data logger using an Arduino Uno with a power-controller circuit to regulate connection between a battery pack and the Arduino. It has a battery life of months and is suited for remote data collection.
Documentation Wiki: 


This data logger records soil moisture levels using a corrosion-resistant capacitance sensor at a set frequency and stores those values on an SD card. The power-controller circuit between the battery pack and the Arduino Uno greatly extends the battery life to many months, allowing for long-term data collection that can help elucidate soil-water dynamics across a field. This design is modular and other Arduino-compatible sensor types could be used in place of the soil moisture probe.


I recently conducted my senior thesis exploring how these sensors can help parse zones of similar soil behavior--with regard to soil-water dynamics and static characteristics like texture and SOM--across a field. While that may not be of immediate interest to most farmers, the design I arrived at for this data logger can be applied to gather other types of data over long periods of time in remote conditions.

How it works:

This design was drawn largely from work done by Alan Mitchell, which is now slightly outdated given the development of new modules by Adafruit. The explanation of how the circuit works remains the same as he describes here; however, instead of the PIC I just used the Adafruit TPL5110 Low Power Timer Breakout board.

Expand the reference thumbnail (or look in the gallery, but I can't seem to embed the image here) to see the circuit schematic with a functional description.

List of materials, prices, sources:

Additional tools required include a 40W soldering iron station, solder (I prefer lead-free), wire cutter, and wire stripper.


Building the tool:

@jennajane has already uploaded a nice guide/overview on how to set up the Arduino Uno with the Adafruit SD data logger shield. Adafruit has their own picture guide for this available here, which I found helpful. Additionally, you'll want to set up the real time clock via the same tutorial and format your SD card to FAT16 or FAT32 using the official SD card formatter

If using the Soil Watch 10 soil moisture probe, solder the green wire to a GND pin on the shield, the white wire to an analog pin (A0-A5), and the brown wire to a digital pin (0-9; 10-13 do not work with this shield).

The power-controller circuit is the most annoying part to build, so I opted to use a solderless mini breadboard to speed up the assembly process. While this makes wires in the circuit a little vulnerable to falling out, I had no issues with this during my field usage of these prototypes. Simply arrange the power timer, boost converter, necessary wires, the capacitor, and the resistor on the breadboard as per the above schematic, and you're good to go. The period of the power timer module is set by the orientation of the screw head--all the way to the left (counterclockwise) means the module will drive the enable pin high once every 100 ms, while all the way to the right (clockwise) is once every 2 hours. 

Some kind of enclosure will be necessary to weatherproof the unit. I opted to use a Glad food container with a silica gel packet to control moisture and silicone sealant for the edges and the opening slit cut for the moisture probe itself. I'm sure someone here could come up with a more elegant solution, but this did the trick for me. I recommend adhering the mini breadboard to the wall of the enclosure so it is less likely to move around and dislodge a wire.

Here is the power-controller from a closer view so it may be more easily recreated.

Arduino sketch:

I used the following sketch to record and save moisture measurements to the SD card.

#include "SD.h"
#include <SPI.h>
#include <Wire.h>
#include "RTClib.h"


const int soilPin = A0;
const int soilPower = 4; // to be compatible with SD data-logger shield, must be any digital pin other than 10-13
const int powerCtrl = 7;
int moisture = 0;

const int chipSelect = 10;
File logfile;

const char* filename = "sensor02.csv";

#define redLEDpin 2
#define greenLEDpin 3

void setup() {
 pinMode(soilPower, OUTPUT);
 digitalWrite(soilPower, LOW);

 pinMode(powerCtrl, OUTPUT);
 digitalWrite(powerCtrl, LOW);

 pinMode(10, OUTPUT);

 pinMode(redLEDpin, OUTPUT);
 pinMode(greenLEDpin, OUTPUT);

 if (!SD.begin(SS)){
   digitalWrite(redLEDpin, HIGH);

 logfile =, FILE_WRITE);
 if (! logfile) {
   digitalWrite(redLEDpin, HIGH);

 if (!RTC.begin()) {
   logfile.println("RTC failed");

void loop() {
 int moistureValue = readSoil();
 DateTime now;

 digitalWrite(greenLEDpin, HIGH);

 uint32_t m = millis();
 if (logfile) {
   logfile.print(", ");

   now =;
   logfile.print(", ");
   logfile.print(now.year(), DEC);
   logfile.print(now.month(), DEC);
   logfile.print(, DEC);
   logfile.print(now.hour(), DEC);
   logfile.print(now.minute(), DEC);
   logfile.print(now.second(), DEC);

   logfile.print(", ");

 digitalWrite(redLEDpin, HIGH);
 digitalWrite(redLEDpin, LOW);


 digitalWrite(powerCtrl, HIGH);

int readSoil() {
 digitalWrite(soilPower, HIGH);
 moisture = analogRead(soilPin);
 digitalWrite(soilPower, LOW);
 return moisture;


A final note:

The values returned here are integers proportional to the voltage returned by the moisture probe. Multiply this integer by (5/1023) to return the original voltage value. That voltage can be converted into volumetric water content via one of the following calibration curves provided to me by Pino-Tech

2 users have voted.
0 users have voted.