/********* Pleasedontcode.com **********
Pleasedontcode thanks you for automatic code generation! Enjoy your code!
- Terms and Conditions:
You have a non-exclusive, revocable, worldwide, royalty-free license
for personal and commercial use. Attribution is optional; modifications
are allowed, but you're responsible for code maintenance. We're not
liable for any loss or damage. For full terms,
please visit pleasedontcode.com/termsandconditions.
- Project: Smart Automation
- Source Code NOT compiled for: ESP32 DevKit V1
- Source Code created on: 2025-11-19 21:19:09
********* Pleasedontcode.com **********/
/****** SYSTEM REQUIREMENTS *****/
/****** SYSTEM REQUIREMENT 1 *****/
/* relé umidificatore On se rh da dht11 <82 e off se */
/* rh da dht11 >85. relé ventole (AC e DC) on 6 volte */
/* in 24 ore per 74 secondi ogni volta. relé luci 12 */
/* ore on e 12 ore off */
/****** END SYSTEM REQUIREMENTS *****/
/* START CODE */
/*******************************************************
* ESP32 + Blynk IoT + DHT11 + Fototransistor + 4 Relè + Buzzer
* - Umidificatore: isteresi RHmin/RHmax (editabili da app)
* - Ventole: 6 cicli/24h, ON 74 s ciascuno (2 relè: DC e AC)
* - Luci: 12 h ON / 12 h OFF (ciclo relativo all'avvio)
* - Fototransistor: verifica accensione luci (soglia editabile)
* - Allarmi (buzzer attivo):
* A) RH < RHmin per 30 min: 1 min beep 1 s ON / 1 s OFF
* B) Luci dovrebbero essere ON ma luce < soglia per 30 min:
* 1 min beep 2 s ON / 2 s OFF
* Dopo 1 min l'allarme si ferma; la finestra 30 min riparte.
*******************************************************/
#define BLYNK_TEMPLATE_ID "TMPL4X0xNGkPD"
#define BLYNK_TEMPLATE_NAME "Camera Fruttificazione"
#define BLYNK_AUTH_TOKEN "yu5gwTTfR31Gf1GBrGyEn8i2rxM7Ie9y"
#define BLYNK_PRINT Serial
#include
#include // Blynk IoT per ESP32 (Virtual Pins, BlynkTimer)
#include // Adafruit DHT library
// ---- Credenziali Wi-Fi ----
char ssid[] = "WiFi";
char pass[] = "azz";
// ====== Pinout ======
#define PIN_DHT 4
#define PIN_PHOTO 34 // ADC1 (necessario con WiFi attivo)
#define PIN_RELAY_HUM 26
#define PIN_RELAY_FAN_DC 27
#define PIN_RELAY_FAN_AC 25
#define PIN_RELAY_LIGHT 33
#define PIN_BUZZER 32
// Moduli relè spesso "active LOW"
#define RELAY_ACTIVE_ON LOW
#define RELAY_ACTIVE_OFF HIGH
// ====== DHT ======
#define DHTTYPE DHT11
DHT dht(PIN_DHT, DHTTYPE);
// ====== Blynk ======
BlynkTimer timer;
// Virtual Pins
#define VP_HUM V0
#define VP_TMP V1
#define VP_HUM_RLY V2
#define VP_FAN_DC V3
#define VP_FAN_AC V4
#define VP_LIGHT_RLY V5
#define VP_PHOTO V6
#define VP_RH_MIN V7
#define VP_RH_MAX V8
#define VP_LUX_THR V9
#define VP_EMERG V10
#define VP_ALARM V11
// ====== Parametri editabili da app (default) ======
volatile float rhMin = 82.0; // % RH
volatile float rhMax = 85.0; // % RH
volatile int lightThreshold = 200; // ADC 0..4095
// ====== Stati ======
bool emergency = false;
bool humidifierOn = false;
bool fanDCOn = false;
bool fanACOn = false;
bool lightsOn = false;
// Scheduli
const unsigned long FAN_PERIOD = 4UL * 60UL * 60UL * 1000UL; // ogni 4 h (6 volte/24h)
const unsigned long FAN_ON_TIME = 74UL * 1000UL; // 74 s
unsigned long nextFanMillis = 0;
const unsigned long LIGHT_HALF_DAY = 12UL * 60UL * 60UL * 1000UL; // 12 h
unsigned long nextLightToggle = 0;
// Allarmi (finestre 30 min)
const unsigned long WINDOW_30M = 30UL * 60UL * 1000UL;
unsigned long lowRHStart = 0;
unsigned long darkStart = 0;
// ====== Buzzer / allarme ======
enum AlarmType { ALARM_NONE, ALARM_HUM_LOW, ALARM_LIGHT_FAIL };
AlarmType currentAlarm = ALARM_NONE;
bool alarmActive = false;
bool buzzerState = false; // stato ON/OFF corrente del buzzer
uint16_t buzzerPeriodMs = 1000; // 1000 o 2000
int buzzerToggleTimerId = -1;
int alarmStopTimerId = -1;
// ====== Prototipi funzioni ======
void setRelay(int pin, bool on);
void publishStates();
void startBuzzer(AlarmType t, uint16_t periodMs, const char* logEventCode, const char* msg);
void readAndPublishSensors();
void controlHumidifier();
void fanScheduler();
void lightScheduler();
void checkAlarms();
// Callback timer (no lambda)
void buzzerToggleTask();
void alarmStopTask();
void fanOffTask();
// ====== Utility ======
void setRelay(int pin, bool on) {
digitalWrite(pin, on ? RELAY_ACTIVE_ON : RELAY_ACTIVE_OFF);
}
void publishStates() {
Blynk.virtualWrite(VP_HUM_RLY, humidifierOn);
Blynk.virtualWrite(VP_FAN_DC, fanDCOn);
Blynk.virtualWrite(VP_FAN_AC, fanACOn);
Blynk.virtualWrite(VP_LIGHT_RLY, lightsOn);
}
// ====== Blynk ======
BLYNK_CONNECTED() {
Blynk.syncVirtual(VP_RH_MIN, VP_RH_MAX, VP_LUX_THR, VP_EMERG);
}
BLYNK_WRITE(VP_RH_MIN) { rhMin = param.asFloat(); }
BLYNK_WRITE(VP_RH_MAX) { rhMax = param.asFloat(); }
BLYNK_WRITE(VP_LUX_THR){ lightThreshold = param.asInt(); }
BLYNK_WRITE(VP_EMERG) {
emergency = param.asInt();
if (emergency) {
// spegni tutto
humidifierOn = fanDCOn = fanACOn = lightsOn = false;
setRelay(PIN_RELAY_HUM, false);
setRelay(PIN_RELAY_FAN_DC,false);
setRelay(PIN_RELAY_FAN_AC,false);
setRelay(PIN_RELAY_LIGHT, false);
publishStates();
} else {
// riavvia scheduler da ora
nextFanMillis = millis() + FAN_PERIOD;
nextLightToggle = millis() + LIGHT_HALF_DAY;
}
}
// ====== Sensori e logiche ======
void readAndPublishSensors() {
float h = dht.readHumidity();
float t = dht.readTemperature();
if (!isnan(h) && !isnan(t)) {
Blynk.virtualWrite(VP_HUM, h);
Blynk.virtualWrite(VP_TMP, t);
}
int raw = analogRead(PIN_PHOTO); // 0..4095
Blynk.virtualWrite(VP_PHOTO, raw);
// Gestione finestre 30 min
unsigned long now = millis();
if (!isnan(h)) {
if (h < rhMin) {
if (lowRHStart == 0) lowRHStart = now;
} else {
lowRHStart = 0;
}
}
if (lightsOn) {
if (raw < lightThreshold) {
if (darkStart == 0) darkStart = now;
} else {
darkStart = 0;
}
} else {
darkStart = 0;
}
}
void controlHumidifier() {
if (emergency || alarmActive) return;
float h = dht.readHumidity();
if (isnan(h)) return;
if (!humidifierOn && h < rhMin) {
humidifierOn = true;
} else if (humidifierOn && h > rhMax) {
humidifierOn = false;
}
setRelay(PIN_RELAY_HUM, humidifierOn);
Blynk.virtualWrite(VP_HUM_RLY, humidifierOn);
}
void fanScheduler() {
if (emergency || alarmActive) return;
unsigned long now = millis();
if (now >= nextFanMillis) {
// Avvia ON di 74 s per entrambe le ventole
fanDCOn = fanACOn = true;
setRelay(PIN_RELAY_FAN_DC, true);
setRelay(PIN_RELAY_FAN_AC, true);
publishStates();
// Spegni dopo 74 s (callback senza lambda)
timer.setTimeout(FAN_ON_TIME, fanOffTask);
nextFanMillis = now + FAN_PERIOD;
}
}
void lightScheduler() {
if (emergency || alarmActive) return;
unsigned long now = millis();
if (now >= nextLightToggle) {
lightsOn = !lightsOn; // 12 h ON / 12 h OFF
setRelay(PIN_RELAY_LIGHT, lightsOn);
Blynk.virtualWrite(VP_LIGHT_RLY, lightsOn);
nextLightToggle = now + LIGHT_HALF_DAY;
}
}
void checkAlarms() {
if (alarmActive || emergency) return;
unsigned long now = millis();
// A) Umidità bassa persistente 30 min
if (lowRHStart != 0 && (now - lowRHStart >= WINDOW_30M)) {
lowRHStart = 0;
startBuzzer(ALARM_HUM_LOW, 1000, "humidity_low_30m", "Umidità sotto soglia per 30 minuti");
return;
}
// B) Luci ON attese ma non rilevate per 30 min
if (darkStart != 0 && (now - darkStart >= WINDOW_30M)) {
darkStart = 0;
startBuzzer(ALARM_LIGHT_FAIL, 2000, "light_fail_30m", "Luci attese ON ma non rilevate per 30 minuti");
return;
}
}
// ====== Buzzer ======
void startBuzzer(AlarmType t, uint16_t periodMs, const char* logEventCode, const char* msg) {
if (alarmActive) return;
alarmActive = true;
currentAlarm = t;
buzzerPeriodMs = periodMs;
if (logEventCode) {
Blynk.logEvent(logEventCode, msg); // Richiede eventi creati nel Template
}
Blynk.virtualWrite(
VP_ALARM,
(t == ALARM_HUM_LOW) ? "ALLARME: Umidità bassa" :
(t == ALARM_LIGHT_FAIL) ? "ALLARME: Luci non rilevate" : ""
);
pinMode(PIN_BUZZER, OUTPUT);
buzzerState = true;
digitalWrite(PIN_BUZZER, HIGH);
// Toggle periodico (1 s o 2 s)
buzzerToggleTimerId = timer.setInterval(buzzerPeriodMs, buzzerToggleTask);
// Stop dopo 60 s
alarmStopTimerId = timer.setTimeout(60UL * 1000UL, alarmStopTask);
}
void buzzerToggleTask() {
buzzerState = !buzzerState;
digitalWrite(PIN_BUZZER, buzzerState ? HIGH : LOW);
}
void alarmStopTask() {
if (buzzerToggleTimerId != -1) {
timer.disable(buzzerToggleTimerId);
timer.deleteTimer(buzzerToggleTimerId);
buzzerToggleTimerId = -1;
}
digitalWrite(PIN_BUZZER, LOW);
alarmActive = false;
currentAlarm = ALARM_NONE;
Blynk.virtualWrite(VP_ALARM, "");
}
void fanOffTask() {
fanDCOn = fanACOn = false;
setRelay(PIN_RELAY_FAN_DC, false);
setRelay(PIN_RELAY_FAN_AC, false);
publishStates();
}
// ====== Setup/Loop ======
void setup() {
Serial.begin(115200);
// Relè
pinMode(PIN_RELAY_HUM, OUTPUT);
pinMode(PIN_RELAY_FAN_DC, OUTPUT);
pinMode(PIN_RELAY_FAN_AC, OUTPUT);
pinMode(PIN_RELAY_LIGHT, OUTPUT);
// Tutto OFF
setRelay(PIN_RELAY_HUM, false);
setRelay(PIN_RELAY_FAN_DC,false);
setRelay(PIN_RELAY_FAN_AC,false);
setRelay(PIN_RELAY_LIGHT, false);
publishStates();
// ADC: 12 bit e attenuazione 11 dB (~0..3.1 V)
analogReadResolution(12);
analogSetPinAttenuation(PIN_PHOTO, ADC_11db);
dht.begin();
Blynk.begin(BLYNK_AUTH_TOKEN, ssid, pass);
// Timers (funzioni senza lambda)
timer.setInterval(2000, readAndPublishSensors); // ogni 2 s
timer.setInterval(1000, controlHumidifier); // ogni 1 s
timer.setInterval(1000, fanScheduler); // ogni 1 s
timer.setInterval(1000, lightScheduler); // ogni 1 s
timer.setInterval(5000, publishStates); // ogni 5 s
timer.setInterval(10000, checkAlarms); // ogni 10 s
// Inizializza scheduler da "adesso"
unsigned long now = millis();
nextFanMillis = now; // prima accensione ventole subito
lightsOn = true; // avvia con 12 h ON
setRelay(PIN_RELAY_LIGHT, lightsOn);
Blynk.virtualWrite(VP_LIGHT_RLY, lightsOn);
nextLightToggle = now + LIGHT_HALF_DAY;
}
void loop() {
Blynk.run();
timer.run();
}
/* END CODE */