Go Down

Topic: Codice azionamento passerella idraulica imbarcazione. (Read 538 times) previous topic - next topic

vince59

Grazie Claudio, però sinceramente fatico un pò a comprendere del tutto la tua spiegazione.
I pulsanti in locale (quelli sul tastierino per intenderci) sono quelli che "..opportunamente valutati decidono l'uscita..." ed azionano i relè.
I pulsanti in remoto, in realtà non saranno altro che una scheda radiocomando 433 MHz a 4 canali che azioneranno lo stesso relè. IN pratica li parallelo fisicamente.
Questo è uno step iniziale perchè in realtà vorrei realizzare un circuito che invece dei relè utlizzi semiconduttori..tipo MOSFET o simili.

PS: tieni conto che sono un hobbista autodidatta per cui alcune nozioni mi mancano.



Claudio_FF

#16
Jul 17, 2019, 11:06 pm Last Edit: Jul 18, 2019, 06:28 am by Claudio_FF
Per me i 4 canali del ricevitore del radiocomando è meglio leggerli con altri 4 ingressi di Arduino, così i relé li comandi solo da Arduino e non fa nessuna differenza premere un pulsante locale o uno remoto.
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

vince59

Grazie Claudio, ottimo suggerimento.
C'è un limite alle condizioni che posso porre internamente ad un if?

Claudio_FF

#18
Jul 18, 2019, 07:47 pm Last Edit: Jul 19, 2019, 08:18 pm by Claudio_FF
C'è un limite alle condizioni che posso porre internamente ad un if?
In senso di quantità? Non credo. Attendiamo smentite.
Certo che se devi mettere dieci o venti condizioni assieme, forse c'è qualcosa da rivedere nel design del programma ;)

Tra l'altro per azionamenti così semplici alle volte può essere più facile ragionare a relé. Il seguente schema simulato a programma sono 19 righe in tutto, letture ingressi, temporizzatori e scrittura uscite compresi, e prevede anche che la pompa non si fermi immediatamente, in modo che se si vuole premere un altro tasto non tocca aspettare di nuovo ripartenza pompa e ritardo (i pulsanti sono ovviamente mutuamente esclusivi, quando uno è premuto gli altri sono esclusi):



Ad esempio:
Code: [Select]
// la prima riga
f1 = (digitalRead(PULS_ALZO)==PRESSLVL || digitalRead(telec_al)==TELECLVL) && !f2 && !f3 && !f4;


// il temporizzatore T1 (ritardato all'avvio)
if (!f1) { T1=0; t1=millis(); } else if (millis()-t1 > TDEL) T1=1;


// il temporizzatore T5 (ritardato al rilascio)
if (f1 || f2 || f3 || f4) { T5=1; t5=millis(); } else if (millis()-t5 > TSTOP) T5=0;


// comando rele'pompa
digitalWrite(RL_POMPA, T5 ? ONLVL : OFFLVL);


// il comando alzo
alzo = T1 || (f1 && f5);


// il rele'ausiliario f5 con autoritenuta
f5 = T5 && (alzo || abbasso || attendi || ritrai || f5);
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

vince59

veramente interessante come codice....devo studiarlo e comprenderlo bene.
Claudio, pur comprendendo la logica dei comandi della prima riga, comprendo cosa sia stato costruito.
Ovvero, l'intera riga che parte  f1:

f1 = (digitalRead(PULS_ALZO)==PRESSLVL || digitalRead(telec_al)==TELECLVL) && !f2 && !f3 && !f4;

che cosa è dal punto di vista tecnico?
Purtroppo, difficilmente arriverò ad un livello del genere.

Maurotec

Quote
f1 = (digitalRead(PULS_ALZO)==PRESSLVL || digitalRead(telec_al)==TELECLVL) && !f2 && !f3 && !f4;
Poco leggibile, quando si è costretti a fare ciò preferisco l'algebra di bool confinata dentro una funzione che restituisce true o false.

prima valuta  (digitalRead(PULS_ALZO)==PRESSLVL || digitalRead(telec_al)==TELECLVL), dove,
PULS_ALZO e telec_al sono dei pin di ingresso e PRESSLVL, TELECLVL sono costanti, se questa espressione viene valuta vera (true) procede a valutare il resto, tutta l'espressione allora risulta vera se f2, f3 e f4 sono false (nota la negazione !).

