Skip to content

Commit

Permalink
Merge pull request #7 from ConnerWill/smart-plug-humidifier
Browse files Browse the repository at this point in the history
Smart plug humidifier
  • Loading branch information
ConnerWill authored Jan 26, 2025
2 parents ff3a546 + fd8e770 commit 25b3cde
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 69 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*.theia/
launch.json
src/main/.theia

*.FCBak
3D-models/ESP32-housing/ESP32-housing.20250126-111227.FCBak

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v5.0.1
v5.1.1
3 changes: 2 additions & 1 deletion src/main/bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,5 @@ const unsigned char bitmap_image[] PROGMEM = {
0x77, 0x77, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff
};

#endif
#endif
//vim: filetype=arduino:shiftwidth=2:softtabstop=2:expandtab:nowrap:cursorline:cursorcolumn:number:relativenumber
29 changes: 18 additions & 11 deletions src/main/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// ============================================================================
// WIFI CONFIGURATION
constexpr char WIFI_SSID[] = ""; // Wi-Fi SSID
constexpr char WIFI_PASSWORD[] = ""; // Wi-Fi password
constexpr char WIFI_PASSWORD[] = "!"; // Wi-Fi password
constexpr char WIFI_HOSTNAME[] = "esp32-plant"; // Hostname
constexpr int WIFI_TIMEOUT_TIME = 30000; // Timeout if unable to connect to WiFi (ms)
constexpr int WIFI_CHECK_INTERVAL = 5000; // Check WiFi time (ms)
Expand All @@ -28,7 +28,7 @@ constexpr int SCREEN_WIDTH = 128; // OLED display width,
constexpr int SCREEN_HEIGHT = 64; // OLED display height, in pixels
constexpr uint8_t SCREEN_ADDRESS = 0x3C; // Address of OLED display (could also be '0x3D' depending on screen resolution)
constexpr int SCREEN_UPDATE_TIME = 1000; // Time to wait before updating OLED (ms)
constexpr int SCREEN_STARTUP_DISPLAY_TIME = 4000; // Startup screen delay time (ms)
constexpr int SCREEN_STARTUP_DISPLAY_TIME = 3000; // Startup screen delay time (ms)
bool SHOW_STARTUP = true; // Set to true to show the startup sequence
bool SHOW_BITMAP = true; // Set to true to show the bitmap
bool SHOW_CUSTOM_TEXT = true; // Set to true to show custom text
Expand All @@ -39,16 +39,23 @@ bool INTERRUPT_WITH_BITMAP = true; // Periodically show bi
constexpr int INTERRUPT_BITMAP_TIME = 300000; // Check WiFi time (ms)

// SMART PLUG CONFIGURATION
const char *intakePlugAlias = "plug_intake"; // Kasa plug alias (Intake)
const char *exhaustPlugAlias = "plug_exhaust"; // Kasa plug aliases (Exhaust)
constexpr int SMARTPLUG_UPDATE_TIME = 30000; // Update smart plugs time (ms)
constexpr float DESIRED_TEMP = 75.0; // Desired temperature in F
constexpr float DESIRED_HUMIDITY = 50.0; // Desired humidity in percentage
constexpr float DESIRED_CO2 = 800.0; // Desired CO2 level (ppm)
constexpr float TEMP_HYSTERESIS = 1.0; // Temperature hysteresis to prevent rapid switching
constexpr float HUMIDITY_HYSTERESIS = 5.0; // Humidity hysteresis to prevent rapid switching
constexpr float CO2_HYSTERESIS = 100.0; // CO2 hysteresis to prevent rapid switching
const char *intakePlugAlias = "tent1_intake"; // Kasa plug alias (Intake)
const char *exhaustPlugAlias = "tent1_exhaust"; // Kasa plug aliases (Exhaust)
const char *humidifierPlugAlias = "tent1_humidifier"; // Kasa plug aliases (Humidifier)
//const char *lightPlugAlias = "tent1_light"; // Kasa plug aliases (Lights)
constexpr int SMARTPLUG_UPDATE_TIME = 30000; // Update smart plugs time (ms)
bool FLOWER = false; // Set to true to set flower mode //TODO: Link this to a physical switch
constexpr float DESIRED_TEMP_VEG = 75.0; // Desired temperature in F (veg)
constexpr float DESIRED_HUMIDITY_VEG = 60.0; // Desired humidity in percentage (veg)
constexpr float DESIRED_CO2_VEG = 800.0; // Desired CO2 level (ppm) (veg)
constexpr float DESIRED_TEMP_FLOWER = 70.0; // Desired temperature in F (flower)
constexpr float DESIRED_HUMIDITY_FLOWER = 45.0; // Desired humidity in percentage (flower)
constexpr float DESIRED_CO2_FLOWER = 1000.0; // Desired CO2 level (ppm) (flower)
constexpr float TEMP_HYSTERESIS = 1.0; // Temperature hysteresis to prevent rapid switching
constexpr float HUMIDITY_HYSTERESIS = 5.0; // Humidity hysteresis to prevent rapid switching
constexpr float CO2_HYSTERESIS = 100.0; // CO2 hysteresis to prevent rapid switching

