stesso PIN che riceve istruzioni da più parti dello sketch.

Buongiorno,
probabilmente il titolo del topic non è proprio chiaro, cercherò di seguito di spiegarmi meglio.
Praticamente ho 6 piastrine led a 9 V collegate a coppie a 3 mosfet pilotati da una pro-micro.
Le 6 piastrine per comodità le assumiamo come 3 led, che chiamiamo outFdx, outLuci, outFsx.
Lo sketch che ho fatto funziona, ovvero se premo il pulsante inFdx si accende outFdx, se premo il pulsante in luci si accende outluci, se premo inFsx si accende outFsx. E fin qui tutto bene, però non è proprio quello che voglio.
Quello che dovrebbe fare è che se premo inLuci, si dovrebbe accendere outLuci, outFdx, outFsx. Da questo stato se premo ad esempio inFdx, outFdx deve lampeggiare per poi ritornare allo stato di outLuci quando ripremo inFdx. allo stesso modo se outFdx sta lampeggiando e premo inFsx, outFdx deve portarsi allo stato dei outLuci e deve lampeggiare outFsx.
Ho provato con dei digitalwrite( ) multipli ma poi ho letto che non può funzionare.
ho fatto lo sketch in un unica scheda, in più schede richiamandole con #include, ma non ci sono riuscito.
Mi serve sapere se si può fare e come a livello software, altrimenti dovrò farlo a livello hardware aggiungendo dei diodi, ma non è la stessa cosa.
Allego lo sketch e se riesco anche il circuito con tinkercad.
Grazie a tutti per l'aiuto che vorrete darmi.
Manuel

Non c'è lo sketch allegato...

Si scusate, ora dovrebbe esserci.
Premetto che ho copiato da diversi sketch trovati in rete, ho cercato di capirli e poi di mettere assieme quello che mi interessava. La definizione dei numeri dei pin è quella della pro-micro. Come potrete notare c’è un out… e un led… out è riferito al pin che va al gate del mosfet, mentre led è riferito al led del pulsante. Per QF non c’è outQF perché sarebbero le quattro frecce , quindi quando premo inQF l’uscita deve essere outFdx e outFsx.
Spero di essermi spiegato.
Grazie
Manuel

Fdx.h (900 Bytes)

Fsx.h (970 Bytes)

luci_JD_promicro.ino (431 Bytes)

Luci.h (709 Bytes)

QF.h (809 Bytes)

Ok, solo un consiglio intanto: per il futuro, se il progetto include più file, fai un unico ZIP con tutti i file all'interno, così si fa tutti prima :wink:

In questo caso in particolare, magari condividi pure il link al circuito Tinkercad se ce l'hai, perché lì si può non solo vedere come lo hai realizzato e sperimentare, ma anche eventualmente clonarlo e fare le modifiche provandole prima di sottoportele, senza dover "costruire" nulla.

Infine dalla tua descrizione temo che la cosa migliore sarebbe quella di ripensare il tutto come "macchina a stati finiti" o FSM (Finite State Machine). Non so se hai mai avuto a che fare con queste FSM ma puoi provare a cercare in rete qualche descrizione, perché molte applicazioni di controllo (e quindi anche per Arduino) si implementano molto più facilmente con una FSM che non con una miriade di if(), else, e funzioni varie.

Nel tuo caso poi non è generalmente male dividere il progetto in più file *.h in base alle sezioni logiche o "moduli" un poco assimilabili ad "oggetti", e la cosa la faccio in genere per progetti da una certa dimensione in su, anche se quando possibile preferisco creare direttamente delle classi C++ (diciamo come delle librerie) ed usare quelle per gli oggetti che "gestiscono" qualcosa.

