Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 108 additions & 1 deletion arduino/ctrl_box_esp32.ino
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ const unsigned long tempCheckPeriod = 30000; // How long to wait, in mil
const unsigned long tempCompPeriod = 600000; // How long to wait, in milliseconds, between sending temperature compensation factor to ezo pH circuit
unsigned long atlasPeriod = 5000; // How long to wait, in milliseconds, between polling Atlas sensors for values
unsigned long dosingPumpPeriod[6]; // Array of modifiable "pump on" times that are sent by Home Assistant. These determine how long to keep pump on before shutting off.
// Fan control variables
unsigned long fanLastCommandTime = millis(); // Timer to track when last fan command was sent
const unsigned long fanTimeout = 10000; // Timeout period in milliseconds to ensure fan doesn't stop due to control system failure

// WiFi/MQTT/Serial
const char* ssid = "YOUR___SSID";
Expand Down Expand Up @@ -73,6 +76,12 @@ const int dosingPumpPWMpin[6]
};
const int pwmNoctuaFanPin = 15;

// Fan control variables
float fanTempSetpoint = 25.0; // Temperature setpoint for fan activation (default 25°C)
float fanHumiditySetpoint = 60.0; // Humidity setpoint for fan activation (default 60%)
String fanMode = "auto"; // Fan mode: "auto" or "manual"
int manualFanSpeed = 125; // Manual fan speed setting (0-255)

// PWM properties
const int freq = 5000;
const int resolution = 8;
Expand Down Expand Up @@ -252,6 +261,35 @@ void callback(char* topic, byte* payload, unsigned int length)
}
}
}

/***************** CALLBACK: Fan Control *****************/
// Handle temperature setpoint updates from Home Assistant
if (strcmp(topic, "control/fan/temperature_setpoint") == 0) {
fanTempSetpoint = atof(payloadStr);
// Send confirmation back to Home Assistant
client.publish("feedback/fan/temperature_setpoint", payloadStr);
}

// Handle humidity setpoint updates from Home Assistant
if (strcmp(topic, "control/fan/humidity_setpoint") == 0) {
fanHumiditySetpoint = atof(payloadStr);
// Send confirmation back to Home Assistant
client.publish("feedback/fan/humidity_setpoint", payloadStr);
}

// Handle fan mode updates from Home Assistant
if (strcmp(topic, "control/fan/mode") == 0) {
fanMode = payloadStr;
// Send confirmation back to Home Assistant
client.publish("feedback/fan/mode", payloadStr);
}

// Handle manual fan speed updates from Home Assistant (when in manual mode)
if (strcmp(topic, "control/fan/speed") == 0) {
manualFanSpeed = atoi(payloadStr);
// Send confirmation back to Home Assistant
client.publish("feedback/fan/speed", payloadStr);
}
}

void reconnect()
Expand Down Expand Up @@ -345,6 +383,10 @@ void loop()
{
getWaterTemp();
getBoxTemp();

// Enhanced fan control based on temperature and humidity readings
controlFanBasedOnConditions(boxTemperature, humidity);

tempCheckMillis = currentMillis;
}

Expand Down Expand Up @@ -385,6 +427,14 @@ void loop()

recvWithStartEndMarkers(); // Gather data sent from Mega over serial
processSerialData();

// Enhanced fan control with watchdog mechanism
// Check if fan control has timed out and ensure fan continues operation
if (fanLastCommandTime > 0 && (currentMillis - fanLastCommandTime > fanTimeout)) {
// If no command received in timeout period, run fan at minimum safe speed
ledcWrite(pwmChannel[NOCTUA], 150); // Safe minimum speed
}

client.loop(); // MQTT client loop is required at end of void loop().
}

Expand Down Expand Up @@ -514,6 +564,58 @@ void processSerialData()
}
}

// Function to control fan based on temperature and humidity conditions with setpoints
// This function adjusts fan speed automatically based on sensor readings and user-defined setpoints
void controlFanBasedOnConditions(float temperature, float humidity) {
// Check if fan control is in manual mode
if (fanMode == "manual") {
// Use manual speed setting
ledcWrite(pwmChannel[NOCTUA], manualFanSpeed);
fanLastCommandTime = millis();
return;
}

// Auto mode - use setpoints for fan control logic
int fanSpeed = 0;

// If temperature is above threshold, set appropriate fan speed
if (temperature > fanTempSetpoint) {
// Calculate temperature difference from setpoint
float tempDiff = temperature - fanTempSetpoint;

// Increase fan speed based on how much above threshold
fanSpeed = 100 + (tempDiff * 10); // Scale fan speed with temperature difference

// Ensure fan doesn't exceed maximum speed
if (fanSpeed > 255) {
fanSpeed = 255;
}

// Add humidity consideration (if humidity is also above setpoint, increase fan speed further)
if (humidity > fanHumiditySetpoint) {
float humidityDiff = humidity - fanHumiditySetpoint;
fanSpeed += humidityDiff * 2; // Additional speed for high humidity

// Ensure max speed is not exceeded
if (fanSpeed > 255) {
fanSpeed = 255;
}
}
}

// Apply calculated fan speed
if (fanSpeed > 0) {
ledcWrite(pwmChannel[NOCTUA], fanSpeed);
} else {
// Turn fan off when below setpoint
ledcWrite(pwmChannel[NOCTUA], 0);
}

// Update watchdog timer to indicate that fan control is still active
fanLastCommandTime = millis();
}


void getWaterTemp()
{
float f = celcius;
Expand All @@ -526,9 +628,14 @@ void getWaterTemp()
}
}

float boxTemperature = 0; // Store the current box temperature for fan control
float humidity = 0; // Store the current humidity for fan control

void getBoxTemp()
{
dtostrf(bme.readTemperature(), 3, 1, bmeBuffer);
boxTemperature = bme.readTemperature();
humidity = bme.readHumidity();
dtostrf(boxTemperature, 3, 1, bmeBuffer);
client.publish("feedback/boxTemp", bmeBuffer);
}

Expand Down