Go Down

Topic: Indicatore direzione moto (Read 1 time) previous topic - next topic

Stilita

May 06, 2019, 01:18 pm Last Edit: May 06, 2019, 01:50 pm by Stilita
Devo realizzare un indicatore di direzione per moto, con 3 pulsanti, SX DX ed EMERGENZA.

Quando premo SX lampeggia, al successivo azionamento si spegne.E così per il DX.
Se mentre sta lampeggiando una direzione aziono il pulsante dell'altra, immediatamente commuta su
quest'ultima.
Se premo il pulsante emergenza si attivano tutt'e due le frecce.


Il progetto è ancora all'inizio, e mi sono arenato in un punto:

lo schetch qui mostrato funziona, cioè il led lampeggia con ritardo 500 ms , ma non ho il pulsante nel loop.

Se inverto il commento nel  loop, se commento "sinistra();" e scommento l'if,  il programma salta a funzione sinistra() ma il led resta acceso, se premo il pulsante si spegne, e si riaccende alla successiva
premuta.

In poche parole vorrei che nel loop al pigiare di un pulsante il led lampeggi.

...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

Standardoil

Strano, non vedo particolari problemi, a parte una certa confusione,
Secondo me dovrebbe andare...
Non presurrò più la buona fede di chi:
NON indenta o USA la classe string o NON esegue le ricerche
Troppe volte e' stato segnalato che è sbagliato, quindi se si comportano così NON sono in buona fede

Non bado a studenti, che copino altrove

Stilita

#2
May 06, 2019, 01:41 pm Last Edit: May 09, 2019, 10:27 am by Stilita
Code: [Select]
#define pulsante 2
#define led 7
int ledState = LOW;

unsigned long previousMillis = 0;
const long interval = 500;
void setup() {
  pinMode(pulsante, INPUT);
  pinMode(led, OUTPUT);
}

void loop() {
  // if (digitalRead(pulsante) == 0) {  lampeggio(); }
  lampeggio();
}
int  lampeggio() {

  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }
    digitalWrite(led, ledState);
  }
lampeggio();
}


L'ho ridotto e ripulito.
Quindi se lo lascio così il led lampeggia, se inverto il commento nel loop si accende e si spegne solo se premo il pulsante, e così non mi va bene.
Vorrei che fosse il pulsante a far iniziare il lampeggio.
...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

docdoc

Prima domanda: i pulsanti come sono collegati? Ossia hanno una resistenza di pull-down o pull-up?

Detto questo, nel codice c'è un certo disordine che indica che non hai ben chiaro cosa tu stia facendo, vedo spezzoni di copiaincolla qui e lì.. ;)

Quando inizi un progetto, non iniziare subito dal codice, parti prima chiarendoti bene alcune cose, nell'ordine (in pratica passi al punto successivo quando hai ben chiaro il precedente):

1) la TUA definizione dei requisiti (ossia COSA esattamente vuoi ottenere)
2) uno schema di massima dei collegamenti (se ci sono pulsanti, quanti, se ci sono LED, o altri componenti, eccetera)
3) inizia a scrivere il codice affrontando però UN problema alla volta
4) unisci il tutto in un unico codice, ma partendo magari scrivendo solo i commenti, più strutturati possibile.

Per il punto 1) hai espresso abbastanza bene le cose, e puoi partire da quello.
Per il punto 2) è relativamente semplice, hai 3 pulsanti e 2 LED, e fin qui va bene (ma per i pulsanti devi stabilire se pulldown quindi se HIGH sono premuti, se invece sono pullup sono LOW quando premuti).
Per il punto 3) stai iniziando, ma a parte alcune scelte "stilistiche" che ti conviene iniziare a considerare (es. le costanti/define maiuscole per convenzione, evitare di usare "== 0" per verificare i pulsanti ma meglio "== HIGH" che è più evidente, e così via) , il discorso di "un problema per volta" è proprio qui.

Di fatto lascia perdere per ora il lampeggiamento, fai un programmino che quando premi il pulsante il LED si accende e resta acceso fino a che non lo premi nuovamente.
Questo già ti basta, perché oltre alla resistenza di pull-down (sai come si mette?) include anche un minimo di gestione del debounce (sai di cosa si tratta?) ed inversione dello stato di un pin.

Una volta che quel codice ti funziona, allora avrai capito già molte cose utili, per cui puoi iniziare a cercare di aggiungere il lampeggiamento (ossia il led deve iniziare a lampeggiare quando premi il pulsante, e smettere quando lo premi nuovamente).

Fai questi due step (o almeno il primo, se non riesci), e posta qui il risultato e cerchiamo di aiutarti.

Per iniziare, parti da questo:

Code: [Select]
#define PIN_KEY 2
#define PIN_LED 7

