Semaforo Complesso OK-Flip Flop Semplice ( e non ci salto fuori).

Salve
premesso che sono alle prime armi,
sto tentando di realizzare il mio primo programma concreto,IL SEMAFORO.
Ora avendo gia scritto un programma per prendere confidenza,ho ipotizzato un incrocio ed i semafori che lavorano nella loro sequenza,poi pero mi sono posto un problema;

e se arriva un Vecchio che preme il pulsante Pedonale,che succede?

Nulla,perchè se ho capito bene o lo preme in un preciso istante del LOOP,oppure resta li e continua ad invecchiare.

Mi è venuto in mente una soluzione elettrotecnica(in cui sono più ferrato) in cui il pulsante si comporta ON quando viene premuto e ritorna OFF dopo un certo periodoe E QUI in ELETTRONICA ed PROGRAMMAZIONE per ignoranza mi sono arenato.

DOMANDA:

1 esiste una programmaziione che legge un input digitale DURANTE ed INDIPENDENTE dal LOOP?
2 se non esiste,come posso replicare la mia soluzione elettrotecnica,il più semplicemente possibile, magari con un transistor (che sono la mia dannazione e non mi entrano in testa)?

Grazie se mi rispondete

Ciao Puso,

presentati nell'apposita sezione QUI.

poi per fare quello vuoi ti ci sono diversi modi...anche solo software.

ho cliccato
ma non ho capito dove devo scrivere.

scusate ma non sono pratico dei forum

ciao...ti sei già presentato...non so perchè ma prima non vedevo il tuo post di presentazione...detto questo se fai una ricerca nei miei post ...un po' di tempo fa...ho postato quello che ti serve.

ciao orso
grazie per avermi risposto

io non sono piu un ragazzino e faccio fatica atrovare i tuoi post e non leggo inglese( è come i transitor,non mi entrano in testa).

puoi darmi qualche riferimento?

in pratica mi son messo dalla parte del vecchietto che preme un pulsante per attraversare un passaggio pedonale mentre è in esecuzione un CICLO.

e mi trovo al punto che o mi studio tutto il ciclo e premo il pulsante al momento opportuno, oppure;
-resto li fino a diventare una mummia.
-ci provo e passo durante il cilo LOOP, rischiando di farmi investire.
-oppure mi arrangio con un semolice Relè ed un Timer (ELETTROTECNICA).
-oppure qualkuno mi aiuta e mi da un alternativa.

ciao...

bhe...al momento ho scritto solo nella sezione in italiano...per cercare nei post di qualcuno basta che clicchi sulla suo icona/avater...ho il dubbio che il tuo sketch faccia tanto uso della funzione delay()...no buono!

se non vuoi fare un po' di ricerca nei vari post devo dirti di dare un occhio QUI e QUI

alternative:

monostabile che memorizza il fatto di aver premuto un tasto almeno per un tempo superiore ad un ciclo di loop
santo 555 aiutami tu

ma un metodo del genere è concettualmente arcaico

usare un interrupt, connesso al pulsante
funziona certamente, ma è come sparare con un 88/70 contro una zanzara
uno spreco di risorse

pensiero laterale
far gestire la cosa alla setup invece che alla loop
il pulsante invece che normalmente aperto è normalmente chiuso, e taglia l'alimentazione di arduino
una pressata, l'arduino resetta e riparte la setup
si potrebbe anche usare direttamente il pin reset

ma questi son metodi da macellaio, non da veri programmatori

secondo me la soluzione vera è tenere la loop veloce,velocissima ed eseguire le azioni di accensione/spegnimento delle luci non in funzione di una delay, ma di un test sulla millis

io farei così

per cominciare una funzione di "comando luci" che riceve in ingresso un array di char
ad ogni elemento dell'array associo una terna di luci, e una lettera che indica lo stato
del tipo RGRG indica rosso sulla palina 1 giallo( col verde) sulla palina 2
e via così

così comandare il semaforo diventa semplice
comanda_luci("RGRG");

se questo va passerei a scrivere nella loop una cosa del tipo

if tempo>millis()....{
comanda_luci(quello che serve)
tempo=millis()+nuova attesa
}

appena fatto questo , che richiede il tempo minimo tecnico
posso controllare il pulsante
e naturalmente iniziare la nuova sequenza che serve

si potrebbe pensare ad una array di strutture
-configurazione luci
-tempo che deve durare

la loop si limita a ciclare l'array principale

Si lo ammetto
tanto uso della funzione delay per rendere i semafori abbastanza realistici(in tutto il loop dura circa 20 secondi)

credo che anche utilizzando

if tempo>millis()....{
comanda_luci(quello che serve)
tempo=millis()+nuova attesa
}

tutto il ciclo completo dei semafori durerebbe sempre 20 secondi.

