// Nucleo + Wokwi: sensors + LCD1602A for Temp/Humidity display
// LCD1602A (HD44780 parallel, 4-bit):
// RS=PB8, E=PB9, D4=PB10, D5=PB11, D6=PA11, D7=PB13, RW=GND
// Alimentazione: usa E5V nel diagramma (non 5V).
#include <LiquidCrystal.h>
#if defined(ARDUINO_ARCH_STM32)
#define PIN_SOIL PA0
#define PIN_TEMP PA1
#define PIN_HUM PA4
#define PIN_TANK PB1
#define PIN_PUMP PA5
// LCD pins
#define LCD_RS PB8
#define LCD_E PB9
#define LCD_D4 PB10
#define LCD_D5 PB11
#define LCD_D6 PA11
#define LCD_D7 PB13
#else
#error "Questo sketch è per STM32 (Arduino core)."
#endif
LiquidCrystal lcd(LCD_RS, LCD_E, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
// ---- Parametri controllo ----
const float TH_LOW = 40.0; // %
const float TH_HIGH = 50.0; // %
const unsigned long T_ON_MAX_MS = 20000UL; // 20 s
// ---- Campionamento / ADC ----
const unsigned SAMPLE_MS = 500;
const int ADC_BITS = 12; // STM32: 12-bit
const float ADC_FS = (float)((1 << ADC_BITS) - 1); // 4095
const float VREF = 5.0; // chip 0..5V
bool pumpOn = false;
unsigned long pumpStartMs = 0;
unsigned long lastSample = 0;
static inline float clampf(float x, float lo, float hi) {
if (x < lo) return lo;
if (x > hi) return hi;
return x;
}
static inline float readVoltage(int pin) {
int raw = analogRead(pin);
return (raw / ADC_FS) * VREF;
}
static inline float readPercentFromVoltage(float v) {
return clampf((v / 5.0f) * 100.0f, 0.0f, 100.0f);
}
void setup() {
Serial.begin(115200);
delay(300);
analogReadResolution(ADC_BITS);
pinMode(PIN_PUMP, OUTPUT);
digitalWrite(PIN_PUMP, LOW);
pinMode(PIN_TANK, INPUT);
// LCD
lcd.begin(16, 2);
lcd.clear();
lcd.setCursor(0, 0); lcd.print("Irrigation demo");
lcd.setCursor(0, 1); lcd.print("Temp/Hum display");
delay(800);
}
void loop() {
const unsigned long now = millis();
if (now - lastSample < SAMPLE_MS) return;
lastSample = now;
// --- Letture ---
const float vSoil = readVoltage(PIN_SOIL);
const float vTemp = readVoltage(PIN_TEMP);
const float vHum = readVoltage(PIN_HUM);
const float soilPct = readPercentFromVoltage(vSoil);
const float humPct = readPercentFromVoltage(vHum);
const float tempC = vTemp * 100.0f; // LM35: 10 mV/°C
const bool tankOK = (digitalRead(PIN_TANK) == HIGH);
// --- Controllo (isteresi + timeout) ---
if (!tankOK) {
pumpOn = false;
} else {
if (!pumpOn && soilPct < TH_LOW) {
pumpOn = true; pumpStartMs = now;
}
if (pumpOn && (soilPct >= TH_HIGH)) pumpOn = false;
if (pumpOn && (now - pumpStartMs >= T_ON_MAX_MS)) pumpOn = false;
}
// --- Attuatore ---
digitalWrite(PIN_PUMP, pumpOn ? HIGH : LOW);
// --- LCD: scrivi NUMERI, pulendo ogni riga con 16 spazi ---
// Riga 0: "T:xx.xC H:yy.y%"
lcd.setCursor(0, 0); lcd.print(" ");
lcd.setCursor(0, 0);
lcd.print("T:"); lcd.print(tempC, 1); lcd.print("C ");
lcd.print("H:"); lcd.print(humPct, 1); lcd.print("%");
// Riga 1: stato rapido
lcd.setCursor(0, 1); lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print("P:"); lcd.print(pumpOn ? "ON " : "OFF");
lcd.print(" Tank:"); lcd.print(tankOK ? "OK " : "NO ");
// --- Serial log (opzionale) ---
static uint32_t line = 0;
if ((line++ % 16) == 0) {
Serial.println(F(" time[s] | soil[%] | temp[C] | hum[%] | tank | pump "));
Serial.println(F("---------+--------+---------+--------+------+------"));
}
Serial.print(now / 1000.0f, 1); Serial.print(" | ");
Serial.print(soilPct, 1); Serial.print(" | ");
Serial.print(tempC, 1); Serial.print(" | ");
Serial.print(humPct, 1); Serial.print(" | ");
Serial.print(tankOK ? "OK" : "NO"); Serial.print(" | ");
Serial.println(pumpOn ? "ON" : "OFF");
}