Ma in questo caso mi sembra non solo poco utile questa divisione, ed anche fonte di problemi: capisco che stai cercando di assemblare programmi trovati in rete, ma se hai interdipendenza tra i vari led la vedo difficile implementare la modifica che hai richiesto anche per via della divisione per "moduli" che hai attualmente, in quanto ti costringerebbe ad utilizzare "qualcosa" in comune e soprattutto dovrai "spargere" la logica per i vari moduli/funzioni (cosa questa che contrasta con l'approccio "ad oggetti")

Inizia a disegnare su carta la logica sotto forma di FSM, ossia uno schema in cui ogni cerchio è uno stato a cui assegni un nome ed un identifiativo numerico (1, 2,..), quindi unisci gli stati con degli archi sui quali scrivi la condizione (che, se verificata, fa andare il flusso lungo quell'arco) e l'eventuale azione (ossia cosa deve fare il programma quando la condizione è verificata e prima di passare al nuovo stato).

Provaci, e fammi sapere se hai problemi a capire cosa o come fare, e vedrò di aiutarti.

Quando avrai terminato questo schema e verificato che corrisponde con ciò che vuoi ottenere, potrai iniziare a rappresentare nel programma gli stati con un valore intero (byte) possibilmente associato ad un simbolo (es. "#define S_ACCENDI 2"), lo stato corrente con una variabile byte (inizializzata con il codice dello stato iniziale), ed implementare le condizioni nella loop() con altrettanti "case".

Se vuoi avere un'idea di come sarebbe la struttura di uno sketch per FSM, un esempio di implementazione lo trovi QUI.
Se non riesci a capire bene come funziona, ovviamente scrivi qui.

grazie mille, proverò sicuramente a seguire i tuoi consigli.
Studio un po' le FSM, sistemo il progetto in tinkercad e lo condivido al più presto. Purtroppo mi ci vorranno alcuni giorni.
per ora grazie mille e a presto.
Manuel

Buongiorno, finalmente sono riuscito a dedicarmi al progetto in tinkercad che vi allego.
Nel progetto è presente anche un buzzer comandato da un pulsante. Ho fatto un codice anche per il buzzer ma lo rimando a quando ho (abbiamo :)) sistemato le luci.
Nel disegno mancano le resistenze tra PIN e GATE dei mosfet, considerate che ce n'è una da 100 ohm per ogni mosfet.
Il mosfet per il buzzer invece verrà pilotato da un driver in quanto vorrei farlo suonare alcuni temi.
Ho studiato un po' di FMS ma per ora con scarsi risultati, devo approfondire.
Grazie e a presto.
Buona serata a tutti

di seguito anche il link a tinkercad.

Per le FSM, io a suo tempo mi feci una mia piccola libreria per “semplificare” la scrittura di programmi nei quali si debba implementare una FSM (nel io caso un robot) visto che quelle che avevo trovato in giro non mi soddisfacevano. Se vuoi provarla si chiama (con non troppa fantasia) “FiniteState”, la puoi trovare QUI dove puoi trovare anche documentazione ed esempi di uso.

PS: ne sto preparando una versione ancora più semplificata, spero, che chiamo “EasyFSM” ma è in lavorazione, e visto lo scarso tempo libero che ho a disposizione tra lavoro ed altro, credo che la finirò forse durante le feste di Natale ;).

buonasera, fatto tutto quello che mi hai richiesto, cancellato post doppio e modificato post#6.

Ho fatto un po’ di prove con le FSM, ovviamente con scarsi risultati.
L’ultima prova che ho fatto, e che posto, l’ho pensata che riconosco il fronte di salita del pulsante e gli assegno uno stato, per semplicità un numero.
Poi all’interno del caso di switch(stato) faccio fare il debounce e lo stato del pulsante e l’azione che deve essere fatta, ovvero l’accensione delle luci o il lampeggio delle frecce.
Non funziona.

Avevo provato ad assegnare uno stato quando il pulsante veniva schiacciato con digitalRead(pulsante) ma anche cosi non funzionava.

Ho raggiunto il limite delle prove, ho bisogno di suggerimenti.

Grazie mille

JD_FSM_rev1.ino (4.12 KB)

Troppo mescolate le varie competenze (lettura pulsante, edge detect, debounce, logica), diventa difficilissimo venirne fuori.

Si semplifica separando rigorosamente le operazioni:

Lettura pulsante, ok, è semplice:

readingLuci = digitalRead(inLuci);