void setup() {
  pinMode(PIN_KEY, INPUT);
  pinMode(PIN_LED, OUTPUT);
}

void loop() {
  // Verifico se il tasto è premuto
 
    // Tasto premuto
    // Inverto lo stato del LED
   
}
Alex "docdoc"
- "Qualsiasi cosa, prima di rompersi, funzionava"

Standardoil

Capito problema
C'è da ribaltare l'approccio..
Dopo...
Non presurrò più la buona fede di chi:
NON indenta o USA la classe string o NON esegue le ricerche
Troppe volte e' stato segnalato che è sbagliato, quindi se si comportano così NON sono in buona fede

Non bado a studenti, che copino altrove

Stilita

#5
May 06, 2019, 02:08 pm Last Edit: May 06, 2019, 02:08 pm by Stilita
Doc, va bene tutto quello che dici, ma io parto dal fare funzionare il lampeggio, per poi metterlo in bella copia..sbaglio?

Non capisco perche se la funzione la chiamo direttamente dal loop funziona, se invece la chiamo tramite un If (salto sempre alla funzione, ma si comporta in modo diverso).
...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

Standardoil

In realtà è ovvio
Se la chiami sempre funziona sempre
Se la chiami ogni tanto quando non la chiami non funziona, si ferma nello stato in cui era all'istante che hai mollato il pulsante...
Non presurrò più la buona fede di chi:
NON indenta o USA la classe string o NON esegue le ricerche
Troppe volte e' stato segnalato che è sbagliato, quindi se si comportano così NON sono in buona fede

Non bado a studenti, che copino altrove

Stilita

#7
May 06, 2019, 02:16 pm Last Edit: May 06, 2019, 02:27 pm by Stilita
In realtà è ovvio
Se la chiami sempre funziona sempre
Se la chiami ogni tanto quando non la chiami non funziona, si ferma nello stato in cui era all'istante che hai mollato il pulsante...
Esatto, ci ero arrivato; i soliti retaggi del Basic, una volta che si salta in un'altra serie d'istruzioni
il programma resta li se non gli si dice che deve "ritornare", al contrario delle funzioni in C...mannaggia
Vorrei fare 3 funzioni per ogni pulsante, e restare sotto di una di essa finchè
un altro pulsante non venga  premuto.
Comunque credo che si possa fare tutto nel loop, ma ci devo studiare...
I pulsanti sono pulappati
...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

Stilita

#8
May 06, 2019, 02:54 pm Last Edit: May 06, 2019, 03:56 pm by Stilita
Sto provando a svolgere il compito assegnatomi da docdoc,
Adesso il pulsante fa partire il lampeggio (richiamo la funzione lampeggio da se stessa)
al secondo "pigiamento" torno al loop, ed è quello che volevo, ma dopo i 100 ms dell'antirimbalzo
ritorna al lampeggio.. :smiley-confuse:
Pulsante pulappato

Code: [Select]
#define PIN_KEY 2
#define PIN_LED 7
int ledState = LOW;
unsigned long previousMillis = 0;
unsigned long currentMillis;
const long interval = 500;
void setup() {
  pinMode(PIN_KEY, INPUT);
  pinMode(PIN_LED, OUTPUT);

}
void loop() {
  if (digitalRead(PIN_KEY) == LOW) {
    delay(100);
    lampeggio();
  }
}
int lampeggio() {
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    if (ledState == LOW) {
      ledState = HIGH;
    } else {
      ledState = LOW;
    }

    digitalWrite(PIN_LED, ledState);
  }
  if (digitalRead(PIN_KEY) == LOW) {
    digitalWrite(PIN_LED, LOW);
    delay(100);
    loop();
  }
  lampeggio();
}
...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

torn24

Ma dal tuo codice lampeggia fin quando il pulsante è premuto, è questo quello che vuoi?
Se invece vuoi che i led lampeggino in automatico dovresti avere una variabile stato per ogni led.

statosx, statodx



a stato 1 tramite if faccio lampeggiare il led

premendo il pulsante sx inverto lo stato di statosx=!statosx e statodx=0
premendo il pulsante dx inverto lo stato statodx=!statodx e statosx=0
premendo emergenza porto statosx=1 e statodx=1, in questo modo lampeggiano entrambi

docdoc

Allora, intanto quello che ti serve più che "ledState" (che puoi anche ricavare leggendo il pin stesso) è una variabile (diciamo "blinking") che ti dica se il led deve lampeggiare o meno, quindi basta una bool. Se è "true" allora va fatto lampeggiare, se è "false" devi spegnere il LED.

