Project in progress
Self Sufficient Automated Greenhouse

Self Sufficient Automated Greenhouse © GPL3+

This greenhouse only needs quarterly maintenance, water refills, and heat maintenance to grow high-quality plants in the optimal conditions.

  • 9,464 views
  • 17 comments
  • 42 respects

Components and supplies

Apps and online services

About this project

Update! I am in the process of turning this whole project description from WiFi to BLE. If you want to replicate this project, check back in a day or two for the project to be finished.




Sometimes, taking care of plants is a big hassle. You need to give them just the right amount of sunlight, water them constantly, and keep them at the right heat. Well, work hard no more! With this greenhouse, you only have to perform three easy things. (1), fill the water tank every so often, (2), change the heat level of the greenhouse. And (3), provide maintenance to the electronics every 1-3 months. It's as easy as pie!

What The Greenhouse Does

  • Light: It provides sufficient lighting to the plant. The amount of lighting that enters the greenhouse is measured, and depending on how much, it adjusts the brightness of the grow lights. The color of the grow light is 3 parts red, one part blue for each individual Neopixel.
  • Water: Via a peristaltic pump, the plant is watered. The water comes from an external tank that you can either 3-D print or retrofit yourself. The pump provides approximately 100ml per minute. There are two different programs provided, and they water the plant in different ways. One waters the plant depending on the soil moisture reading provided by the Adafruit STEMMA soil sensor. However, the unit I got was extremely inaccurate, and if anybody has the same problem or wants to do the project without it, there is a second way. Te second way waters the plant at 7:00 P.M every day for 2 minutes. This provides about 200ml of water, and the time of day and amount of water can be easily changed.
  • Water Tank Emptiness Detection: The user is alerted when the water tank is below the set level using a water level sensor. If the water is above the sensor, the light in the Blynk app is green. If the water is below the sensor, the light in the Blynk app is red.
  • Uploading to Blynk: The Arduino MKR WiFi 1010 with an ENV shield will upload soil moisture, temperature, and humidity to the Blynk application. Go to the Connecting And Using Blynk section for instructions on how to set up Blynk and what the app will look like.

Step 1: The MKR 1010 WiFi Side

The MKR is the brains of the operations. All the connections made to the MKR will serve as sensors, or inputs. It'll send data to the Uno WiFi, the output manager.

  • First, put the MKR ENV shield on. All connections will be made from the top of that.
  • Next, connect the liquid level sensor. It'll tell you if the water level in your tank is below what you want it to be, and it needs a refill. Connect the power wire (red) to the 5V rail, Ground (blue or black) to the Ground rail, and Data (Green) to A1. You can use any analog pin you want, but don't use A2, because that's a pin the ENV shield uses.
  • Finally, connect the STEMMA soil sensor to Ground, 5V, Pin 11 and Pin 12. This happens to be the same pins that the ENV Shield uses for some of its sensors, but don't worry! The code is designed to turn off the shield before the STEMMA sensor checks the soil moisture.

Step 2: The Uno WiFi Side

The Uno WiFi handles the big, powerful electronics that produce an output, which are the NeoPixels and the pump

First, let's handle the NeoPixels. You will need to place the barrel jack on the breadboard now. Connect the Ground pin on the barrel jack to Ground on the Arduino Uno WiFi (any one will work) AND ground on the NeoPixel strip. Put one pin of the capacitor between the barrel jack pin and the ground wires to the NeoPixel and Arduino. Next, connect the power pin on the barrel jack to the power pin on the NeoPixel strip. Put the second side of the capacitor between the power wire and the power pin on the barrel jack. Finally, connect pin 9 on the Arduino to the data line on the NeoPixel. Put a 330 Ohm resistor in between, so you don't fry the strip.

  • Next comes the pump. It'll pump water from the tank to the plant. Put your MOSFET on the breadboard and follow the schematic in the schematic section for this step, since it's pretty hard to explain. Ask a question in the comment section if you have any questions about the schematic.

Step 3: Connecting and Using Blynk

