Introduction: Arduino Soil Moisture Device - DIY

I created a soil moisture monitoring device using an Arduino Nano, a capacitive soil moisture sensor, an OLED 1.3" display, and a custom 3D printed case. It helps me monitor the moisture levels of plants all around my house.

With the Arduino Nano as the brain, the capacitive soil moisture sensor measures the moisture content in the soil by detecting changes in electrical capacitance. The OLED 1.3" display provides a clear visual interface for me to view the moisture readings conveniently.

The custom 3D-printed case neatly houses and protects all the components, making it easy for me to place the device near my plants without any hassle.

I made this device to ensure that my plants receive the right amount of water. By monitoring their soil moisture levels, I can prevent overwatering or underwatering, promoting optimal plant growth and reducing the risk of damage or death.

Additionally, having a device that allows me to monitor plants all around my house helps me identify any plants that require immediate attention or adjustments to their watering routine. It saves me time and effort by focusing my care where it is needed most.

Overall, my soil moisture monitoring device provides a convenient and efficient way for me to maintain the health of my plants, ensuring they receive adequate moisture and enhancing my gardening experience.

Supplies

For this project you will need:

  • Arduino Nano Every
  • Capacitive Soil Moisture Sensor (link)
  • OLED 1.3 " I2C. Any OLED 1.3" will do, but the code and case are designed for this one
  • On/Off button for at least 9v (link)
  • 9V battery and a connector (preferably I-Type)
  • Soldering Equipment
  • Wires
  • Access to a 3D printer
  • pliers, tweezers
  • Super Glue
  • Arduino IDE

All links are for reference only. You may purchase the material from the store of your choice

Step 1: 3D Print the Case

The base and lid are a bit tight. If you need more space you can modify it the models as you wish. I used Blender. I use an Ender Envy 3 V2 and simple PLA, 0.2 mm. If you don't have a 3D printer, you can either order t online or find a local Fabrication Lab (many public libraries have one).

Step 2: Prepare the Arduino Nano

  1. Install the Arduino IDE (if not already installed) on your computer and connect the Arduino Nano via USB cable.
  2. Select the appropriate board (Arduino Nano Every) and port in the Arduino IDE
  3. Install any necessary libraries for the soil moisture sensor and OLED display (if required).
  4. Wire
  5. U8g2lib
  6. Upload the Code to the Arduino Nano

NOTE: The code calibrates the sensor for a 5V input. You may have to change the values, here's a link on how to calibrate the sensor as well as other info you may need

#include <U8g2lib.h>
#include <Wire.h>
U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
const int moisturePin = A2;

void setup() {
u8g2.begin();
Serial.begin(9600);
}

void loop() {
  int moistureValue = analogRead(moisturePin);
  moistureValue = constrain(moistureValue, 180,460);
  moistureValue = map(moistureValue,180,460,100,0);
  Serial.print("Moisture: ");
  Serial.println(moistureValue);

  u8g2.clearBuffer();
  //do{
    u8g2.setFont(u8g_font_9x18);
    u8g2.setCursor(0,10);
    //u8g2.drawStr(0, 20,"Moisture: ");
    u8g2.setCursor(0, 20);
    u8g2.print("Moisture: ");
    u8g2.print(moistureValue);
    //u8g2.print(moistureValue);
    u8g2.print(" %");

    //u8g.setPrintPos(0,40);

    if(moistureValue<30){
      u8g2.setFont(u8g_font_6x12);
      u8g2.drawStr(0,40, "Too Dry!");
    //   u8g2.setPrintPos(0,40);
    // u8g2.print("Too Dry!");
    u8g2.drawStr(0, 50, "Water me,");
    // u8g2.setPrintPos(0,50);
    // u8g2.print("Water me,");
    u8g2.drawStr(0,60,"or I'll die!");
    // u8g2.setPrintPos(0,60);
    // u8g2.print("or I'll die!");    
    draw_X_Smiley();
    }

    else if (moistureValue >= 30 && moistureValue <= 60) {
      u8g2.setFont(u8g_font_6x12);
      u8g2.drawStr(0,40,"Optimal Level!");
      // u8g2.setPrintPos(0,40);
      // u8g2.print("Optimal Level!");
      u8g2.drawStr(0,50,"Thank you,");
      //u8g2.setPrintPos(0,50,"Thank you,");
      //u8g2.print("Thank you,");
      u8g2.drawStr(0, 60,"Plant Parent" );
      // u8g2.setPrintPos(0,60);
      // u8g2.print("Plant Parent");
      draw_HappySmille();

  } else {
    u8g2.setFont(u8g_font_6x12);
    u8g2.drawStr(0,40,"Too Wet!");
      u8g2.setCursor(0,40);
      u8g2.print("Too Wet!");
      u8g2.setCursor(0,50);
      u8g2.print("Let me dry,");
      u8g2.setCursor(0,60);
      u8g2.print("or I'll die");
      draw_ScaredSmille();

  }
  //} while (u8g2.nextPage());
  u8g2.sendBuffer();
  delay(200);  // Delay for 1 second before reading moisture again

}

