vorrei utilizzare Arduino per controllare delle elettrovalvole tramite un sensore di prossimità.
Ho realizzato un prototipo con Arduino Nano, sensore di prossimità, e relè SSR per controllare le valvole. Sia gli ingressi del/dei sensori che le uscite per i relè SSR sono interfacciati tramite fotoaccoppiatori.
Questo sistema mi serve per lavare tramite getto d'acqua un attrezzo e successivamente asciugarlo tramite getto d'aria
Quando il sensore rileva la presenza dell'attrezzo attiva per 3 secondi il getto d'aqua e subito a seguire il getto di aria. Se l'attrezzo viene allontanato in qualunque momento la sequenza si deve interrompere.
Per verificare il principio di funzionamento ho realizzato un primo sketch molto banale con i famosi "Delay"...
Ora però vorrei realizzare un qualcosa di più serio e, grazie a questo forum ho capito che ero sulla strada completamente sbagliata ed ho riprovato con la funzione "Millis".
Purtroppo le mie conoscenze di programmazione sono molto basiche, direi primordiali, e mi sono arenato...
Vi allego lo sketch che con il quale sto provando, chiedendovi se potete darmi una mano su come impostare un corretto flusso e quali funzioni utilizzare per ottenere il mio scopo...
Grazie in anticipo per le dritte che vorrete darmi
PS: come vedete ho fatto un po' di prove e quindi forse è un pochino incasinato...
PS2: se la cosa può interessare ad altri posso poi postare circuito e PCB
Michele
// Attività da eseguire
// Quando si attiva il sensore Relè 1 va ON per 3 secondi poi OFF
// e Relè 2 ON per 3 secondi poi off.
// se sensore va OFF relè 1 e relè 2 subito spenti
const int sens1Pin = 10; // Pin sensore prossimità
const int rel1Pin = 3; // Pin relè elettrovalvola 1
const int rel2Pin = 5; // Pin relè elettrovalvola 2
//const int rel3Pin = 6; // Pin relè elettrovalvola 3 (in seguito servirà per riempire vasca di lavaggio)
unsigned long rel1OnTime;
unsigned long rel2OnTime;
//unsigned long rel3OnTime;
bool rel1On;
bool rel2On;
//bool rel3On;
bool statrel1;
bool statrel2;
void setup() {
pinMode(rel1Pin, OUTPUT);
pinMode(rel2Pin, OUTPUT);
// pinMode(rel3Pin, OUTPUT);
pinMode(sens1Pin, INPUT);
digitalWrite(sens1Pin, HIGH); //Abilita res.
rel1On = false;
rel2On = false;
// rel3On = false;
statrel1 = false; // stato relè 1
statrel2 = false; // stato relè 2
}
void loop(){
if (digitalRead(sens1Pin) == LOW) { // Legge stato sensore
digitalWrite(rel1Pin, HIGH); // se sensore ON relè 1 ON
rel1On = true; // imposta varialbile stato relè 1 a TRUE
rel1OnTime = millis(); //
}
else
{
digitalWrite(rel1Pin, LOW);
}
if (digitalRead(sens1Pin) == LOW && (statrel1 = false)) {
digitalWrite(rel2Pin, HIGH);
rel2On = true;
rel2OnTime = millis();
}
else
{
digitalWrite(rel2Pin, LOW);
}
if(rel1On)
if(millis() - rel1OnTime > 3000) { // mantiene ON relè 1 per 3 secondi poi OFF
digitalWrite(rel1Pin, LOW);
rel1On = false;
if(statrel1 == false);
statrel1 = true;
}
else
{ statrel1 = false;
}
if(rel2On)
if(millis() - rel2OnTime > 3000) { // mantiene acceso relè 2 per 3 secondi poi OFF
digitalWrite(rel2Pin, LOW);
rel2On = false;
statrel2 = true;
}
}
Grazie mille per la risposta e l'aiuto
Ho provato lo sketch e rilevo che quando il sensore è ON il relè1 si attiva per un istante e poi subito OFF. Il relè 2 è sempre OFF
Se elimino l' else if i due relè funzionano correttamente tranne che, ovviamente, non vanno in OFF se il sensore si disattiva prima del tempo previsto....
Ho provato a capire il perchè, ma non capisco proprio come mai venga eseguito subito la parte di programma condizionata da else if
Prova a stampare il valore su seriale, in modo da capire se è il sensore che non funziona bene o il codice.
if (digitalRead(sens1Pin) == LOW) { // Legge stato sensore
digitalWrite(rel1Pin, HIGH); // se sensore ON relè 1 ON
stato=1;
rel1OnTime = millis(); //
}
else if(digitalRead(sens1Pin) == HIGH){
stato=0; //Spegne tutto
Serial.println(stato) ;// se stampa dopo poco tempo è la lettura del sensore che da HIGH
}
Per essere sicuro del corretto funzionamento del sensore ho anche provato con un pulsante al suo posto.
Ho fatto un piccolo sketch di test e sul monitor leggo correttamente 0 a pulsante rilasciato e 1 a pulsante premuto.
(ho utilizzato una resistenza esterna di Pulldown per questo nel listato ho sostituito LOW con HIGH
void loop() {
if (digitalRead(sens1Pin) == HIGH) { // Legge stato sensore
digitalWrite(rel1Pin, HIGH); // se sensore ON relè 1 ON
stato=1;
}
else if(digitalRead(sens1Pin) == LOW){
digitalWrite(rel1Pin, LOW);
stato=0; //Spegne tutto
}
Serial.println(stato);
}
Ricapitolando:
con il codice completo sul monitor leggo sempre 0 sia a sensore attivo che non attivo, ma a sensore attivo si attiva il relè 1 e si disattiva a sensore disattivato
Se elimino else if a sensore attivo leggo 1 e lo stato non cambia se non a sensore disattivo dove a questo punto inizia la sequenza che fa spegnere 1, accendere 2 spegnere 2
Serial print l'ho spostato fuori da else if altrimenti a sensore attivo non invia più dati
Ho aggiunto un flag alla lettura del sensore, secondo me la logica è quella che ti posto, ma non riesco a trovare l'errore, else if del sensore dovrebbe essere eseguito solo se allontani il pezzo dal sensore, quindi zero solo se allontani il pezzo o finisci la lavorazione.
Codice modificato, Non trovo l'errore logico, a me pare che dovrebbe funzionare
int stato=0;
byte flag=1; // flag che mi stabilisce se deve eseguire le operazioni, al termine del lavaggio il sensore è ancora
// attivo, senza un flag ripeterebbe le operazioni
void loop(){
//1 leggo il sensore
if (digitalRead(sens1Pin) == LOW && flag) { // Legge stato sensore
digitalWrite(rel1Pin, HIGH); // se sensore ON relè 1 ON
stato=1;
flag=0;// ripete il lavaggio solo una volta fino allo scattare del sensore
rel1OnTime = millis(); //
}
else if(digitalRead(sens1Pin) == HIGH){ // il pezzo si è allontanato dal sensore
stato=0; //Spegne tutto
flag=1;
}
if(stato==1){
if(millis() - rel1OnTime > 3000) { // mantiene ON relè 1 per 3 secondi poi OFF
digitalWrite(rel1Pin, LOW);
digitalWrite(rel2Pin, HIGH);
rel2OnTime = millis();
stato=2; //Abilito aria temporizzata quando ha finito acqua
}
}
else if(stato==2){// Ho messo un else if, in modo che l'if è valutato solo se diverso da uno
// mentre con un un if, è valutato sempre anche quando non necessario
if(millis() - rel2OnTime > 3000) { // mantiene acceso relè 2 per 3 secondi poi OFF
digitalWrite(rel2Pin, LOW);
stato=0
}
}
if(stato==0){// terminato aria spegne tutto
digitalWrite(rel1Pin, LOW);
digitalWrite(rel2Pin, LOW);
}
}
torn24:
Ho aggiunto un flag alla lettura del sensore, secondo me la logica è quella che ti posto, ma non riesco a trovare l'errore, else if del sensore dovrebbe essere eseguito solo se allontani il pezzo dal sensore, quindi zero solo se allontani il pezzo o finisci la lavorazione.
Codice modificato, Non trovo l'errore logico, a me pare che dovrebbe funzionare
Grazie mille torn24, così come è impostato ora funziona perfettamente.
Non mi resta che testarlo sul campo...
Un paio di domande:
Volendo aggiungere il controllo di un terzo relè, che controlla il riempimento della vaschetta, è sufficiente inserire un terzo stato ?
La gestione del ritardo di spegnimento dei relè può essere gestita con dei potenziometri? Si complica troppo ?
Dipende da come vuoi gestire la vaschetta, SECONDO ME, se devi riempire la vaschetta ad ogni lavaggio all'ora userei un terzo stato, se invece devi riempirla dopo x lavaggi, userei una variabile contatore che arrivata a x lavaggi attiva il relè della vaschetta, questo con un codice a parte all'interno della funzione loop().
Mentre per stabilire la pausa con un potenziometro, ti basta leggere il potenziometro con analogRead() e usare la funzione map() per avere i valori voluti inseriti in una variabile, e poi usare la variabile al posto del tempo.