At first, Blynk might seem intimidating. I'll walk you through everything you'll need to put in the app and how to use it.

  • Download the Blynk app and create a Blynk account. This will allow you to create a custom app with Blynk's easy-to-use software.
  • Now we have to input some starter variables. Name your project anything you like. For the Device, choose Arduino MKR1000. It's close enough to what we're using, and it'll still work! For connection type, choose WiFi. Lastly, choose a theme: dark or light. Then press "create project", and there you have it! The basis for your very own app.
  • Now that we have an app, we have to customize it to fit our needs. Press any blank area to create an object. From displays, select Gauge and place it in the app template. Click the Gauge to open its settings. Name the Gauge Temperature, set the source as the MKR1010, set the input as V0, set the label as /pin/°F, and set the minimum/maximum to 0/100, respectively. Now, make two more gauges for Light and Soil Moisture. Their details are shown below.
  • Put an led in the app and input the details below.
  • Note that you don't have to put the bridge widgets in, as they are only there to notify people that such a feature exists. However, you can if you want to, but note that this will cost 200 energy.
  • Now it's time to add the Uno WiFi into the mix. Press the nut icon in the top right corner of the app. Press "device", and then press "new device". Name the device, make it an Arduino UNO, and set connection type as WiFi. Press Create, and voila! You've created the next device.
  • To view your devices' auth tokens, press my devices and press the device you want to see its auth token. You have to fill it in the code, along with your WiFi SSID and password.

Step 4: Put It In The Greenhouse

First, the NeoPixels. Put them in such a way that they curve around the section of the greenhouse where the plants will be placed. This will ensure that maximum amounts of light will hit the plant's leaves.

Next, the pump. Place it near a corner, as the pump tubing will be able to fit under the greenhouse when near the corners. You could also make a 5mm/0.2" hole in the glass, and put the tube inside. The water will be able to flow if you do both the former and the latter.

Now, the water sensor. Drill a hole in your tank, and make it so that the sensor will be relatively firm.

Finally, we have to deal with cables. All the cables can go through the bottom, and they will fit. But make sure that there is not too much pressure on the cables. In my case, there wasn't, but it's better to be safe than sorry!

Step 5: Use it!

After you upload the code to the MKR and Uno WiFi, power them with the cables. Also connect the power to the pump and NeoPixels, and you've done it! You will see the data being uploaded to the Blynk app, and the effects of the data will be shown in the form of the pump and lights. Provide routine maintenance every 1-3 months, and fill the tank when needed. Also monitor temperature daily or every two days and adjust, and your plants will flourish! Note that this tutorial was meant for the care of a curry plant, and you will probably have to adjust the code so that it suits the need of whatever plant you are going to use. Many official sources (reputable blogs or official plant groups, like the American Rose Society) will most likely tell you the specs for your plant. Have fun!

Help

For help with the Arduino boards and shield, visit Arduino.cc. For help with Blynk and the Blynk library, visit docs.blynk.cc.

Code

Arduino MKR WiFi 1010 with ENV Shield Code (With Soil Sensor)Arduino
This is the code that you upload to the MKR with the ENV Shield. It will read data, store some, and send the rest to the Arduino Uno WiFi.
#include <SPI.h>
#include <WiFiNINA.h>
#include <BlynkSimpleWiFiNINA.h>
// for Blynk
#include <Arduino_MKRENV.h>
// For the ENV Shield


char auth[] = "Your Blynk Auth"; 
char ssid[] = "Your WiFi SSID";
char pass[] = "Your WiFi password";
// Blynk credentials
int temperature; 
int illuminance;
int water; 
// the variables from the ENV shield and water sensor 

BlynkTimer timer;
WidgetBridge bridge1(V1); 
WidgetLED led(V2); 
// Declares the functions that the MKR will utilize with Blynk. 

void (* resetFunc) (void) = 0; 
/* I found that after running for about seven minutes, the MKR and the UNO crash. Doing a reset every five minutes solves the problem, and doesn't affect anything else.*/

void Sensor() {
  //This is the function that does all the sensor reading
  water = analogRead(A1); 
  if (water == 0) {
    Blynk.setProperty(V2, "color", "#23C48E"); 
    led.on(); 
  }
  else if (water != 0) {
    Blynk.setProperty(V2, "color", "#D3435C"); 
  }
  temperature = ENV.readTemperature(FAHRENHEIT);
  Blynk.virtualWrite(V0, temperature - 5); 
  illuminance = ENV.readIlluminance(LUX);
  Serial.println(illuminance);
  Blynk.virtualWrite(V4, illuminance); 
  if (illuminance < 1400 and illuminance >1300) {
    bridge1.virtualWrite(V1, 1); 
  }
  
  else if (illuminance < 1300 and illuminance > 1200) {
    bridge1.virtualWrite(V1, 2);
  }
  
  else if (illuminance < 1200 and illuminance > 1100) {
    bridge1.virtualWrite(V1, 3);
  }
  
  else if (illuminance < 1100 and illuminance > 1000) {
    bridge1.virtualWrite(V1, 4);
  }
  
  else if (illuminance < 1000 and illuminance > 900) {
    bridge1.virtualWrite(V1, 5);
  }
  else if (illuminance > 1400) {
    bridge1.virtualWrite(V1, 6); 
  }
  else if (illuminance < 900) {
    bridge1.virtualWrite(V1, 5);  
  }
}




  

