CanGrow/Arduino/CanGrow/CanGrow.ino

330 lines
9.5 KiB
Arduino
Raw Normal View History

2024-03-30 03:04:48 +01:00
/*
* CanGrow - simply DIY automatic plant grow system (for cannabis).
*
* Pin assignment
* ==============
*
2024-03-30 03:38:31 +01:00
* D0 - MOSFET Fan
2024-03-30 03:04:48 +01:00
* D1, D2 - I2C
2024-03-30 03:38:31 +01:00
* D3 - DHT11
* D5 - MOSFET Pump
* D6 - MOSFET Grow LED, PWM
2024-04-01 23:47:11 +02:00
* D7 - waterlevel (set HIGH to read value)
2024-04-02 02:18:10 +02:00
* D8 - analog soil moisture (set HIGH to read value)
2024-04-01 23:47:11 +02:00
* A0 - analog input for soil moisture and waterlevel readings
2024-03-31 04:41:50 +02:00
*
2024-04-01 23:47:11 +02:00
* D4 and D7 cannot be HIGH at the same time!
2024-03-30 03:04:48 +01:00
*/
2024-03-30 01:25:58 +01:00
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
2024-03-30 03:04:48 +01:00
#include "DHT.h"
2024-04-01 23:47:11 +02:00
// D0 is HIGH at boot, no PWM
2024-03-31 04:41:50 +02:00
uint8_t PINfan = D0;
2024-04-01 23:47:11 +02:00
// If D3 is pulled to LOW, boot fails
2024-03-30 03:04:48 +01:00
uint8_t PINdht = D3;
2024-04-01 23:47:11 +02:00
// D4 is HIGH at boot, boot fail if pulled to LOW
uint8_t PINpump = D5;
uint8_t PINled = D6; //
2024-04-01 23:47:11 +02:00
uint8_t PINwaterlevel = D7;
2024-04-02 02:18:10 +02:00
uint8_t PINsoilmoisture = D8;
2024-04-01 23:47:11 +02:00
uint8_t PINanalog = A0;
2024-03-30 01:25:58 +01:00
2024-04-07 03:55:17 +02:00
int D6status = false;
2024-03-30 01:25:58 +01:00
#define WIRE Wire
2024-03-30 03:04:48 +01:00
#define DHTTYPE DHT11
2024-03-30 01:25:58 +01:00
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &WIRE);
// 'CanGrow_Logo', 128x32px
const unsigned char bmpCanGrow_Logo [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x07, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0e, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x00, 0x38, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x1c, 0x03, 0x00, 0x00, 0x00, 0x00, 0x07, 0xe0, 0x00, 0x70, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x03, 0x00, 0x00, 0x00, 0x04, 0x07, 0xe0, 0x20, 0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x03, 0x00, 0x00, 0x00, 0x06, 0x07, 0xe0, 0xe0, 0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
0x18, 0x00, 0x00, 0x00, 0x00, 0x03, 0x87, 0xe1, 0xc0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x00, 0x3f, 0xc3, 0xff, 0x03, 0xc7, 0xe3, 0xc0, 0xcf, 0xf9, 0xff, 0xe3, 0xfc, 0xc1, 0x83,
0x30, 0x00, 0x7f, 0xe3, 0xff, 0x83, 0xe7, 0xe7, 0xc0, 0xcf, 0xfb, 0xff, 0xe7, 0xfe, 0xc3, 0x87,
0x30, 0x00, 0xe0, 0x73, 0x80, 0xc1, 0xf7, 0xef, 0xc0, 0xc0, 0x1b, 0x80, 0x0e, 0x03, 0xc3, 0x86,
0x30, 0x00, 0xc0, 0x33, 0x00, 0xc1, 0xff, 0xff, 0x80, 0xc0, 0x1b, 0x00, 0x0c, 0x03, 0xc7, 0x8e,
0x30, 0x01, 0xc0, 0x37, 0x00, 0xc0, 0xff, 0xff, 0x80, 0xc0, 0x3b, 0x00, 0x1c, 0x03, 0xc7, 0x8c,
0x60, 0x01, 0xc0, 0x37, 0x00, 0xc0, 0xff, 0xff, 0x01, 0x80, 0x3f, 0x00, 0x18, 0x03, 0xcf, 0x9c,
0x60, 0x00, 0x00, 0x37, 0x00, 0xc0, 0x7f, 0xfe, 0x01, 0x80, 0x37, 0x00, 0x18, 0x03, 0xcf, 0x9c,
0x60, 0x00, 0x00, 0x76, 0x01, 0xc0, 0x1f, 0xfc, 0x01, 0x80, 0x36, 0x00, 0x18, 0x06, 0xdf, 0xb8,
0x60, 0x00, 0x7f, 0xe6, 0x01, 0x9f, 0x9f, 0xfc, 0xf9, 0x80, 0x36, 0x00, 0x18, 0x06, 0xdd, 0xb8,
0x60, 0x00, 0xff, 0xe6, 0x01, 0x87, 0xff, 0xff, 0xf1, 0x80, 0x76, 0x00, 0x18, 0x06, 0xdd, 0xb0,
0xc0, 0x01, 0xc0, 0xee, 0x01, 0x83, 0xff, 0xff, 0xc3, 0x00, 0x7e, 0x00, 0x30, 0x06, 0xf9, 0xf0,
0xc0, 0x0b, 0x80, 0x6e, 0x01, 0x81, 0xff, 0xff, 0x83, 0x00, 0x6e, 0x00, 0x30, 0x06, 0xf9, 0xe0,
0xc0, 0x1b, 0x00, 0xec, 0x01, 0x80, 0x1f, 0xf8, 0x03, 0x00, 0x6c, 0x00, 0x30, 0x0e, 0xf1, 0xe0,
0xc0, 0x3b, 0x00, 0xcc, 0x03, 0x80, 0x3f, 0xfc, 0x03, 0x00, 0xec, 0x00, 0x30, 0x0c, 0xf1, 0xc0,
0xc0, 0x7b, 0x01, 0xcc, 0x03, 0x00, 0x7f, 0xfe, 0x03, 0x01, 0xec, 0x00, 0x30, 0x1c, 0xe1, 0xc0,
0x7f, 0xf1, 0xff, 0xdc, 0x03, 0x00, 0xf0, 0x8f, 0x01, 0xff, 0xfc, 0x00, 0x1f, 0xf8, 0xe1, 0xc0,
0x3f, 0xe0, 0xff, 0xcc, 0x03, 0x00, 0x00, 0x80, 0x00, 0xff, 0xcc, 0x00, 0x0f, 0xf0, 0xc1, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 528)
const int bmpallArray_LEN = 1;
const unsigned char* bmpallArray[1] = {
bmpCanGrow_Logo
};
2024-03-30 03:04:48 +01:00
DHT dht(PINdht, DHTTYPE);
2024-03-30 01:25:58 +01:00
void writeI2CRegister8bit(int addr, int value) {
Wire.beginTransmission(addr);
Wire.write(value);
Wire.endTransmission();
}
unsigned int readI2CRegister16bit(int addr, int reg) {
Wire.beginTransmission(addr);
Wire.write(reg);
Wire.endTransmission();
delay(20);
Wire.requestFrom(addr, 2);
unsigned int t = Wire.read() << 8;
t = t | Wire.read();
return t;
}
2024-03-31 05:47:43 +02:00
int getWaterlevel() {
/*
* waterlevelRAW
* ===========
* 0 - 199 : CRITICAL
* 200 - 399 : WARNING
* >400 : OK
*
* waterlevel
* ==========
* 2 : CRITICAL
* 1 : WARNING
* 0 : OK
*/
int waterlevelWARN = 200;
int waterlevelOK = 400;
int waterlevelRAW = 0;
int waterlevel = 0;
// enable Vcc for water level sensor
2024-04-01 23:47:11 +02:00
digitalWrite(PINwaterlevel, HIGH);
// wait a bit to let the circuit stabilize
2024-04-07 01:18:54 +02:00
delay(100);
2024-03-31 05:47:43 +02:00
// get the value
2024-04-01 23:47:11 +02:00
waterlevelRAW = analogRead(PINanalog);
2024-04-07 01:18:54 +02:00
// disable Vcc for the sensor to prevent electrolysis effect and release analog pin
2024-04-01 23:47:11 +02:00
digitalWrite(PINwaterlevel, LOW);
2024-03-31 05:47:43 +02:00
if( waterlevelRAW >= waterlevelOK) {
waterlevel = 0;
} else if( waterlevelRAW >= waterlevelWARN) {
waterlevel = 1;
} else {
waterlevel = 2;
}
return waterlevel;
}
float getTemperature(bool tempSensor) {
/*
* tempSensor
* ==========
* 0/false : DHT11 temp sensor
* 1/true : chirp I2C temp sensor
*/
float temperature = 0;
if(tempSensor == false ) {
// read temperature from DHT11
temperature = dht.readTemperature();
} else {
// read temperature from chrip I2C
temperature = readI2CRegister16bit(0x20, 5) * 0.10 ;
}
return temperature;
}
float getHumidity() {
float humidity = dht.readHumidity();
return humidity;
}
2024-04-07 01:18:54 +02:00
int getSoilmoisture(bool moistureSensor) {
2024-04-07 02:10:45 +02:00
/*
* moistureSensor
* ==============
* 0/false : analog capacitive moisture sensor
* 1/true : chirp I2C moisture sensor
*/
2024-04-07 01:56:33 +02:00
// value to return
2024-04-07 01:18:54 +02:00
int soilmoisture;
2024-04-07 01:56:33 +02:00
// value for wet
int wet;
// value for dry
int dry;
2024-04-07 01:18:54 +02:00
if(moistureSensor == false ) {
// read analog value from analog moisture sensor
2024-04-07 02:10:45 +02:00
wet = 180;
2024-04-07 01:56:33 +02:00
dry= 590;
2024-04-07 01:18:54 +02:00
digitalWrite(PINsoilmoisture, HIGH);
// wait a bit to let the circuit stabilize
2024-04-07 01:20:30 +02:00
delay(100);
2024-04-07 01:56:33 +02:00
// get analog input value
2024-04-07 01:18:54 +02:00
soilmoisture = analogRead(PINanalog);
// disable Vcc for the sensor to release analog pin
digitalWrite(PINsoilmoisture, LOW);
} else {
// read soil moisture from chrip I2C
2024-04-07 02:10:45 +02:00
wet = 560;
2024-04-07 01:56:33 +02:00
dry= 250;
2024-04-07 02:10:45 +02:00
2024-04-07 01:56:33 +02:00
// get raw value from I2C chirp sensor
2024-04-07 01:18:54 +02:00
soilmoisture = readI2CRegister16bit(0x20, 0);
}
2024-04-07 01:56:33 +02:00
return map(soilmoisture, wet, dry, 100, 0);
2024-03-31 05:47:43 +02:00
}
2024-03-31 05:53:57 +02:00
int getLightchirp() {
// get the "light value" from I2C chirp module
writeI2CRegister8bit(0x20, 3); //request light measurement
int lightchirp = readI2CRegister16bit(0x20, 4);
return lightchirp;
}
2024-03-30 01:25:58 +01:00
void setup() {
2024-03-31 04:41:50 +02:00
// setup pins
pinMode(PINfan, OUTPUT);
pinMode(PINdht, INPUT);
2024-04-01 23:47:11 +02:00
pinMode(PINwaterlevel, OUTPUT);
2024-04-07 01:18:54 +02:00
pinMode(PINsoilmoisture, OUTPUT);
2024-03-31 04:41:50 +02:00
pinMode(PINled, OUTPUT);
pinMode(PINpump, OUTPUT);
// set all OUTPUT to low
digitalWrite(PINfan, LOW);
2024-04-01 23:47:11 +02:00
digitalWrite(PINwaterlevel, LOW);
2024-04-07 01:18:54 +02:00
digitalWrite(PINsoilmoisture, LOW);
2024-03-31 04:41:50 +02:00
digitalWrite(PINled, LOW);
digitalWrite(PINpump, LOW);
// initialise Wire for I2C
2024-03-30 01:25:58 +01:00
Wire.begin();
2024-03-31 04:41:50 +02:00
// initialise Serial output
2024-03-30 01:25:58 +01:00
Serial.begin(115200);
//Serial.println("Test123");
2024-03-31 04:41:50 +02:00
// reset chirp
2024-03-30 01:25:58 +01:00
writeI2CRegister8bit(0x20, 6); //reset
2024-03-31 04:41:50 +02:00
// initialise I2C display
2024-03-30 01:25:58 +01:00
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // Address 0x3C for 128x32
2024-03-31 04:41:50 +02:00
// initialise DHT11
2024-03-30 03:04:48 +01:00
dht.begin();
2024-03-30 01:25:58 +01:00
display.clearDisplay();
display.display();
2024-03-31 04:41:50 +02:00
// set display settings
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
// display Logo
2024-03-30 01:25:58 +01:00
display.drawBitmap(0, 0, bmpCanGrow_Logo, 128, 32, WHITE);
display.display();
2024-03-30 03:04:48 +01:00
delay(2500);
2024-03-31 04:41:50 +02:00
// clear display
2024-03-30 03:04:48 +01:00
display.clearDisplay();
display.display();
2024-03-30 01:25:58 +01:00
}
void loop() {
2024-03-31 05:53:57 +02:00
// set display cursor to top left
2024-03-30 03:04:48 +01:00
display.setCursor(0,0);
2024-03-31 05:53:57 +02:00
// display text
2024-03-30 03:04:48 +01:00
display.print("I2C: ");
2024-04-07 01:18:54 +02:00
display.print(getSoilmoisture(1));
2024-03-30 03:04:48 +01:00
display.print(", ");
2024-03-31 05:47:43 +02:00
display.println(getTemperature(1));
2024-03-31 05:53:57 +02:00
Serial.print("I2C: ");
2024-04-07 01:18:54 +02:00
Serial.print(getSoilmoisture(1));
Serial.print(", ");
Serial.println(getTemperature(1));
2024-03-30 01:25:58 +01:00
2024-03-30 03:04:48 +01:00
display.print("DHT11: ");
2024-03-31 05:47:43 +02:00
display.print(getTemperature(0));
2024-03-30 03:04:48 +01:00
display.print(", ");
2024-03-31 05:47:43 +02:00
display.println(getHumidity());
Serial.print("DHT11: ");
Serial.print(getTemperature(0));
Serial.print(", ");
Serial.println(getHumidity());
2024-03-30 01:25:58 +01:00
2024-03-31 04:41:50 +02:00
2024-03-31 05:53:57 +02:00
display.print("Water Status: ");
2024-03-31 05:47:43 +02:00
display.println(getWaterlevel());
Serial.print("Water Status: ");
Serial.println(getWaterlevel());
2024-03-31 04:41:50 +02:00
2024-04-07 01:18:54 +02:00
display.print("ASM: ");
2024-04-07 02:10:45 +02:00
display.print(getSoilmoisture(0));
display.println(", ");
2024-04-07 01:18:54 +02:00
Serial.print("ASM: ");
Serial.println(getSoilmoisture(0));
2024-03-31 05:53:57 +02:00
// print everything on the display
2024-03-31 04:41:50 +02:00
display.display();
Serial.println("Test");
2024-04-07 03:55:17 +02:00
if(D6status == true) {
2024-04-07 03:55:17 +02:00
digitalWrite(PINled, LOW);
digitalWrite(PINpump, LOW);
digitalWrite(PINfan, LOW);
D6status = false;
Serial.println("D6 is off now");
} else {
digitalWrite(PINled, HIGH);
digitalWrite(PINpump, HIGH);
digitalWrite(PINfan, HIGH);
D6status = true;
Serial.println("D6 is ON now");
}
delay(100);
2024-03-30 01:25:58 +01:00
}