// SERIAL CONFIGURATION
constexpr int BAUD_RATE = 115200; // Baud rate
// ============================================================================
//vim: filetype=arduino:shiftwidth=2:softtabstop=2:expandtab:nowrap:cursorline:cursorcolumn:number:relativenumber
133 changes: 78 additions & 55 deletions src/main/main.ino
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ AsyncWebServer server(SERVER_PORT); // Define serv
KASAUtil kasaUtil; // Kasa utility object
KASASmartPlug *intakePlug = NULL; // Smart plug pointers (Intake)
KASASmartPlug *exhaustPlug = NULL; // Smart plug pointers (Exhaust)
KASASmartPlug *humidifierPlug = NULL; // Smart plug pointers (Humidifier)
// ============================================================================

// ============================================================================
Expand Down Expand Up @@ -123,10 +124,14 @@ void initSmartPlugs() {
} else if (strcmp(plug->alias, exhaustPlugAlias) == 0) {
exhaustPlug = plug;
Serial.println("Exhaust plug initialized.");
} else if (strcmp(plug->alias, humidifierPlugAlias) == 0) {
humidifierPlug = plug;
Serial.println("Humidifier plug initialized.");
}
}

// Check if plugs were found
//TODO: Could clean this up
if (intakePlug == NULL) {
Serial.println("Error: Intake plug not found!");

Expand All @@ -145,13 +150,21 @@ void initSmartPlugs() {
display.display();
delay(1000);
}
if (humidifierPlug == NULL) {
Serial.println("Error: Humidifier plug not found!");

display.clearDisplay();
display.setCursor(0, 0);
display.print("ERROR: Humidifier plug not found");
display.display();
delay(1000);
}
}

// Function to turn a plug on or off
void setPlugState(KASASmartPlug* plug, bool state) {
// Setting variable for printing. otherwise dont need this
//TODO: Figure out how to turn this into a string
KASASmartPlug *plugAlias = kasaUtil.GetSmartPlug(plug->alias);
//KASASmartPlug *plugAlias = kasaUtil.GetSmartPlug(plug->alias);

if (plug == NULL) {
//Serial.printf("Error: Could not find plug with alias '%s'\n", plugAlias);
Expand All @@ -167,7 +180,38 @@ void setPlugState(KASASmartPlug* plug, bool state) {
}
}

//TODO: Function to get plug state
// Function to control fans based on temperature
void handleTemperature(float temperatureF, float desiredTemp, const char* mode) {
if (temperatureF > desiredTemp + TEMP_HYSTERESIS) { // Temp too high
Serial.printf("Temperature too high in %s mode! Turning on intake and exhaust fans...\n", mode); //
setPlugState(exhaustPlug, true); // Turn on exhaust fan
setPlugState(intakePlug, true); // Turn on intake fan

} else if (temperatureF < desiredTemp - TEMP_HYSTERESIS) { // Temp too low
Serial.printf("Temperature too low in %s mode! Turning off intake and exhaust fans...\n", mode); //
setPlugState(exhaustPlug, false); // Turn off exhaust fan
setPlugState(intakePlug, false); // Turn off intake fan

} else { // Temperature within range
setPlugState(exhaustPlug, false); // Turn off exhaust fan to save energy
setPlugState(intakePlug, false); // Turn off intake fan to save energy
}
}

// Function to control humidifier based on humidity
void handleHumidity(float humidity, float desiredHumidity, const char* mode) {
if (humidity > desiredHumidity + HUMIDITY_HYSTERESIS) { // Humidity too high
Serial.printf("Humidity too high in %s mode! Turning off humidifier...\n", mode); //
setPlugState(humidifierPlug, false); // Turn off humidifier

} else if (humidity < desiredHumidity - HUMIDITY_HYSTERESIS) { // Humidity too low
Serial.printf("Humidity too low in %s mode! Turning on humidifier...\n", mode); //
setPlugState(humidifierPlug, true); // Turn on humidifier

} else { // Humidity within range
setPlugState(humidifierPlug, false); // Turn off humidifier to save energy
}
}

// -------------------------------------
// WIFI Functions
Expand Down Expand Up @@ -246,27 +290,34 @@ void initOLED() {
}

// Default text settings
display.clearDisplay();
display.cp437(true); // Use correct CP437 character codes
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.clearDisplay();
}


// Function to show startup display
void showStart() {
int16_t text_x, text_y;
uint16_t text_w, text_h;

// Clear display, set size
display.clearDisplay();
display.setTextSize(3);
display.setTextSize(2);
display.setTextColor(SSD1306_WHITE);
display.setCursor(32, 16);
display.println(STARTUP_TEXT);
display.display();

// Scroll diag right
//display.startscrolldiagright(0x00, 0x07);
// Scroll left
display.startscrollleft(0x00, 0x0F);
// Calculate text bounds (0, 0 is a dummy position for now)
display.getTextBounds(STARTUP_TEXT, 0, 0, &text_x, &text_y, &text_w, &text_h);

// Calculate coordinates to center the text
int16_t x = (SCREEN_WIDTH - text_w) / 2;
int16_t y = (SCREEN_HEIGHT - text_h) / 2;

display.setCursor(x, y);
display.print(STARTUP_TEXT);
display.display();
delay(SCREEN_STARTUP_DISPLAY_TIME);
display.stopscroll();
display.clearDisplay();
}

Expand Down Expand Up @@ -327,13 +378,17 @@ void updateOLED(float co2, float temperature, float temperatureF, float humidity
display.setCursor(0, 16);
display.print("Temp: ");
display.print(temperature);
display.println(" C");
display.print(" "); // print space
display.write(0xF8); // Print the degrees symbol
display.println("C");

// Temperature
display.setCursor(0, 26);
display.print("Temp: ");
display.print(temperatureF);
display.println(" F");
display.print(" "); // print space
display.write(0xF8); // Print the degrees symbol
display.println("F");

// Humidity
display.setCursor(0, 36);
Expand Down Expand Up @@ -448,15 +503,6 @@ void loop() {
}
}

/*
* Temperature Too High -> Turn on the exhaust fan, consider additional cooling (e.g., A/C).
* Temperature Too Low -> Turn off the exhaust fan, possibly add a heater.
* Humidity Too High -> Turn on the exhaust fan to vent humid air, or use a dehumidifier.
* Humidity Too Low -> Turn off the exhaust fan, reduce intake, and add a humidifier if needed.
* CO2 Too High -> Turn on the exhaust fan to vent excess CO2.
* CO2 Too Low -> Turn off the exhaust fan to retain CO2, or add a CO2 source.
*/

// Update Smart plugs
if (currentTime - lastPlugCheck >= SMARTPLUG_UPDATE_TIME) {
lastPlugCheck = currentTime;
Expand All @@ -467,40 +513,16 @@ void loop() {
float temperatureF = celsiusToFahrenheit(temperature);
float humidity = readHumidity();

// Temperature control logic
if (temperatureF > DESIRED_TEMP + TEMP_HYSTERESIS) { // Temp too high
Serial.println(F("Temperature too high! Turning on intake and exhaust fans..."));
setPlugState(exhaustPlug, true); // Turn on exhaust fan
setPlugState(intakePlug, true); // Turn on intake fan
} else if (temperatureF < DESIRED_TEMP - TEMP_HYSTERESIS) { // Temp too low
Serial.println(F("Temperature too low! Turning off intake and exhaust fans..."));
setPlugState(exhaustPlug, false); // Turn off exhaust fan
setPlugState(intakePlug, false); // Turn off intake fan
} else {
// If temperature is within the target range, turn off fans to save energy
setPlugState(exhaustPlug, false); // Turn off exhaust fan
setPlugState(intakePlug, false); // Turn off intake fan
}
// Determine mode (Flower or Veg) and set desired values
const char* mode = FLOWER ? "FLOWER" : "VEG";
float desiredTemp = FLOWER ? DESIRED_TEMP_FLOWER : DESIRED_TEMP_VEG;
float desiredHumidity = FLOWER ? DESIRED_HUMIDITY_FLOWER : DESIRED_HUMIDITY_VEG;

// // Humidity control logic
// if (humidity > DESIRED_HUMIDITY + HUMIDITY_HYSTERESIS) { // Humidity too high
// Serial.println(F("Humidity too high! Turning on exhaust fan..."));
// setPlugState(exhaustPlug, true); // Turn on exhaust fan
// } else if (humidity < DESIRED_HUMIDITY - HUMIDITY_HYSTERESIS) { // Humidity too low
// Serial.println(F("Humidity too low! Turning off intake and exhaust fans..."));
// setPlugState(intakePlug, false); // Turn off intake fan
// setPlugState(exhaustPlug, false); // Turn off exhaust fan
// // Optionally, activate a humidifier if available
// } else {
// // If humidity is within the target range, turn off fans to save energy
// setPlugState(exhaustPlug, false); // Turn off exhaust fan
// setPlugState(intakePlug, false); // Turn off intake fan
// }

//TODO: Add CO2 levels
// Handle temperature and humidity
handleTemperature(temperatureF, desiredTemp, mode);
handleHumidity(humidity, desiredHumidity, mode);
}


// Periodically show bitmap
if (INTERRUPT_WITH_BITMAP) {
if (currentTime - lastBitmapCheck >= INTERRUPT_BITMAP_TIME) {
Expand All @@ -510,3 +532,4 @@ void loop() {
}
}
// ============================================================================
//vim: filetype=arduino:shiftwidth=2:softtabstop=2:expandtab:nowrap:cursorline:cursorcolumn:number:relativenumber

0 comments on commit 25b3cde

Please sign in to comment.