Debounce in pressione e rilascio (la variabile 'debounceLuci' segue in ritardo le variazioni stabili di 'readingLuci'):

if (readingLuci == debounceLuci) { tLuci = millis();           }
else if (millis()-tLuci > 50)    { debounceLuci = readingLuci; }
readingLuci = debounceLuci;

Edge detect che valorizza la variabile 'clickLuci' a uno solo nel momento della pressione e per un solo ciclo di programma:

clickLuci = !previousLuci && readingLuci;
previousLuci = readingLuci;

A questo punto nella logica applicativa non serve altro che testare if (clickLuci)

Consiglio: le graffe dei blocchi di istruzioni sotto condizione/ciclo si consiglia di metterle sempre e comunque, anche se c'è una sola istruzione, si evitano tanti errori e la logica appare più chiara a colpo d'occhio.

Grazie mille. Quindi dopo aver fatto le modifiche che hai proposto per testare le condizioni dovrei scrivere di seguito al codice che hai postato:

stato = 1

switch(stato)

case 1

if (!ledLuci_state) ledLuci_state = true;{
     else ledLuci_state = false;

     digitalWrite(outLuci, ledLuci_state );
     digitalWrite(outFdx, ledLuci_state );
     digitalWrite(outFsx, ledLuci_state );
}

non so, sono abbastanza confuso

rebesko:
L'ultima prova che ho fatto, e che posto, l'ho pensata che riconosco il fronte di salita del pulsante e gli assegno uno stato, per semplicità un numero.

Ok, allora, intanto il primo ("solito") consiglio: indenta bene il codice, ed evita di inserire inutili righe vuote!
Serve soprattutto a te per poter "vedere" meglio il flusso del codice (per le righe vuote mettine UNA solo tra le funzioni e tra eventuali "blocchi" di codice che vuoi evidenziare, come anche prima dei "case" ad esempio) ed a noi per leggere meglio quello che hai scritto (visto che comunque dobbiamo in qualche modo "interpretare" quello che stavi cercando di fare).
Nell'IDE premi Ctrl-T e te lo fa lui, poi cerca di mantenere quel formato.

Veniamo quindi al tuo codice.

La prima cosa che si nota è che lo "stato" della FSM non devi definirlo come variabile interna al loop() altrimenti ti "perdi" lo stato tra un ciclo ed il successivo. Devi averlo come variabile globale, e che cambi solamente quando le condizioni lo consentono. Inoltre è opportuno codificare gli stati con un simbolo (quindi usando delle "#define"), come ti avevo consigliato, per fare in modo che invece di un poco comprensibile "case 1:" tu possa avere ad esempio "case ATTESA_TASTO:".
Nello switch() selezionerai il codice da eseguire in base allo stato corrente, ed all'interno di questo cambierai lo stato (ossia il valore della variabile globale) solamente se si verifica una condizione che impone di cambiare stato.

A parte questo, però, quando pensi di implementare una FSM devi prima definire come debba funzionare facendo uno schemino, e poi iniziare a codificare.

In realtà te l'avevo già scritto quello che ti consigliavo di fare:

