Skip to content

Instantly share code, notes, and snippets.

@inthuriel
Created June 1, 2022 19:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save inthuriel/e6d510d2b8b68ef35206463df1d2e3fa to your computer and use it in GitHub Desktop.
Save inthuriel/e6d510d2b8b68ef35206463df1d2e3fa to your computer and use it in GitHub Desktop.
#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