Brian CottrellRuby HsuChristine CottrellJoe Gonzalez
Created May 12, 2019 © GPL3+

Air Garden

An aeroponic planter for indoor gardening and improved air purification.

AdvancedFull instructions provided3 days390
Air Garden

Things used in this project

Story

Read more

Custom parts and enclosures

Top

Spacer

Top Trim

Base

Bottom

Schematics

Design

Diagram

Code

Aergrow_mini_2.2.ino

Arduino
/*
Air Planter

Humidifier control for Air Planter


 A2  = Sensor Measurement pin
 D6 to relay
 A4 SDA
 A5 SCL
 D2 Enter Button
 D3 Escape Button

*/

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <EEPROM.h>
const int moisture = A2; //reads voltage from soil sensor
const int powerpin = 11; //provides power to voltage divider
const int groundpin = 12; //ground for voltage divider, reverses after measurement
const int relaypin = 6; //powers relay
const int enterButton= 2; // pin 7 to ground
const int escButton = 3;  // pin 8 to ground

int vacOn = 0; // "1" indicaated vacation mode is on
int moisture_val;
byte count = 0;
byte screenRefresh ;
byte wet_val;
byte high_val;
byte oldWet; //high wet value stored in eeprom 1.
byte buttonState = 0;
int lowLevel = 0; // counter for moisture dropping while humidifier is on
//--------------------------------------------------------------------
byte offset = 15; // (epprom 2) 10 for moist plants, 50 for plants that need drying, 20 normal
byte readingRate = 30; //(eeprom 3)time between sensor readings in minutes
int highRaw = 900; // raw reading for sensor saturated with water. stored in eeprom 5 and 6
//---------------------------------------------------------------------------
unsigned long lastMillis = 0; // holds the last read millis()
unsigned long previousMillis = 0; //used for flashing led routine
unsigned long currentMillis = 0;
unsigned long onMillis = 0; //used for blinking display
unsigned long offMillis = 0; //used for blinking display

unsigned long interval; // sampling interval
long  testInterval = 0; //allows for immediate moisture measurement
//const long interval = 3000; //used for testing
byte calHours = 12; //(eeprom 4)
unsigned long cal_period = 3600000 * calHours; //defines cal period (12hrs = 43200000)
//#####################################################################################
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //FOR BLUE DISPLAY
//LiquidCrystal_I2C lcd(0x20, 4, 5, 6, 0, 1, 2, 3, 7, NEGATIVE); //for alternate IIC display
//LiquidCrystal_I2C lcd(0x20, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); //FOR YELLOW DISPLAY LCM1602
//#####################################################################
//---------------------------------------------------------------------

void setup()
{
 pinMode(powerpin,OUTPUT);
 pinMode(groundpin,OUTPUT);
 pinMode (relaypin,OUTPUT);
 pinMode(moisture,INPUT);
 pinMode (enterButton,INPUT);
 pinMode (escButton,INPUT);
 digitalWrite(enterButton, HIGH); //enable pull-up resistor
 digitalWrite(escButton,HIGH);//enable pull-up resitor
 
 digitalWrite(relaypin, HIGH); //turns on humidifier
  
 lcd.begin(16,2);
 lcd.backlight();
 lcd.clear();
  lcd.setCursor(0,0);
  lcd.print ("Aergrow 2.2");
  lcd.setCursor(0,1);
  lcd.print("std sensor ");
 
 delay (2000);
 
  
 if (EEPROM.read(10) != 2) //runs if no data in eeprom or program was reset in Settings
 {
 EEPROM.write(2, offset);
 EEPROM.write(3, readingRate);
 EEPROM.write(4, calHours);
 byte hiByte = highByte(highRaw);
 byte loByte = lowByte(highRaw);
 EEPROM.write(6, hiByte);
 EEPROM.write(7, loByte);
 EEPROM.write(8, 0);
 EEPROM.write(10, 2);
 }
 else //uses data stored in eeprom
 {
 oldWet = EEPROM.read(1);
 offset = EEPROM.read(2);
 vacOn = EEPROM.read(8);
 readingRate = EEPROM.read(3);
 calHours = EEPROM.read(4);
  byte hByte = EEPROM.read(6);
 byte lByte =EEPROM.read(7);
 highRaw = word(hByte, lByte);
 }
  if (EEPROM.read(8) == 1)
  {
    vacationOn();
  }
  else if (oldWet > 5 && digitalRead(enterButton) == HIGH) //calibration will be skipped if data in eeprom or left button is pushed
 {EEPROM.write(1,oldWet);
  wet_val = oldWet;
  high_val = oldWet;
 moisture_val = readSensor (); //takes reading and outputs moisture_val
 }
 
 else
 {
   calibrating();
 }
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print ("Initializing");
  lcd.setCursor(0,1);
  lcd.print("high value = ");
  lcd.setCursor(13,1);
  lcd.print(high_val);
   
 lastMillis = millis(); // do this last in setup
 delay (1);
 }