Inizia a disegnare su carta la logica sotto forma di FSM, ossia uno schema in cui ogni cerchio è uno stato a cui assegni un nome ed un identifiativo numerico (1, 2,..), quindi unisci gli stati con degli archi sui quali scrivi la condizione (che, se verificata, fa andare il flusso lungo quell'arco) e l'eventuale azione (ossia cosa deve fare il programma quando la condizione è verificata e prima di passare al nuovo stato).

Se non fai questo prima di iniziare a codificare, ti troverai sempre in confusione soprattutto all'inizio, quindi prendi carta e penna e provaci!

Basandomi sulla tua definizione del primo post, credo che ti bastino due stati, uno START (comportamento normale per accendere e spegnere sx e dx) ed un BLINK (quando accendi tutti i led, e fai lampeggiare sx o dx a seconda del pulsante che premerai in questo stato).

lo schema potrebbe essere questo qui sotto, ma rivedilo e se va bene vediamo di costruire insieme questa semplice FSM.

Image1.png

Image1.png

Grazie mille docdoc. In realtà lo schemino a "pallocchi" l'ho fatto e lo allego. Vedendo il tuo però si nota subito che il mio è sbagliato e probabilmente non porta a nulla.
La variabile stato la avevo definita come variabile globale, avevo letto che doveva essere cosi, ma quando compilavo mi restituiva l'errore "stato non definita in this scope" (scusa il mix italoinglese). Allora mettendola dentro il loop non mi dava questo errore. Ecco perchè l'ho lasciata li.
Sostanzialmente il cambio di stato ce l'ho ogni qualvolta premo un pulsante.

Ehm, non c'è allegato nulla... :wink:

Poi posta la tua versione dello sketch e dicci se ti funziona o se hai bisogno di qualche altro consiglio (suppongo che serva per far lampeggiare i led, ma non viglio ancora anticipare le cose perché, come dico sempre, "fare una cosa per volta"!:D)

Non mi accetta l’allegato, mi restituisce sempre un errore. Mi sa che ho un problema di connessione.

Ho provato ad aggiornare il codice con i vari suggerimenti ricevuti.
Adesso non passa nemmeno la fase di compilazione.

JD_FSM_rev2.ino (3.5 KB)

La dimensione massima di un allegato è 2MB, quindi verifica che l'immagine sia più piccola o più compressa.

Guglielmo

rebesko:
Ho provato ad aggiornare il codice con i vari suggerimenti ricevuti.

Andavano prima ben compresi :wink:

Scrivi:

  if (readingLuci == debounce) { t0btt = millis();           }
    else if (millis()-t0btt > 50)    { debounce = readingLuci; }
  readingLuci = debounce;
  

   if (readingFsx == debounce) { t0btt = millis();           }
    else if (millis()-t0btt > 50)    { debounce = readingFsx; }
  readingFsx = debounce;

usi le variabili 'debounce' e 't0btt' contemporaneamente per due cose diverse...

Se 't0btt' deve contenere il tempo per effettuare il debounce di 'readingLuci', non puoi poi usarla, cioè alterarne il valore, usandola anche per contenere il tempo per fare il debounce di 'readingFsx'.

Stessa cosa per la variabile 'debounce' che deve contenere il livello precedente stabile di 'readingLuci', non la puoi usare anche per gestire il livello precedente stabile di 'readingFsx'.

Inoltre tutti quegli assegnamenti stato = 0, stato = 1 dopo ogni lettura dei pulsanti ecc non hanno senso logico. Se li esegui tu a mano cosa producono?

Grazie Claudio, come avrai capito non sono una spada nella programmazione, meglio non ne so nulla. Sto cercando di capirci qualcosa e per ora mi muova a tentoni. Mi scuso in anticipo e ti chiedo gentilmente di portare un po' pazienza.
Giusto per farmi capire, nel primo sketch che avevo postato il debounce l'ho fatto per ogni pulsante e siccome è uguale per tutti i pulsanti ho usato lo stesso t0btt (tempo iniziale) e lo stesso valore di debounce. Allo stesso modo ho usato lo stesso t0led sia per il lampeggio di Fdx che di Fsx. E funzionava.
Perchè non si può fare la stessa cosa anche per il codice che mi hai scritto tu?
Altra cosa vorrei capire a cosa serve e cos'è Edge detect

clickLuci = !previousLuci && readingLuci;
previousLuci = readingLuci;

.

Sicuramente la soluzione suggerita da te è migliore di quella che ho fatto io scopiazzando ed incollando pezzi di codice trovati sparsi qua e la. Il codice iniziale funzionava solo per pura fortuna e come non ho capito niente di quello che ho fatto io ho capito gran poco anche di quello che mi hai suggerito tu.
Se potessi spiegarmelo un po' di più te ne sarei grato.
Ciao Manuel

@ Guglielmo, grazie. In effetti il file era troppo grande.

@ docdoc, allego qui il diagramma della FSM.

Grazie per l'aiuto e la vostra pazienza.
Manuel

:confused: :frowning:
Mi sono accorto che forse mancano degli stati, questo dovrebbe essere più completo.
Scusate