void setup() {
  
  Serial.begin(9600); 
  Blynk.begin(auth, ssid, pass); 
  bridge1.setAuthToken("The UNO WiFi's Auth Token");  
  if (!ENV.begin()) {
    Serial.println("Failed to initialize MKR ENV shield!");
    while (1);
  }
  timer.setInterval(333L, Sensor); 
  // Executes Sensor() every 333 milliseconds
  timer.setInterval(300000, resetFunc); 
  // resets the board every five minutes
  
  }
  

void loop() { 
  Blynk.run();
  // Runs Blynk
  timer.run(); 
  // Runs the Blynk timer
}
















  
Arduino MKR WiFi 1010 with ENV Shield Code (Without Soil Sensor)Arduino
#include <SPI.h>
#include <WiFiNINA.h>
#include <BlynkSimpleWiFiNINA.h>
#include <WidgetRTC.h>
#include <TimeLib.h>
// for Blynk and the RTC widget
#include <Arduino_MKRENV.h>
// For the ENV Shield
#include "Adafruit_seesaw.h"



//Blynk auth token and WiFi credentials, replace with yours
char auth[] = "Blynk_Auth_Token"; 
char ssid[] = "WiFi_SSID";
char pass[] = "WiFi_Password";
//Values that are used later on 
int temperature; 
int illuminance;
int water;  
bool pumpState = false; 
unsigned long whenWater = 0; 
unsigned long Now; 
int currentHour; 
int currentMinute; 

// Instances and Virtual Pin declarations 
BlynkTimer timer;
WidgetBridge bridge1(V1); 
WidgetBridge bridge2(V6); 
WidgetLED led(V2); 
WidgetRTC rtc; 
Adafruit_seesaw ss;

/* I've found that after a while, the Arduino just shuts down due to the burden held upon it. If you reset it every once in a while, it seems to be fine*/
void(* resetFunc) (void) = 0;

/* Checks sensor values, executes functions dependent on the values, and sends the values to the Blynk app*/
void Sensor() {
  water = analogRead(A1); 
  if (water == 0 and pumpState == false) { 
    Now = millis();
    if (Now - 60000 >= whenWater and pumpState == true) {
      Blynk.setProperty(V2, "color", "#23C48E"); 
      led.on(); 
    }
  }
  else if (water != 0) {
    Blynk.setProperty(V2, "color", "#D3435C"); 
    whenWater = millis();
  }
  
  temperature = ENV.readTemperature(FAHRENHEIT);
  Blynk.virtualWrite(V0, temperature - 5); 
  
  illuminance = ENV.readIlluminance(LUX);
  Serial.println(illuminance);
  Blynk.virtualWrite(V4, illuminance); 
  
  if (illuminance < 1400 and illuminance >1300) {
    bridge1.virtualWrite(V1, 1); 
  }
  
  else if (illuminance < 1300 and illuminance > 1200) {
    bridge1.virtualWrite(V1, 2);
  }
  
  else if (illuminance < 1200 and illuminance > 1100) {
    bridge1.virtualWrite(V1, 3);
  }
  
  else if (illuminance < 1100 and illuminance > 1000) {
    bridge1.virtualWrite(V1, 4);
  }
  
  else if (illuminance < 1000 and illuminance > 900) {
    bridge1.virtualWrite(V1, 5);
  }
  else if (illuminance > 1400) {
    bridge1.virtualWrite(V1, 6); 
  }
  else if (illuminance < 900) {
    bridge1.virtualWrite(V1, 5);  
  }
}

// Pours water to the plant if the time is 7:00 PM(19:00) and stops it two minutes later 
void Pour() {
  currentHour = hour(); 
  currentMinute = minute();
  /*change the 19 and the 0 if you want to change when the plant is watered*/
  if (currentHour == 19) {
      if (currentMinute == 0) {
        bridge2.virtualWrite(V6, 1); 
        pumpState = true; 
      }
      /* Change the number 3 if you want to change the length of time that the plant is watered. Keep in ming that the pump outputs about 100 ml per minute.*/
      else if (currentMinute == 3) {
        bridge2.virtualWrite(V6, 0); 
        pumpState = false; 
      }
      }
  }

