Created
June 1, 2022 19:58
-
-
Save inthuriel/e6d510d2b8b68ef35206463df1d2e3fa to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Adafruit_NeoPixel.h> | |
// necessary constants | |
const unsigned int ambient_diode_pin = A1, // input pin for ambient light phototransistor | |
set_moisturize_level_input_pin = A2, // input pin for DIP switch to set level of moisturize start | |
set_moisturize_duration_input_pin = A3, // input pin for DIP switch to set moisturize duration time | |
night_only_pin = 3, // input pin for DIP switch to set if we want to check if it's dark | |
moisture_sensor_pin = A0, // input pin for moisture sensor | |
motor_enable_pin = 10, // output pin to set motor speed | |
motor_pin1 = 9, // output pin for motor connector 1 | |
motor_pin2 = 8, // output pin for motor connector 2 | |
red_light_pin = 7, // output pin to set level of red in RGB diode | |
green_light_pin = 5, // output pin to set level of green in RGB diode | |
blue_light_pin = 6, // output pin to set level of blue in RGB diode | |
bar_display_pin = 2, // output pin to communicate with didoes bar | |
moisture_levels = 6, // number of levels we want to split moisture sensor readings into (also number of diodes in bar) | |
interval = 1000, // check interval for moisture sensor (in miliseconds) | |
moisturizing_cooldown_interval = 10000, // interval between single moisturization (in miliseconds) | |
moisturize_check_interval = 100, // check interval for valve open / close function (in miliseconds) | |
motor_speed = 300; // speed of the motor opening valve | |
// variables | |
int ambient_state, // light intensity value from phototransistor | |
current_moisture_level, // current moisture level from moisture sensor | |
moisture_display, // number generated by mapping from current_moisture_level to moisture_levels | |
moisture_level_setting, // read from set_moisturize_level_input_pin | |
moisture_duration_setting, // read from set_moisturize_duration_input_pin | |
night_only, // read from night_only_pin | |
start_moisturize_level, // moisture_level_setting converted to number using getLevelByValue() | |
moisture_duration_level; // moisture_duration_setting converted to number using getLevelByValue() | |
unsigned long probe_time = 0, // initial value for check interval for moisture sensor | |
moisturize_start_time = 0, // initial value for start single moisturization | |
moisturize_cooldown_time = 0, // initial value for interval between single moisturization | |
moisturize_check_time = 0; // initial value for check interval for valve open / close function | |
bool system_error = false, // define if system has error in runtime | |
moisturizing_going = false, // define if single moisturization is ongoing | |
moisturizing_cooldown = false, // define if we are in cooldown period between moisturizations | |
start_moisturize = false; // define if we should start moisturization | |
// analog values of levels from DIP switch to set level of moisturize start | |
int moisture_levels_values[6] = { | |
16, // 1 | |
348, // 2 | |
375, // 3 | |
422, // 4 | |
499, // 5 | |
606 // 6 | |
}; | |
// analog values of levels from DIP switch to set moisturize duration time | |
int moisture_duration_levels_values[4] = { | |
341, // 1 | |
393, // 2 | |
477, // 3 | |
592 // 4 | |
}; | |
// start RGB bar | |
Adafruit_NeoPixel pixels = Adafruit_NeoPixel(moisture_levels, bar_display_pin, NEO_GRB + NEO_KHZ800); | |
// functions headers | |
int getLevelByValue(int measurement, int levels[], int number_of_levels); | |
void moisturize(); | |
void runMotor(int speed, boolean direction); | |
void light_color_diode(int red_light_value, int green_light_value, int blue_light_value); | |
void setup() { | |
Serial.begin(9600); | |
pinMode(ambient_diode_pin, INPUT); | |
pinMode(moisture_sensor_pin, INPUT); | |
pinMode(set_moisturize_level_input_pin, INPUT); | |
pinMode(set_moisturize_duration_input_pin, INPUT); | |
pinMode(night_only_pin, INPUT); | |
pinMode(motor_pin1, OUTPUT); | |
pinMode(motor_pin2, OUTPUT); | |
pinMode(motor_enable_pin, OUTPUT); | |
pinMode(red_light_pin, OUTPUT); | |
pinMode(green_light_pin, OUTPUT); | |
pinMode(blue_light_pin, OUTPUT); | |
} | |
void loop() { | |
// check setting for moisturize level | |
moisture_level_setting = analogRead(set_moisturize_level_input_pin); | |
start_moisturize_level = getLevelByValue(moisture_level_setting, moisture_levels_values, sizeof(moisture_levels_values)/sizeof(int)); | |
// set error if level couldn't be matched | |
if (start_moisturize_level < 0) { | |
system_error = true; | |
} | |
// check settings for moisturize duration | |
moisture_duration_setting = analogRead(set_moisturize_duration_input_pin); | |
moisture_duration_level = getLevelByValue(moisture_duration_setting, moisture_duration_levels_values, sizeof(moisture_levels_values)/sizeof(int)); | |
// set error if level couldn't be matched | |
if (moisture_duration_level < 0) { | |
system_error = true; | |
} | |
// check if we should run only over night | |
night_only = digitalRead(night_only_pin); | |
ambient_state = analogRead(ambient_diode_pin); | |
// read moisture level and convert to number | |
current_moisture_level = analogRead(moisture_sensor_pin); | |
moisture_display = map(current_moisture_level, 0, 876, 0, moisture_levels); | |
if(millis() >= probe_time + interval){ | |
probe_time +=interval; | |
if (system_error) { | |
light_color_diode(255, 0, 0); | |
} else { | |
// update bar | |
for(int i=0;i<moisture_levels;i++){ | |
if (i < moisture_display) { | |
pixels.setPixelColor(i, pixels.Color(0, 51, 204)); | |
} else { | |
pixels.setPixelColor(i, pixels.Color(0, 0, 0)); | |
} | |
pixels.show(); | |
} | |
// check if we should and could run moisturization | |
if (moisture_level_setting > 0 && moisture_duration_level > 0 ) { | |
if (!moisturizing_cooldown && !moisturizing_going) { | |
light_color_diode(0, 0, 0); | |
} | |
if (night_only && ambient_state < 245) { | |
if (moisture_display < start_moisturize_level) { | |
if (!moisturizing_cooldown && !moisturizing_going) { | |
start_moisturize = true; | |
} | |
} else { | |
Serial.println("It's ok (at night)."); | |
} | |
} else if (night_only && ambient_state >= 245) { | |
Serial.println("It's not night we shouldn't start moisture"); | |
} else { | |
if (moisture_display < start_moisturize_level) { | |
if (!moisturizing_cooldown && !moisturizing_going) { | |
start_moisturize = true; | |
} | |
} else { | |
Serial.println("It's ok."); | |
} | |
} | |
} else { | |
// moisturization suspended | |
light_color_diode(255, 204, 0); | |
} | |
} | |
} | |
// check if we should and could open the valve | |
if(millis() >= moisturize_check_time + moisturize_check_interval) { | |
moisturize_check_time +=moisturize_check_interval; | |
moisturize(); | |
} | |
} | |
int getLevelByValue(int measurement, int levels[], int number_of_levels) { | |
if (measurement == 0) { | |
return 0; | |
} | |
for (int i=0; i<number_of_levels; i++) { | |
if(measurement == levels[i]) { | |
return i + 1; | |
} | |
} | |
return -1; | |
} | |
void moisturize() { | |
if (start_moisturize && !moisturizing_going && !moisturizing_cooldown) { | |
// light green diode to show process is running | |
light_color_diode(0, 255, 0); | |
start_moisturize = false; | |
moisturizing_going = true; | |
Serial.println("Open valve"); | |
moisturize_start_time = millis(); | |
// start and stop motor | |
// delay is used here to avoid race conditions and flood | |
runMotor(motor_speed, 1); | |
delay(1000); | |
runMotor(0, 1); | |
} | |
if (moisturizing_going && !moisturizing_cooldown) { | |
start_moisturize = false; | |
if (millis() >= moisturize_start_time + (moisture_duration_level * 2000)) { | |
// turn off green diode when process stopped | |
light_color_diode(0, 0, 0); | |
Serial.println("Close valve"); | |
moisturizing_cooldown = true; | |
moisturizing_going = false; | |
moisturize_cooldown_time = millis(); | |
// start and stop motor | |
// delay is used here to avoid race conditions and flood | |
runMotor(motor_speed, 0); | |
delay(1000); | |
runMotor(0, 1); | |
} | |
} | |
if(!moisturizing_going && moisturizing_cooldown) { | |
start_moisturize = false; | |
if (millis() >= moisturize_cooldown_time + moisturizing_cooldown_interval) { | |
moisturizing_cooldown = false; | |
Serial.println("Cooldown ended"); | |
} | |
} | |
} | |
void runMotor(int speed, boolean direction) | |
{ | |
analogWrite(motor_enable_pin, speed); | |
digitalWrite(motor_pin1, ! direction); | |
digitalWrite(motor_pin2, direction); | |
} | |
void light_color_diode(int red_light_value, int green_light_value, int blue_light_value) | |
{ | |
analogWrite(red_light_pin, red_light_value); | |
analogWrite(green_light_pin, green_light_value); | |
analogWrite(blue_light_pin, blue_light_value); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment