Domotica: cancello automatico

Buonasera, vi spiego il mio problema, sto realizzando una casa domotica (intelligente) da portare a scuola per esami, è ho un problema con il cancello automatico, non riesco a farlo invertire di marcia appena tocca il fine corsa( appena tocca il fine corda di apertura si ferma il motore, e non fa niente fin quando non tocco IO il fine corsa di chiusura e allora riparte).. ora vi posto la programmazione, grazie in anticipo :slight_smile:
ovviamente per fare invertire il senso di marcia del motore uso il ponte H(in dotazione nello starter kit di arduino), infatti i controlpin che potete notare nel codice sono proprio quelli che mi permettono di invertire il senso.

else if (com =="ApriC"){
       i= digitalRead(fotodietro);
      while(i != 0){
    i= digitalRead(fotodietro);
    delay(1);
        digitalWrite(controlpin1,HIGH);
        digitalWrite(controlpin2,LOW);
        delay(1);
        analogWrite(enablepin,255);
  }
  y= digitalRead(fotoavanti);
  Serial.print(y);
  while ( y != 0){
    y= digitalRead(fotoavanti);
    delay(1);
    digitalWrite(controlpin1,LOW);
        digitalWrite(controlpin2,HIGH);
        delay(1);
        analogWrite(enablepin,255);
        }
      }

Ciao Gianluca, è un pò complicato capire.... è il fotodietro o il fotoavanti che fa fine corsa ?
Aggiungi qualche commento altrimenti è un problema.....

Stefano

cam9500:
Ciao Gianluca, è un pò complicato capire.... è il fotodietro o il fotoavanti che fa fine corsa ?
Aggiungi qualche commento altrimenti è un problema.....

Stefano

Ciao, si hai ragione, allora il fotodietro fa da fine corsa in apertura( quando il cancello si apre del tutto e quindi tocca il finecorsa il fotodietro invia il segnale), invece il fotoavanti fa da finecorsa in chiusura( quando il cancello si chiude del tutto , il finecorsa invia il segnale) il problema sta che appena tocca il fotodietro il cancello si blocca (come giusto) pero non riparte fino a quando non premo manualmente il fotoavanti..

Ciao, non mi pare che elimini il controllo fotodietro quando sei in chiusura e fotoavanti in apertura, probabilmente facendo 3 funzioni (apri,stop,chiudi) forse semplifichi un pò la struttura del codice....

Stefano

Come ti hanno suggerito, rende più chiaro il tutto l'uso di funzioni apri e chiudi.

prova a vedere se capisci il codice e se ti può essere utile, TI CHIEDO UN FAVORE, non abbandonare il thread senza scrivere un messaggio, è gradito e cortesia, che dicessi se hai risolto e se il codice ti è stato utile, GRAZIE...

//nel loop()
else if (com =="ApriC"){

        ApriCancello();
	delay(3000);
	ChiudiCancello();
      

  }
  
 //----------------------------------- 
  
  
  
  
void ApriCancello(){

        
	if(digitalRead(fotodietro)!=LOW){//Se il cancello non è aperto
		
		    /* Seleziono il senso di rotazione del motore
			   e avvio il motore */
	      digitalWrite(controlpin1,HIGH);
              digitalWrite(controlpin2,LOW);
        
               analogWrite(enablepin,255);//Presumo che questo accenda il motore ?????
               while(digitalRead(fotodietro)!=LOW); //Il motore continua a funzionare finché il     sensore diventa HIGH, notare il punto e virgola while();
          }//end if
          analogWrite(enablepin,0);//Il sensore è diventato HIGH, e il motore viene spento,  termine funzione
}  



void ChiudiCancello(){

        
	if(digitalRead(fotoavanti)!=LOW){//Se il cancello  è aperto
		
	    /* Seleziono il senso di rotazione del motore
			   e avvio il motore */
	      digitalWrite(controlpin1,LOW);
              digitalWrite(controlpin2,HIGH);
        
               analogWrite(enablepin,255);//Presumo che questo accenda il motore ?????
               while(digitalRead(fotoavanti)!=LOW); //Il motore continua a funzionare finché il sensore diventa HIGH, notare il punto e virgola while();
          }//end if
          analogWrite(enablepin,0);//Il sensore è diventato HIGH, e il motore viene spento, termine funzione

}

Ciao, intanto grazie Torn per aver chiarito in maniera esemplare quanto ho scritto.
Unica implementazione che suggerisco (magari nella versione 2) di non bloccare il codice con un while :adesso quando entra nella funzione di apertura/chiusura ci sta fino allo stop quindi arduino non può fare altro.
Strutturato al meglio le funzioni settano le uscite per il motore in apri-chiudi-stop ma non bloccano il flusso del programma così si potrà aggiungere senza modificare il codice,un eventuale comando remoto, una lampada di segnalazione ecc.

Stefano

ciao, il while(digitalRead(fotoavanti)!=LOW);, non blocca il programma, una volta acceso il motore, resta in "lettura" del sensore, raggiunto il sensore esce dal while, è cosi che dovrebbe essere un automazione, occorre sempre un loop, per controllare i sensori di continuo.

Per il suo sistema, che è semplificato e non prevede una fotocellula di "pericolo, ostacolo" come invece è presente nei veri cancelli automatici, si legge solo i sensori chiusura e apertura, altrimenti bisognerebbe anche leggere la fotocellula di ostacolo, e se attiva provvedere all'apertura del cancello in caso di ostacolo.

Per essere concisi, il suo modo di gestire un cancello automatico, non è corretto, un cancello automatico funziona in modo diverso, io ho dato una soluzione per quello che vuole fare lui, "ma non è il modo corretto di gestire un cancello automatico" :slight_smile: >:(

Oh scusa... ma

while(digitalRead(fotoavanti)!=LOW); //Il motore continua a funzionare finché il sensore diventa HIGH, notare il punto e virgola while();

non sta qui dentro finchè il cancello non si è aperto?
Se ho letto male, scusa.....

Per essere concisi, il suo modo di gestire un cancello automatico, non è corretto, un cancello automatico funziona in modo diverso, io ho dato una soluzione per quello che vuole fare lui, "ma non è il modo corretto di gestire un cancello automatico"

Certo ne convengo appieno.... sono sicuro che farà la versione 2 :wink:

Stefano

@cam9500, hai letto e capito bene, ma la questione che in un cancello automatico non dovrebbe esserci il tasto stop :wink:

Gestione cancello automatico

1)Premo un pulsante apri, il cancello si apre fino a che il sensore aperto è attivo, serve un loop
per leggere di continuo il sensore "aperto", attendo un intervallo di tempo, poi attivo chiusura.

2)Premo un pulsante chiudi, il cancello si chiude, ma se la fotocellula ostacolo si attiva, inverte e riapre il cancello, serve un loop, che legge sia il sensore "chiuso" che la fotocellula "ostacolo"

Non esiste un pulsante stop, perché il cancello è fatto per aprirsi e chiudersi, e non rimanere a mezza strada.

Comunque, visto che a parole è difficile spiegare, puoi postare un esempio di codice, cosi capisco cosa vuoi dire, io penso che sia indispensabile leggere i sensori di continuo, e in una funzione mi sembra indispensabile che ci sia un loop, per questo scopo, entrati in una funzione, la funzione loop() di arduino è sospesa, fino a che non si esce dalla funzione chiamata, di conseguenza i controlli sensori non possono essere nella funzione arduino loop()

torn24:
io penso che sia indispensabile leggere i sensori di continuo, e in una funzione mi sembra indispensabile che ci sia un loop, per questo scopo, entrati in una funzione, la funzione loop() di arduino è sospesa, fino a che non si esce dalla funzione chiamata, di conseguenza i controlli sensori non possono essere nella funzione arduino loop()

Premesso che quello di Gianluca4697 è solo un esercizio su un modellino e che nella realtà se fate una cosa come qui è fatta ... vi arrestano :smiley: ... si può benissimo fare proprio sfruttando il fatto che loop() gira in continuazione.

Con controlli sui vari sensori e su eventuali pulsati, tutti temporizzati con l'uso di millis() (in modo da non arrestare mai il loop()) si fa tutto senza mai fermare il programma e rilevando gli eventi nel momento in cui accadono.

Guglielmo

@gpb01, giusto, ma poi saranno fatti meglio questi programmi per cancelli ? in fondo è l'automazione più basilare, non mi vengono in mente automazioni più semplici di macchine :slight_smile:

