Smart Plant Care! Build a Qwiic Soil Moisture Sensor System
Introduction
Have you ever wanted your plants to tell you how they're feeling? While we might be a ways away from understanding or communicating with plant consciousness, we can tell if they're thirsty or not, and with the SparkFun Soil Moisture Sensor, you can do just that! This tutorial will show you how to take soil moisture readings and then display those readings on an OLED as a happy, meh, or sad face, depending on how wet or dry the soil is.
Materials
Required Materials
To follow along with the project at the end of this tutorial, you will need the following. You may not need everything, though, depending on what you already have and which sensor you prefer. Add it all to your cart and modify as necessary.
Note: The 9V battery isn't suitable to keep plugged in for long periods of time. With this current configuration, the project will last plugged in for about a day. We recommend only powering the project when you want to see how your plant is feeling!
Hardware Setup
The hardware setup for this project is super straightforward. Attach the Qwiic Soil Moisture Sensor to the Qwiic OLED via a Qwiic Cable and then attach the OLED to the Redboard. We used a 9V battery and 9V battery holder to power this project so that we could keep it portable, but you could use a portable charger or hook it up straight to your computer depending on your use case and availability of parts on hand. We also used some screws and a 3D-printed base plate to keep the display and sensor together, but that is also not necessary. So simple!
Calibration
System Calibration To get any sort of useful data out of your Soil Moisture Sensor, it is advised that you calibrate it to whatever soil you plan to monitor. Different types of soil can affect the sensor, and you may get different readings from one composition tot he next. Before you start storing moisture data or triggering events based on that value, you should see what values you are actually getting from your sensor. Using the sketch above, note what values your sensor outputs when the sensor is completely dry vs when the sensor is completely submerged in a shallow cup of water. Depending on what microcontoller you're using, the operating voltage of that microcontoller, and the resolution of its analog-to-digital converter, you're results will vary.
For example, using the same circuit above, if I detach the VCC pin from D7 and attach it directly to the 5V supply on the RedBoard, you'll see the close to the following values in the serial monitor when the sensor is dry (~0) and when it is completely saturated with moisture (~880).
Code
The code for this project is really simple, just download the Arduino libraries for the products used and past the code below into the terminal! Make sure to adjust the moisture values to suit your plant's needs. The values used below seem to work pretty well for my money tree, which is a pretty low-fuss plant.
#include <Wire.h> #include <SparkFun_Qwiic_OLED.h> #include <res/qw_fnt_5x7.h> QwiicMicroOLED myOLED; #define COMMAND_GET_VALUE 0x05 const uint8_t qwiicAddress = 0x28; uint16_t ADC_VALUE = 0; const int dryValue = 1023; const int wetValue = 400; void setup() { Serial.begin(115200); Wire.begin(); while (myOLED.begin() == false) { Serial.println("OLED not connected, check wiring!"); delay(1000); } testForConnectivity(); } void loop() { int moistureValue = getMoisture(); displayMoisture(moistureValue); delay(1000); } int getMoisture() { get_value(); return map(ADC_VALUE, dryValue, wetValue, 0, 100); } void get_value() { Wire.beginTransmission(qwiicAddress); Wire.write(COMMAND_GET_VALUE); Wire.endTransmission(); Wire.requestFrom((uint8_t)qwiicAddress, (uint8_t)2); if (Wire.available() >= 2) { uint8_t ADC_VALUE_L = Wire.read(); uint8_t ADC_VALUE_H = Wire.read(); ADC_VALUE = (ADC_VALUE_H << 8) | ADC_VALUE_L; } } void displayMoisture(int moistureValue) { myOLED.erase(); if (moistureValue < 30) { // Happy Face when well-watered myOLED.line(20, 0, 30, 0); // Left eye myOLED.line(40, 0, 50, 0); // Right eye // Smile: \__/ myOLED.line(20, 20, 30, 10); // Left smile myOLED.line(30, 10, 40, 10); // Bottom of smile myOLED.line(40, 10, 50, 20); // Right smile } else if (moistureValue >= 50 && moistureValue < 70) { // Neutral Face myOLED.line(20, 0, 30, 0); // Left eye myOLED.line(40, 0, 50, 0); // Right eye myOLED.line(20, 20, 50, 20); // Neutral line } else { // Sad Face when dry myOLED.line(20, 0, 30, 0); // Left eye myOLED.line(40, 0, 50, 0); // Right eye // Sad mouth: /--\ myOLED.line(20, 10, 30, 20); // Left sad myOLED.line(30, 20, 40, 20); // Bottom of sad myOLED.line(40, 20, 50, 10); // Right sad } myOLED.display(); Serial.print("Moisture: "); Serial.print(moistureValue); Serial.println("%"); } void testForConnectivity() { Wire.beginTransmission(qwiicAddress); if (Wire.endTransmission() != 0) { Serial.println("Check connections. No soil sensor found."); while (1); } }