Potrei aggiungere ulteriori delay velocissimi in modo da far lampeggiare i led velocissimamente (cosi l'occhio umano li percepirebbe accesi) ed in mezzo ad ogni stringa infilarci la lettura del pulsante,ma per farlo dovrei scrivere uno sketch lungo come la bibbia e i vangeli assieme.

Ammetto anche che utilizzare il Reset oppure NE555........sono state le prime 2 soluzioni che mi sono venute in mente e per il momento vedo poche alternative.

In realtà mi servirebbe una funzione che stia ell'esterno del LOOP e che agisca comunque.

docsavage:
ma questi son metodi da macellaio, non da veri programmatori

Mi sono appena reso conto che nessuno in questo forum, ma anche su i vari libri per Arduino, ha mai spiegato come si deve scrivere un programma, a partire dal fatto che usare una variabile di tipo int per definire i pin è uno spreco assurdo della ram, risorsa preziosa e limitata sulle piccole mcu, per finire col fatto che il ciclo main(), loop() su Arduino, deve essere ripetuto il maggior numero possibile di volte al secondo e che nessuna funzione deve essere bloccante e/o impegnare la cpu per più di pochi ms.
Se oggi trovo un'oretta libera da dedicare alla cosa vedo di preparare un pdf che spiega, almeno il minimo sindacale, come si deve scrivere un programma.

:confused:
nel frattempo mi dici se al mio problema esiste un metodo alternativo a quelli da macellaio.

Puso:
Potrei aggiungere ulteriori delay velocissimi in modo da far lampeggiare i led velocissimamente (cosi l'occhio umano li percepirebbe accesi) ed in mezzo ad ogni stringa infilarci la lettura del pulsante,ma per farlo dovrei scrivere uno sketch lungo come la bibbia e i vangeli assieme

Ci sei quasi, l'idea del "velocissimo spezzettato" per fare più cose assieme è corretta, ma probabilmente non l'implementazione a cui pensi. In realtà è più semplice (macchine a stati finiti), attendiamo il post di Astro per avere qualcosa di pratico su cui discutere.

Tra l'altro, se riesci a fare uno schema a relè/temporizzatori/pulsanti "classici", tradurlo in funzioni logiche equivalenti è un altro modo ancora per affrontare il problema.

In entrambi i casi il loop dovrebbe procedere a diverse migliaia di cicli completi al secondo.

Io creerei una struttura del genere

void loop(){
controllopulsanti();
controllotempo();
comandasemafori();
}

il codice deve girare sempre senza delay usando la funzione millis() per determinare lo stato di accensione delle varie luci.
Userei poi una struttura per definire i semafori e passare i parametri da una funzione all'altra.

Fare uno schema a relè/temporizzatori/pulsanti "classici", tradurlo in funzioni logiche equivalenti potrei anche riusirci,resta il fatto che il LOOP,legge le righe in fila ed una volta che è partito non posso aggiungere o toglier niente.

Anche utilizzando la struttura che consigli,resta sempre il fatto che il ciclo completo dei semafori durerebbe 20 secondi e dovrei premere il pulsante al momento giusto per fargli leggere lo stato differente.

mi sa che devo preparmi davvero ad uno sketch lungo come la divina commedia.

Non stai pensando quadrimensionalmente! (cit.)

Anche se una lampadina deve rimanere accesa 20 secondi, il loop() non deve durare 20 secondi.
Il ciclo loop() deve durare una frazione di secondo e deve essere sufficientemente breve da intercettare la pressione del pulsante.

Esempio:

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= 20000) {
    previousMillis = currentMillis;
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(ledPin, ledState);
  }

}

Il led si accende e si spegne ad intervalli di 20 secondi. il ciclo dura meno di un millisecondo.

potrebbe essere la soluzione...mo ci provo grazie per il momento

mi da errore....ho fatto copia incolla ed ho solo corretto il setup

void setup() {
pinMode(31, OUTPUT);
pinMode(33, OUTPUT);  

}



void loop() {
 unsigned long currentMillis = millis();

 if (currentMillis - previousMillis >= 20000) {
   previousMillis = currentMillis;
   if (ledState == LOW) {
     ledState = HIGH;
   } else {
     ledState = LOW;
   }
   digitalWrite(ledPin, ledState);
 }

}

Puso:
credo che anche utilizzando

if tempo>millis()....{
comanda_luci(quello che serve)
tempo=millis()+nuova attesa
}

tutto il ciclo completo dei semafori durerebbe sempre 20 secondi.

il ciclo completo certamente

Ma non la loop
Che sarebbe velocissima...

E che naturalmente interromperebbe il ciclo

perfetto prima avevo le idee confuse...adesso sto pensando seriamente di fargli leggere il pulsante quando voglio io ......con un martello

secondo me vuoi fare il passo più lungo della gamba, inizia a far lampeggiare due led con tempi diversi con millis(), poi intercetta la pressione di un pulsante e fai fare qualcosa di conseguenza ai due led, che so che rimangano accesi per 2 secondi.... una volta che hai le idee ben chiare su come gestire millis() e leggere un input lo espandi per realizzare tutto il semaforo