Voglio postare un programma che avevo fatto "PER MODELLINO" di cancello, francamente uso pochissimo millis() non so perché, visto l'uso intensivo del sistema con mills() per contatore di tempo, magari venga introdotta una funzione nella libreria arduino "certo uno se la potrebbe fare e usarla sempre" ma per i novizi averla a disposizione sarebbe utile...

Esempio mio cancello, motore gestito da relè

#define Fotocellula 12
#define PulsanteApertura 11
#define PulsanteChiusura 10
#define SensoreAperto 9
#define SensoreChiuso 8
#define MotoreApertura 7
#define MotoreChiusura 6
byte F,PA,PC,SA,SC;
void setup()
{
  pinMode(Fotocellula,INPUT);
  pinMode(PulsanteApertura,INPUT);
  pinMode(PulsanteChiusura,INPUT);
  pinMode(SensoreAperto,INPUT);
  pinMode(SensoreChiuso,INPUT);
  pinMode(MotoreApertura,OUTPUT);
  pinMode(MotoreChiusura,OUTPUT);
  
  
}

void loop()
{
  
  PA=digitalRead(PulsanteApertura);
  PC=digitalRead(PulsanteChiusura);
  
  
  if(PA==HIGH)
     Apri();
   else if (PC==HIGH)
     Chiudi();
     
  
  
}

void Apri()
{
   SA=digitalRead(SensoreAperto);
   while(SA!=HIGH)
   {
   
    
    SA=digitalRead(SensoreAperto);
    
    digitalWrite(MotoreApertura,HIGH);
    
   }

    digitalWrite(MotoreApertura,LOW);

}


void Chiudi()
{
  
  F=digitalRead(Fotocellula);
  SC=digitalRead(SensoreChiuso);
  
  while(SC!=HIGH )
  {
     F=digitalRead(Fotocellula);
     SC=digitalRead(SensoreChiuso);
     if(F!=HIGH)
          digitalWrite(MotoreChiusura,HIGH);
     else
     {
        digitalWrite(MotoreChiusura,LOW);
        delay(4000);
        Apri();
        return;
     
     
     }     
  
  
  }
  digitalWrite(MotoreChiusura,LOW);
}

scusate: Mi riferivo al post pre Gpb01!

Ah, ecco :slight_smile:
Il mio cancello elettrico ad esempio è perfetto per i punti 1 e 2 ma ho la possibilità di fermare il cancello anticipando la fine apertura (modalità carraio se non erro) utile nel caso anzichè entrare con la macchina si entri solo a piedi...
Purtroppo non ho un codice di esempio, poi il modo di scrivere il codice è abbastanza personale (ognuno ha la sua logica in testa).
Io farei le funzioni che si limitano a comandare il motore(apri, stop, chiudi), nel loop la sequenza standard apre-pausa-chiude-stop in un registro di stato e, sempre nel loop i controlli dei sensori che, ad esempio, in caso di ostacolo mettono in pausa la sequenza nel punto in cui è in quel momento. Avrei quindi nel loop un timer che a seconda dello stato, in un array si prende il tempo dello stato ed in caso di ostacolo "resetta" il timer stesso fino alla scomparsa dell'ostacolo.

Di fatto anch'io leggo i sensori di continuo ma non li chiudo in un ciclo per mio modo di ragionare: il ciclo è una costrizione che se devi modificare il programma rischi di doverlo riscrivere tutto

Grazie per le risposte, provo le soluzioni che mi avete dato e vi faccio sapere!
SI è solo una dimostrazione, per quanto riguarda le fotocellule ho già scritto il codice, usando il sensore a infrarossi e quando la distanza è minore di un tot, e il cancello è in fase di chiusura deve invertire la marcia, solo che fino ad ora ho provato con un led :). Prima vorrei risolvere sto problema di apertura e chiusura e poi aggiungo anche la fotocellula.
Vi faccio sapere tra poco!

torn24:
Come ti hanno suggerito, rende più chiaro il tutto l'uso di funzioni apri e chiudi.

prova a vedere se capisci il codice e se ti può essere utile, TI CHIEDO UN FAVORE, non abbandonare il thread senza scrivere un messaggio, è gradito e cortesia, che dicessi se hai risolto e se il codice ti è stato utile, GRAZIE...

