Problemi con il codice, soglie temperatura

Buongiorno,

Sto "costruendo" un serra non troppo grande con mio padre, sono riuscito bene o male a scrivere tutto il codice ma c'è una parte che non mi è proprio chiara, la parte della gestione delle ventole (premetto che è circa una settimana che cerco ovunque una possibile soluzione cercando su internet, chiedendo ad amici e anche su vari forum ma senza alcun successo);

Il problema che mi porto avanti e che non riesco a risolvere è evitare che le ventole (azionate una volta superata una certa soglia di temperatura rilevata da un DHT11) facciano da "interruttore" ovvero attacca e stacca, in quanto inizialmente le avevo programmate così e in questo modo appena varcata di un grado la soglia partono le ventole e pochi secondi dopo si spengono dato l'abbassamento della temperatura di 1 °C facendo così un attacca e stacca continuo;

 if (t > valore_massimo_temp)
   digitalWrite (10, HIGH); // Attiva Relè 2
  else
    digitalWrite (10, LOW); // Spegni Relè 2

Forse mi sono dilungato troppo ma era in modo da rendere il tutto più chiaro,

La cosa che non riesco a fare è quindi scrivere la parte di codice relativa all'accensione delle ventole che permetta ad esse di accendersi superata una certa soglia ( quindi quando t >= valore_massimo_temp che è da me impostato a 40 °C) e rimanere accese fin quando la temperatura non scenda sotto ad un'altra soglia, quella della temperatura ideale (quindi quando t <=valore_ideale_temp che è da me impostato a 35 °C).

Ho provato in mille modi, con mille variabili e con mille cicli ma essendo alle prime armi purtroppo senza successo.
Spero vivamente che qualche saggio di Arduino o della programmazione riesca ad aiutarmi, Grazie mille in anticipo. :smile:

Buongiorno e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE (... quello che vedi in blu è un link, fai click su di esso per raggiungere la discussione) spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

Presa visione del regolamento e presentazione compilata , spero possa andar bene :laughing:

Il problema sembra relativo alla mancanza di isteresi, posta il codice.
Se il codice è molto grande conviene creare uno sketch di massima che comprenda il sensore, il comando (relè o altro) e il codice che in relazione alla temperatura esegue il codice.

Qui a seguire un link al primo dei 3 articoli su termostati con arduino:

Ciao.

1 Like

Devi creare un ciclo di isteresi in modo da avere due soglie differenziate.
Esempio:

  // Controllo del relè con isteresi
  if (t > valore_massimo_temp + isteresi) {
   digitalWrite (10, HIGH); // Attiva Relè 2
  } else if (t < valore_massimo_temp - isteresi) {
    digitalWrite (10, LOW); // Spegni Relè 2
  }

Il valore della isteresi lo puoi inizializzare con:
const float isteresi = 2.0; // isteresi

1 Like

Ciao, mi informerò sull'argomento isteresi,

Questa è la parte di codice relativa alla gestione del relè delle ventole in base alla temperatura:

const int valore_massimo_temp = 40; //Temperatura massima che la serra può raggiungere
const int valore_ideale_temp = 35; //Temperatura ideale della serra alla quale deve essere riportata dalle ventole non appena si è raggiunta la temperatura massima
bool att_ventola = LOW;
int t=0, h=0, 

//librerie per DHT11
#include "DHT.h"
#define DHTPIN 12    //sensore collegato al pin 12 
#define DHTTYPE DHT11 
DHT dht(DHTPIN, DHTTYPE);

void setup() {

  // PIN 10 al relè - IN2
  pinMode(10, OUTPUT);

  // Avvio sensore DHT11  
  dht.begin();
}

