Salve a tutti
sto testando un prototipo di riempimento di un silos di materiale (segatura) mediante l' avvio e lo spegnimento di 3 motori (simulati da 3 led), comandati da due sensori capacitivi per controllare il livello MAX e il livello MIN.(simulati con 2 interruttori a scorrimento).
Ho usato il sistema della macchina a stati in quanto i led hanno comportamenti diversi a seconda dell' ordine di attivazione dei sensori.
Il mio problema è che i led devono accendersi a distanza di 5 secondi uno dall'altro in fase di accensione, e devono spegnersi a distanza di 5 secondi uno dall' altro in fase di spegnimento.
Cioè 1-pausa -2 -pausa 3 ...poi 3-pausa-2-pausa-1.
Nello sketch che posto ho provato a farlo ma il comportamento dei
LED non è quello voluto.
Chiedo aiuto.
/*
Controllo Caricamento silos segatura con due sensori capacitivi simulati con 2 tasti a scorrimento
(esempio di macchina a stati)
D2: sensore livello minimo del silos
D3: sensore livello massimo del silos
Il carico è effettuato medianto un soffiante che aspira la segatura da un mulino raffinatore che a sua volta
è alimentato da una vasca contenente cippato di legno, quindi in totale sono 3 motori che qui vengono simulati con 3 led
che però devono partire o fermarsi (comandati dai sensori) a distanza di 5 secondi uno dall' altro.
Sequenza partenza: Soffiante-pausa 5 sec.-Mulino-pausa 5 sec.-Vasca
Sequenza Stop: Vasca-pausa 5 sec.-Mulino-pausa 5 sec.-Soffiante
min MAX| motori| stato
---------------------------------
1 1 | 0 | 1
1 0 | 0 | 2
0 0 | 1 | 3
1 0 | 1 | 4
*/
int stato = 1;
unsigned long t1,dt;
const long interval = 5000;
void setup() {
//unsigned long t1 = millis;
Serial.begin(9600);
pinMode(2, INPUT);
pinMode(3, INPUT);
pinMode(7, OUTPUT);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
}
void loop(){
dt = millis()- t1;
if (dt>=interval)
t1 = millis();
//leggo i sensori
int lmin = digitalRead(2);
int lmax = digitalRead(3);
String str = "s: " + String(stato) +
" min: " + String(lmin) + " max:" + String(lmax);
Serial.println(str);
switch (stato){
case 1:
digitalWrite(9, LOW);
if (dt>=interval){
digitalWrite(8, LOW);
dt = millis()-t1;
t1 = millis();
if (dt>=interval)
digitalWrite(7, LOW);
dt = millis()-t1;
t1 = millis();
}
//cambio di stato se:
if (lmin && !lmax) stato = 2;
break;
case 2:
digitalWrite(9, LOW);
if (dt>=interval){
digitalWrite(8, LOW);
dt = millis()-t1;
t1 = millis();
if (dt>=interval)
digitalWrite(7, LOW);
dt = millis()-t1;
t1 = millis();
}
//cambio di stato se:
if (!lmin && !lmax) stato = 3;
break;
case 3:
digitalWrite(7, HIGH);
if (dt>=interval){
digitalWrite(8, HIGH);
dt = millis()-t1;
t1 = millis();
if (dt>=interval)
digitalWrite(9, HIGH);
dt = millis()-t1;
t1 = millis();
}
//cambio di stato se:
if (lmin && !lmax) stato = 1;
break;
case 4:
digitalWrite(7, HIGH);
if (dt>=interval){
digitalWrite(8, HIGH);
dt = millis()-t1;
t1 = millis();
if (dt>=interval)
digitalWrite(9, HIGH);
dt = millis()-t1;
t1 = millis();
}
//cambio di stato se:
if (lmin && lmax) stato = 1;
break;
}
delay(200);
}
[/code]
Hai ragione in parte, perchè in realtà fanno la stessa cosa ...ma a seguito di un comportamento diverso dei sensori.
Se quando inizia il loop ho la vasca piena, avrò Lmin & Lmax (attivi) quindi non mi serve attivare i motori (accendere il led), e questo lo faccio con lo stato 4.
Mentre lo stato 3 mi accende i motori (i Led) a seguito di una lettura di Low di entrambi i sensori sensori.
All' inizio avevo messo un if all' inizio prima del switch che mi teneva fermo il tutto finchè i sensori erano tutti e due High,
Così:
if (lmin && lmax);{
}
poi a furia di fare prove ho provato anche a tirarlo via e mettere 4 stati.
...non mi è chiaro cosa farei con la funzione che mi hai suggerito.
Flaviano
stato 0: attesa.
Se il livello scende al di sotto del minimo, accende Motore 1 -> stato 1.
stato 1: attende che siano trascorsi 5 secondi, poi accende Motore 2 -> stato 2.
stato 2: attende che siano trascorsi 5 secondi, poi accende Motore 3 -> stato 0.
stato 0: attesa.
Se il livello raggiunge il massimo, spegne Motore 3 -> stato 3.
stato 3: attende che siano trascorsi 5 secondi, poi spegne Motore 2 -> stato 4.
stato 4: attende che siano trascorsi 5 secondi, poi spegne Motore 1 -> stato 0.
Io vedo un diverso tipo di problema, ma questo dipende da cosa fanno (o si suppone che facciano) nella realta' gli oggetti mulino, vasca e soffiante.
Ad esempio, presumiamo che mulino produca la segatura, vasca la raccolga dal mulino e soffiante la immetta nel silos, l'accensione sarebbe corretta anche come mulino > vasca > soffiante (anche se sarebbe meglio l'opposto), ma anche lo spegnimento dovrebbe essere uguale mulino > vasca > soffiante (se spengo prima soffiante, vasca e mulino si intasano o comunque si riempiono, e magari al secondo ciclo di accensione qualcosa si scassa o non funziona)
Quello che intendo e' che se stai facendo solo un test tuo, per divertimento o esercizio, va bene tutto, se stai facendo, ad esempio, un modello didattico, anche queste cose andrebbero prese in considerazione.
Questo dipende da quanta "logica", cioè altri flag, si vogliono far stare dentro uno stato. Ragionando solo con una sola variabile di stato direi:
0: se < minimo: on motore 1 -> stato 1
1: se trascorsi 5s: on motore 2 -> stato 2
2: se trascorsi 5s: on motore 3 -> stato 3
3: se > massimo: off motore 3 -> stato 4
4: se trascorsi 5s: off motore 2 -> stato 5
5: se trascorsi 5s: off motore 1 -> stato 0
Questo senza tenere conto di quanto detto da Etemenanki e senza fare altre considerazioni, tipo avvio/arresto manuale, timeout in caso di guasto sensori ecc.
Massimo e minimo li avevo messi nello stesso stato 0: se raggiunge il minimo fa una cosa; se raggiunge il massimo ne fa un'altra. In queto modo, per fermare i motori non deve necessariamente trovarsi nella stato 3.
0 -> 1 -> 2 -> 0
0 -> 3 -> 4 -> 0
a dir la verità a me sembra che siano i casi due e quattro ad essere uguali, come sensori anche se non come motori
comunque, secondo me la maniera più semplice per fare il lavoro è questa
array di piedini
nel setup () tutto il cinema necessario
nella loop() pochi casi if
se non Livello basso accende (stato=1) e tempo zero
se Livello alto spegne (stato=0) e tempo zero
se stato (occhio che c'è un else)
cicla l'array e alza in progressione i piedini che hanno superato il timeout
else
cicla l'array a rovescio e abbassa in progressione i piedini che hanno superato il timeout (occhio che il timeout va calcolato a rovescio)
con 56 righe si fa tutto
e sono 56 righe delle mie che scrivo più righe vuote e righe con solo graffe e metto graffe anche a cicli for di una sola riga
se si contasssero le sole righe con statement non saprei, ma sarebbe uno "sputicchio" di programma
Grazie a tutti per le risposte.
Inizio dallo spiegare il perchè del ritardo nelle accensioni, come (quasi) giustamente ha intuito Etemenanki si tratta di ovviare a un problema di intasamento alle successive accensioni. Infatti la vasca (per mezzo di una coclea) va ad alimentare il mulino e il soffiante/aspiratore va ad aspirare il materiale dal mulino, per cui per evitare che il mulino si ingorghi bisogna spegnere prima la vasca, poi dopo 5 secondi il mulino in modo da lasciargli il tempo di svuotarsi del materiale che si trova all' interno e dopo altri 5 secondi spegnere l' aspiratore che estrae il materiale raffinato dal mulino e lo manda dentro al silos.
Alla successiva accensione si avrà l' avviamento in senso inverso cioè 1-aspiratore 2-mulino 3-vasca cosicchè quando la coclea della vasca inizierà a fuoriuscire materiale il mulino sarà già avviato al massimo dei giri perchè era vuoto dallo spegnimento precedente.
Allego schema del processo di riempimento e svuotamento del silos in cui si nota che i motori assumono stati differenti a seconda che si stia riempiendo o svuotando.
Infatti i motori in fase di riempimento rimarranno accesi finchè il materiale non avrà raggiunto il Livello max, poi si spegneranno e rimarranno spenti finchè il materiale non scenderà sotto il Livello min.
Ho trascurato il fatto che il materiale viene espulso dal silos riempito mediante un altra coclea, perchè questo non fa parte del processo che stiamo esaminando.
Sembra di capire che si sta parlando di sequenze. Nelle sequenze A, B, C le leggiamo normalmente da sinistra verso destra. Invertendo il senso di lettura abbiamo C, B, A.
Se A, B e C sono i motori è corretto accenderli o spegnerli con questa sequenza?
Ora, l'accensione e spegnimento sono azioni composte. L'azione composta è la seguente: A(on), 5s, B(on), 5s, C(on). L'azione composta si considera eseguita dopo 10 secondi e la verifica è che A, B, C risultano accesi.
L'azione composta di spegnimento è identica, ciò che cambia è la sequenza che risulta invertita: C(off), 5s, B(off), 5s, A(off).
L'azione composta di spegnimento si considera eseguita dopo 10 secondi e la verifica è che A, B, C risultano spenti.
L'azione composta richiede quindi una variabile di stato che indica lo stato. Lo stato può essere: "In esecuzione", "ON", "OFF".
Mi concentrerei su un funzione C che esegue questa azione composta.
Si è una sequenza da seguire , prima A, (5s)B (5s), C poi C,(5s) B (5s), A sempre che sia abbia il consenso dai sensori come indicato nello schema qui sopra (post 13).
Ok. Supponi di avere una funzione già pronta che esegue questa azione composta. Ad esempio la funzione si chiama "azionaMotori" e prende come argomenti ON o OFF.
Lo pseudo codice potrebbe essere qualcosa di simile alla codifica finale.
IF SILOS(FULL)
AZIONA_MOTORI(OFF)
IF SILOS(EMPTY)
AZIONA_MOTORI(ON)
Più che parlare di sensori tiro in ballo lo stato del SILOS che mi aiuta a descrivere l'algoritmo in modo che sia comprensibile.
PS: non ho il codice pronto e il mio teorizzare è quello che faccio normalmente quando affronto un nuovo problema.
Il fulcro del problema sembra proprio la funzione che accende (e spegne) i motori in sequenza e se l'azione non è ancora completa se lo appunta nella variabile di stato.
Si il fulcro è proprio la funzione che inverte la sequenza A, B, C.
Per modellare la sequenza usero un array.
Se comprendi il codice di seguito possiamo andare avanti.
io vorrei avere qui il programma del quale ho parlato pochi giorni fa...
ma purtroppo (o come cantava Francesco Guccini, per fortuna)
mi è capitato di salvarlo inavvertitamente con un nome sbagliato, quindi lo ho cancellato durante una pulizia
perché dico per fortuna?
perché così hai la stupenda occasione di seguire le mie indicazioni e fartelo da te, invece che copiarlo
sono sicuro che se segui le mie indicazioni sarai certamente in grado di ottenere il risultato richiesto
Sono sicuro perché avevo provato il programma...
Magari questa volta accetterai un consiglio...
non so, io te lo do lo stesso:
Questa volta, segui quello che ti si dice
perché la volta scorsa ti avevo dato indicazioni al settimo post della discussione, e tu all'ottavo mi avevi dato torto, sei arrivato al centoventiquattresimo per ottenere la soluzione
Questa volta non mi lascerò "trasportare" in giro dalle tue considerazioni "fantasiose":
fai quello che ti ho indicato oppure cerca un'altra strada senza il mio aiuto
Io accetto l' aiuto di tutti per arrivare alla soluzione, solo che io non essendo un esperto faccio più fatica a seguire te piuttosto che Maurotec, nel senso che è più probabile che ci arrivi da solo se ho un codice di base di partenza (anche stilizzato). Tutto qui.
Anche tu hai detto che avevi risolto...ma non hai messo neanche una riga di codice e quindi, ripeto, mi riesce difficile uscirne partendo solo da una decrizione.
Emmm ... però hai presente il punto 16.1 del REGOLAMENTO ? ...
Tenete sempre presente che qui sul forum nessuno scrive software per conto terzi o realizza schemi su ordinazione, ma si aiuta chi viene qui a correggere/ottimizzare il software che lui scrive o gli schemi che lui realizza .
... quindi, TU dovresti scrivere il codice e noi dovremmo aiutarti a correggerlo ...