programma arduino per irrigatore automatizzato

Salve a tutti!
Avrei bisogno di un consiglio/aiuto per un piccolo progetto a cui sto lavorando. in futuro dovrebbe trattarsi di una serra automatizzata, ma per adesso sono fermo alle righe di codice che mi servono per l’irrigazione.
Idealmente il progetto dovrebbe funzionare così: un sensore per umidità immerso nel terreno rileva la percentuale di acqua presente. Non appena tale valore scende sotto una soglia critica, Arduino comanda l’avvio di una pompa e di un piccolo servo, il quale muovendosi a destra e sinistra, permette al tubo che porta l’acqua attaccato alla sua estremità di irrigare il meglio possibile.
La pompa e il servo si fermano esattamente 6 secondi dopo che il valore di l’umidità del terreno è salito sopra la soglia critica.
I problemi per ora sono questi:
1)Al primo avvio di Arduino, non appena le condizioni per far partire la pompa e il servo sono favorevoli, il servo per pochi attimi comincia a muoversi a rilento, per poi continuare muovendosi normalmente. Questa cosa che non accade più le altre volte che il servo parte.
2) ogni volta che apro il monitor seriale, Arduino si blocca per pochi attimi per poi ripartire.

Questo è il codice del programma:

#include <Servo.h>
Servo myservo;
const int pompa=4;
int pompaState= LOW;
int sensoreUmidita=A0;
int umidita;
int letturaUmidita=0;
int umiditaTemp;
int pos=0;
int value=0;
int condizioneServo;
int poshead = 0;
long timerVal = 50;
long timerVal1 = 50;
int countupdown =4;
unsigned long time;
unsigned long pompaTime;
unsigned long letturaDati;
unsigned long letturaUmidita_time;

void setup() {
  pinMode (sensoreUmidita, INPUT);
  pinMode (pompa, OUTPUT);
  Serial.begin(9600);
  myservo.attach(9);
  time=millis();
  pompaTime=millis();
  letturaDati=millis();
  letturaUmidita_time = millis();
  timerVal=millis();
  umidita=0;
  letturaUmidita_time=0; 
  umiditaTemp=0;
  myservo.write(90);
}


void loop() {
  time = millis();
  if (time>letturaUmidita_time+5){
    sensoreUmidita=analogRead(A0);
    umidita=map(sensoreUmidita,0,1023,100,0);
    umiditaTemp=umiditaTemp+umidita;
  }

  
  if ((time>pompaTime+15)&&(umidita<30)){
    digitalWrite (pompa, HIGH);
    condizioneServo = true;
    pompaTime=millis();
  }
  
  if ((umidita>30)&&(time>pompaTime+6000)){
    digitalWrite (pompa, LOW);
    condizioneServo = false;
    pompaTime=millis();
  }

  if (condizioneServo == true){
    muoviServo();
  }
  if ((condizioneServo == false) && ((timerVal1 + 50) <= millis())){
    myservo.write(90);
    timerVal1 = millis();
  }

  if (time>letturaDati+1000){
    Serial.print("Umidita':""%");
    Serial.println(umidita,DEC);
    letturaDati=millis();
  }
}

questa invece è la scheda relativa la movimento del servo:

