restructure logic to work on groups of valves and sensors instead of being 1:1:1
This commit is contained in:
		
							parent
							
								
									794c17052f
								
							
						
					
					
						commit
						7a25e4b46e
					
				
					 2 changed files with 347 additions and 233 deletions
				
			
		
							
								
								
									
										292
									
								
								config.hpp
									
										
									
									
									
								
							
							
						
						
									
										292
									
								
								config.hpp
									
										
									
									
									
								
							|  | @ -1,21 +1,30 @@ | |||
| #pragma once | ||||
| #include <Arduino.h> | ||||
| 
 | ||||
| typedef struct { | ||||
| struct Sensor { | ||||
|   /// Which analog pin this is connected to (A0, A1, ...)
 | ||||
|   uint8_t pin; | ||||
|   /// The value sensors read when completely dry
 | ||||
|   int calibration_dry; | ||||
|   /// The value sensors read when completely wet
 | ||||
|   int calibration_wet; | ||||
| } Sensor; | ||||
|   /// Pot group index this sensor belongs to
 | ||||
|   unsigned int pot_group; | ||||
| }; | ||||
| 
 | ||||
| typedef struct { | ||||
|   uint8_t valve_pin; | ||||
| struct Group { | ||||
|   /// Enable or disable the group
 | ||||
|   bool enabled; | ||||
|   /// Which pin the indicator light is connected to
 | ||||
|   uint8_t led_pin; | ||||
|   Sensor sensor; | ||||
|   // define additional per-pot config here
 | ||||
| } PotConfig; | ||||
| }; | ||||
| 
 | ||||
| struct Valve { | ||||
|   /// The digital pin this valve is connected to
 | ||||
|   uint8_t pin; | ||||
|   /// Pot group index this valve belongs to
 | ||||
|   unsigned int pot_group; | ||||
| }; | ||||
| 
 | ||||
| constexpr unsigned int SECOND = 1000; | ||||
| constexpr unsigned int MINUTE = SECOND * 60; | ||||
|  | @ -33,7 +42,7 @@ constexpr int MAX_HUMIDITY_PERCENT = 70; | |||
| /// the amount of time a valve needs to open/close
 | ||||
| constexpr int VALVE_DELAY_MS = 1 * SECOND / 4; | ||||
| 
 | ||||
| /// the amount of time the pump needs to start/stop
 | ||||
| /// the amount of time the pump needs to szcttart/stop
 | ||||
| constexpr int PUMP_DELAY_MS = 1 * SECOND / 4; | ||||
| 
 | ||||
| /// the amount of time to water the plot (valve open and pump running)
 | ||||
|  | @ -53,152 +62,137 @@ constexpr uint8_t PUMP_LED_PIN = 3; | |||
| 
 | ||||
| constexpr uint8_t OK_LED_PIN = 2; | ||||
| 
 | ||||
| /// Per-pot configuration
 | ||||