Poi nella funzione lampeggio() tu gestisci (male) il rilascio del pulsante: quando programmi devi ricordare sempre di separare la logica. La gestione del pulsante lasciala fuori, nella funzione lampeggio() gestisci solo il lampeggiamento! Tu nel loop() pensa prima ad impostare la variabile ("blinking") che indica se debba lampeggiare o meno in base alla pressione del tasto, e POI chiamerai "lampeggia()" ma solo se è attivo il lampeggiamento ("blinking == true").

Per finire, vedo una cosa pericolosissima, tu dentro alla funzione lampeggio() richiami nuovamente se stessa, che fai, le chiamate ricorsive??? Evita! La "lampeggio()" deve limitarsi, quando chiamata, a gestire l'accensione/spegnimento del led in caso di lampeggiamento e se il tempo dall'ultima azione è trascorso.

Ora prova a rivedere il tuo codice in base a queste indicazioni, e manda qui l'esito (anche negativo, ma con l'ultima versione del codice e relativo comportamento rilevato).
Eventualmente in serata se non riesci proprio, provo a darti qualche indicazione più specifica (ma preferirei se tu ti impegnassi in prima persona a capire e correggere, più che darti "la pappa pronta" ;) ).
Alex "docdoc"
- "Qualsiasi cosa, prima di rompersi, funzionava"

Stilita

#11
May 06, 2019, 04:52 pm Last Edit: May 06, 2019, 04:53 pm by Stilita
@docdoc, ci sto riuscendo, sono arrivato alle due frecce, mi manca solo l'emergenza
ecco dove sono arrivato:
accendo e spengo le frecce dal loro pulsante, e se mentre sta andando una e premo l'altro
pulsante il lampeggio commuta.
Quindi basta fare così anche per l'emergenza, ridondando i led.

Purtroppo sto richiamando una funzione da se stessa, cosa che mi hai sconsigliato
ma non so come restare sotto quella funzione, se non faccio nulla ritorna al loop  :(
...non sapete quanto ho cercato...pfui pfui
prima di rivolgermi al forum...

docdoc

#12
May 06, 2019, 04:58 pm Last Edit: May 06, 2019, 05:13 pm by docdoc
Purtroppo sto richiamando una funzione da se stessa, cosa che mi hai sconsigliato
ma non so come restare sotto quella funzione, se non faccio nulla ritorna al loop  :(
Eh certo che DEVE tornare al loop... Come ti ho detto, ogni porzione di codice deve gestire una cosa, non mescolare la gestione del lampeggiamento con quella del pulsante.

Ok, dai, avevo 5 minuti, vedi questa versione del singolo pulsante e dimmi cosa ci vedi di diverso, oltre ai commenti (SEMPRE metterli):

Code: [Select]
#define PIN_KEY 2
#define PIN_LED 7

bool blinking = false;
int curKey, prevKey = LOW;
 
unsigned long previousMillis = 0;
unsigned long currentMillis;
const long interval = 500;

void setup() {
  pinMode(PIN_KEY, INPUT);
  pinMode(PIN_LED, OUTPUT);
}
void loop() {
  // Vedo se è stato premuto il pulsante (deve passare
  // da LOW a HIGH, ignoro tutti gli altri stati!)
  curKey = digitalRead(PIN_KEY);
  if (curKey == HIGH && prevKey == LOW) {
    delay(100); // Un minimo di debounce
    blinking = !blinking;
    // Se non deve più lampeggiare spengo il led
    if ( !blinking )
      digitalWrite(PIN_LED, LOW);
  }
  prevKey = curKey;
 
  if ( blinking )
    lampeggio();
}

int lampeggio()
{
  // Gestisco il lampeggiamento
  currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    digitalWrite(PIN_LED, !digitalRead(PIN_LED));
  }
}


EDIT: ovviamente qui dò per scontato che il pulsante sia in pulldown, se pullup devi cambiare l'inizializzazione "prevKey = LOW" in "prevKey = HIGH" ed invertire il test "curKey == HIGH && prevKey == LOW" in "curKey == LOW && prevKey == HIGH"...
Alex "docdoc"
- "Qualsiasi cosa, prima di rompersi, funzionava"

torn24

#13
May 06, 2019, 05:05 pm Last Edit: May 06, 2019, 05:06 pm by torn24
Volevo rispondere, ma docdoc ha già fatto "cancellato post"

docdoc

Premi il pulsante richiami la funzione, rilasci il pulsante non richiami più la funzione, allora richiamando la funzioni in se stessa resti sempre nella funzione premendo una sola volta il pulsante. UNA SOLUZIONE SBAGLIATA.
Più che quello, una chiamata ricorsiva infinita alla fine farà andare in crash il povero Arduino appena finisce lo spazio per lo stack...
Alex "docdoc"
- "Qualsiasi cosa, prima di rompersi, funzionava"

Go Up