Paul Henley
Published © MIT

farmMinder

farmMinder monitors soil moisture level and scares away squirrels! Using the Blynk platform, you can monitor your farm remotely.

AdvancedFull instructions provided8 hours842
farmMinder

Things used in this project

Hardware components

SparkFun Blynk Board - ESP8266
SparkFun Blynk Board - ESP8266
×1
SparkFun lithium polymer ion battery
×1
Relay (generic)
Try to find a 3V relay, although a 5V relay may work.
×1
Resistor 10k ohm
Resistor 10k ohm
×2
Resistor 221 ohm
Resistor 221 ohm
Anything 100 - 220 ohm is fine.
×1
1N4148 – General Purpose Fast Switching
1N4148 – General Purpose Fast Switching
×2
General Purpose Transistor NPN
General Purpose Transistor NPN
Any similar transistor will do, I used a p2n2222a
×1
Resistor 2.21k ohm
Resistor 2.21k ohm
×1
PIR Motion Sensor (generic)
PIR Motion Sensor (generic)
This will need to modified to run at 3V by bypassing the onboard regulator and reverse-voltage protection diode. Adafruit sells one with adjustable sensitivity.
×1
8-32 bolts, nuts, and washers
×1
Vibration Motor
The relay configuration allows this motor to run at the battery's voltage rather than the Blynk Board's 3.3V. Choose a motor that is strong enough to vibrate your rubber snake that works at the battery's voltage.
×1
Rubber Snake
Use a sufficiently large rubber snake to scare the squirrels, but small enough to be vibrated by your motor.
×1
Waterproof enclosure
×1

Software apps and online services

Blynk
Blynk
Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Power drill

Story

Read more

Schematics

Wiring schematic

These are the connections between the Blynk Board and the various components.

Code

farmMinder.ino

Arduino
Download this to your Blynk Board to interface
#define DEBUG // Comment this out to disable prints and save space
#include <ESP8266WiFi.h>
#include <BlynkSimpleEsp8266.h>
#include <Adafruit_NeoPixel.h>
#include "SparkFunHTU21D.h"

////////////////////
// Blynk Settings //
////////////////////
char BlynkAuth[] = "yourBlynkAuthCodeHere";
char WiFiNetwork[] = "yourSSID";
char WiFiPassword[] = "yourWiFiPassword";
char emailAddress[] = "yourEmail@server";

///////////////////////
// Hardware Settings //
///////////////////////
#define WS2812_PIN 4 // Pin connected to WS2812 LED
#define BUTTON_PIN 0
#define LED_PIN    5
Adafruit_NeoPixel rgb = Adafruit_NeoPixel(1, WS2812_PIN, NEO_GRB + NEO_KHZ800);
#define MOTION_DETECT_PIN 12
#define SNAKE_PIN 5
#define SOIL_PIN A0
HTU21D thSense;

// Virtual pins
#define TEMP V9
#define HUMID V10
#define SOIL V11
#define SOIL_LIMIT V12
#define SNAKE_TEST V13
#define SNAKE_ARM V14

// Globals
uint32_t lastPush = 0;
boolean motion = false;
float tempF = 0;
float humidity = 0;
int soil = 0;
int soilLimit = 0;
uint32_t lastSnake = 0;
boolean snakeArmed = false;
boolean soilAlertSent = false;

BLYNK_READ(TEMP) {
  Blynk.virtualWrite(TEMP, tempF); // Update Blynk virtual value
}

BLYNK_READ(HUMID) {
  Blynk.virtualWrite(HUMID, humidity); // Update Blynk virtual value
}

BLYNK_READ(SOIL) {
  Blynk.virtualWrite(SOIL, soil);
}

BLYNK_READ(SNAKE_ARM) {
  Blynk.virtualWrite(SNAKE_ARM, snakeArmed);
}

BLYNK_WRITE(SNAKE_ARM) {
  snakeArmed = param.asInt();
}

BLYNK_READ(SOIL_LIMIT) {
  Blynk.virtualWrite(SOIL_LIMIT, soilLimit);
}

BLYNK_WRITE(SOIL_LIMIT) {
  soilLimit = param.asInt();
}

BLYNK_WRITE(SNAKE_TEST) {
  digitalWrite(SNAKE_PIN, HIGH);
  delay(500);
  digitalWrite(SNAKE_PIN, LOW);
}

void setup()
{
  // Initialize hardware
#ifdef DEBUG
  Serial.begin(9600); // Serial for debugging
#endif
  rgb.begin(); // RGB LED
  pinMode(SOIL_PIN, INPUT);
  pinMode(MOTION_DETECT_PIN, INPUT);
  pinMode(SNAKE_PIN, OUTPUT);
  digitalWrite(SNAKE_PIN, LOW);
  thSense.begin();
  // Initialize Blynk
  Blynk.begin(BlynkAuth, WiFiNetwork, WiFiPassword);
}

void loop()
{
  // Execute Blynk.run() as often as possible during the loop
  Blynk.run();
  motion = digitalRead(MOTION_DETECT_PIN);
  float tempC = thSense.readTemperature(); // Read from the temperature sensor
  tempF = tempC * 9.0 / 5.0 + 32.0; // Convert to farenheit
  humidity = thSense.readHumidity(); // Read from humidity sensor
  soil = analogRead(A0);

  // See if we need to send an email alert re: soil moisture
  if (soil < soilLimit) {
    if (soilAlertSent == false) { // only send if we haven't already
      Blynk.email(emailAddress, "Low soil moisture.", "Soil moisture has fallen below your chosen threshold.\nThanks,\nfarmMinder");
      soilAlertSent = true;
    }
  }
  else {
    soilAlertSent = false; // reset the alert flag if the soil has been watered
  }

  // See if we need to move the snake
  if (motion && snakeArmed) {
    if (millis() - lastSnake > 10000) { // max out at one snake rattle per 10 seconds
      lastSnake = millis();
      digitalWrite(SNAKE_PIN, HIGH);
      delay(500);
      digitalWrite(SNAKE_PIN, LOW);
    }
  }

  // Force a push if we haven't had one for a minute
  if (millis() - lastPush > 60000 || millis() < lastPush) {
    lastPush = millis();
    Blynk.virtualWrite(TEMP, tempF); // Update Blynk virtual value
    Blynk.virtualWrite(HUMID, humidity); // Update Blynk virtual value
    Blynk.virtualWrite(SOIL, soil);
  }

  // For debugging:
#ifdef DEBUG
  Serial.print(" motion: ");
  Serial.print(motion ? "Yes" : "No ");
  Serial.print(" humidity: ");
  Serial.print(humidity);
  Serial.print(" temp: ");
  Serial.print(tempF);
  Serial.print(" soil: ");
  Serial.print(soil);
  Serial.print(" soilLimit: ");
  Serial.print(soilLimit);
  Serial.print(" soilAlertSent: ");
  Serial.println(soilAlertSent ? "Yes" : "No ");
#endif
}

Credits

Paul Henley

Paul Henley

1 project • 0 followers

Comments