// initializes the rtc when it connects to the Blynk server
BLYNK_CONNECTED() {
  rtc.begin(); 
}

void setup() {
  //Begin serial, useful for debugging
  Serial.begin(9600); 
  //Initializes Blynk
  Blynk.begin(auth, ssid, pass); 
  bridge1.setAuthToken("3M7_KAqE_eksQxq4uSuATTpknVCsjrdy");
  bridge2.setAuthToken("3M7_KAqE_eksQxq4uSuATTpknVCsjrdy");  
  // Sends an error message if the shield is not connected or broken
  if (!ENV.begin()) {
    Serial.println("Failed to initialize MKR ENV shield!");
    while (1);
  }
  else {
    Serial.println("The MKR ENV shield in connected!"); 
  }
  /*Sets timer intervals, runs Sensor every 2 minutes, Pour every minute, and resets every five minutes. */
  timer.setInterval(2000L, Sensor); 
  timer.setInterval(1000L, Pour); 
  timer.setInterval(5000L, resetFunc); 
  setSyncInterval(1*60);   
  bridge2.virtualWrite(V6, 0); 
  }
  

void loop() { 
  //Runs Blynk every iteration of the loop. 
  Blynk.run();
  timer.run(); 
}
















  
Arduino Uno WiFi Rev.2 CodeArduino
This is the code used in the Arduino Uno WiFi Rev.2.
#include <SPI.h>
#include <WiFiNINA.h>
#include <BlynkSimpleWiFiNINA.h>
//needed for Blynk
#include <Adafruit_NeoPixel.h>
#define LED_PIN 9
#define LED_COUNT 30
//needed for the Neopixel strip

char auth[] = "Your auth";
char ssid[] = "Your WiFi ssid";
char pass[] = "Your WiFi password";
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
//change for your strip
uint32_t gLight1 = strip.Color(51, 0, 17);
uint32_t gLight2 = strip.Color(102, 0, 34);
uint32_t gLight3 = strip.Color(153, 0, 51);
uint32_t gLight4 = strip.Color(204, 0, 68);
uint32_t gLight5 = strip.Color(255, 0, 85);
//the five brightnesses of the Neopixel strip
int pinData; 
BlynkTimer timer; 
//the blynk timer definition
void (* resetFunc) (void) = 0; 
/* I've found that around seven minutes of runtime, the Uno runs into
errors. Reseting every five minutes solves this problem, and 
doesn'y affect anything.*/
BLYNK_WRITE(V1){
  /*reads the pindata over the bridge, so it can change the brightness of the neopixels*/
  pinData = param.asInt(); // pinData variable will store value that came via Bridge
  Serial.println(pinData);
  if (pinData == 1) {
     strip.fill(gLight1, 0, 30); 
     strip.show();
  }

  else if (pinData == 2) {
     strip.fill(gLight2, 0, 30); 
     strip.show();
       
  }

  else if (pinData == 3) {
     strip.fill(gLight3, 0, 30); 
     strip.show();
       
  }
  else if (pinData == 4) {
     strip.fill(gLight4, 0, 30);
     strip.show();
       
  }
  else if (pinData == 5) {
     strip.fill(gLight5, 0, 30);
     strip.show();
       
  }
  else if (pinData == 6) {
    strip.clear();
    strip.show();  
  }
}
BLYNK_WRITE(V6){
  // Checks if the soil is dry, sensor data coming over bridge2
  pinData2 = param.asInt(); 
  if (pinData2 == 1) {
    // If the soil is dry, turn on the pump
    digitalWrite(motorPin, HIGH); 
  }
  else if (pinData2 == 0) {
    //If the soil is moist enough, turn off the pump
    digitalWrite(motorPin, LOW); 
  }
}



void setup() {
  Serial.begin(9600); 
  Blynk.begin(auth, ssid, pass);
  strip.begin(); 
  strip.show();  
  // starts and resets neopixels
  timer.setInterval(300000, resetFunc); 
  //resets every 5 minutes

}

void loop() {
  // put your main code here, to run repeatedly:
  Blynk.run();  
  //runs Blynk
  timer.run(); 
  // runs Blynk timer
  Blynk.syncVirtual(V1, V6); 
  //syncs the bridge and bridge2 info
}

Schematics

Schematic For The Uno WiFi Rev.2
uno_wifi_fritzing_JXLFWFeEkO.fzz
Schematic For The MKR WiFi 1010
If you are not using the soil sensor, simply do not connect the wires in the schematic.
arduino-mkr-wifi-1010_(1)_UZsdygQVtR.fzpz

Comments

Add projectSign up / Login