|| OR
&& AND

Ciao. 

vince59

Grazie. Volevo conferma di essere sulla giusta strada.

Claudio_FF

f1 = (digitalRead(PULS_ALZO)==PRESSLVL || digitalRead(telec_al)==TELECLVL) && !f2 && !f3 && !f4;
che cosa è dal punto di vista tecnico?
È un'espressione logica esattamente come questa del tuo codice (ho solo aggiunto l'OR con l'ingresso per il telecomando):
Code: [Select]
(digitalRead (btnStateUp) == LOW && digitalRead (btnStateDown) == HIGH && digitalRead (btnStateOut) == HIGH && digitalRead (btnStateIn) == HIGH)

Potrebbe sfuggire questa sintassi:
Code: [Select]
a = b && c;
che vuole dire:
Code: [Select]
if (b && c) a=1; else a=0;

Un'espressione logica restituisce un valore true/false (che è esattamente la stessa cosa di 1/0), quindi tutte le variabili "relé simulati" assumono di volta in volta solo i valori 1 e 0 e possono essere usate in altre espressioni.

Le costanti PRESSLVL e TELECLVL invece servono per non scrivere dappertutto LOW/HIGH, se leggo la seguente riga non capisco se un pulsante è premuto oppure no, perché bisogna guardare lo schema elettrico, oppure ci devono essere dei commenti ben precisi che facciano capire che LOW corrisponde a premuto:
Code: [Select]
if (digitalRead(btnStateUp) == LOW) ...
Se invece leggo la seguente riga so senza dubbio che sto testando se il pulsante è premuto:
Code: [Select]
if (digitalRead(btnStateUp) == LIVELLO_PREMUTO) ...
Poi come dice Maurotec usare funzioni rende ancora più chiare le cose (si può scrivere tutta la logica in italiano, ma non volevo aggiungere troppe cose):
Code: [Select]
if (pulsanteUpPremuto()) ...
....
bool pulsanteUpPremuto() { return digitalRead(btnStateUp) == LIVELLO_PREMUTO; }
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

vince59

Grazie delle spiegazioni. Avevo anche io aggiunto l'OR e stavo perfezionand il codice ma la tua versione mi piace di più.
In effetti formulando le difnizioni in maniera mirata è molto più semplice comprendere il codice ed il relativo flusso.
Ora una domanda probabilmente molto molto banale...ma all'interno del codice come "chiamo o attivo"  "f1"?
Mi spiego, le mie condizioni sono nel ciclo if e quindi al verificarsi dell'evento "partono".
Ma questa come parte?
...non insultatemi  :-*

Claudio_FF

#24
Jul 19, 2019, 08:16 pm Last Edit: Jul 19, 2019, 08:37 pm by Claudio_FF
all'interno del codice come "chiamo o attivo"  "f1"?
Mi spiego, le mie condizioni sono nel ciclo if e quindi al verificarsi dell'evento "partono".
Ma questa come parte?
Qui siamo a un livello più basso rispetto al codice "standard" (o algoritmico) che stavi scrivendo. Con i relé simulati di fatto fai solo funzionare dei "finti relé" rappresentati da variabili in memoria. La riga di cui si parla (che corrisponde al primo "piolo" dello schema) è un'espressione il cui risultato è lo stato assegnato a 'f1' (1 o 0) ad ogni giro di loop. Se la condizione complessiva è vera allora 'f1' vale 1, altrimenti 0. Ad ogni giro di loop viene riverificata e il valore di 'f1' si "adegua".
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

vince59

caxx....fatico un pò a comprendere. Ci devo tornare su a mente fresca.
Non mi è chiaro come, devo strutturare il codice.
Devo solo inserire la varie righe all'interno del loop e queste verranno poi verificate ecc. ecc.?

Cmq con i cicli "if" sono riuscito a far funzionare il codice (simulando con led).
Ora ho questa situazione: 8 input, 4 del tastierino e 4 del telecomando che entrano in Arduino (ottimo il tuo suggerimento).
Viene monitorato lo stato e - subordinatamente a quello degli altri input - viene azionato il motore e relativa valvola.
Avendo imposto delle condizioni, riesco a far si che non vi sia sovrapposizione dei comandi ed uno esclude l'altro. Quindi se sono in ALZO (pulsante o tx) e premo ABBASSO (pulsante o TX) il sistema si blocca.
Se invio lo stesso comando, premendo pulsante e tx, il sistema continua.
Cmq ora vorrei scrivere un codice utlizzando le tue indicazioni.