//nel loop()

else if (com =="ApriC"){

ApriCancello();
delay(3000);
ChiudiCancello();

}
 
//-----------------------------------
 
 
 
 
void ApriCancello(){

if(digitalRead(fotodietro)!=LOW){//Se il cancello non è aperto

	    /* Seleziono il senso di rotazione del motore
		   e avvio il motore */
      digitalWrite(controlpin1,HIGH);

digitalWrite(controlpin2,LOW);
       
              analogWrite(enablepin,255);//Presumo che questo accenda il motore ?????
              while(digitalRead(fotodietro)!=LOW); //Il motore continua a funzionare finché il    sensore diventa HIGH, notare il punto e virgola while();
          }//end if
          analogWrite(enablepin,0);//Il sensore è diventato HIGH, e il motore viene spento,  termine funzione
}

void ChiudiCancello(){

if(digitalRead(fotoavanti)!=LOW){//Se il cancello  è aperto

    /* Seleziono il senso di rotazione del motore
		   e avvio il motore */
      digitalWrite(controlpin1,LOW);

digitalWrite(controlpin2,HIGH);
       
              analogWrite(enablepin,255);//Presumo che questo accenda il motore ?????
              while(digitalRead(fotoavanti)!=LOW); //Il motore continua a funzionare finché il sensore diventa HIGH, notare il punto e virgola while();
          }//end if
          analogWrite(enablepin,0);//Il sensore è diventato HIGH, e il motore viene spento, termine funzione

}

Grazie per il codice, hai capito tutto, enablepin accende il motore,però purtroppo ho sempre lo stesso problema :frowning:
IL cancello si apre poi si ferma come di giusto ma per ripartire devo premere manualmente il (fotoavanti), e non sto capendo il motivo, ho provato tutti i modi che mi sono venuti in mente ma succede sempre la stessa cosa, avevo anche ipotizzato che il finecorsa avanti non funzionava ma ho fatto la prova del 9 stampando tramite seriale lo stato del finecorsa avanti e funziona come quello indietro.. Quindi ho eliminato anche questa ipotesi..

torn24:
... ma poi saranno fatti meglio questi programmi per cancelli ? ...

Ehm ... premesso che si, alcuni saranno anche fatti male, ma sui cancelli reali ci sono sequenze che DEVONO ASSOLUTAMENTE essere rispettate, a meno che, come dice Guglielmo, non vogliate farvi arrestare :wink: ... prima di tutto le sicurezze (tipo bordi pneumatici, ad esempio, che devono assolutamente agire anche se i finecorsa e le fotocellule non si attivano per qualche guasto o altri motivi) ... poi i cicli che devono garantire l'arresto in caso le fotocellule vengano interrotte ... poi ovviamente le pause fra le varie sequenze per evitare di incollare i contatti (esempio: se si sta chiudendo ed interrompo la fotocellula, deve fermarsi, fare una pausa, in genere un secondo basta, e poi riaprirsi, mai invertire di colpo la direzione) ...

Se e' un modellino che stai realizzando per te', magari poco importa, se invece fosse, ad esempio, un'applicazione che ti chiedono per un'esame, queste cose potrebbero chiedertele, e rimproverarti se non le prevedi ...

Grazie per la risposta, è sottinteso che per cambiare direzione , si fermava aspettava un secondo, invertiva il senso di marcia e ripartiva. E' un progetto per gli esami.

Gianluca4697 , non vedo motivo perché il codice non debba funzionare, hai postato solo una parte del tuo programma e se esistono bug da altre parti non lo possiamo conoscere.

Il fatto che tu devi intervenire sul sensore avanti, è strano, se tu attivi il sensore manualmente si dovrebbe arrestare il tutto, perché considerato arrivato a fine corsa, mentre tu dici che parte.

Da quello che possiamo sapere, senza vedere l'intero programma, senza avere il modellino e il circuito sotto mano, non si può stabilire dove sia il problema.

Ma posso dirti che la logica dei programmi è giusta, i sensori sono collegati nel giusto modo?
Ossia se usi nel pinMode() INPUT_PULLUP, devono dare valore LOW quando premuti-attivi, se usi INPUT devono dare valore HIGH quanto premuti-attivi, ma devi prevedere resistenze in pull down.

