Hackster is hosting Hackster Holidays, Ep. 6: Livestream & Giveaway Drawing. Watch previous episodes or stream live on Monday!Stream Hackster Holidays, Ep. 6 on Monday!
Brian CottrellChristine CottrellJoe GonzalezRuby HsuChih-Wei Hsu
Published © GPL3+

Air Garden

An aeroponic planter for indoor gardening and improved air purification.

AdvancedFull instructions provided3 days8,738
Air Garden

Things used in this project

Story

Read more

Custom parts and enclosures

Top Trim

Spacer

Top

Base

Bottom

Schematics

Design

Diagram

Code

aergrow_mini_2_2_ino.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.
Christine Cottrell

Christine Cottrell

1 project • 1 follower
Joe Gonzalez

Joe Gonzalez

1 project • 1 follower
Ruby Hsu

Ruby Hsu

2 projects • 3 followers
Chih-Wei Hsu

Chih-Wei Hsu

1 project • 1 follower

Comments