//#########################################################################
void loop()
{

  assignButton();

  boolean relaypinVal = digitalRead(relaypin);

  int highCount = (600 / readingRate); // (eeprom 5) cycles before watering stopsv 10 hrs. total
  int safety = (offset * 2);
  unsigned long cal_period = 3600000 * calHours;
  interval = (readingRate * 60000);
  currentMillis = millis();

  if (lastMillis > currentMillis)
  {
    lastMillis = currentMillis;
  }

  if (wet_val < (high_val - 10) && vacOn == 0)
  {
    calibrating();
  }
  //------------------------------------------------------
  if (currentMillis > lastMillis + testInterval)
  {
    moisture_val = readSensor(); //takes reading and outputs moisture_val
    lastMillis = currentMillis;
    testInterval = interval;
    screenRefresh = 1;

    if (relaypinVal == HIGH)// Is humidifier on?
    {
      count++;
    }
    else
    {
      count = 0;
    }
    lowLevel = 0;
    
    //----------------------------------------------------------------

    if (moisture_val <= (wet_val - offset))
      digitalWrite (relaypin, HIGH); //TURNS ON HUMIDIFIER
    if (moisture_val >= wet_val) //checks if moisture value returned to close to wet value
    {
      digitalWrite(relaypin, LOW); //turns off humidifier
      wet_val =(wet_val +((moisture_val- wet_val)/2));
      EEPROM.write(1, wet_val);
      count = 0;
    }
    if (moisture_val >= (wet_val - (offset / 5))) //checks if moisture value returned to close to wet value
    {
      digitalWrite(relaypin, LOW); //turns off humidifier
      count = 0;
    }
    
    //------------------------------------------------------------------

    if ((count > highCount) && (moisture_val >= (wet_val - (offset /2))) && (moisture_val >= 40)) //allows 18 watering cycles
    {
     if (moisture_val < wet_val)  
     { wet_val =(moisture_val +((wet_val-moisture_val)/2));
      EEPROM.write(1, wet_val);}
      count = 0;  // resets counter
      digitalWrite(relaypin, LOW); //turns off humidifier
    }
  }

//-------------------------------------------------------------
  if (screenRefresh == 1)
  {

    if ((((count > highCount) && (moisture_val <= (wet_val - (offset / 2))) && (moisture_val >= 20)) || lowLevel > 10 ) && vacOn == 0)
      displayCheck();

    else if (moisture_val > 10 && (moisture_val < (wet_val - safety) || moisture_val < (high_val / 2)) && vacOn == 0 && testInterval > 500)
      displayCaution();

    else if (moisture_val <= 10)
      displayWarning();

    else if (vacOn == 1)
    { vacationOn();
      screenRefresh = 0;
    }

    else
    {
      displayInfo();
      screenRefresh = 0;
    }
  }
}

Credits

Brian Cottrell

Brian Cottrell

11 projects • 16 followers
I am a software developer with a background in physics and low level programming and I am currently focused on web and mobile development.
Ruby Hsu

Ruby Hsu

2 projects • 3 followers
Christine Cottrell

Christine Cottrell

1 project • 1 follower
Joe Gonzalez

Joe Gonzalez

1 project • 1 follower

Comments