void muoviServo() {
        
if ((timerVal + 50) <= millis()) {     
   myservo.write(poshead);                 
   poshead = poshead + countupdown;     
   if (poshead == 160) {                
   countupdown = -10;                   
   } 
   if (poshead == 30) {                 
   countupdown = 10;                    
   }
   timerVal = millis();                 
}

Ciao prima cosa vorrei chiederti fino a quanti grammi può muovere il servo e tu quanti grammi gli fai spostare. Stai anche attento al sensore dell'umidità del terreno si corrode dopo circa 2 settimane e ti da valori sballati rischiando così di farti bruciare qualcosa! (Come: ti farebbe bruciare qualcosa in questi modi qui descritti:

  1. Accendendo e spegnendo un relay.
  2. Dando un valore basso e tenendo la pompa attaccata costantemente facendo consumare l'acqua del serbatoio e cosi si brucia la pompa e se il servo resta attaccato 24 ore su 24 al servo non fa bene.)

Secondo problema : E' normale che arduino si riavvia all'apertura del monitor seriale.

Poi ti aggiungo un altro problema io. ATTENTO CON LA POMPA CHE ATTIVI SE FUNZIONA A 230 VOLT! E STAI ANCHE ATTENTO A NON TOCCARE I COLLEGAMENTI QUANTO E ATTIVO IL CIRCUITO. CON LA 230 NON SI SCHERZA! IN CONCLUSIONE STAI ATTENTO A QUALUNQUE TENSIONE SOPRA I 40 VOLT

Ernesto

Grazie mille Ernesto per i preziosi consigli; qualcosa di quello che hai scritto la sapevo già, altre cose invece mi erano completamente oscure, come per esempio il fatto che i sensori di umidità per terreno si corrodoino dopo pochi giorni di utilizzo.
In ogni caso per il piccolo servo non c’è problema; per adesso non sta spostando alcun peso, mentre a “regime” (trattandosi di un servo che funziona con il voltaggio e l’amperaggio fornitogli da arduino) sposterà solo i pochi grammi di un piccolo tubo di gomma.
Comunque secondo te come posso ovviare al problema relativo alla corrosione del sensore di umidità?
Per quale motivo il servomotore al primissimo avvio di arduino, come ho spiegato in precedenza, non funziona correttamente, mentre successivamente comincia a muoversi con una velocità costante? Sono quasi sicuro che questo problema sia dato da un’errata compilazione del codice, dato che è la prima volta che mi cimento con la funzione millis, al posto dell’utilizzo dei delay…

Ho provato anche a collegare un relè per attivare la pompa, ma questo non appena avvio arduino si accende e si spegne velocemente per circa un secondo, per poi cominciare a funzionare normalmente..è normale?

Ciao Filippo.... se senza relè va bene allora si direbbe un problema di alimentazione...... Come alimenti relè e arduino?

Arduino è alimentato tramite i 5V dell'usb. Il problema del servo, che al primo giro si avvia lentamente per poi funzionare alla velocità corretta (come ho spiegato nel primo post), l'ho riscontrato anche senza il modulo dei relè collegato. Al suo posto però c'era collegato un motorshield e un motore dc, usati solo per testare il programma. Oggi però ho deciso di sostituire il motorshied con un modulo da 8 relè di quelli alimentati dai 5v di arduino. Questo però, non appena collego la presa USB, e arduino si accende, il relè si apre e si chiude velocemente per qualche secondo per poi funzionare correttamente.

Ciao, senz'altro la USB ha problemi ad alimentare correttamente lo shield ed arduino. Per far funzionare bene il tuo progetto per prima devi progettare l'alimentazione, sembra una sciocchezza ma in realtà è fondamentale. Uno shield con 8 relè ha bisogno di una alimentazione separata da arduino (ad esempio un alimentatore da 5v 2A) poichè i disturbi ed il carico dei relè darebbero problemi ad arduino.

Stefano

Ok vedrò di procurarmene uno...ma come mai secondo te il relè si apre e si chiude velocemente per qualche secondo all'avvio di arduino e dopo comincia a funzionare correttamente, funzionandoi secondo i parametri impostatigli tramite il programma?

Ho risolto in parte il problema del relè… da buon principiante lo avevo infatti collegato al pin 13 e all’accensione di arduino, parallelamente al lampeggiare del led del pin 13, si apriva e si chiudeva anche il relè -.-’
Adesso però non capisco perchè lo stesso relè, sempre all’accensione di arduino, parte acceso e rimane tale per qualche secondo, per poi funzionare correttamente, nonostante nel setup sia impostato per restare spento…
Inoltre non ho ancora risolto il problema del servo, il quale alla prima rotazione si muove lentamente per poi continuare successivamente a muoversi ad una velocità costante.
Ed infine non capisco perchè sul piccolo lcd che ho implementato, sul quale dovrebbe comparire il valore percentuale di umidità misurato dalla sonda, quando tale valore scende sotto le decine, al posto della cifra decimale compare un’altro simbolo “%” ( per fare un’esempio “45%” oppure “3%%”).
Infine all’avvio del Servo la retroilluminazione dell’lcd sfarfalla un po’, ma questo vredo sia un problema legato alla carente alimentazione che gli arriva dall’USB.
In ogni caso riposto il codice nel quale ho implementato la parte necessaria al funzionamento dell’lcd

#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
#include <Servo.h>
Servo myservo;
int backlight=10;
const int pompa=7;
int pompaState=LOW;
int sensoreUmidita=A0;
int umidita;
int letturaUmidita=0;
int umiditaTemp;
int pos=0;
int value=0;
int condizioneServo;
int poshead = 0;
int replay;
long timerVal = 50;
long timerVal1 = 50;
int countupdown =4;
unsigned long time;
unsigned long pompaTime;
unsigned long letturaDati;
unsigned long letturaUmidita_time;

void setup() {
  pinMode (sensoreUmidita, INPUT);
  pinMode (pompa, OUTPUT);
  pinMode (backlight, OUTPUT);
  Serial.begin(9600);
  myservo.attach(9);
  lcd.begin(16, 2);
  time=millis();
  pompaTime=millis();
  letturaDati=millis();
  letturaUmidita_time = millis();
  timerVal=millis();
  digitalWrite (backlight, LOW);
  digitalWrite (pompa, LOW); 
  letturaUmidita_time=0; 
  umiditaTemp=0;
  myservo.write(90);
}


void loop() {
  time = millis();
  if (time>letturaUmidita_time+5){
    sensoreUmidita=analogRead(A0);
    umidita=map(sensoreUmidita,00,1023,100,0);
    umiditaTemp=umiditaTemp+umidita;
  }

  
  if (umidita<=30){
    digitalWrite (pompa, LOW);
    condizioneServo = true;
    pompaTime=millis();
  }
  
  if ((time>pompaTime+6000)&&(umidita>=30)){
    digitalWrite (pompa, HIGH);
    condizioneServo = false;
    pompaTime=millis();
  }

  if (condizioneServo == true){
    muoviServo();
  }
  if ((condizioneServo == false) && ((timerVal1 + 50) <= millis())){
    myservo.write(90);
    timerVal1 = millis();
  }

  if (time>letturaDati+1000){
    Serial.print("Umidita':""%");
    Serial.println(umidita);
    lcd.setCursor(0, 0);
    lcd.print("Umidita': ");
    lcd.print(umidita);
    lcd.print("%");
    letturaDati=millis();

Questa è la sezione relativa alla funzione muoviServo:

void muoviServo() {
        
if ((timerVal + 50) <= millis()) {     
   myservo.write(poshead);                 
   poshead = poshead + countupdown;     
   if (poshead == 160) {                
   countupdown = -10;                   
   } 
   if (poshead == 30) {                 
   countupdown = 10;                    
   }
   timerVal = millis();
}
}

ciao, aggiungi uno spazio dopo il % ti spiego, quando scendi da un numero a due cifre a uno a singola cifra il setCursor è impostato sempre allo stesso punto quindi la scrittura si sposta di una colonna però mica tu gli dici di cancellare ciò che è scritto nell altra casella quindi rimane il simbolo %

così:

Serial.print("Umidita':""% ");

dimmi se ti funziona, poi per sicurezza metti unsigned long per gli intervalli di tempo, ti durerà di più

grazie mille ci provo subito :)

Grazie mille, con questa modifica la percentuale compare correttamente sull'lcd..Mi rimane adesso da capire il perchè del problema relativo al servo, che non si muove con la velocità corretta solo la prima volta dopo l'avvio di arduino, e per quale motivo sembra ci sia un calo di tensione ogni volta parte il piccolo servomotore (nonostante sia un modello SM-S2308S di quelli che si trovano nello starter kit di arduino, che dovrebbero funzionare senza l'ausilio di un'alimentazione esterna)

prova qeusto:

int countupdown = 10; //oppure -10 dipende da come metti il poshead int poshead = 30; //oppure 160 prova questi due valori dipende da come è posizionato in aperto o chiuso

quindi:

int countupdown = 10; int poshead = 30;

oppure

int countupdown = -10; int poshead = 160;

Grazie mille adesso funziona correttamente :)

Ultima domanda poi la smetto di assillare :) E' normale secondo te che i relè collegati alla scheda per qualche secondo all'avvio di arduino si accendano e dopo si spengano funzionando correttamente? Ho provato per curiosità ad usarli anche con altri sketch, come ad esempio l'esempio "blink", e si comportano nello stesso modo..