void loop() {
 
  // Lettura umidità e temperatura del sensore DHT11
  h = dht.readHumidity();
  t = dht.readTemperature();

  // Misura la temperatura e se maggiore di 39 gradi attiva relè per accendere la ventola
  if (t >= valore_massimo_temp){
    att_ventola = HIGH;
  }
  if(att_ventola == HIGH){
    digitalWrite (10, HIGH); // Attiva Relè 2
    if(t <= valore_ideale_temp){
      digitalWrite (10, LOW); // Spegni Relè 2
      att_ventola = LOW;
    }
  }

Nel frattempo cercherò di capire qualcosa di questa isteresi :grimacing:

Leggi il link postato da MauroTec.

1 Like

Ciao, come dicevo prima mi studierò l'isteresi,

nel frattempo ne approfitto per ringraziarti e per dei chiarimenti:

dato che la temperatura ideale è 35 gradi e la massima è 40 gradi, nel mio codice l'inizializzazione dell'isteresi dovrà essere così ? ---> const float isteresi = 5.0; // isteresi

Usi già due soglie di temperatura.

OFF->ON SE T >= 40
ON->OFF SE T <= 35

ISTERESI = 40 - 35 = 5°C.

Con 5° di isteresi per quanto tempo resta accesa la ventola?

Ciao.

1 Like

Purtroppo non ho ancora avuto modo di verificare la cosa dato il mio non riuscire a trovare un codice adeguato; comunque uso due ventole da 5V che posso tranquillamente sostituire con ventole da 12V, quindi in caso il tempo sia troppo elevato posso provare delle combinazioni e cercare la soluzione più adeguata.

... attento perché di queste qui NON puoi parlare ... ti ricordo il REGOLAMENTO, punto 15 e suoi sottopunti.

Guglielmo

Chiedo venia, ho modificato il messaggio

1 Like

Ok, il codice che hai postato qui: Problemi con il codice, soglie temperatura - #6 by francesco-2202
lo hai scritto al volo e non lo hai ancora testato.

valore ideale_temp = valore_massimo_temp - isteresi

I termostati elettromeccanici hanno 5°C di isteresi, mentre per quelli digitali usati nel frigo di casa in genere isteresi = 2°C.

C'è anche da considerare la temperatura dell'aria prelevata dalla ventola in aspirazione e la posizione della sonda tenendo conto che il calore si stratifica e la massima temperatura si ha nel cielo (tetto).

Ciao.

1 Like

Cercherò di creare meno confusione possibile,

ora sono impossibilitato a provare il codice sulla serra, quindi mi sono fatto un piccolo impiantino su una breadboard con un termistore ed un led, in modo tale da replicare lo stesso principio e provare ad ultimare il codice,

const float isteresi = 25;
int valore_base = 270;
int valore_massimo = valore_base + isteresi;
int valore_ideale = valore_massimo - isteresi;

void setup() {

  Serial.begin(9600);
  pinMode(12, OUTPUT);
}

void loop() {
  
  int v = analogRead(A0);
  Serial.println(v);

  digitalWrite(12, LOW);

if (v >= valore_massimo){
  digitalWrite(12,HIGH);
   Serial.println("soglia massima varcata");

} else if (v <= valore_ideale){
  digitalWrite (10, LOW);
  Serial.println("soglia ideale ");

 }

  delay(500);
}

Sicuramente sbaglio, però il problema che mi si pone è sempre lo stesso finche la temperatura è maggiore della soglia massima allora il led (ventola per la serra) si accende, il problema è che appena la temperatura si abbassa al di sotto della soglia massima allora l'esecuzione del codice non entra più nell'if.

Come posso fare quindi? ho provato ad usare l'isteresi ma non riesco comunque, dove sbaglio?

Grazie mille ancora per la vostra disponibilità.

const float isteresi = 25;
int valore_base = 270;
int valore_massimo = valore_base + isteresi;
int valore_ideale = valore_base - isteresi;
// valore_massimo = 270 + 25 = 295
//  valore_ideale = 270 - 25 = 245
// In questo caso isteresi vale 50 perché la differenza tra le due soglie
// Isteresi = 295 - 245 = 50.
// Per usare isteresi = 25
// int valore_massimo = valore_base 

void setup() {

  Serial.begin(9600);
  pinMode(12, OUTPUT);
}

void loop() {
  
  int v = analogRead(A0);
  Serial.println(v);

  digitalWrite(12, LOW);

if (v >= valore_massimo){
  digitalWrite(12,HIGH);
   Serial.println("soglia massima varcata");

} else if (v <= valore_ideale){
  digitalWrite (10, LOW);
  Serial.println("soglia ideale ");

 }

}

Meglio uniformarsi con la terminologia standard in cui il setpoint è il punto di intervento in cui deve accadere qualcosa.

# Pseudo codice
// t = 40.01 °C
// setpoint = 40.0 °C
// isteresi = 5.0
if (t >= setpoint) {  // soglia OFF->ON
    fan(ON);
} else if (t <= setpoint - isteresi) { // soglia ON->OFF
   fan(OFF);
}

La soglia ON->OFF vale 40 - 5 = 35 (setpoint - isteresi), quando t <= 35 si spegne la ventola.

Il caso specifico lo equiparo a quello del frigorifero, poiché accendendo la ventola la temperatura tenderà a scendere, allora la funzione del termostato cambia leggermente:

// Il valore di g_setpoint è regolato tramite un potenziometro e 
// supponiamo di regolarlo a 35.0°C.

bool checkThermostate(bool state) {
  switch (state) {
    case LOW: // 40°C >= 35°C + 5°C = 40°C accende ventola
    if (g_temperature >= g_setpoint + g_isteresi) {
        state = HIGH;
    }
    break;
    case HIGH: // 35°C <= 35°C spegne ventola
    if (g_temperature <= g_setpoint) {
        state = LOW;
    }
    break;
     
  } // end switch (thermostateState)
  return state;
} // end checkThermostate()

Ciao.

Grazie al vostro aiuto ho risolto la problematica, in questo modo:

#define soglia_on 400
#define soglia_off 370

int stato = LOW;

void setup() {

  Serial.begin(9600);
  pinMode(12, OUTPUT);
}

void loop() {
  
  int v = analogRead(A0);
  Serial.println(v);

if (v >= soglia_on){
  stato = HIGH;
    Serial.println("ventole accese");
}
if (v < soglia_off){
  stato = LOW;
    Serial.println("temperatura ideale");
 
}
   digitalWrite(12, stato);
  delay(2500);
}

Ora proverò ad adattare questo codice alla serra;
Grazie ancora a tutti. :smile:.

Ottimo, hai soglie fisse e isteresi di 400 - 370 = 30.
Però ti sconsiglio di applicarlo paro paro nella serra.
Quanto meno se preferisci fatti un tua funzione da richiamare nel loop. Quando si sposta il codice in una funzione si da per scontato che il codice funziona ed è testato e metterlo in una funzione significa rimuoverlo dal loop dove involontariamente si possono apportare modifiche. :wink:

Ciao.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.