Ciao a tutti,
sto impazzendo dietro un progetto di controllo di una minuscola serra tramite arduino.
In pratica uso un sensore di temperatura lm35 e uno di umidità analogico a forcella di cui ora non ricordo il nome.
In sostanza i problemi sono 2: LM35 sul display mi fornisce dei valori di temperatura estremamente variabili che generalmente oscillano dalla temperatura corretta ai 40 °C di secondo in secondo (a volte 400 :o ) e non riesco a capire il perchè.
inoltre i comandi che avviano l'apertura, la chiusura della serra, le ventole e l'irrigazione di fatto non fanno niente. Ho sempre attiva l'uscita digitale sul pin 3 e basta.
Qualche anima pia mi spiega in parole semplici qual è il problema del codice?
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
int mot_av= 3; //il motore gira avanti e apre la serra
int mot_ind= 4; //il motore gira indietro e chiude la serra
int ventola= 5; // inizia a girare la ventola
int pompa= 6; //avvia la pompa
int LM35= A0;
int sensor;
float celsius;
float millivolts;
int stato = 0; // se stato=1 serra aperta, se stato=0 serra chiusa
int sensorU =A3;
int Hum;
int Valore;
LiquidCrystal_I2C lcd(0x27, 16, 2);
void setup() {
pinMode(mot_av, OUTPUT);
pinMode(mot_ind, OUTPUT);
pinMode(ventola, OUTPUT);
pinMode(pompa, OUTPUT);
pinMode(LM35, INPUT);
pinMode(sensorU, INPUT);
}
void loop() {
sensor=analogRead(LM35);
millivolts=(sensor/1024.0)*5000;
celsius=millivolts/10;
Valore = analogRead(sensorU);
Hum = map(Valore, 1023, 220, 0, 100);
delay(1000);
lcd.init(); //init dice che non esiste
lcd.backlight();
lcd.setCursor(0,0);
lcd.print("Temp");
lcd.setCursor(5,0);
lcd.print(celsius);
lcd.setCursor(11,0);
lcd.print("C");
lcd.setCursor(0,1);
lcd.print("Umid");
lcd.setCursor(5,1);
lcd.print(Hum);
lcd.setCursor(11,1);
lcd.print("%");
Serial.print(Hum);
if ((celsius<21)&&(stato==1)){ //chiusura
digitalWrite(mot_av, LOW);
digitalWrite(mot_ind, HIGH);
delay(2000);
stato=0;
}
/*else {
digitalWrite(mot_ind, LOW);
}*/
if ((celsius>21)&&(stato==0)){
digitalWrite(mot_av, HIGH);
digitalWrite(mot_ind, LOW);
delay(10000);
stato=1;
}
/*else {
digitalWrite(mot_av, LOW);
}*/
if (celsius>28){
digitalWrite(ventola, HIGH); }
else {
digitalWrite(ventola, LOW);
}
if (digitalRead(Hum<50)){
digitalWrite(pompa, HIGH);
}
else {
digitalWrite(pompa, LOW);}
}
le due letture dai 2 pin analogici fatte di seguito una all'altra danno (nel secondo) un valore errato, devi leggerlo 2 volte buttando via il primo risultato
void loop() {
sensor=analogRead(LM35);
millivolts=(sensor/1024.0)*5000;
celsius=millivolts/10;
//aggiungiamo anche un piccolo delay :-)
Valore = analogRead(sensorU); //prima lettura da scartare
delay(20);
Valore = analogRead(sensorU); // seconda lettura corretta
Hum = map(Valore, 1023, 220, 0, 100);
delay(1000);
questa comunque non vuol dire nulla
if (digitalRead(Hum<50)){
hum non è un pin digitale, è una variabile
if ((celsius>21)&&(stato==0)){
digitalWrite(mot_av, HIGH);
qui dici se celsius > 21 e serra chiusa
apri serra
dopodichè non esiste un comando che interrompa il funzionamento del motore di apertura fino a quando la temperatura non cala sotto i 21 (nel qual caso il motore di chiusura rimane sempre attivo)
1 di tempo ne ho pochissimo, un paio di giorni
2 No, ma mi farebbe piacere scoprirlo
3 Stranamente le singole parti se montate da sole con sketch propri funzionano
Grazie Patrick, ho provato la doppia lettura anche se non l'ho ben capita, il problema si attenua sull'LM35 ma non è completamente risolto.
il motore si ferma solo se gli dici di fermarsi, cioè: lo stato di un pin cambia solo quando tu lo fai cambiare
dicendo motore_avanti, HIGH
il pin resterà high fino a quando non incontrerà l'istruzione motore_avanti, LOW
il delay() causa solamente il freeze (blocco) del programma in quel punto per la durata dei millisecondi specificati nelle parentesi e null'altro
siccome può succedere che lo sketch cicli di continuo ti conviene aggiungere la doppia lettura anche nel primo analogRead
Visto che cambia lo stato a 0 dopo il delay, ovvero non è più verificata la condizione di movimento del motore if (celsius<21 && stato==1) perchè dovrebbe continuare ad andare?
Al limite posso introdurre nuovamente l'else che ho commentato.
entro in una stanza se non c'è un fiocco rosso attaccato alla maniglia
accendo la luce
attacco un fiocco rosso alla maniglia
esco dalla stanza
................
anche se c'è il fiocco rosso alla maniglia
perchè dovrebbe spegnersi la luce?
tu fai la stessa cosa
if ((celsius<21)&&(stato==1)){ //chiusura
digitalWrite(mot_av, LOW);
digitalWrite(mot_ind, HIGH);
delay(2000);
stato=0;
}
chi e dove è scritto
digitalWrite(mot_ind, LOW)
in modo che quando il motore ha fatto il suo lavoro si spenga
io immagino che il codice giusto possa essere
if ((celsius<21)&&(stato==1)){ //chiusura
digitalWrite(mot_av, LOW);
digitalWrite(mot_ind, HIGH); // attivo la chiusura
delay(2000); // attendo il tempo sufficiente alla chiusura (se non ci sono finecorsa)
digitalWrite(mot_ind,LOW); // fermo il motore
stato=0; // questo serve per sapere se la tenda è chiusa o aperta
} // ora è chiusa
secondo me ti manca definire bene tutti gli stati possibili della tua serra.
Per te la serra può essere o troppo calda o troppo fredda, non esiste uno stato di temperatura ideale?
Credo che l'utilizzo di uno switch...case renderebbe più chiara questa cosa.
Per non far impazzire le aperture/chiusure dovresti valutare l'utilizzo dell'isteresi.