| constexpr PotConfig POT_CONFIGS[] = { | ||||
|   { | ||||
|     .valve_pin = 23, | ||||
| constexpr struct Group GROUPS[] = { | ||||
|   { // 0
 | ||||
|     .enabled = true, | ||||
|     .led_pin = 22, | ||||
|     .sensor = { | ||||
|       .pin = A0, | ||||
|       .calibration_dry = 540, | ||||
|       .calibration_wet = 250, | ||||
|     } | ||||
|   }, | ||||
|   //{
 | ||||
|   //  .valve_pin = 25,
 | ||||
|   //  .led_pin = 24,
 | ||||
|   //  .sensor = {
 | ||||
|   //    .pin = A1,
 | ||||
|   //    .calibration_dry = 520,
 | ||||
|   //    .calibration_wet = 100,
 | ||||
|   //  }
 | ||||
|   //},
 | ||||
|   //{
 | ||||
|   //  .valve_pin = 27,
 | ||||
|   //  .led_pin = 26,
 | ||||
|   //  .sensor = {
 | ||||
|   //    .pin = A2,
 | ||||
|   //    .calibration_dry = 520,
 | ||||
|   //    .calibration_wet = 100,
 | ||||
|   //  }
 | ||||
|   //},
 | ||||
|   //{
 | ||||
|   //  .valve_pin = 29,
 | ||||
|   //  .led_pin = 28,
 | ||||
|   //  .sensor = {
 | ||||
|   //    .pin = A3,
 | ||||
|   //    .calibration_dry = 520,
 | ||||
|   //    .calibration_wet = 100,
 | ||||
|   //  }
 | ||||
|   //},
 | ||||
|   { | ||||
|     .valve_pin = 31, | ||||
|   }, { // 1
 | ||||
|     .enabled = false, | ||||
|     .led_pin = 24, | ||||
|   }, { // 2
 | ||||
|     .enabled = false, | ||||
|     .led_pin = 26, | ||||
|   }, { // 3
 | ||||
|     .enabled = false, | ||||
|     .led_pin = 28, | ||||
|   }, { // 4
 | ||||
|     .enabled = true, | ||||
|     .led_pin = 30, | ||||
|     .sensor = { | ||||
|       .pin = A4, | ||||
|       .calibration_dry = 520, | ||||
|       .calibration_wet = 100, | ||||
|     } | ||||
|   }, | ||||
|   //{
 | ||||
|   //  .valve_pin = 33,
 | ||||
|   //  .led_pin = 32,
 | ||||
|   //  .sensor = {
 | ||||
|   //    .pin = A5,
 | ||||
|   //    .calibration_dry = 520,
 | ||||
|   //    .calibration_wet = 100,
 | ||||
|   //  }
 | ||||
|   //},
 | ||||
|   //{
 | ||||
|   //  .valve_pin = 35,
 | ||||
|   //  .led_pin = 34,
 | ||||
|   //  .sensor = {
 | ||||
|   //    .pin = A6,
 | ||||
|   //    .calibration_dry = 520,
 | ||||
|   //    .calibration_wet = 100,
 | ||||
|   //  }
 | ||||
|   //},
 | ||||
|   //{
 | ||||
|   //  .valve_pin = 37,
 | ||||
|   //  .led_pin = 36,
 | ||||
|   //  .sensor = {
 | ||||
|   //    .pin = A7,
 | ||||
|   //    .calibration_dry = 520,
 | ||||
|   //    .calibration_wet = 100,
 | ||||
|   //  }
 | ||||
|   //},
 | ||||
|   //{
 | ||||
|   //  .valve_pin = 39,
 | ||||
|   //  .led_pin = 38,
 | ||||
|   //  .sensor = {
 | ||||
|   //    .pin = A8,
 | ||||
|   //    .calibration_dry = 520,
 | ||||
|   //    .calibration_wet = 100,
 | ||||
|   //  }
 | ||||
|   //},
 | ||||
|   { | ||||
|     .valve_pin = 41, | ||||
|   }, { // 5
 | ||||
|     .enabled = false, | ||||
|     .led_pin = 32, | ||||
|   }, { // 6
 | ||||
|     .enabled = false, | ||||
|     .led_pin = 34, | ||||
|   }, { // 7
 | ||||
|     .enabled = false, | ||||
|     .led_pin = 36, | ||||
|   }, { // 8
 | ||||
|     .enabled = false, | ||||
|     .led_pin = 38, | ||||
|   }, { // 9
 | ||||
|     .enabled = true, | ||||
|     .led_pin = 40, | ||||
|     .sensor = { | ||||
|       .pin = A9, | ||||
|       .calibration_dry = 520, | ||||
|       .calibration_wet = 100, | ||||
|     } | ||||
|   }, | ||||
|   //{
 | ||||
|   //  .valve_pin = 43,
 | ||||
|   //  .led_pin = 42,
 | ||||
|   //  .sensor = {
 | ||||
|   //    .pin = A10,
 | ||||
|   //    .calibration_dry = 520,
 | ||||
|   //    .calibration_wet = 100,
 | ||||
|   //  }
 | ||||
|   //},
 | ||||
|   //{
 | ||||
|   //  .valve_pin = 45,
 | ||||
|   //  .led_pin = 44,
 | ||||
|   //  .sensor = {
 | ||||
|   //    .pin = A11,
 | ||||
|   //    .calibration_dry = 520,
 | ||||
|   //    .calibration_wet = 100,
 | ||||
|   //  }
 | ||||
|   //},
 | ||||
|   { | ||||
|     .valve_pin = 47, | ||||
|   }, { // 10
 | ||||
|     .enabled = false, | ||||
|     .led_pin = 42, | ||||
|   }, { // 11
 | ||||
|     .enabled = false, | ||||
|     .led_pin = 44, | ||||
|   }, { // 12
 | ||||
|     .enabled = true, | ||||
|     .led_pin = 46, | ||||
|     .sensor = { | ||||
|       .pin = A12, | ||||
|       .calibration_dry = 520, | ||||
|       .calibration_wet = 100, | ||||
|     } | ||||
|   }, | ||||
|   { | ||||
|     .valve_pin = 49, | ||||
|   }, { // 13
 | ||||
|     .enabled = true, | ||||
|     .led_pin = 48, | ||||
|     .sensor = { | ||||
|       .pin = A13, | ||||
|       .calibration_dry = 520, | ||||
|       .calibration_wet = 100, | ||||
|     } | ||||
|   }, { // 14
 | ||||
|     .enabled = false, | ||||
|     .led_pin = 50, | ||||
|   }, { // 15
 | ||||
|     .enabled = false, | ||||
|     .led_pin = 52, | ||||
|   }, | ||||
|   //{
 | ||||
|   //  .valve_pin = 51,
 | ||||
|   //  .led_pin = 50,
 | ||||
|   //  .sensor = {
 | ||||
|   //    .pin = A14,
 | ||||
|   //    .calibration_dry = 520,
 | ||||
|   //    .calibration_wet = 100,
 | ||||
|   //  }
 | ||||
|   //},
 | ||||
|   //{
 | ||||
|   //  .valve_pin = 53,
 | ||||
|   //  .led_pin = 52,
 | ||||
|   //  .sensor = {
 | ||||
|   //    .pin = A15,
 | ||||
|   //    .calibration_dry = 520,
 | ||||
|   //    .calibration_wet = 100,
 | ||||
|   //  }
 | ||||
|   //},
 | ||||
| }; | ||||
| 
 | ||||
| constexpr unsigned int POT_COUNT = sizeof(POT_CONFIGS) / sizeof(POT_CONFIGS[0]); | ||||
| constexpr struct Sensor SENSORS[] = { | ||||
|   { | ||||
|     .pin = A0, | ||||
|     .calibration_dry = 540, | ||||
|     .calibration_wet = 250, | ||||
|     .pot_group = 0, | ||||
|   }, { | ||||
|     .pin = A4, | ||||
|     .calibration_dry = 520, | ||||
|     .calibration_wet = 100, | ||||
|     .pot_group = 4, | ||||
|   }, { | ||||
|     .pin = A9, | ||||
|     .calibration_dry = 520, | ||||
|     .calibration_wet = 100, | ||||
|     .pot_group = 9, | ||||
|   }, { | ||||
|     .pin = A12, | ||||
|     .calibration_dry = 520, | ||||
|     .calibration_wet = 100, | ||||
|     .pot_group = 12, | ||||
|   }, { | ||||
|     .pin = A13, | ||||
|     .calibration_dry = 520, | ||||
|     .calibration_wet = 100, | ||||
|     .pot_group = 13, | ||||
|   }, | ||||
| 
 | ||||
|   // the rest of A0-A15 are not used
 | ||||
| }; | ||||
| 
 | ||||
| constexpr struct Valve VALVES[] = { | ||||
|   { | ||||
|     .pin = 23, | ||||
|     .pot_group = 0, | ||||
|   }, { | ||||
|     .pin = 25, | ||||
|     .pot_group = 1, | ||||
|   }, { | ||||
|     .pin = 27, | ||||
|     .pot_group = 2, | ||||
|   }, { | ||||
|     .pin = 29, | ||||
|     .pot_group = 3, | ||||
|   }, { | ||||
|     .pin = 31, | ||||
|     .pot_group = 4, | ||||
|   }, { | ||||
|     .pin = 33, | ||||
|     .pot_group = 5, | ||||
|   }, { | ||||
|     .pin = 35, | ||||
|     .pot_group = 6, | ||||
|   }, { | ||||
|     .pin = 37, | ||||
|     .pot_group = 7, | ||||
|   }, { | ||||
|     .pin = 39, | ||||
|     .pot_group = 8, | ||||
|   }, { | ||||
|     .pin = 41, | ||||
|     .pot_group = 9, | ||||
|   }, { | ||||
|     .pin = 43, | ||||
|     .pot_group = 10, | ||||
|   }, { | ||||
|     .pin = 45, | ||||
|     .pot_group = 11, | ||||
|   }, { | ||||
|     .pin = 47, | ||||
|     .pot_group = 12, | ||||
|   }, { | ||||
|     .pin = 49, | ||||
|     .pot_group = 13, | ||||
|   }, { | ||||
|     .pin = 51, | ||||
|     .pot_group = 14, | ||||
|   }, { | ||||
|     .pin = 53, | ||||
|     .pot_group = 15, | ||||
|   } | ||||
| }; | ||||
|  |  | |||
							
								
								
									
										288
									
								
								drop.ino
									
										
									
									
									
								
							
							
						
						
									
										288
									
								
								drop.ino
									
										
									
									
									
								
							|  | @ -1,43 +1,179 @@ | |||
| #include "config.hpp" | ||||
| 
 | ||||
| /// a connected pot
 | ||||
| typedef struct { | ||||
|   PotConfig *config; | ||||
| // TODO: configuration validation subroutine
 | ||||
| // - sensors belong to an existing group
 | ||||
| // - valves belong to an existing group
 | ||||
| // - all groups have a sensor
 | ||||
| 
 | ||||
| constexpr unsigned int VALVE_COUNT = sizeof(VALVES) / sizeof(VALVES[0]); | ||||
| constexpr unsigned int SENSOR_COUNT = sizeof(SENSORS) / sizeof(SENSORS[0]); | ||||
| constexpr unsigned int GROUP_COUNT = sizeof(GROUPS) / sizeof(GROUPS[0]); | ||||
| 
 | ||||
| struct GroupState { | ||||
|   const Group *group_config; | ||||
|   /// pointer to first element of sensors array
 | ||||
|   const Sensor **sensors; | ||||
|   /// element count of sensors array
 | ||||
|   unsigned int sensor_count; | ||||
|   /// pointer to first element of valves array
 | ||||
|   const Valve **valves; | ||||
|   /// element count of valves array
 | ||||
|   unsigned int valve_count; | ||||
| 
 | ||||
|   unsigned long last_watering; | ||||
|   // anything changing per pot goes here
 | ||||
| } Pot; | ||||
| }; | ||||
| 
 | ||||
| /// all connected pots
 | ||||
| Pot pots[POT_COUNT]; | ||||
| GroupState group_states[GROUP_COUNT]; | ||||
| 
 | ||||
| void setup() { | ||||
|   Serial.begin(9600); | ||||
|   Serial.println(""); | ||||
|   Serial.println("Initializing..."); | ||||
| void turn_everything_off() { | ||||
|   set_pump(false); | ||||
| 
 | ||||
|   for (int i = 0; i < VALVE_COUNT; i++) { | ||||
|     set_valve(&VALVES[i], false); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| ///  (╯°□°)╯︵ ┻━┻
 | ||||
| ///
 | ||||
| /// Will never return
 | ||||
| void panic(const __FlashStringHelper *message) { | ||||
|   turn_everything_off(); | ||||
| 
 | ||||
|   // keep doing this until someone notices the blinking lights and looks at the serial output
 | ||||
|   while (true) { | ||||
|     Serial.print(F("PANIC: ")); | ||||
|     Serial.println(message); | ||||
| 
 | ||||
|     digitalWrite(PUMP_LED_PIN, HIGH); | ||||
|     digitalWrite(OK_LED_PIN, LOW); | ||||
|     delay(300); | ||||
|     digitalWrite(PUMP_LED_PIN, LOW); | ||||
|     digitalWrite(OK_LED_PIN, HIGH); | ||||
|     delay(300); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void setup_pinmodes(void) { | ||||
|   Serial.print(F("Setting pin modes...")); | ||||
| 
 | ||||
|   pinMode(PUMP_LED_PIN, OUTPUT); | ||||
|   pinMode(PUMP_PIN, OUTPUT); | ||||
|   pinMode(LED_BUILTIN, OUTPUT); | ||||
|   pinMode(OK_LED_PIN, OUTPUT); | ||||
| 
 | ||||
|   set_pump(false); | ||||
|   for (unsigned int i = 0; i < VALVE_COUNT; i++) | ||||
|     pinMode(VALVES[i].pin, OUTPUT); | ||||
|   for (unsigned int i = 0; i < SENSOR_COUNT; i++) | ||||
|     pinMode(SENSORS[i].pin, INPUT); | ||||
|   for (unsigned int i = 0; i < GROUP_COUNT; i++) | ||||
|     pinMode(GROUPS[i].led_pin, OUTPUT); | ||||
| 
 | ||||
|   // link pots to their config
 | ||||
|   for (unsigned int i = 0; i < POT_COUNT; i++) { | ||||
|     Pot *pot = &pots[i]; | ||||
| 
 | ||||
|     pot->config = &POT_CONFIGS[i]; | ||||
|     pot->last_watering = 0; | ||||
| 
 | ||||
|     pinMode(pot->config->valve_pin, OUTPUT); | ||||
|     pinMode(pot->config->led_pin, OUTPUT); | ||||
| 
 | ||||
|     set_valve(pot->config->valve_pin, false); | ||||
|   } | ||||
|   Serial.println(F(" Done")); | ||||
| } | ||||
| 
 | ||||
| void loop() { | ||||
| void setup_config(void) { | ||||
|   Serial.print(F("Loading configuration...")); | ||||
| 
 | ||||
|   bool found_enabled = false; | ||||
| 
 | ||||
|   for (unsigned int group_index = 0; group_index < GROUP_COUNT; group_index++) { | ||||
|     struct GroupState *group = &group_states[group_index]; | ||||
|     *group = { | ||||
|       .group_config = &GROUPS[group_index], | ||||
|       .sensors = NULL, | ||||
|       .sensor_count = 0, | ||||
|       .valves = NULL, | ||||
|       .valve_count = 0, | ||||
|       .last_watering = 0, | ||||
|     }; | ||||
| 
 | ||||
|     digitalWrite(group->group_config->led_pin, HIGH); | ||||
| 
 | ||||
|     // link valves to group
 | ||||
|     for (unsigned int valve_index = 0; valve_index < VALVE_COUNT; valve_index++) { | ||||
|       if (VALVES[valve_index].pot_group != group_index) | ||||
|         continue; | ||||
| 
 | ||||
|       group->valve_count++; | ||||
|       group->valves = (const Valve **) realloc(group->valves, group->valve_count * sizeof(Valve *)); | ||||
|       if (group->valves == NULL) | ||||
|         panic(F("valve realloc failed")); | ||||
|       group->valves[group->valve_count - 1] = &VALVES[valve_index]; | ||||
|     } | ||||
| 
 | ||||
|     // link sensors to group
 | ||||
|     for (unsigned int sensor_index = 0; sensor_index < SENSOR_COUNT; sensor_index++) { | ||||
|       if (SENSORS[sensor_index].pot_group != group_index) | ||||
|         continue; | ||||
| 
 | ||||
|       group->sensor_count++; | ||||
|       group->sensors = (const Sensor **) realloc(group->sensors, group->sensor_count * sizeof(Sensor *)); | ||||
|       if (group->sensors == NULL) | ||||
|         panic(F("sensor realloc failed")); | ||||
|       group->sensors[group->sensor_count - 1] = &SENSORS[sensor_index]; | ||||
|     } | ||||
| 
 | ||||
|     // check that all enabled groups have valid configuration
 | ||||
|     if (group->group_config->enabled) { | ||||
|       found_enabled = true; | ||||
| 
 | ||||
|       if (group->valve_count == 0) | ||||
|         panic(F("invalid configuration - no valves in enabled group!")); | ||||
|       if (group->sensor_count == 0) | ||||
|         panic(F("invalid configuration - no sensors in enabled group!")); | ||||
|     } | ||||
| 
 | ||||
|     digitalWrite(group->group_config->led_pin, LOW); | ||||
|   } | ||||
| 
 | ||||
|   if (!found_enabled) | ||||
|     panic(F("invalid configuration - all groups are disabled")); | ||||
| 
 | ||||
|   for (unsigned int sensor_index = 0; sensor_index < SENSOR_COUNT; sensor_index++) { | ||||
|     if (SENSORS[sensor_index].pot_group >= GROUP_COUNT) | ||||
|       panic(F("sensor is mapped to group that does not exist")); | ||||
|   } | ||||
| 
 | ||||
|   for (unsigned int valve_index = 0; valve_index < VALVE_COUNT; valve_index++) { | ||||
|     if (VALVES[valve_index].pot_group >= GROUP_COUNT) | ||||
|       panic(F("valve is mapped to group that does not exist")); | ||||
|   } | ||||
| 
 | ||||
|   Serial.println(F(" Done")); | ||||
| } | ||||
| 
 | ||||
| void setup(void) { | ||||
|   Serial.begin(9600); | ||||
|   Serial.println(""); | ||||
|   Serial.println(F("Initializing...")); | ||||
|   setup_pinmodes(); | ||||
|   Serial.print(F("Turning everything off in case of power cycle...")); | ||||
|   turn_everything_off(); | ||||
|   setup_config(); | ||||
|   Serial.println(F("Initialization completed.")); | ||||
| } | ||||
| 
 | ||||
| void water_group(GroupState *state) { | ||||
|   digitalWrite(LED_BUILTIN, HIGH); | ||||
| 
 | ||||
|   for (unsigned int valve_index = 0; valve_index < VALVE_COUNT; valve_index++) { | ||||
|     const Valve *valve = state->valves[valve_index]; | ||||
| 
 | ||||
|     set_valve(valve, HIGH); | ||||
|     set_pump(HIGH); | ||||
| 
 | ||||
|     delay(WATER_TIME_MS); | ||||
|     state->last_watering = millis(); | ||||
| 
 | ||||
|     set_pump(LOW); | ||||
|     set_valve(valve, LOW); | ||||
|   } | ||||
| 
 | ||||
|   digitalWrite(LED_BUILTIN, LOW); | ||||
| } | ||||
| 
 | ||||
| void loop(void) { | ||||
|   Serial.println(""); | ||||
|   Serial.println("LOOP"); | ||||
| 
 | ||||
|  | @ -45,66 +181,46 @@ void loop() { | |||
|   delay(100); | ||||
|   digitalWrite(OK_LED_PIN, LOW); | ||||
| 
 | ||||
|   for (unsigned int g = 0; g < GROUP_COUNT; g++) { | ||||
|     GroupState *state = &group_states[g]; | ||||
|     if (!state->group_config->enabled) | ||||
|       continue; | ||||
| 
 | ||||
|   for (unsigned int i = 0; i < POT_COUNT; i++) { | ||||
|     Serial.print("Pot "); | ||||
|     Serial.println(i); | ||||
|     per_pot(pots[i]); | ||||
|     Serial.println(""); | ||||
|     digitalWrite(state->group_config->led_pin, HIGH); | ||||
| 
 | ||||
|     Serial.print(F("Group ")); | ||||
|     Serial.print(g); | ||||
|     Serial.print(F(": ")); | ||||
| 
 | ||||
|     int humidity = get_group_humidity(state->sensors, state->sensor_count); | ||||
|     Serial.println(humidity); | ||||
| 
 | ||||
|     if (state->last_watering + MIN_WATERING_INTERVAL_MS > millis()) { | ||||
|       Serial.println(F("watered recently -> not watering")); | ||||
|     } else if (humidity > MAX_HUMIDITY_PERCENT) { | ||||
|       Serial.println(F("too wet -> not watering")); | ||||
|     } else if (humidity < MIN_HUMIDITY_PERCENT) { | ||||
|       Serial.println(F("too dry -> watering")); | ||||
|       water_group(state); | ||||
|     } else if (state->last_watering + MAX_WATERING_INTERVAL_MS < millis()) { | ||||
|       Serial.println(F("not been watered for a long time -> watering")); | ||||
|       water_group(state); | ||||
|     } else { | ||||
|       Serial.println(F("happy plant")); | ||||
|     } | ||||
| 
 | ||||
|     digitalWrite(state->group_config->led_pin, LOW); | ||||
|   } | ||||
|    | ||||
| 
 | ||||
|   delay(LOOP_DELAY_MS); | ||||
| } | ||||
| 
 | ||||
| void per_pot(Pot &pot) { | ||||
|   if (pot.last_watering + MIN_WATERING_INTERVAL_MS > millis()) { | ||||
|     Serial.println(F("watered recently -> not watering")); | ||||
|     return; | ||||
|   } | ||||
| 
 | ||||
|   int percentage = get_humidity(pot.config->sensor); | ||||
|   if (percentage > MAX_HUMIDITY_PERCENT) { | ||||
|     Serial.println(F("too wet -> not watering")); | ||||
|   } else if (percentage < MIN_HUMIDITY_PERCENT) { | ||||
|     Serial.println(F("too dry -> watering")); | ||||
|     water_pot(pot); | ||||
|   } else if (pot.last_watering + MAX_WATERING_INTERVAL_MS < millis()) { | ||||
|     Serial.println(F("not been watered for a long time -> watering")); | ||||
|     water_pot(pot); | ||||
|   } else { | ||||
|     Serial.println(F("happy plant")); | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| void water_pot(Pot &pot) { | ||||
|   digitalWrite(LED_BUILTIN, HIGH); | ||||
| 
 | ||||
|   digitalWrite(pot.config->led_pin, HIGH); | ||||
| 
 | ||||
|   set_valve(pot.config->valve_pin, HIGH); | ||||
|   set_pump(HIGH); | ||||
| 
 | ||||
|   delay(WATER_TIME_MS); | ||||
|   pot.last_watering = millis(); | ||||
| 
 | ||||
|   set_pump(LOW); | ||||
|   set_valve(pot.config->valve_pin, LOW); | ||||
| 
 | ||||
|   digitalWrite(pot.config->led_pin, LOW); | ||||
| 
 | ||||
|   digitalWrite(LED_BUILTIN, LOW); | ||||
| } | ||||
| 
 | ||||
| /// get humidity sensor value as a percentage
 | ||||
| int get_humidity(Sensor &sensor) { | ||||
| int get_humidity(const Sensor *&sensor) { | ||||
|   // take average of multiple measurements
 | ||||
|   int sensorVal {0}; | ||||
|   for (unsigned int i = 0; i < MEASUREMENT_COUNT; i++) { | ||||
|     sensorVal += analogRead(sensor.pin); | ||||
|     Serial.print(F("Measurement ")); | ||||
|     Serial.print(i); | ||||
|     Serial.print(F(" = ")); | ||||
|     Serial.println(sensorVal); | ||||
|     sensorVal += analogRead(sensor->pin); | ||||
|     delay(MEASUREMENT_DELAY); | ||||
|   } | ||||
| 
 | ||||
|  | @ -115,11 +231,15 @@ int get_humidity(Sensor &sensor) { | |||
|   // Sensor has a range of e.g. 236 to 520
 | ||||
|   // We want to translate this to a scale or 0% to 100%
 | ||||
|   // More info: https://www.arduino.cc/reference/en/language/functions/math/map/
 | ||||
|   sensorVal = map(sensorVal, sensor.calibration_wet, sensor.calibration_dry, 100, 0); | ||||
|   Serial.print(F("Humidity: ")); | ||||
|   Serial.print(sensorVal); | ||||
|   Serial.println(F("%")); | ||||
|   return sensorVal; | ||||
|   return map(sensorVal, sensor->calibration_wet, sensor->calibration_dry, 100, 0); | ||||
| } | ||||
| 
 | ||||
| int get_group_humidity(const Sensor **sensors, unsigned int sensor_count) { | ||||
|   int sum = 0; | ||||
|   for (unsigned int s = 0; s < sensor_count; s++) { | ||||
|     sum += get_humidity(sensors[s]); | ||||
|   } | ||||
|   return sum / sensor_count; | ||||
| } | ||||
| 
 | ||||
| void set_pump(bool on) { | ||||
|  | @ -130,11 +250,11 @@ void set_pump(bool on) { | |||
|   delay(PUMP_DELAY_MS); | ||||
| } | ||||
| 
 | ||||
| void set_valve(uint8_t valve, bool open) { | ||||
| void set_valve(const Valve *valve, bool open) { | ||||
|   Serial.print("setting valve on pin "); | ||||
|   Serial.print(valve); | ||||
|   Serial.print(valve->pin); | ||||
|   Serial.print(" to state "); | ||||
|   Serial.println(open); | ||||
|   digitalWrite(valve, open ? LOW : HIGH); | ||||
|   digitalWrite(valve->pin, open ? LOW : HIGH); | ||||
|   delay(VALVE_DELAY_MS); | ||||
| } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Vinzenz Schroeter
						Vinzenz Schroeter