Autore: admin

  • GAS

    0
    ATTESA DATI…

  • Il mio termostato

    Progetto Termostato

    Il controller usato:
    Arduino nano

    Piedinatura Arduino

    I sensori usati:

    DHT11: il sensore di temperatura e umidità

    Sensore DHT11

    Il relè:

    KY-019 Funziona bene

    Relè difettoso

    Il display:
    Display OLED I2C SSH1106

    Display OLED

    Il potenziometro: EC11

    Encoder EC11

    Lo Sketch (Versione 11.9.1):

    #include <U8g2lib.h>
    #include <Wire.h>
    
    // --- LIBRERIE NECESSARIE ---
    #include <Adafruit_Sensor.h>
    #include <DHT.h>
    #include <Encoder.h>
    
    // **********************************************
    // DICHIARAZIONE DEI PROTOTIPI
    // **********************************************
    void displayStatus(String status, int interventi);
    void readSensorData();
    
    // **********************************************
    // CONFIGURAZIONE PIN
    // **********************************************
    #define PIN_RELE 7 
    #define DHTPIN 8 
    #define DHTTYPE DHT11
    
    #define ENCODER_CLK_PIN 2 
    #define ENCODER_DT_PIN 3 
    #define ENCODER_SW_PIN 4
    
    // Inizializzazione degli oggetti
    DHT dht(DHTPIN, DHTTYPE); 
    U8G2_SH1106_128X64_NONAME_1_HW_I2C u8g2(U8G2_R0, U8X8_PIN_NONE, A5, A4);
    Encoder myEncoder(ENCODER_CLK_PIN, ENCODER_DT_PIN);
    
    // **********************************************
    // VARIABILI GLOBALI E LOGICA
    // **********************************************
    bool isHeating = false; 
    int conteggioInterventi = 0;
    
    float currentTemperature = 21.0;
    float currentHumidity = 0.0;
    float setpoint_target = 5.0; // Partenza sicura a 5 gradi
    
    const float MIN_TEMP = 5.0; 
    const float MAX_TEMP = 20.0;
    const float STEP_TEMP = 0.25;
    
    // NUOVA ISTERESI: 1 grado di distacco dal Target per la riaccensione
    const float HYSTERESIS = 1.0;
    
    int lastButtonState = HIGH; 
    long oldPosition = -999;
    
    const unsigned long INTERVALLO_LETTURA = 1000; 
    unsigned long ultimoLetturaMillis = 0;
    
    // **********************************************
    // SETUP
    // **********************************************
    void setup() {
    Serial.begin(9600); 
    Serial.println("--- Termostato v11.9.1: Pronto! ---");
    
    pinMode(PIN_RELE, OUTPUT);
    digitalWrite(PIN_RELE, LOW); 
    isHeating = false;
    
    pinMode(ENCODER_SW_PIN, INPUT_PULLUP); 
    
    u8g2.begin();
    u8g2.setFont(u8g2_font_6x10_tf); 
    
    dht.begin();
    
    // Sincronizza encoder con il setpoint iniziale
    myEncoder.write(setpoint_target * (1 / STEP_TEMP)); 
    
    ultimoLetturaMillis = millis();
    readSensorData(); 
    }
    
    // **********************************************
    // LOOP PRINCIPALE
    // **********************************************
    void loop() {
    
    unsigned long currentMillis = millis();
    
    // --- GESTIONE ENCODER (SETPOINT) ---
    long newPosition = myEncoder.read();
    if (newPosition != oldPosition) {
    oldPosition = newPosition;
    float newSetpoint = newPosition * STEP_TEMP; 
    
    if (newSetpoint < MIN_TEMP) {
    newSetpoint = MIN_TEMP;
    myEncoder.write(newSetpoint * (1 / STEP_TEMP)); 
    } else if (newSetpoint > MAX_TEMP) {
    newSetpoint = MAX_TEMP;
    myEncoder.write(newSetpoint * (1 / STEP_TEMP)); 
    }
    setpoint_target = newSetpoint;
    }
    
    // --- LOGICA DI CONTROLLO (OGNI 1 SECONDO) ---
    if (currentMillis - ultimoLetturaMillis >= INTERVALLO_LETTURA) {
    ultimoLetturaMillis = currentMillis; 
    
    readSensorData();
    
    // NUOVA LOGICA: Il Setpoint è il tetto massimo
    // 1. Accensione: se la temperatura scende sotto (Target - 1.0)
    if (!isHeating && currentTemperature <= (setpoint_target - HYSTERESIS)) {
    isHeating = true;
    conteggioInterventi++; 
    Serial.println("Caldaia: ON (Sotto soglia minima)");
    } 
    // 2. Spegnimento: se la temperatura raggiunge il Target
    else if (isHeating && currentTemperature >= setpoint_target) {
    isHeating = false;
    Serial.println("Caldaia: OFF (Target raggiunto)");
    }
    
    // --- LOGICA OSTINATA ANTI-DISTURBO ---
    // Mantiene la tensione sul pin costante senza far scattare il relè
    if (isHeating) {
    digitalWrite(PIN_RELE, HIGH); 
    } else {
    digitalWrite(PIN_RELE, LOW);
    }
    
    displayStatus(isHeating ? "ON" : "OFF", conteggioInterventi);
    } 
    }
    
    // **********************************************
    // FUNZIONI DI SERVIZIO
    // **********************************************
    void readSensorData() {
    float h = dht.readHumidity();
    float t = dht.readTemperature();
    
    if (!isnan(h) && !isnan(t)) {
    currentHumidity = h;
    currentTemperature = t;
    }
    
    Serial.print("T: "); Serial.print(currentTemperature, 1);
    Serial.print(" | Ts: "); Serial.println(setpoint_target, 1);
    }
    
    void displayStatus(String status, int interventi) {
    u8g2.firstPage();
    do {
    u8g2.setFont(u8g2_font_6x10_tf); 
    
    // Riga 1: Temp Attuale e Umidità
    u8g2.drawStr(0, 10, ("Ta: " + String(currentTemperature, 1) + " C").c_str());
    u8g2.drawStr(80, 10, ("H: " + String(currentHumidity, 0) + " %").c_str()); 
    
    // Riga 2: Setpoint Target
    u8g2.drawStr(0, 25, ("Ts: " + String(setpoint_target, 1) + " C").c_str());
    
    // Riga 3: Stato Caldaia
    u8g2.drawStr(0, 40, "CALDAIA:"); 
    u8g2.drawStr(80, 40, status.c_str()); 
    
    // Riga 4: Contatore
    u8g2.drawStr(0, 55, "N Int:"); 
    char buffer[4]; 
    sprintf(buffer, "%03d", interventi); 
    u8g2.drawStr(40, 55, buffer); 
    
    } while ( u8g2.nextPage() );
    }
     
  • Ben venuti nel mio sito.

    Questo è il sito personale di Roberto.

    Io sono un libero professionista che si diletta in varie attività ludiche.

    La mia passione è lo sport in particolare l’esercizio aerobico.
    Al momento mi sto impegnando molto in Mywhoosh.
    https://mywhoosh.com/