Ciao F1L1PPO, Per rimediare al problema della sonda che si corrode ho visto sul alcuni siti come alibaba e aliexpress le sonde ovvero le cose che infili nella terra a 50 cent oppure a 5€ 10 PEZZI. Comunque ti consiglio di cambiarle come vedi che sta per corrodersi per evitare danni che ti ho descritto nel post #2 che ti quoto qui sotto.

Ernesto079569: 1. Accendendo e spegnendo un relay. 2. Dando un valore basso e tenendo la pompa attaccata costantemente facendo consumare l'acqua del serbatoio e cosi si brucia la pompa e se il servo resta attaccato 24 ore su 24 al servo non fa bene.)

Ernesto

Oppure se vuoi cacciarti questa cosa di sostituire le sonde prendi un modulo RTC che sarebbe un orologio e così ogni giorno alla stessa ora annaffia. Scusate per il rosso!

volevo proprio evitare il timer perchè irrigare in base all'umidità del terreno è sicuramente più ottimale per le piante. Inoltre per il problema dell'assenza d'acqua nel serbatoio avevo intenzione di comprare un sensore in grado di leggere il minimo dl'acqua presente al suo interno.

Filippo se vuoi comprare quei sensori ovvero quelli per misurare il livello dell'acqua sono troppo corti e vanno bene per un bicchiere ma non per un secchio o serbatoio perciò vedi su internet se trovi qualcosa o fatti consigliare da altri. Cmq scusa per le brevi risposte ma sono in vacanza e fuori casa perciò non ho ne computer ne arduino per verificare ciò che dici.

Ernesto

grazie comunque