void draw_X_Smiley() {
  u8g2.setColorIndex(1);  // Set color index to 1 (on)

  // Draw the face circle
  u8g2.drawCircle(96,48,15);


  u8g2.drawLine(89,40,93,47);
  u8g2.drawLine(89,47,93,40);

  u8g2.drawLine(89+12,40,93+12,47);
  u8g2.drawLine(89+12,47,93+12,40);

  u8g2.drawLine(89+6,40+12,93+6,47+12);
  u8g2.drawLine(89+6,47+12,93+6,40+12);
}


void draw_HappySmille(){
  u8g2.setColorIndex(1);  // Set color index to 1 (on)

  // Draw the face circle
  u8g2.drawCircle(96,48,15);
  u8g2.drawEllipse(90, 44, 5,2);
  u8g2.drawEllipse(90+12, 44, 5,2);
  // Draw the mouth
  int cx = 96;  // X-coordinate of the center of the arc
  int cy = 55;  // Y-coordinate of the center of the arc
  int radius = 5;  // Radius of the arc
  int startAngle = 20;  // Starting angle of the arc
  int endAngle = 160;  // Ending angle of the arc
  int numSegments = 20;  // Number of line segments to approximate the arc

  float angleStep = (endAngle - startAngle) / float(numSegments - 1);
  for (int i = 0; i < numSegments; i++) {
    float angle = startAngle + i * angleStep;
    float x1 = cx + radius * cos(angle * PI / 180.0);
    float y1 = cy + radius * sin(angle * PI / 180.0);
    float x2 = cx + radius * cos((angle + angleStep) * PI / 180.0);
    float y2 = cy + radius * sin((angle + angleStep) * PI / 180.0);
    u8g2.drawLine(x1, y1, x2, y2);

  };

}

void draw_ScaredSmille(){
  u8g2.setColorIndex(1);  // Set color index to 1 (on)

  // Draw the face circle
  u8g2.drawCircle(96,48,15);
  u8g2.drawDisc(90, 44, 3);
  u8g2.drawDisc(90+12, 44, 3);
  u8g2.drawEllipse(96, 55, 3,7);



}


Step 3: Prepare the Capacitive Soil Moisture Sensor

Place the sensor in its case, and connect the wires. You can use 3 individual wires or find a cheap joint online. Also, make the wires as long as you want. Put the other ends through the main case and make sure they are female.

Step 4: Prepare the OLED

Attach four wires to the display and put the other ends through the top of the main case and make sure they are female. Carefully place the monitor in its place and attach its lid.

Step 5: Prepare the On/off Button

First place the 9v battery in the case, and the solder the positive end (RED) to one of the button's pins. On the other pin, solder a red wire with a female end.

Step 6: Connect Everything

Connect everything according to the diagram.

  1. Connect the Capacitive Soil Moisture Sensor
  2. Connect the power pin to the 5V pin on the Arduino Nano.
  3. Connect the ground pin to the GND pin on the Arduino Nano.
  4. Connect the signal pin to A2.
  5. Connect the OLED Display
  6. Identify the display's pins for power, ground, SDA (Serial Data), and SCL (Serial Clock).
  7. Connect the power pin to the 3.3V pin on the Arduino Nano.
  8. Connect the ground pin to the GND coming from the battery.
  9. Connect the SDA pin to A4 on the Arduino Nano
  10. Connect the SCL pin to A5 on the Arduino Nano
  11. Connect 9V Battery and Button
  12. Place the button in the side opening. Use glue to secure it.
  13. Connect GND with oled's wire and both to the GND pin on the Arduino Nano.
  14. Connect RED wire from the button to the VIN pin on the Arduino Nano.



Step 7: Assemble the Components in the Case

  1. Carefully place the Arduino Nano inside the 3D-printed case.
  2. Ensure all components are securely positioned and aligned with the case openings.
  3. Organize and route the jumper wires neatly to connect the components.
  4. Close the lid


Step 8: Test the Device

  • Power on the device and observe the OLED display.
  • Verify that the moisture readings are displayed accurately based on the soil moisture levels.
  • Ensure the sensor responds appropriately to changes in soil moisture.


Step 9: Conclusion

I enjoyed designing and building this device. If you have any comments or feedback please share them with me. Also, if you make it yourself, I would love to see how it came out.


Thanks for reading,

Yiannis