Facci sapere se trovi il problema :slight_smile:

torn24, grazie per il consiglio, ho fatto sempre cosi , usando il metodo TOP DOWN ho scomposto il problema.
E' finalmente dopo svariati tentativi mi sono reso conto il problema (almeno penso), ho provato a fare due funzioni uno per apri e una per chiudi (ovviamente cambiando il controlpin1 e il controlpin2) e mi sono reso conto ora che non è la funziona di chiusura che non funziona, ma il problema sta proprio nei controlpin, appena cambio il valore e lo imposto cosi:

  digitalWrite(controlpin1,LOW);
  digitalWrite(controlpin2,HIGH);

il motore non parte! e me ne sono reso conto anche cambiando combinazione, cioè questa combinazione che ho appena elencato l'ho messa in fase di apertura è il motore non parte . Quindi all'80% il problema sta proprio nella combinazione.. ma non sto capendo il motivo .. che può essere? il motore o qualcosa collegata male ?

RISOLTO! non vi dico il motivo perché penso che ... avevo sbagliato a collegare enablepin, avevo scambiato le uscite nel ponte H, apposto del controlpin2 ho collegato enablepin(per far capire).
Grazie per le risposte, e soprattutto per il modo di farlo funzionare, sicuramente più semplice e facile del mio! :slight_smile:

Ho aggiunto anche la fotocellula (col sensore a ultrasuoni) , e l'apertura pedonale. Che ne pensate?
Ecco il codice:

const int fotodietro=33;
const int fotoavanti=34;
const int controlpin1=32;
const int controlpin2=31;
const int enablepin=30;
const int triggerPort = 28;
const int echoPort = 29;
char c;
boolean i= true;
void setup() {
  // put your setup code here, to run once:
     pinMode(fotodietro,INPUT);
     pinMode(fotoavanti,INPUT);
     pinMode(echoPort, INPUT);
     pinMode(triggerPort, OUTPUT);
     pinMode(controlpin1,OUTPUT);
     pinMode(controlpin2,OUTPUT);
     pinMode(enablepin,OUTPUT);
     Serial.begin(9600);
}
void apri(){
  digitalWrite(controlpin1,LOW);
  digitalWrite(controlpin2,HIGH);
  while(((digitalRead(fotodietro)) != 0) && (i==true)){
    analogWrite(enablepin,255);
  }
  analogWrite(enablepin,0);
  i=false;
}
void apri1(){
  digitalWrite(controlpin1,LOW);
  digitalWrite(controlpin2,HIGH);
  while(((digitalRead(fotodietro)) != 0) && (i==true)){
    analogWrite(enablepin,255);
  }
  analogWrite(enablepin,0);
  i=false;
  delay(3000);
  chiudi();
}
void pedonale(){
  digitalWrite(controlpin1,LOW);
  digitalWrite(controlpin2,HIGH);
   analogWrite(enablepin,255);
   delay(3000);
   analogWrite(enablepin,0);
   delay(2000);
   i= false;
   chiudi();   
}
void chiudi(){
   digitalWrite(controlpin1,HIGH);
  digitalWrite(controlpin2,LOW);
  while(((digitalRead(fotoavanti)) != 0) && (i==false)){
    analogWrite(enablepin,255);
      digitalWrite( triggerPort, LOW );
      digitalWrite( triggerPort, HIGH );
      delayMicroseconds( 10 );
      digitalWrite( triggerPort, LOW );
      long durata = pulseIn( echoPort, HIGH );
      long distanza = 0.034 * durata / 2;
      if(distanza < 10){
       analogWrite(enablepin,0);
        delay(3000);
        i=true;
        apri1();
        break;
      }
  }
  analogWrite(enablepin,0);
  i=true;
}
void loop() {
  // put your main code here, to run repeatedly:
  c= Serial.read();
  Serial.println(digitalRead(fotodietro));
  //delay(3000);
  Serial.println(digitalRead(fotoavanti));
 //delay(3000);
 if (c== 's') {
      apri();
      delay(3000);
      chiudi();
   }
 if ( c == 'p') {
      pedonale();
 }
 }

:slight_smile: