Cerco consigli per compilazione sketch

Ciao a tutti, sono nuovo del mondo Arduino.
Sto piano piano imparando le basi ma vorrei alcune delucidazioni su come meglio compiere la "stesura" del programma che vorrei fare.

Il progetto:

Un interruttore inizia il lampeggio di un led per 5 o 10 secondi, durante i quali arduino controlla se avviene un cambio di stato del suddetto interruttore (nello specifico uno con spina da inserire in blocchetto, che inserita disattiva i contatti per cui collegato in pullup - se non ho fatto una stupidata-), e se lo stato cambia attiva un output, altrimenti lo mantiene disattivo una volta terminato il conteggio.

La stessa cosa avviene per spegnere l'output finale, inserisco la chiave, lampeggia ed entro tot secondi devo togliere la chiave oppure arduino lascerà attivo l'output.

Buonasera e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto. :wink:

Nella programmazione ci sono due cose:

  • La logica: rappresentabile tramite diagrammi di flusso, diagrammi di stato, diagrammi di interazione, diagrammi di struttura o pseudocodice ecc, che descrive in modo schematico e preciso l'idea "discorsiva" iniziale.
  • Le istruzioni: che codificano praticamente la logica in uno specifico linguaggio per uno specifico hardware.

Le due cose sono ovviamente legate tra loro, come una ricetta di cucina al pentolame, ma si possono anche analizzare separatamente. Con la pratica, conoscendo il pentolame a disposizione, si impara a impostare la ricetta (procedura da eseguire) in modo ottimizzato seguendo specifici pattern (metodi di lavoro), all'inizio invece è sempre una salita ripida.

La delucidazione riguarda quale aspetto?

ad esempio come creare la riga dove, durante il blink, attende il cambio di stato del pulsante per eseguire il compito.

Sono davvero neofita e non ho nessuno accanto a cui chiedere per cui cerco di essere comprensibile:
Se non ho capito male dovrei creare un ciclo for per il blink, e poi metterci un while durante cui leggere lo stato e quindi un if-else per l'operazione finale.

mi fareste degli esempi? non trovo nulla e vorrei aiuto

@marra92: ... hai letto il punto 16.1 del REGOLAMENTO ? In quel punto sono elencati sia dei .pdf gratuiti da scaricare e studiare, sia un'ottimo libro da acquistare.

Guglielmo

L'ho letto tuttavia non vedo nello specifico la mia richiesta di scrivermi lo sketch.
Ho chiesto se è corretto il principio di funzionamento forcycle-while-ifelse oppure se devo separarli.

Un esempio poteva essere " (forcycle(while(ifelse)))" giusto perchè non ho ben chiaro questo aspetto, per non farla lunga sono una di quelle persone che hanno a volte problemi a comprendere certe formule, necessitando di una mano in più per prendere il volo.

for while if sono... padelle, certamente bisogna conoscere come si usano, ma come maneggiarle per arrivare a un certo risultato è un altro paio di maniche, e riguarda appunto la logica.
Provare a usare più o meno a tentativi le diverse padelle non porta ad alcun risultato se prima non è definita la procedura che si vuole seguire.

In particolare dalla descrizione secondo me emergono almeno sei stati/situazioni in cui il sistema si può trovare, e questi devono essere ben chiari ed esplicitati prima di pensare di buttare giù una sola istruzione:

7864875444

NOTA: i numeri degli stati non indicano alcuna sequenza (che è quella indicata dalle frecce) ma sono solo nomi per identificarli.

Già solo con questa schematizzazione (che descrive bene l'ordine temporale in cui avvengono o ci si aspettano le cose) si nota che il LED deve blinkare negli stati 1 e 4, e che l'uscita deve essere attiva negli stati 1, 2 e 5. Questa è già una buona base di partenza e semplifica tantissime cose (e non stiamo ancora parlando di istruzioni).

Ad ogni ciclo di esecuzione del programma (che avviene nella funzione loop) va gestito lo stato attualmente "valido", che banalmente si può identificare con il valore di una variabile 'fase':

// gestione stato attivo
if (0 == fase) 
{
   ...
}
else if (1 == fase)
{
   ...
}
else if (2 == fase)
{
   ...
}
else if (3 == fase)
{
   ...
}
else if (4 == fase)
{
   ...
}
else if (5 == fase)
{
   ...
}

Dopo questa struttura di selezione in cui verranno valutati gli eventi attesi, si possono scrivere le gestioni del blink e dell'uscita, che in ogni momento dipendono solo dallo stato attivo. Ad esempio:

// gestione blink
if (1 == fase  ||  4 == fase)
    digitalWrite(LED_PIN, (millis() % 500) < 250);
else
    digitalWrite(LED_PIN, ...livello off...);
// aggiornamento uscita
if (1 == fase  ||  2 == fase  ||  5 == fase)
    digitalWrite(USCITA_PIN, ...livello on...);
else
    digitalWrite(USCITA_PIN, ...livello off...);

Già da qui si vede che con questa impostazione tutto il ragionamento di un for per il blink dentro cui aspettarsi il pulsante ecc ecc è inutilmente complicato.

È sufficiente in ogni stato occuparsi solo di riconoscere gli eventi che gli interessano, fare quello che eventualmente serve fare quando sono riconosciuti, e impostare un nuovo valore nella variabile 'fase' se si deve cambiare stato:

if (0 == fase) 
{
   if (chiaveInserita()) 
   {
       resetTimer();  // salvo tempo istante di inserimento
       fase = 4;      // stato valutato al prossimo ciclo di loop
   }
}

Si possono poi scrivere le piccole funzioncine di servizio per svolgere i compiti hardware di base, ad esempio:

bool chiaveInserita() {
  return digitalRead(PIN_CHIAVE) == ...livello premuto...;
}
void resetTempo() {
    tempoInizioConteggio = millis();
}
bool timeout(uint32_t delta) {
    return millis() - tempoInizioConteggio >= delta;
}

Tutto questo è tremendamente più semplice di quanto stavi iniziando a pensare con cicli innestati ecc, permette di scrivere praticamente tutta la logica in italiano con fasi, e passaggi da una fase all'altra, ben espliciti, ed è un metodo generale e universale per affrontare qualsiasi compito di automazione. Come effetto collaterale permette anche di scrivere N processi paralleli indipendenti che vengono eseguiti "contemporaneamente" (a livello di processo, perché poi fisicamente la CPU esegue una sola istruzione per volta).

Non mi riferivo a quello, ma alle cose (link) da scaricare e studiare!

Guglielmo

Comincia a fare le cose più semplici; poi, quando saprai fare con disinvoltura tutto ciò che ti serve, vai avanti. Per esempio: sai far lampeggiare un LED senza bloccare l'esecuzione del loop? Ci sono almeno tre modi: lasciando per il momento da parte timer e interrupt, rimangono il modulo, come ha proposto Claudio_FF, e la variabile che prende il tempo ogni volta. Sperimenta!

Che peraltro ho copiato da te.
Un quarto modo (ancora più peggiorativo come precisione ma comprensibile anche senza parlare di millis) è rallentare il ciclo di loop ad una frequenza voluta con un piccolo delay e contare i passaggi. Con un delay(10) ogni 100 cicli è passato (circa) un secondo. Vantaggio collaterale: il debounce automatico degli ingressi se questi vengono letti una volta ad ogni ciclo.

uint8_t conta = 0;

void loop() 
{
    conta++;

    if (100 == conta) 
    {
        conta = 0;
        ...fa qualcosa -circa- una volta al secondo...
    }

    delayMicroseconds(10000);   // max 16383
}

:smile:
Quale onore!
Quel metodo, però, non è molto bello, perché usa l'operatore modulo che è relativamente lento, usando una divisione. Ero giovane e ingenuo... :slightly_smiling_face:
Il metodo che copia millis() ogni volta è più efficiente.

Grazie a tutti per le risposte, ora mi metto all'opera !
Sono al momento riuscito a fare accendere il led della chiave e a fare lampeggiare quello accanto ad essa e attivare l'uscita che infine attiva una seconda scheda!
Ora in un secondo sketch sto cercando di fare le due sequenze "accensione e spegnimento".

Domanda esiste un modo per fare eseguire il comando dopo la IF una sola volta?
E per simulare di avere un altro input, posso collegare un uscita 5v a un altra che sta in read? ad esempio lingresso 5 si attiva ad ogni uso, mentre il 6 fa toggle cioè una volta on e la successiva off, la 7 fa digitalread su quanto arriva dalla 6.
Questo per creare una seconda IF dove appunto uscita 5 e 6 formano due diverse situazioni senza dover inserire un altro pulsante fisico.

Ha senso o è in termini arduinici una bestemmia? :smiley:
Grazie a tutti

Basta aggiungere alla condizione una variabile di disabilitazione, che va attivata all'interno della if.

E per simulare di avere un altro input, posso collegare un uscita 5v a un altra che sta in read?

Se "sta in read" allora non è un'uscita ma un ingresso. Tecnicamente non c'è alcun problema a collegare un'uscita a un ingresso, basta che i terminali non vengano per errore configurati entrambi come uscite che, se a livelli differenti, potrebbero danneggiarsi (si può ovviare a questo pericolo collegandoli tramite una resistenza da 470 Ω).

ad esempio lingresso 5 si attiva ad ogni uso, mentre il 6

Questo per creare una seconda IF dove appunto uscita 5 e 6

Con questo interscambio dei termini ingresso e uscita qui mi perdo. Gli ingressi leggono tensioni dall'esterno, le uscite generano tensioni verso l'esterno.

inserire un altro pulsante fisico.

Probabilmente basta creare l'informazione in una variabile interna, senza passare per l'esterno.

mi sono espresso male, intendevo collegare ad esempio il pin 5-output al pin 6-input.
Il pin 4 è input con pulsante, che attiva il pin 5 una volta si e una no, in questo caso volevo creare una if con readpin4-high && readpin6-high che accende a sua volta un terzo pin, else lo spegne.

Oggi provo a creare la variabilie di disabilitazione per la IF, anche se nel mio caso potrei ricorrere a un pulsantino collegato al pin Reset mentre il compito dato dalla IF ha come finale un delay di 2 ore per "aggirare" il loop.

Un delay di due ore per aggirare il loop???...
:confounded:

789638222

Chiaro che usare il reset come comando per (ri)avviare l'elaborazione, e bloccare il programma per due ore con delay, sono "errori" di design. Anche se nel singolo caso specifico risolvono il problema, alla prima modifica/implementazione la "soluzione" ultraspecifica diventa un problema insormontabile.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.