Claudio_FF

#26
Jul 19, 2019, 09:50 pm Last Edit: Jul 20, 2019, 04:15 pm by Claudio_FF
Devo solo inserire la varie righe all'interno del loop e queste verranno poi verificate ecc. ecc.?
Esatto, come avviene in un PLC.

Le righe di programma descrivono solo i collegamenti (le condizioni di attivazione) dei relé/temporizzatori simulati.

Ma sono poi i relé/temporizzatori simulati (collegati come da schema) a compiere il lavoro richiesto.

L'unica cosa a cui fare attenzione è inizializzare le variabili a zero prima di eseguire il loop. Ok, magari lo fa già implicitamente il compilatore (almeno per quelle globali), ma meglio scrivere le cose esplicite per essere sicuri di non avere sorprese (punto due dello Zen di Python: «Explicit is better than implicit.»)
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

Maurotec

Quote
caxx....fatico un pò a comprendere. Ci devo tornare su a mente fresca.
Non mi è chiaro come, devo strutturare il codice.
Ci sono almeno due modi di procedere: bottom up o top down, qui il primo link non letto sull'argomento https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=2ahUKEwjvurv_5MHjAhVOsKQKHa26CUoQFjAAegQIAxAB&url=https%3A%2F%2Fit.wikipedia.org%2Fwiki%2FProgettazione_top-down_e_bottom-up&usg=AOvVaw0UX7F_-VxX6iFnE3wuECSd

Bottom up significa dal basso verso l'alto, pertanto ci si concentra a scrivere codice per testare i vari sensori e per commutare le uscite. A questo livello non si mettono in relazione gli ingressi con le uscite ma si prepara il codice in modo che al livello più alto sia possibile mettere in relazione ingresso/uscita. A questo livello si provvede anche a testare il codice e a renderlo più flessibile. Terminate le funzioni "primitive" si passa a livello superiore, ad esempio uno dei livelli più alti è riservato al loop ed alla macchina a stati. Tuttavia questa separazione tra bottom up e top down non è netta e qualche volta si usano entrambe, come dire può capitare di accorgersi che il lavoro fatto con bottom up non si adatta bene e tocca rivederlo e ci si accorge di ciò mentre si affronta il problema dall'alto verso il basso.

Io avevo suggerito di usare il metodo "dal basso verso l'alto" così da creare le funzioni primitive (i mattoncini) testarle e poi salire di un livello.

Per semplificare pensa che la macchina fornisca un solo tipo di prodotto, concentrati su quello. Ancora più elementare scrive del codice che accetta una moneta e stampa sul serial monitor "prodotto erogato" poi parte di questo codice lo confini dentro una funzione C che prende x argomenti e ne restituisce uno. Si procede cosi con altri pezzi di programma testati e infilati dentro funzioni, si testano queste e si passa avanti. Quando tutti (o la maggior parte) dei mattoncini sono stati preparati si implementa il loop, lo swicht case ecc.

Ciao.   

Claudio_FF

Bottom up significa dal basso verso l'alto, pertanto ci si concentra a scrivere codice per testare i vari sensori e per commutare le uscite.
[....]   
Tutto perfetto il discorso, ma nel thread sbagliato  ;)
* * * *    'if' e 'case' non sono cicli   * * * *
* * * Una domanda ben posta è già mezza risposta. * * *
* La corrente si misura in 'mA', la quantità di carica in 'mAh' *

Maurotec

Quote
Bottom up significa dal basso verso l'alto, pertanto ci si concentra a scrivere codice per testare i vari sensori e per commutare le uscite.
[....]   
Vero, ho confuso il post con quello della macchina erogatrice di pezze per pulire l'auto  :smiley-confuse:

Credo che la colpa sia dell'icona sotto il nome del profilo, mi sono ritrovato troppe volte a fissarle. :smiley-mr-green:

Comunque top down e bottom up a quel link sintetizza abbastanza bene il processo di sviluppo e vale la pena di leggerlo.

Ciao.

 

Go Up