-
Notifications
You must be signed in to change notification settings - Fork 0
/
bonsai.ino
184 lines (137 loc) · 4.96 KB
/
bonsai.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
#include <Wire.h>
#include <SerLCD.h> // http://librarymanager/All#SparkFun_SerLCD
#include <I2CSoilMoistureSensor.h> // https://github.com/Apollon77/I2CSoilMoistureSensor
#include <NewPing.h> // https://bitbucket.org/teckel12/arduino-new-ping/wiki/Home
// Customizable pin constants
const unsigned int SONAR_TRIGGER_PIN = 6;
const unsigned int SONAR_ECHO_PIN = 7;
const unsigned int MANUAL_MODE_BTN = 4;
const unsigned int PUMP_PIN = 5;
const unsigned int POTENTIOMETER_PIN = A0;
// Customizable constants
const unsigned int FULL_WATER_LVL = 415; // Sonar ping in uS (57 uS = 1 cm) for full water
const unsigned int LOW_WATER_LVL = 700; // Sonar ping in uS (57 uS = 1 cm) for low water warning
const unsigned int NO_WATER_LVL = 770; // Sonar ping in uS (57 uS = 1 cm) for no water
const unsigned int WATERING_TIME = 15000; // Duration in ms that the pump will be active when watering
const unsigned long MEASUREMENT_DELAY = 600000; // Delay in ms between temp/humidity measures
// Global variables
unsigned long next_measurement, last_poten_adjust;
bool manual_mode;
int temperature, humidity, min_humidity;
// Library objects
SerLCD lcd; // Default I2C address is 0x72
I2CSoilMoistureSensor sensor; // Default I2C address is 0x20
NewPing sonar(SONAR_TRIGGER_PIN, SONAR_ECHO_PIN, 100);
// Check temperature and humidity, return true if low humidity
bool checkTempHum() {
// Use I2CSoilMoisture to measure temperature and humidity
sensor.getCapacitance();
while (sensor.isBusy()) { delay(50); }
sensor.getTemperature();
while (sensor.isBusy()) { delay(50); }
humidity = sensor.getCapacitance(); // In Capacitance
temperature = (sensor.getTemperature() + 5) / 10; // In Celsius with proper rounding
next_measurement = millis() + MEASUREMENT_DELAY;
// Display on LCD
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.print(temperature);
lcd.print(char(223));
lcd.print("C ");
lcd.print(humidity);
lcd.print(" HUMI ");
// Return true if humidity is low
return humidity < min_humidity;
}
// Check if there is enough water
bool enoughWater() {
// Ping the distance to the water
int sonar_ping = sonar.ping();
// Try again up to 4 times if error
for (int i = 0; sonar_ping == 0 && i < 4; i++) {
delay(250);
sonar_ping = sonar.ping();
}
// Status message for LCD
int water_percent = map(min(sonar_ping, NO_WATER_LVL), NO_WATER_LVL, FULL_WATER_LVL, 0, 100);
String status_message = String(" EAU " + String(water_percent) + "% ");
lcd.setCursor(0, 1);
// If the distance to the water is large, there is no more water
if (sonar_ping > NO_WATER_LVL) {
// Display on LCD
lcd.setFastBacklight(0xff0000);// Red
lcd.print(status_message);
return false;
// If the distance to the water is medium, water is low
} else if (sonar_ping > LOW_WATER_LVL) {
// Display on LCD
lcd.setFastBacklight(0xffff00); // Yellow
lcd.print(status_message);
return true;
// If the sonar returns 0, there is a reading error
} else if (sonar_ping == 0) {
// Display on LCD
lcd.setFastBacklight(0xff00ff); // Pink
lcd.print(" ERREUR ");
return false;
// If the distance to the water is low, there is enough water
} else {
// Display on LCD
lcd.setFastBacklight(0xccffcc); // Green
lcd.print(status_message);
return true;
}
}
// Start the pump for WATERING_TIME duration
void pumpWater() {
digitalWrite(PUMP_PIN, HIGH);
delay(WATERING_TIME);
digitalWrite(PUMP_PIN, LOW);
}
// Get the potentiometer value and convert it to humidity capacitance, then set min_humidity.
void getMinHumidity() {
int poten = map(analogRead(POTENTIOMETER_PIN), 0, 1023, 270, 370);
if (poten != min_humidity) {
min_humidity = poten;
// Display on LCD
lcd.setCursor(0, 1);
lcd.print(String("HUMIDITE MIN " + String(min_humidity)));
// Log time
last_poten_adjust = millis();
}
}
void setup() {
Wire.begin();
// Set pin modes
pinMode(POTENTIOMETER_PIN, INPUT);
pinMode(MANUAL_MODE_BTN, INPUT_PULLUP);
pinMode(PUMP_PIN, OUTPUT);
digitalWrite(PUMP_PIN, LOW);
// Set auto or manual mode
manual_mode = digitalRead(MANUAL_MODE_BTN) == LOW;
// Delay before begin
delay(1000);
// LCD - Init and splash screen
lcd.begin(Wire);
lcd.clear();
lcd.setCursor(0, 0);
if (manual_mode) {
lcd.print(" MODE MANUEL ");
lcd.setFastBacklight(0x99ccff); // Blue
} else {
lcd.print(" MODE AUTO ");
lcd.setFastBacklight(0xccffcc); // Green
}
// I2CSoilMoisture - Init
sensor.begin();
}
void loop() {
// Manual mode - Pump continuously
while (manual_mode && enoughWater()) { pumpWater(); }
// Adjust min_humidity using the potentiometer
// Keep checking as long as it has not been adjusted for 2 sec
do { getMinHumidity(); }
while ((millis() - last_poten_adjust) < 2000);
// Auto mode - Pump when humidity is below min_humidity
if (millis() > next_measurement && checkTempHum() & enoughWater()) { pumpWater(); }
}