Buongiorno, nonostante le scarse basi su Arduino mi è stato chiesto di scrivere un programma che permetta di aprire un cancello a due ante tramite telecomando a distanza: premendo, la prima anta si deve aprire dopo un secondo e poi continuare la corsa fino al fondo (il tempo è da stabilire), quando la prima anta è aperta da 4 secondi si aprirà la seconda fino a fine corsa. al contrario rischiacciando il tasto deve partire la seconda anta e il modus operandi equivale a quello già descritto. servirebbe anche un comando che permetta di arrestare il movimento in caso di necessità, visto che non ci sono fotocellule.
Ho provato a giocare con i Led e sono riuscita a programmare qualcosa, ma diventa complicato! Spero possiate aiutarmi con qualche consiglio o bozza di codice, grazie a tutti.
Ho spostato il tuo argomento dalla sezione forum inglese alla sezione forum italiano.
Si prega di fare riferimento alla seguente guida per ulteriori informazioni.
Regolamento
Grazie.
chiedo scusa sono poco pratica, grazie mille!
Consigli si, codice ... hai letto il REGOLAMENTO al punto 16.1 ?
In quel punto sono idicati sia alcuni .pdf introduttivi che un ottimo libro ...
... comincia con studiare quelli poi prova a buttare giù uno schema elettrico dei collegamenti con Arduino ed una prima bozza di codice ...dopo di che ci mostri il tutto e noi possiamo certamente aiutarti a correggere / sistemare / ottimizzare, ma ... il lavoro iniziale lo devi fare TU
Guglielmo
Grazie! Sicuramente non aspettavo la “pappa pronta”… troppo facile altrimenti! sono sincera, per questioni di tempo non ho letto interamente il regolamento ma guarderò bene i pdf. Grazie di nuovo
Oltre al regolamento (16.1), dovresti anche chiarire "chi" ti ha chiesto questo programma, e per "quale scopo".
Se si tratta di un progetto scolastico, per cui verrà realizzato ed installato come prototipo dimostrativo (es. in un plastico) ok.
Se deve invece controllare un vero cancello, ci sono una serie di questioni di carattere normativo (UNI EN 12453-2022) quindi legale oltre che tecnico. Il cancello deve essere a norma nella sua interezza, quindi non può essere privo di meccanismi di sicurezza come le fotocellule ad esempio, deve avere i lampeggianti (dovresti controllare anche questi con Arduino?) e deve quindi riaprirsi automaticamente in caso di presenza di un ostacolo.
In questo caso temo che la richiesta sia da rigettare.
Si tratta di un modellino per il progetto scolastico di un amico. Chiedo scusa per non averlo specificato, non mi metterei a creare veri e propri cancelli e per semplicità, non gli interessa inserire lampeggianti
Ora è più chiaro. Però sarebbe bene che ci mostrassi quello che hai fatto finora anche se non funziona. In sostanza potresti avere già implementato una piccola macchina a stati basata sul comando strutturato switch case del C++ di arduino. Dal codice noi possiamo capire a che livello è la "difficoltà" e perché dici è "complicato".
Sicuramente non sai cosa è uno pseudo linguaggio, bene devi saperlo e per fortuna le inventi tu le parole chiave.
// descrive quello che deve fare arduino quando il cancello è
// nello STATO == CHIUSO.
CICLA [OGNI 1ms] {
IF (BUTTON.WAS_PRESSED[25ms]) {
STATO = PASSA(IN_APERTURA)
}
}
Descritto in lingua corrente diventa complicato:
Cicla ogni 1ms, se il pulsante è stato premuto per 25ms passa allo stato IN_APERTURA, ciò vuole dire che lo stato CHIUSO non viene più eseguito.
Passare dalla pseudo codifica alla codifica su arduino risulta semplificato se alla base c'è un progetto descritto sia graficamente che tramite lo pseudo linguaggio e in ogni altro modo che tu possa inventarti per descriverlo.
PS: Vediamo cosa hai scritto finora.
Ciao.
Lo pseudo linguaggio va bene per noi, forse il concetto di macchina a stati non è conosciuto dall'OP, per cui in prima battuta cercherei di spiegare in cosa consista. Utilizzo parte di un mio post dove parlo proprio di questo aspetto.
Benissimo, immaginavo (speravo) che fosse così. Ok, quindi quando si parla di sistemi di controllo (ed anche questo lo è) è molto spesso utile coimprendere cosa sia una "macchina a stati finiti" o FSM, e disegnare lo schema relativo. Inoltre puoi già preparare un elenco di componenti, ad esempio un Arduino UNO per controllare il cancello, due servomotori per azionare le due ante, un driver per ogni servo, ed un pulsante (in futuro potrai estendere la cosa con un telecomando o un tag RFID, e magari anche un LED come lampeggiante, ma per ora non pensarci). PS: in genere basta aprire le due ante facendone partire prima una, e poco dopo anche la seconda, non è necessario attendere la completa apertura della prima per far partire la seconda, ma per ora mantengo questa tua specifica.
Tornando alla FSM, in poche parole puoi progettarla molto facilmente disegnando su un foglio un grafo composto da cerchi, gli stati, e da frecce che vanno da un cerchio ad un altro (o anche lo stesso) che rappresentano le transizioni di stato. Ogni freccia è etichettata con una condizione (quella che fa "attivare" quel percorso) ed una eventuale azione (ossia cosa deve fare il sistema quando rileva la condizione).
Un consiglio: quando devi realizzare qualcosa con una FSM fatti un disegnino proprio con cerchi (dentro i quali ci scrivi il nome dello stato e magari il suo valore numerico) e frecce (con una descrizione della condizione ed eventuale azione). Una cosa di questo tipo:
Nel tuo caso partirei da uno stato "CHIUSO" nel quale il cancello è inizialmente chiuso, quindi aggiungerai un arco percorso quando l'utente preme il pulsante (evento), iniziare ad aprire la prima anta attivando il servo (azione) e passare allo stato "APERTURA1". Da tale stato ci sarà un secondo arco corrispondente all'evento "passati x secondi", quindi come azione ci sarà l'attivazione dell'apertura della seconda anta e si finirà nello stato "APERTURA2". E così via. Volendo schematizzare questa cosa potremmo fare un disegnino anche brutale con cerchi e linee, come questo (ignora la mia pessima grafia, anche perché l'ho fatto molto "al volo"):
Oppure potresti scrivere su un foglio elettronico una tabella di questo tipo:
STATO EVENTO AZIONE PROSSIMO
CHIUSO pulsante Apro servo 1 APERTURA1
APERTURA1 Tempo > x Apro servo 2 APERTURA2
APERTURA2 Tempo > y (nessuna) APERTO
APERTO pulsante Chiudo servo 2 CHIUSURA2
CHIUSURA2 Tempo > y Chiudo servo 1 CHIUSURA1
CHIUSURA1 Tempo > x (nessuna) CHIUSO
Questo schema sarà molto utile per iniziare a programmare il loop() di Arduino, a patto di avere una variabile che indichi lo stato corrente.
Poi ad esempio implementare la luce durante il movimento diventa facile:
STATO EVENTO AZIONE PROSSIMO
CHIUSO pulsante Apro servo 1;attivo LED APERTURA1
APERTURA1 Tempo > x Apro servo 2 APERTURA2
APERTURA2 Tempo > y spengo LED APERTO
APERTO pulsante Chiudo servo 2;attivo LED CHIUSURA2
CHIUSURA2 Tempo > y Chiudo servo 1 CHIUSURA1
CHIUSURA1 Tempo > x spengo LED CHIUSO
Ovviamente una volta che avrai definito lo schema ed acquisito il materiale, il problema sarà acquisire le conoscenze di base necessarie, per (ti consiglio di farlo in questo ordine):
- leggere lo stato di un pulsante e scrivere su seriale quando viene premuto
- attivare un LED quando premi il pulsante e disattivarlo quando lo premi ancora
- togliere il LED e sapere come inizializzare la posizione di un servo alla partenza (setup())
- far muovere un servo ad una posizione specifica quando premi il pulsante
- far tornare il servo alla posizione iniziale quando premi di nuovo il pulsante
- controllare la velocità del servo per farlo muovere lentamente e non di scatto alla posizione finale
- poi il resto si vedrà....
PS: Puoi trovare altre informazioni sulla macchina a stati finiti anche QUI , è una piccola libreria che scrissi per me stesso qualche anno fa, ma può essere utile anche ad altri.
Forse hai esagerato un poco. Facciamogli fare solo una cosa nel loop, cioè l'attesa della pressione del pulsante con la scritta "Ricevuto comando apertura".
Che ne pensi?
Eh, infatti è il punto 1.
Ma deve avere anche chiaro cosa debba fare il progetto quando lo avrà completato, ed iniziare a capire il modo di ragionare per un controllore...
Il classico grafico per mostrare una macchina a stati finiti, lo trovo poco chiaro, e all'inizio quei grafici mi confondevano solo le idee. Propongo un sito che ho consultato anche io e spiega una macchina a stati finiti con arduino in modo chiaro e semplice. Sicuramente semplice per chi conosce un po il linguaggio di arduino. Un esempio di codice a volte è molto meglio che tanti pseudocodici, grafici e altro. A me sembra un sito dove spiegano bene un automa a stati finiti Capito il concetto un cancello automatico è l'implementazioni tra le piu semplici.
http://spectrum.altervista.org/programmazione-stati-finiti/?doing_wp_cron=1690796098.3129909038543701171875
Spiegazione di una macchina a stati finiti riassunta in 4 righe
- In quali situazioni (e sotto situazioni) si può trovare il processo?
- A quali eventi deve reagire in ogni situazione?
- Quali operazioni deve compiere ad ogni evento?
- A quale stato deve eventualmente passare in seguito ad un evento?
Il grafo degli stati è il modo standard comunemente usato in qualsiasi ambito, un po' come i diagrammi di flusso. Se a te fa confondere le idee mi spiace, forse ti faranno confondere anche i diagrammi di flusso, ma è così che si impara genericamente l'informatica (all'Università ma non solo).
E tra l'altro in quella pagina (che poi rimanda a QUESTA, aggiornata) inizia proprio con un grafo, e ti assicuro che è il modo più generico per descrivere una FSM, prescindendo dalla piattaforma su cui verrà realizzato, se Arduino in C, o su PC in C#, o Python, o qualsiasi altro linguaggio.
In ogni caso quel sito è ben fatto, molto chiaro, anche se il passaggio dal grafo alla codifica non viene spiegato. Tanto per dire, quando a suo tempo (qualche anno fa) volli crearmi una libreria per gestire comodamente una FSM da implementare per un braccio robotico, usai una codifica relativamente semplice per definire stati, condizioni ed azioni.
Si, certo, che poi corrisponde allo schema e descrizione che ti avevo fatto nel post #9: STATO, EVENTO, AZIONE, PROSSIMO.
Opinione personale, comunque non "è meglio" ma "è più facilmente e direttamente utilizzabile" visto che ti dà già parti di codice da inserire.
Al contrario, come dicevo, un grafico è chiarissimo (basta avere un minimo di base di informatica e/o di logica) indipendentemente dall'applicazione specifica, dall'infrastruttura fisica, e vale per qualsiasi linguaggio. Come dire che a me non piace studiare termodinamica, meglio se mi fanno vedere come funziona un termosifone.
Se vuoi vedere del codice, basta chiederlo. uno dei semplici e banali esempi della libreria, utili comunque per dimostrare come creare una FSM, la quale alla pressione di un pulsante accende un LED che dopo un determinato intervallo di tempo si spegne, prevede quindi solo due stati:
// Stati
#define S_START 1
#define S_LED 2
// Condizioni
#define C_BUTTON 1
#define C_TIMER 2
// Azioni
#define A_LED_OFF 0
#define A_LED_ON 1
Quindi nel setup definisco gli stati, condizioni, azioni, eventuale parametro, e stato successivo:
// Dallo stato START se premo il pulsante accendo il led e passo allo stato LED
fsm.Write(S_START, C_BUTTON, A_LED_ON, 0, S_LED);
// Nello stato LED, se nel timer è passato il tempo specificato dal
// parametro (1000=1 secondo) spengo il LED e torno a START
fsm.Write(S_LED, C_TIMER, A_LED_OFF, 1000, S_START);
// Imposto le funzioni per i test e per le azioni
fsm.SetFunctions(&TestCondition, &DoAction);
// Imposto lo stato iniziale
fsm.Set(S_START);
definisco quindi le funzioni che gestiscono le condizioni e le azioni:
boolean TestCondition(int condition) {
switch ( condition ) {
case C_TIMER:
if ( millis() - millis0 > fsm.Param() ) {
millis0 = millis();
return true; // test verificato, eseguo l'azione
}
return false; // test non verificato, non faccio nulla
case C_BUTTON:
// condizione verificara se il pulsante è stato premuto
return ( digitalRead(BUTTON) == HIGH );
case C_ELSE:
// Condizione vuota (se usata) è sempre vera
return true;
}
return false;
}
void DoAction(int action) {
switch ( action ) {
case A_LED_OFF: // Spengo il LED
digitalWrite(LED, LOW);
break;
case A_LED_ON: // Accendo il LED
digitalWrite(LED, HIGH);
break;
}
return;
}
quindi nel loop basta fare:
fsm.Execute();
In sostanza, li dobbiamo digerire anche se indigesti, come pure il formalismo matematico spinto (che a noi sembra spinto) ma chi ci lavora è obbligato e non è mai soddisfatto.
PS: non è il solo che trova poco comprensibile gli stati e le transizioni come spiegate nei libri.
Ciao.
[docdoc] Non si deve mai prendere un post come attacco personale, io ho imparato l'informatica da autodidatta come tanti, anche chi ha frequentato l'università che non sia informatica ovviamente l'ha imparata da autodidatta, e penso di poter dare consigli utili a chi fa lo stesso percorso, si troveranno in situazioni simili alla mia e non simili a chi ha studiato informatica. Se si fa sempre in un modo non vuol dire che sia il modo migliore per spiegare una cosa. Dire che uno fa fatica a capire una cosa vuol dire che non ha i mezzi per capirla, questo implica, adesso da un Qi 95 a 120 si capiscono le stesse cose, quindi è più la voglia di considerarsi speciale "psicologia", che una reale difficolta per chiunque di imparare la stessa cosa io sono un meccanico ho messo impegno a imparare, ma imparare è solo memorizzare, perché poi si memorizzano anche le spiegazioni, e io penso che chiunque possa imparare mettendoci tempo e non penso certo che non riescano a capire. Se l'ho consigliato penso sia utile, è un po come la divulgazione scientifica, non è il modo migliore di insegnare ma il più adatto a chi non ne sa niente.
Ti assicuro che non l'ho presa affatto come attacco personale, ma le mie considerazioni derivano da anni di esperienza nell'informatica (dopo i corsi di Ingegneria Elettronica) fin dal 1985. Ed il motivo per cui ho insistito è proprio nello spirito di collaborazione di questo forum, dove chi ha più esperienza magari prova ad insegnare alcune cose di base a chi è alle prime armi (che a sua volta non dovrebbe mai né sentirsi obbligato né risentirsi dei consigli).
Sicuramente ognuno ha il proprio modo di ragionare, ma se si fa sempre in un modo, e lo si fa da decenni e lo si fa in ambito professionale, (le FSM tra l'altro sono utilizzate ampiamente nella definizione dei sistemi di controllo ed automazione), ci sarà un motivo, non pensi? Ed è altrettanto vero che con un approccio non solo rigoroso ma soprattutto "standard" si è in grado di ragionare con un grado di astrazione molto utile ad ampliare la propria mente e la "visione" di un problema.
Tutt'altro. Quello che cercavo di farti apprendere è un concetto ed un metodo generale, applicabile a moltissimi ambiti, un o schema degli stati così come un diagramma di flusso. Per cui non è affatto vero che "imparare è solo memorizzare" (cosa che tra parentesi ho sempre odiato io stesso) e, ripeto, non volevo farti imparare a memoria qualcosa ma darti la strada per apprendere un metodo utile per imparare a progettare qualcosa, analogamente aidiagrammi di flusso.
Per cui mi spiace che tu non intenda provare ad assimilare questo tipo di criteri, al prezzo di una iniziale leggera difficoltà ne trarresti vantaggio in seguito, ma me ne farò una ragione. Ciao!
Forse non mi hai capito,non sono io l'autore del thread, per me ora è chiaro un grafico per una macchina stati finiti, è chiaro un diagramma di flusso, anche perché in se non sono cose complicate. Ma il grafico di un msf lo capisco ora dopo aver visto esempi di codice, mentre se avessi dovuto imparare ad implementare una msf solo partendo dal grafico sarebbe stato un problema avere un idea di come implementare il codice. Ovviamente propongo la mia esperienza è quello che è stato più utile per me. Poi io non avrei proposto l'esempio della libreria, non mi sembra l'approccio più semplice, se il codice lo deve scrivere lui per la prima volta partirei da qualcosa di più basico. Comunque ben lieto di imparare e con gratitudine, ma in questo thread niente che in qual che modo non sapevo, in realtà non sono bravissimo ma in 30 anni da autodidatta un grafico so capirlo
Diciamole le cose come stanno, pure io lo capisco il grafico.
Neri e bianchi siamo tutti uguali. Noooo, siamo tutti diversi, il rispetto di queste diversità ci eleva un gradino più in alto.
Io ho ancora dubbi riguardo alla mia difficoltà con le equazioni, cioè se è il caso l'equazione me la invento, ma se osservo tutti quei simboli messi assieme mi si muovono e non riesco a fissare se l'elevamento e dentro o fuori ecc, questo problema l'ho sempre avuto e ora con il peggioramento della vista non può che andare peggio. Quindi una sorta di "dislessia" nei confronti delle formule? Una sorta di "dislessia" nei confronti dei diagrammi a stati?
Non lo so, non mi posso diagnosticare una patologia da incompetente.
Ciao.
Be io propongo all'autore del thread l'idea basilare elementare che proporrei a mio nipote di 15 anni con tutto l'affetto che gli porto. Sara l'autore a decidere se gli è stato utile o preferisce altre spiegazioniQuesto è uno pseudocodice traducibile uno a uno, non si useranno funzioni l'apertura delle ante saranno un semplice digitalWrite() sull'attuatore inserito nello switch.
**Se è vietato chiedere non so se è vietato proporre di propria volontà dal regolamento, si parla sempre che è vietato chiedere ma è vietato dare qualcosa ?? Sappiamo tutti che ci sono buoni tutorial su youtube fatti anche da ingegneri, dove si mostra proprio il codice, penso che tutti riteniamo che sia utile per un principiante anche vedere questi esempi che poi volendo potrà adattare, non vedo perche non si posso mostrare uno pseudocodice su un forum, oppure riteniamo criminali chi si guarda gli esempi su youtube, in caso non si possa fare da regolamento NON ARRABBIAMOCI chiediamo al moderatore di canellare
INIZIO PSEUDOCODICE, secondo richieste iniziali
#define ATTESA 0
#define APERTURA1ANTA 1
#define PAUSA1 2
#define PAUSA2 6
#define APERTURA2ANTA 3
#define CHIUSURA2ANTA 4
#define CHIUSURA1ANTA 5
#define CHIUSO 0
#define APERTO 1
int stato=ATTESA;
int flag=0; //mi indica se devo fare la pausa
int statoCancello=CHIUSO;
//Variabili per conteggio tempo tramite millis()
int avviaTimer=0;
unsigned long TempoPrecedente=0;
int intervalloTempo=0;
int tempoTrascorso=0;
void loop(){
// Switch che seleziona gli stati
switch(stato){
case ATTESA:
SE statoCancello==CHIUSO e pulsanteApri==HIGH{
stato=APERTURA1ANTA;
intervalloTempo=5000;//Tempo neccessario alla Apertura
tempoPrecedente=millis();
avviaTimer=1; //Tempo neccessario all'Apertura
}
SE statoCancello==APERTO e pulsanteChiudi==HIGH{
stato=CHIUSURA2ANTA;
intervalloTempo=5000;//Tempo neccessario alla chiusura
tempoPrecedente=millis();
avviaTimer=1; //Tempo neccessario alla chiusura
}
break;
case APERTURA1ANTA:
SE avviaTimer==1 e tempoTrascorso==1 {
avviaTimer=0;
tempoTrascorso=0;
ferma prima anta//digitalWrite()
flag=1;
stato=PAUSA1;
}
break;
case PAUSA1://pausa tra apertura prima anta e apertura seconda anta
SE flag==1 {
flag=0; //non ripete più if
intervalloTempo=4000;//Tempo tra apertura prima e secoda anta
tempoPrecedente=millis();
avviaTimer=1; //Tempo neccessario alla chiusura
tempoTrascorso=0;
}
SE avviaTimer==1 e tempoTrascorso==1 {//sono passati 4 secondi
intervalloTempo=5000;//Tempo neccessario alla Apertura
tempoPrecedente=millis();
avviaTimer=1; //Tempo neccessario all'Apertura;
tempoTrascorso=0;
stato=APERTURA2ANTA;
}
break;
case APERTURA2ANTA:
SE avviaTimer==1 e tempoTrascorso==1 {
avviaTimer=0;
tempoTrascorso=0;
ferma seconda anta//digitalWrite()
statoCancello=APERTO; //abbiamo eseguito l'apertura il cancello ora è aperto
stato=ATTESA;
}
break;
case CHIUSURA2ANTA:
SE pulsanteApri==HIGH o pulsanteSicurezza==HIGH{ // In caso di pericolo
fermo 1 anta
fermo 2 anta
statoCancello=CHIUSTO;
stato=ATTESA; //attendo comandi pulsanti apertura
break;
}
SE avviaTimer==1 e tempoTrascorso==1 {
avviaTimer=0;
tempoTrascorso=0;
ferma seconda anta//digitalWrite()
flag=1;
stato=PAUSA2;
}
break;
case CHIUSURA1ANTA:
SE pulsanteApri==HIGH o pulsanteSicurezza==HIGH{ // In caso di pericolo
fermo 1 anta
fermo 2 anta
break;
statoCancello=CHIUSTO;
stato=ATTESA; //attendo comandi pulsanti di apertura
}
SE avviaTimer==1 e tempoTrascorso==1 {
avviaTimer=0;
tempoTrascorso=0;
ferma pima anta//digitalWrite()
statoCancello=CHIUSTO; // Abbiamo chiuso il cancello, adesso e attivo il pulsante apri
stato=ATTESA;
}
break;
case PAUSA2:
SE flag==1 {
flag=0; //non ripete più if
intervalloTempo=4000;//Tempo tra apertura prima e secoda anta
tempoPrecedente=millis();
avviaTimer=1; //Tempo neccessario alla chiusura
tempoTrascorso=0;
}
SE avviaTimer==1 e tempoTrascorso==1 {//sono passati 4 secondi procedo con altra anta
intervalloTempo=5000;//Tempo neccessario alla Apertura
tempoPrecedente=millis();
avviaTimer=1; //Tempo necessario all'Apertura;
tempoTrascorso=0;
stato=CHIUSURA1ANTA;
}
break;
}
//Timer usato per calcolare gli intervvalli di tempo
SE avviaTimer==1 {
SE millis()-tempoPrecedente >=intervalloTempo{
tempoTrascorso=1;
}
}
Buon giorno a tutti, seguendo questa discussione ho deciso di replicare il progetto copiando il cancello di casa mia.
Da ex installatore elettrico so bene come deve funzionare, ed avendo in magazzino ancora due schede originali , non mi sogno di andare oltre il fine ludico del progetto, ma lo vorrei realizzare ,anche perché non riesco
Comunque, in questo caso si tratta di una sola anta dotata di costa di sicurezza, una coppia di fotocellule , un martinetto a 24V e un lampeggiante.
La logica di funzionamento : premo start ; apre; aspetta; chiude. se mentre chiudeva si aprono le fotocellule il moto si ferma e riapre; aspetta; se le fotocellule sono chiuse si chiude. La costa interrompe ogni movimento che può essere ripristinato (se la cosa è libera) con il tasto start.
Detto ciò , ho scritto il codice a stati (figo) e funziona pure. Però , e non poteva mancare ,
c'è un inghippo. Se le fotocellule restano impegnate per diverso tempo (maggiore al tempo che impiega a "ciclare") non chiude in automatico.
Istintivamente credo che adesso mi servirebbe una cosa tipo "while" più che un "return"
ma dopo innumerevoli tentativi sono entrato in "modalità a casaccio" e non va bene.
Posto il codice certo che saprete sgridarmi e insegnarmi.
Grazie mille.
#define fotocellula 2 //n.c.
#define costa 3 //n.c.
#define tasto_start 4 //n.o
#define tasto_stop 5 //n.o
#define motore_apre 6 //relè motore 24V
#define motore_chiude 7 //relè motore 24V
#define lampeggiante 8 //relè lampeggiante ; oppure led e includere blink nel software
bool stato_fotocellula = 0; //fotocellule libere(1) o ostacolate(0)
bool stato_costa = 0; //costa/e libere(1) o ostacolate(0)
bool stato_tasto_start; //ingresso start (parallelo tra vari ingressi)
bool stato_tasto_stop; //ingresso stop (parallelo tra vari ingressi)
bool aperto ; //stato posizione anta aperta
bool chiuso ; //stato posizione anta chiusa
int ciclo ;
int t_pausa = 15000 ; //tempo ritardo chiusura automatica
int t_lavoro = 30000 ; //tempo di alimentazione del motore per apre / chiude
unsigned long t_riferimento ; //riferimento live
void setup() {
Serial.begin(9600);
Serial.println("seriale ok");
pinMode(tasto_start,INPUT);
pinMode(tasto_stop,INPUT);
pinMode(fotocellula,INPUT);
pinMode(costa,INPUT);
pinMode(motore_apre,OUTPUT);
pinMode(motore_chiude,OUTPUT);
pinMode(lampeggiante,OUTPUT);
t_riferimento = millis(); //tengo traccia del tempo da inizio ciclo
}
void loop() {
//t_ciclo = map(analogRead(A0),0,1024,60000,300000); //regolazione esterna con potenziometro range tra 1' e 5'
//t_pausa = map(analogRead(A1),0,1024,60000,480000); //regolazione esterna con potenziometro range tra 1' e 8'
//Serial.print("tempo pausa ");
//Serial.println(t_pausa);
//Serial.print("tempo ciclo ");
//Serial.println(t_lavoro);
//delay(200);
stato_fotocellula = digitalRead(fotocellula); //leggo stato fotocellule
stato_costa = digitalRead(costa); //leggo stato costa/e
stato_tasto_start = digitalRead(tasto_start); //lettura stato ingresso start
stato_tasto_stop = digitalRead(tasto_stop); //lettura stato ingresso stop
if ((stato_tasto_start == 1) && (stato_fotocellula == 1) && (stato_costa == 1)){ //apertura senza ostacoli/ impedimenti
ciclo = 1; //inizio ciclo automatico
stato_tasto_start =0;
}
if ((stato_fotocellula == 0) && (ciclo == 3)){ //si stava chiudendo ma c'è un ostacolo
ciclo = 4;
}
if (stato_costa == 0){ //emergenza . costa sicurezza premuta, ripristinare il sistema
ciclo = 5;
}
switch (ciclo){
case 0: //blocco sicurezza costa
if ((aperto != 0) || (chiuso != 0)){ //se erano in movimento li fermo
digitalWrite(motore_apre,LOW);
digitalWrite(motore_chiude,LOW);
}
break;
case 1: //apre
digitalWrite(motore_apre,HIGH); //apro il cancello
digitalWrite(lampeggiante,HIGH); //accendo il lampeggiante
if (millis()- t_riferimento >= t_lavoro){ //trascorso il tempo necessario all'apertura totale
digitalWrite(motore_apre,LOW); //spengo il motore
digitalWrite(lampeggiante,LOW); //spengo il lampeggiante
aperto = 1;
ciclo = 2;
t_riferimento = millis();
}
break;
case 2: //pausa aperto
if (millis()- t_riferimento >= t_pausa){ //trascorso il tempo di pausa
ciclo = 3;
t_riferimento = millis();
}
break;
case 3: //chiude
if ((stato_fotocellula == 1) && (aperto = 1)){
digitalWrite(motore_chiude,HIGH); //chiudo il cancello
digitalWrite(lampeggiante,HIGH); //accendo il lampeggiante
aperto = 0;
if (millis()- t_riferimento >= t_lavoro){ //trascorso il tempo necessario all'apertura totale
digitalWrite(motore_chiude,LOW); //spengo il motore
digitalWrite(lampeggiante,LOW); //spengo il lampeggiante
chiuso = 1;
ciclo = 0;
t_riferimento = millis();
}
}
break;
case 4: //fotocellula impegnata mentre chiudeva
digitalWrite(motore_chiude,LOW);
delay(1000);
digitalWrite(motore_apre,HIGH); //apro il cancello
digitalWrite(lampeggiante,HIGH); //accendo il lampeggiante
if (millis()- t_riferimento >= t_lavoro){ //trascorso il tempo necessario all'apertura totale
digitalWrite(motore_apre,LOW); //spengo il motore
digitalWrite(lampeggiante,LOW); //spengo il lampeggiante
aperto = 1;
ciclo = 2;
t_riferimento = millis();
}
break;
}
}