Istvan Sipka
Published © GPL3+

Climate Cube for Greenhouse

Opening 26 pieces of windows at the same time in a 2,000-square-meter greenhouse under just 20 seconds? Yes!

IntermediateFull instructions provided12 hours15,635
Climate Cube for Greenhouse

Things used in this project

Hardware components

Arduino MKR1000
Arduino MKR1000
You can find a BOM file for full list of components
×1
1,3" OLED I2C display
×1
2-channel Opto-isolate Relay Module
×1
5V DC power supply
×2
DS3231 clock
×1
RGB Diffused Common Cathode
RGB Diffused Common Cathode
×1
Limit switch with NO and NC connection
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Custom parts and enclosures

bom2_on59eMkwtx.xlsx

Schematics

climate_cube-window_controller_QBevI9N3WU.fzz

Code

Proba_141os23mkrOled.ino

Arduino
#include <HCMatrixKeypad.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Metro.h>
#include <Wire.h>
#include <Arduino.h>
#include <U8g2lib.h>
#include "RTClib.h"



#define Addrsi 0x40 //Si7021
#define Addrbh 0x23 // BH1750

U8G2_SH1106_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);


#define relayPin0 16 // a 8es kimenetre rakotve az 1 es rele ami a Zaras
#define relayPin1 17 // a 9as kimenetre rakotve a 2 es rele ami a Nyitas

#define HOMERO 0 // A homero bedugva az mcu 2es digitalis bemenetere es elnevezve HOMEROnek

#define LED 19



/*unsigned long myChannelNumber = 258360;
const char * myWriteAPIKey = "I44H7MK2AYDPZBIJ";
const long ThingspeakDelay = 30000;*/

int kivantHomerseklet = 1800;
int homDiff = 50;

/* --------- METRO time constants ----------------- */
const int idoNyit = 700;
const int idoZar = 500;

const long varNyit= 90000;
const long varZar= 60000;
const int varLed = 700;  //3600000=1 ra
const int varHumHomBes = 1923;  //3600000=1 ra
const int varBeSug = 571; 
const int varLcd = 1000;


/*----------------Keypad-----------------*/

#define DEBOUNCE 100 //100

#define C1 1  // DIO for keypad column 1
#define C2 2  // DIO for keypad column 2
#define C3 3  // DIO for keypad column 3
#define C4 4  // DIO for keypad column 4


#define R1 8 // DIO for keypad row 1
#define R2 7 // DIO for keypad row 2
#define R3 6 // DIO for keypad row 3
#define R4 5 // DIO for keypad row 4


HCMatrixKeypad Keypad(DEBOUNCE, C1, C2, C3, C4, ROWMARKER, R1, R2, R3, R4);

/*1=14    .   .   A=11
4=24    .   .   B=21
7=34
*=44
*/
/*---------------------------------------------------------------------*/

int state0 = HIGH;
int state1 = HIGH;
int ledstate = LOW;


int inPin = 19;         // the number of the input pin


int state = LOW;      // the current state of the output pin
int previous = HIGH;    // the previous reading from the input pin

// the follow variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long time = 0;         // the last time the output pin was toggled
long debounce = 200;   // the debounce time, increase if the output flickers

int reading;           // the current reading from the input pin
const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int tempCaverage = 0;                // the average


OneWire oneWire(HOMERO); // A homero egykabeles onewire bekotest kapott
DallasTemperature sensors(&oneWire); // megadtuk a homero gyartasi tipusat es hivatkozunk ra

RTC_DS3231 rtc;


 
Metro metro0 = Metro(varZar); 
Metro metro1 = Metro(varNyit); 
Metro ledMetro = Metro(varLed);
Metro metro3 = Metro(varHumHomBes);
Metro metro4 = Metro(varBeSug);
Metro metro5 = Metro(varLcd);
Metro rtcMetro = Metro(1000);
//Metro metro6 = Metro(ThingspeakDelay);



void setup()
{
  
  // Initialise I2C communication as MASTER
  //Wire.begin();
  u8g2.begin();
  Wire.setClock(32000L); //The slowest i2c speed for Mkr1000
  
  // Initialise serial communication, set baud rate = 9600
  //Serial.begin(9600);
  //u8g2.setFlipMode(1);
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setFont(u8g2_font_7x14_tf); // choose a suitable font
  u8g2.drawStr(43,10,"PaMon!");  // write something to the internal memory
  u8g2.sendBuffer();          // transfer internal memory to the display
  delay(2000);
  u8g2.clearDisplay();

  //Start I2C transmission
  Wire.beginTransmission(Addrsi);
 
  // Stop I2C transmission
  Wire.endTransmission();
  delay(300);

  // Start I2C Transmission
  Wire.beginTransmission(Addrbh);
  // Send power on command
  Wire.write(0x01);
  // Stop I2C Transmission
  Wire.endTransmission();
  delay(300);
  
  // Start I2C Transmission
  Wire.beginTransmission(Addrbh);
  // Send continuous -......-low precision measurement command: 0x13
  Wire.write(0x10);   //0x10- high-continuous measurement;0x11 high0.5 lx cont mode 120ms time
  // Stop I2C Transmission
  Wire.endTransmission();
  delay(300);

 

  pinMode(LED,OUTPUT);
  digitalWrite(LED,ledstate);

  rtc.begin();
  sensors.begin(); // Elindul a homero
  sensors.setResolution(10);
  
  pinMode(relayPin0, OUTPUT);
  digitalWrite(relayPin0, HIGH);
  
  pinMode(relayPin1, OUTPUT);  
  digitalWrite(relayPin1, HIGH);

  // initialize the button pin as a input:
  pinMode(inPin, INPUT);


  // initialize the LED as an output:
  
  
  u8g2.clearBuffer();          // clear the internal memory
  // write something to the internal memory
  //u8g2.sendBuffer(); 
  
  
  
  
  
  
  /*u8g2.setCursor(16,2);
  u8g2.print("W/m2");

  u8g2.setCursor(0,1);
  u8g2.print("Par:");
  u8g2.setCursor(8,1);
  u8g2.print("%");

  u8g2.setCursor(10,1);
  u8g2.print("Hom:");
  
  
  
  u8g2.setCursor(0,3);
  u8g2.print("Aj.Hom:");


/*t = rtc.getTime();
  
  if(t.hour<10) {
    u8g2.setCursor(5,3);
    u8g2.print("0");
    u8g2.setCursor(6,3);
    u8g2.print(t.hour);
  }
  else {
    u8g2.setCursor(5,3);
    u8g2.print(t.hour);
  }
  
  if(t.min<10) {
    u8g2.setCursor(8,3);
    u8g2.print("0");
    u8g2.setCursor(9,3);
    u8g2.print(t.min);
  }
  else {
    u8g2.setCursor(8,3);
    u8g2.print(t.min);
  }*/

  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }

  sensors.requestTemperatures();


  delay(500);
  metro0.reset();
  metro1.reset();
  ledMetro.reset();
  metro3.reset();
  metro4.reset();
  metro5.reset();

 //WiFi.begin(ssid, pass);
 //ThingSpeak.begin(client);
 //delay(2000);
}

void loop()
{

//
  
if (state0 == HIGH && state1 == HIGH) {

  if (ledMetro.check() == 1) { // check if the metro has passed its interval .
    if (ledstate==HIGH)  ledstate=LOW;
    else ledstate=HIGH;
    
    digitalWrite(LED,ledstate);
  }

  
  float tempRaw = sensors.getTempCByIndex(0);
  float tempFloat = tempRaw*100;
  int tempInt = tempFloat;
  

  // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  if(tempInt>0 && tempInt<8000){
    int tempC = tempInt;
    readings[readIndex] = tempC;
    //Serial.println(tempC);
  }
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  tempCaverage = total / numReadings;
  // send it to the computer as ASCII digits
  //Serial.println(tempCaverage);
  //delay(100);
  
  //Serial.println(sensors.getTempCByIndex(0));
  //Serial.println(tempInt);
  
  //Serial.println(tempCaverage);

  u8g2.setCursor(0,10);
  u8g2.print("Bh:");
  
  u8g2.setCursor(0,24);
  u8g2.print("D:");
    
  u8g2.setCursor(0,38);
  u8g2.print("Ah:");

  u8g2.setCursor(0,52);
  u8g2.print("Ido:");

  Keypad.Scan();
  
    /* If so the send the key to the serial port 
    //Serial.print("Number of Key Pressed: ");
    //Serial.println(Keypad.Read());
    if (Keypad.Read() > 0){
     u8g2.setCursor(120,52);
     u8g2.print("*");
  }
    else {
     u8g2.setCursor(120,52);
     u8g2.print(" ");
  }*/

  if (Keypad.Read() == 14) {
        kivantHomerseklet+=100;
        if (kivantHomerseklet == 2600){
          kivantHomerseklet = 1600;
        }
        
  }
  if (Keypad.Read() == 24) {
        kivantHomerseklet-=100;
        if (kivantHomerseklet == 1500){
          kivantHomerseklet = 2500;
        }
  }
  

  if (Keypad.Read() == 13) {
    
        homDiff+=10;
        if (homDiff > 205){
          homDiff = 10;
        }
        
  }
  if (Keypad.Read() == 23) {
        homDiff-=10;
        if (homDiff < 5){
          homDiff = 200;
        }
  }    
  


  if (rtcMetro.check()== 1) {
  
  DateTime now = rtc.now();

    Serial.print(now.year());
    Serial.print('/');
    Serial.print(now.month(), DEC);
    Serial.print('/');
    Serial.print(now.day(), DEC);
    Serial.print(' ');
    
    Serial.print(now.hour(), DEC);
    Serial.print(':');
    Serial.print(now.minute(), DEC);
    Serial.print(':');
    Serial.print(now.second(), DEC);
    Serial.println();
  
    u8g2.setCursor(30,52);
    u8g2.print(now.hour());

    u8g2.setCursor(45,52);
    u8g2.print(":");
    
    u8g2.setCursor(54,52);
    u8g2.print(now.minute());
    
  }
  
  

  
 
  int Bh = kivantHomerseklet/100;
  u8g2.setCursor(23,10);
  u8g2.print(Bh);
  
  if (homDiff > 5 && homDiff < 100) {
    u8g2.setCursor(18,24);
    u8g2.print("0.");
    u8g2.setCursor(34,24);
    u8g2.print(homDiff/10);
    u8g2.setCursor(42,24);
    u8g2.print(" ");
    
  }

  if (homDiff > 95 && homDiff < 200) {
    u8g2.setCursor(18,24);
    u8g2.print(homDiff);
    u8g2.setCursor(26,24);
    u8g2.print(".");
    u8g2.setCursor(34,24);
    u8g2.print(homDiff-100);
    u8g2.setCursor(42,24);
    u8g2.print(" ");
  }
  if (homDiff==200) {
    u8g2.setCursor(18,24);
    u8g2.print(homDiff);
    u8g2.setCursor(26,24);
    u8g2.print(".");
    u8g2.setCursor(34,24);
    u8g2.print(homDiff-200);
    u8g2.setCursor(42,24);
    u8g2.print(" ");
  }
  
  
  

  u8g2.setCursor(23,38);
  u8g2.print(tempRaw,1);
  u8g2.setCursor(62,38);
  u8g2.print("C");

  //Serial.print("Jelenlegi homerseklet: ");
  //Serial.println(sensors.getTempCByIndex(0));  // kiirjuk a monitorra a kapott homersekletet



if (metro3.check()== 1 && state0 == HIGH && state1 == HIGH) {
  
  unsigned int datasi[2];
  
  // Start I2C transmission
  Wire.beginTransmission(Addrsi);
  // Send humidity measurement command, NO HOLD MASTER
  Wire.write(0xF5);
  // Stop I2C transmission
  Wire.endTransmission();
  delay(150);
    
  // Request 2 bytes of data
  Wire.requestFrom(Addrsi, 2);

  // Read 2 bytes of data
  // humidity msb, humidity lsb 
  if(Wire.available() == 2)
  {
    datasi[0] = Wire.read();
    datasi[1] = Wire.read();
  }
    
  // Convert the data
  float humidity  = ((datasi[0] * 256.0) + datasi[1]);
  humidity = ((125 * humidity) / 65536.0) - 6;
  

  // Start I2C transmission
  Wire.beginTransmission(Addrsi);
  // Send temperature measurement command, NO HOLD MASTER
  Wire.write(0xF3);
  // Stop I2C transmission
  Wire.endTransmission();
  delay(150);
    
  // Request 2 bytes of data
  Wire.requestFrom(Addrsi, 2);
  
  // Read 2 bytes of data
  // temp msb, temp lsb
  if(Wire.available() == 2)
  {
    datasi[0] = Wire.read();
    datasi[1] = Wire.read();
  }

  // Convert the data
  float temp  = ((datasi[0] * 256.00) + datasi[1]);
  float cTemp = ((175.72 * temp) / 65536.00) - 46.85;
  

  unsigned int databh[2];
  // Request 2 byte of data
  Wire.requestFrom(Addrbh, 2);

  // Read 2 bytes of data
  // ALS msb, ALS lsb
  if(Wire.available() == 2) 
  {
    databh[0] = Wire.read();
    databh[1] = Wire.read();
  }
    //delay(130);
  
  //convert the data
  float luxraw = (((databh[0] * 256.0000) + databh[1]) / 1.2000);
  float irradiation = (((databh[0] * 256.0000) + databh[1]) / 1.2000)*0.0079;
  int lux = irradiation;


  /*if(humidity<=0) {
    u8g2.setCursor(4,1);
    u8g2.print(" 0  ");
    
  }
  if(humidity>0 && humidity<100) {
    u8g2.setCursor(4,1);
    u8g2.print(humidity,0);
    u8g2.setCursor(6,1);
    u8g2.print("  ");
    }
   if(humidity>=100 && humidity<=115) {
    u8g2.setCursor(4,1);
    u8g2.print(humidity,0);
    u8g2.setCursor(7,1);
    u8g2.print(" ");
    }
   if(humidity>115) {
    u8g2.setCursor(5,1);
    u8g2.print("115");
    u8g2.setCursor(4,1);
    u8g2.print(">");
   }
   
  

  u8g2.setCursor(14,1);
  u8g2.print(cTemp, 1);
  u8g2.setCursor(19,1);
  u8g2.print("C");

  if(lux<10) {
    u8g2.setCursor(12,2);
    u8g2.print(lux);
    u8g2.setCursor(13,2);
    u8g2.print(" ");
    u8g2.setCursor(14,2);
    u8g2.print(" ");
    
  }
  
if(lux>=10 && lux<100) {
    u8g2.setCursor(12,2);
    u8g2.print(lux);
    u8g2.setCursor(14,2);
    u8g2.print(" ");
    
  }

if(lux>=100 && lux<1000) {
    u8g2.setCursor(12,2);
    u8g2.print(lux);

}

if(lux>1000) {
    u8g2.setCursor(11,2);
    u8g2.print(lux);

}
 

if(lux<100) {
    u8g2.setCursor(7,3);
    u8g2.print("18-20 ");
    u8g2.setCursor(13,3);
    u8g2.print("C");
}


if(lux>=100 && lux<200){
    u8g2.setCursor(7,3);
    u8g2.print("21-22 ");
    u8g2.setCursor(13,3);
    u8g2.print("C");
}

if(lux>=200 && lux<300) {
    u8g2.setCursor(7,3);
    u8g2.print("23-24 ");
    u8g2.setCursor(13,3);
    u8g2.print("C");
}

if(lux>=300 && lux<400) {
    u8g2.setCursor(7,3);
    u8g2.print("25-26 ");
    u8g2.setCursor(13,3);
    u8g2.print("C");
}
if(lux>=400) {
    u8g2.setCursor(7,3);
    u8g2.print("Arnyek");
    u8g2.setCursor(13,3);
    u8g2.print(" ");
}*/

  
    // Output data to serial monitor
  Serial.print("Ambient Light Luminance   :");
  Serial.print(irradiation);
  Serial.println(" lux"); 
   
  // Output data to serial monitor
  Serial.print("Relative humidity : ");
  Serial.print(humidity);
  Serial.println(" % RH");
  Serial.print("Temperature in Celsius : ");
  Serial.print(cTemp);
  Serial.println(" C");
  Serial.print("LUX: ");
  Serial.print(luxraw);
  Serial.println(" lx");
  
  
  //u8g2.setCursor(0,2);
  //u8g2.print("Besugarzas:");
  
  
}


  reading = digitalRead(inPin);

  // if the input just went from LOW and HIGH and we've waited long enough
  // to ignore any noise on the circuit, toggle the output pin and remember
  // the time
  if (reading == HIGH && previous == LOW) {
    if (state == HIGH)
      state = LOW;
    else
      state = HIGH;
      metro5.reset();
  }
  
  if (state == HIGH) {
      u8g2.sendBuffer();
      Serial.println("OLED ON");
      metro5.interval(20000);
  }

  if(metro5.check() == 1 && state == HIGH){
      state = LOW;
  }
        
  if (state == LOW) { 
      // if the current state is LOW then the button
      // wend from on to off:
      u8g2.clearDisplay();
  }
  previous = reading;


 

} // closes the display and measuring methods

if ((kivantHomerseklet-homDiff) == tempCaverage ) {
digitalWrite(relayPin0, HIGH);
digitalWrite(relayPin1, HIGH);
}
if ((kivantHomerseklet+homDiff) == tempCaverage) {
digitalWrite(relayPin0, HIGH);
digitalWrite(relayPin1, HIGH);
}
if (((kivantHomerseklet-homDiff) < tempCaverage &&  tempCaverage < (kivantHomerseklet+homDiff)) && relayPin0==LOW) {
digitalWrite(relayPin0, HIGH);

}
if (((kivantHomerseklet-homDiff) < tempCaverage && tempCaverage < (kivantHomerseklet+homDiff)) && relayPin1==LOW) {
digitalWrite(relayPin1, HIGH);
}

if ((tempCaverage < (kivantHomerseklet-homDiff)) && relayPin1==LOW) {
digitalWrite(relayPin1, HIGH);
}

if ((tempCaverage > (kivantHomerseklet+homDiff)) && relayPin0==LOW) {
digitalWrite(relayPin0, HIGH);
}

if ((metro0.check() == 1) && (tempCaverage < (kivantHomerseklet-homDiff))) { // check if the metro has passed its interval .
    if (state0==HIGH)  { 
      state0=LOW;
      metro0.interval(idoZar); //Zarasi ido
    } 
    else {
      state0=HIGH;
      metro0.interval(varZar); // if the pin is LOW, set the interval to 1 second.
    }
    digitalWrite(relayPin0,state0);
}
if ((metro1.check() == 1) && (tempCaverage > (kivantHomerseklet+homDiff))) { // check if the metro has passed its interval .
    if (state1==HIGH)  { 
      state1=LOW;
      metro1.interval(idoNyit); // if the pin is HIGH, set the interval to 0.25 seconds.
    } 
    else {
      state1=HIGH;
      metro1.interval(varNyit); // if the pin is LOW, set the interval to 1 second.
    }
    digitalWrite(relayPin1,state1);
}

    
        sensors.requestTemperatures(); // Homerotol beolvassunk a homersekletet  
    


}

Credits

Istvan Sipka

Istvan Sipka

4 projects • 28 followers
Heart of an engineer mind of an economist. Actually an entreprenuer at the field of growing sweet pepper. My goal is: IoT for Plants!

Comments