Vai al contenuto
PLC Forum


Filtro su pulsante


roberto8303

Messaggi consigliati

Salve,

con questo codice devo fare accendere un led e contare quante volte è stato acceso.

Il problema è che quando premo il pulsante legato all interrupt sul pin 2 non ottengo un accensione precisa cosi anche allo spegnimento, a volte si accende e a volte il led resta acceso e devo ripremere

Credo sia un disturbo legato al pulsante come posso filtrare eventuali impulsi non desiderati?

 

int pin = 5;
 int state = LOW;

void setup()
{
  Serial.begin(9600);
  pinMode(pin, OUTPUT);
  attachInterrupt(0, blink,RISING);
}

void loop()
{
  Serial.println(state);  

  
}

void blink()
{
  state = !state;
digitalWrite(pin,state);
}

Link al commento
Condividi su altri siti


Cerca in rete qualche esempio sul "debounce" dei pulsanti (es. questo , anche se personalmente userei uno schema diverso). Inoltre non usare l'interrupt per leggere un pulsante, non serve a niente, puoi benissimo leggere lo stato del pulsante nel loop. A livello elettrico usa un pin attivando il pullup e collega il pulsante tra il pin e la massa, mettendoci in parallelo un condensatore da 0.1 uF, questo già aiuta a prevenire i rimbalzi. Come esempio di codice vedi quello del link, se adotti la soluzione del pullup e pulsante verso massa ricordati che con il pulsante premuto lo stato è LOW, quindi cambia il codice di conseguenza.

 

Ciao, Ale.

Link al commento
Condividi su altri siti

11 minuti fa, ilguargua scrisse:

Cerca in rete qualche esempio sul "debounce" dei pulsanti

 

No, perchè è legato all'intrrupt.

 

Roberto devi agire nella routine di interrupt.

void blink()
{
   noInterrupts();
   state = !state;
   digitalWrite(pin,state);
   delay(10);
   Interrupts();
} 

Oppure

void blink()
{
   noInterrupts();
   state = !state;
   digitalWrite(pin,state);
   tempo = millis();
}

void loop()

......

tempoI = millis();
if (tempoI - tempo >= 10)
      Interrupts(); 

La via più semplice è mettere un delay, anche se è bloccante .

Altrimenti puoi usare la funzione millis() al di fuori dell'interrupt;

Link al commento
Condividi su altri siti

grazie ho provato la soluzione tua Livio, perchè giustamente voglio legare il pulsante all interrupt altrimenti avrei letto semplicemente lo stato memorizzandolo in una variabile. Comunque

ho provato con millis anche cambiando il tempo di ritardo non ottegno miglioramenti, a volte il led si spegne e altre volte no

Questo esempio in rete che ho trovato funziona bene ma non utilizza gli interrupts

 

const int buttonPin = 6;    // the number of the pushbutton pin
const int ledPin = 3;      // the number of the LED pin
int ledState =0;         // the current state of the output pin
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin
unsigned long lastDebounceTime = 0;  // the last time the output pin was toggled
unsigned long debounceDelay = 30;  
unsigned long accensioni=0;

void setup() {
  pinMode(buttonPin, INPUT);
  pinMode(ledPin, OUTPUT);
  digitalWrite(ledPin, ledState);
  Serial.begin(9600);
}

void loop() {
  int reading = digitalRead(buttonPin);
 
 if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }
   
  if ((millis() - lastDebounceTime) > debounceDelay) {
   if (reading != buttonState) {
      buttonState = reading;
      if (buttonState == HIGH) {
        ledState = !ledState;
      } } }
  digitalWrite(ledPin, ledState);
  lastButtonState = reading;
}

Link al commento
Condividi su altri siti

Alcune osservazioni :

1) delay() e millis() non funzionano dentro gli interrupt

2) le variabili usate dentro l'interrupt devono essere dichiarate volatile, perlomeno se si usano anche fuori dagli interrupt

3) generalmente non si usa un interrupt per leggere un pulsante, poi ognuno è libero di complicarsi la vita come vuole

 

Ciao, Ale.

Link al commento
Condividi su altri siti

Quote

3) generalmente non si usa un interrupt per leggere un pulsante, poi ognuno è libero di complicarsi la vita come vuole

 

A me serve anche incrementare una variabile ogni volta che il led in questo caso passa da spento ad acceso, quindi utilizzavo il Rising per scatenare l evento di interrupt.

Ho provato ad utilizzare il normale ciclo loop ma la variabile si incrementa continuamente facendo variabile= variabile+1

Link al commento
Condividi su altri siti

Per questo basta che aggiungi una variabile che ti faccia da contatore che incrementi ogni volta che l'uscita cambia stato se è alta :

 

unsigned int counter = 0  //adegua il tipo di variabile al valore max che può assumere!

[setup, etc..]

if ((millis() - lastDebounceTime) > debounceDelay) {
   if (reading != buttonState) {
      buttonState = reading;
      if (buttonState == HIGH) {
        ledState = !ledState;

        if (ledState) counter += 1;
      } } }

 

Ciao, Ale.

Link al commento
Condividi su altri siti

15 ore fa, ilguargua scrisse:

le variabili usate dentro l'interrupt devono essere dichiarate volatile, perlomeno se si usano anche fuori dagli interrupt

 

No! Serve solo per risparmiare memoria. Io uso regolarmente variabili globali all'interno della routine di servizio del timer per leggere ingressi a tempo ed eseguire debouncing degli ingressi.

15 ore fa, ilguargua scrisse:

generalmente non si usa un interrupt per leggere un pulsante, poi ognuno è libero di complicarsi la vita come vuole

 

Gli interrupts sono proprio fatti per riconoscere eventi di particolare rilevanza o per priorità o per gravità.

15 ore fa, ilguargua scrisse:

delay() e millis() non funzionano dentro gli interrupt

 

Si hai ragione vanno usati esternamente all'interrupt; l'errore mio è stato nell'usare le funzioni noInterrupts(); e Interrupts;

in luogo di attachInterrupt e  detachInterrupt .

 

Ad esempio

attachInterrupt(0,blink, RISING);


void blink()
{
  detachInterrupt(0);
  state = !state;
  digitalWrite(pin,state);
  delay(10);
  attachInterrupt(0,blink, RISING);
}

 

Io, comunque preferisco leggere gli ingressi con funzioni particolari nella routine di servizio di un  interrupt a tempo, così posso anche eseguire un debouncing automatico.

Link al commento
Condividi su altri siti

2 ore fa, Livio Orsini scrisse:
17 ore fa, ilguargua scrisse:

le variabili usate dentro l'interrupt devono essere dichiarate volatile, perlomeno se si usano anche fuori dagli interrupt

 

No! Serve solo per risparmiare memoria. Io uso regolarmente variabili globali all'interno della routine di servizio del timer per leggere ingressi a tempo ed eseguire debouncing degli ingressi.

No Livio, "volatile" non serve a risparmiare memoria, e dovresti saperlo, "volatile" avverte il compilatore di non compiere ottimizzazioni su quella variabile, perchè essendo usata (ad esempio) nell'interrupt, può cambiare il valore in ogni momento, indipendentemente dal flusso del programma.

 

2 ore fa, Livio Orsini scrisse:
17 ore fa, ilguargua scrisse:

generalmente non si usa un interrupt per leggere un pulsante, poi ognuno è libero di complicarsi la vita come vuole

 

Gli interrupts sono proprio fatti per riconoscere eventi di particolare rilevanza o per priorità o per gravità.

Infatti, ma generalmente si usano per eventi piuttosto veloci, che altrimenti potrebbero sfuggire nel loop. Ora, sempre parlando generalmente, un pulsante si associa ad una persona che lo preme, quindi con tempi di reazione umani, di svariati ordini di grandezza più lenti per i tempi dell'MCU. In un programma ben scritto non hai alcun problema a leggere dei pulsanti senza usare l'interrupt.

 

2 ore fa, Livio Orsini scrisse:

Ad esempio [...]

All'interno della routine dell'interrupt non serve usare detachInterrupt() o noInterrupts(), sono già impliciti (dalla documentazione ufficiale):

Generally, an ISR should be as short and fast as possible. If your sketch uses multiple ISRs,
only one can run at a time, other interrupts will be executed after the current one finishes
in an order that depends on the priority they have. millis() relies on interrupts to count,
so it will never increment inside an ISR. Since delay() requires interrupts to work, it will
not work if called inside an ISR. micros() works initially, but will start behaving erratically 
after 1-2 ms. delayMicroseconds() does not use any counter, so it will work as normal. 

 

Ciao, Ale.

Link al commento
Condividi su altri siti

Non per polemica ma per precisione.

 

4 ore fa, ilguargua scrisse:

No Livio, "volatile" non serve a risparmiare memoria, e dovresti saperlo,

 

Non è solo un accesso senza ottimizzazioni, ma identifica una precisa area di memoria e, in senso lato, fa risparmiare memoria e non tempo macchina.

Se non si dichiara "volatile" una variabile, il compilatore può anche lasciarlatemporaneamente in un registro di servizio ed andare a scriverla quando è più conveniente per l'uso della CPU. Questa modalità potrebbe in determinate condizioni, non aggiornare correttamente la variabile in questione.

Se la medesima variabile è usata sia in interrupt che in altra funzione, l'uso della definizione "volatile" potrebbe diminuire la probabilità di non sincronizzazione della variabile stessa.

Ho volutamente scritto "diminuire la probabilità" perchè non hai la certezza, certezza che hai solo se hai programmato secondo determinate regole che non sto a descrivere in questa sede.

A solo tiotolo di esempio descrivo un caso in cui la definizione "volatile" non assicura la corretta sincronizzazione.

 

Si assuma che "Pluto" sia definito conme variabile globale e volatile.

Sto eseguendo una funzione in cui, al termine, sarò scritto un valore in "Pluto".

Durante l'esecuzione scatta un interrupt e nella routine di servizio di questo andrò a scrivere un valore in "Pluto".

Dopo il ritorno da interrupt la funzione proseguirà ed al termine andrà a scrivere in "Pluto".

E' un errore di programamzione? certamente.

 

 

 

4 ore fa, ilguargua scrisse:

In un programma ben scritto non hai alcun problema a leggere dei pulsanti senza usare l'interrupt.

 

 

Anche questo non è vero o, almeno, non è sempre vero.

Dipende dalla funzione di questo pulsante e dal contesto del programma.

Esempio banale.

Se volgio eseguire un arresto rapido (rapido, non emergenza) e voglio avere una risposta nel più breve tempo possible associo il pulsante ad un ingresso di interrupt.

Se nel programma, per motivi que no sto a descrivere qui, devo eseguire dei loops abbastanza lunghi, o sono obbligato ad eseguire dei loops che durano sino al verificarsi di un determinato evento (anche se non è una buona cosa), se volgio interrompere il loop da comando esterno associo questo comando ad un interrupt.

 

Non esiste una regola univoca.

La buona programamzione è quella che risolve il problema nel migliore dei modi, non è un fatto estetico, è un fatto funzionale, pragmatico.

La programamzione fine  a se stessa è pessima programmazione , equivale al "parlarsi addosso":).

 

Quote

All'interno della routine dell'interrupt non serve usare detachInterrupt() o noInterrupts(), sono già impliciti

 

A parte il fatto che la citazione fa riferimento ai problemi relativi ai tempi (delay(x) , mills(), le funzioni detachInterrupt() o noInterrupts() non sono implicite.

La funzione noInterrupts() serve a bloccare l'esecuzione di tutti gli interrupts, equivale all'istruzione "di" (disable interupts che si usa in asm). La funzione detachInterrupt(pin) disabilita uno specifico interrupt.

Dalla documentazione ufficiale di arduino:


 

Quote

 

detachInterrupt()

Description

Turns off the given interrupt. (Disattiva l'interrupt specificato).

 

 

Si usano proprio per evitare che la permanenza delle condizioni di interrupt riscateni lo interrupt al termine della routine di servizio.

Se voglio che, dopo il primo fronte non si verifichi nessun altro interrupt per un certo tempo devo disattivare l'interrupt per il tempo necessario.

Classico è il caso in cui voglio che un interrupts sia sensibile al livello (non al fronte), ma che una volta riconosciuto l'evento l'interrupt possa riverificarsi solo dopo che sia trascorso un tempo minimo.

Non mi dilungo con altri casi altrimenti sarebbero necesarie più pagine.

Link al commento
Condividi su altri siti

7 ore fa, Livio Orsini scrisse:

Ad esempio


attachInterrupt(0,blink, RISING);


void blink()
{
  detachInterrupt(0);
  state = !state;
  digitalWrite(pin,state);
  delay(10);
  attachInterrupt(0,blink, RISING);
}

 

57 minuti fa, Livio Orsini scrisse:
Quote

All'interno della routine dell'interrupt non serve usare detachInterrupt() o noInterrupts(), sono già impliciti

 

A parte il fatto che la citazione fa riferimento ai problemi relativi ai tempi (delay(x) , mills(), le funzioni detachInterrupt() o noInterrupts() non sono implicite.

La funzione noInterrupts() serve a bloccare l'esecuzione di tutti gli interrupts, equivale all'istruzione "di" (disable interupts che si usa in asm). La funzione detachInterrupt(pin) disabilita uno specifico interrupt.

Dalla documentazione ufficiale di arduino:

 

Solo per amore della precisione (si, Livio, lo so, sono uno scassaballe, porta pazienza :) ) come puoi vedere parlavi proprio di detachInterrupt() dentro una routine di interrupt che NON può essere interrotta comunque da un altro interrupt, poichè la MCU ne serve uno alla volta. Se durante l'esecuzione della routine di interrupt scatta un altro interrupt viene messo in coda, ed eseguito dopo, quindi non è necessario ne staccare l'interrupt specifico ne bloccare in todo gli interrupts.

 

1 ora fa, Livio Orsini scrisse:

Si assuma che "Pluto" sia definito conme variabile globale e volatile.

Sto eseguendo una funzione in cui, al termine, sarò scritto un valore in "Pluto".

Durante l'esecuzione scatta un interrupt e nella routine di servizio di questo andrò a scrivere un valore in "Pluto".

Dopo il ritorno da interrupt la funzione proseguirà ed al termine andrà a scrivere in "Pluto".

E' un errore di programamzione? certamente.

 

Ma infatti il problema non si pone se la variabile la vai a riscrivere, in quel caso è chiaro che il valore sarà l'ultimo che le viene assegnato, ma nel caso che invece la vai a leggere. Se assegno pluto = 1 all'inizio di una funzione (es. loop()) , poi pluto viene modificato da un interrupt con pluto = 0 , poi alla fine della funzione controllo il valore if (pluto == 1), in questo caso la differenza tra usare volatile o no si sente tutta, ed è una trappola abbastanza comune...

 

Spero che per te, ed il resto dei lettori del forum, questo non appaia come uno sterile battibecco, personalmento credo che il forum sia un momento ed un'occasione di crescita per tutti, le cose che scriviamo qua rimaranno (si spera!) anche per molti anni a venire, e spero potranno esser utili, se sono corrette.

 

Ciao, Ale.

Link al commento
Condividi su altri siti

Quote

Solo per amore della precisione (si, Livio, lo so, sono uno scassaballe, porta pazienza :) ) come puoi vedere parlavi proprio di detachInterrupt() dentro una routine di interrupt che NON può essere interrotta comunque da un altro interrupt, poichè la MCU ne serve uno alla volta.

 

Non è assolutamente vero.

Leggiti il data sheet di qaulsiasi micro.

Una routine di servizio di interrupt può essere interrotta da un interrupt di livello superiore. Questo se, e solo se, non sia stata riconusciuta un'istruzione di DI.

Questo te lo dice anche la documentazione di arduino quando descrive il vettore di interrupts delle varie MCU usate nelle vdifferenti versioni di scheda.

In alcuni micro, come il vecchio 8085, esiste anche un interrupt che non può essere mai mascherato (trap = trappola) ed è sensibile sia l fronte che al livello; questo interrupt in genere viene associato ad eventi catastrofici.

La sensibilità al livello, che hanno alcuni interrupt, ti fa permanere in un loop continuo all'interno del servizio sino a che non disabiliti l'interrupt o non cambia il livello. In alcuni casi, rarissimi, può essere utile non uscire dall'interrupt sino all'avvenuto cambio di livello.

Uno degli errori che capitano a che programma senza pensare a cosa sta sotto, è trovarsi, per alcune condizioni non considerate, una coda di interrupt di lunghezza tale per cui il registro di stack, dove vengono accumulati gli indirizzi di ritorno, va in over flow ed il programma va per farfalle.

 

17 ore fa, ilguargua scrisse:

si, Livio, lo so, sono uno scassaballe, porta pazienza

 

Io porto anche pazienza, ma tu prima di scrivere certe cose documentati leggendo i manuali del micro che sta sotto. Vedere solo la parte ad alto livello è bello e comodo, però si perde di vista la macchina.;)

 

Il primo micro che ho visto era l'antenato dello F8 Farchild, non si chiamavano ancora micro processori, ed era l'anno 1972 (allora lavoravo nei laboratori di ricerca Olivetti ad Ivrea). Da allora ne ho usati (e studiati) parecchi di questi dispositivi, di differenti tipi e costruttori. Credo di avere un minimo di conoscenza su questi dispositivi.

 

 

17 ore fa, ilguargua scrisse:

in questo caso la differenza tra usare volatile o no si sente tutta, ed è una trappola abbastanza comune...

 

Il tuo esempio è esattamente uguale al mio, chiosato con: " E' un errore di programamzione? certamente. "

E' una trappola abbastanza comune per chi non sa programmare.

Se programmi in modo corretto non c'è nessuna necessità di dichiarare una variabile "volatile", questa è un'assegnazione utile solo a molti utenti tipici di schede come arduino, programmatori che programmano come se dovessero spaccare pietre.

 

Io non dichiaro mai "volatile" una variabile ma non ho mai avuto alcun problema di sincronizzazione.

Se vai a vedere qualche sempio che ho messo in varie discussioni, noterai che solitamente creo un interrupt a tempo con timer1, con clock a 10ms. Uso l'interrupt per acquisire ingressi digitali ed analogici ed eseguire il debouncing degli ingressi digitali.

Il valore degli analogici lo uso regolarmente all'interno del main loop o di altre funzioni senza mai avere problemi di sincronizzazione.

Questa tecnica la uso da almeno 40 anni, usando asm, PLM e "C" indifferentemente senza mai avere problemi.

 

Quote

Spero che per te, ed il resto dei lettori del forum, questo non appaia come uno sterile battibecco, personalmento credo che il forum sia un momento ed un'occasione di crescita per tutti, le cose che scriviamo qua rimaranno (si spera!) anche per molti anni a venire, e spero potranno esser utili, se sono corrette.

 

 

Se lo avessi ritenuto un semplice e sterile battibecco lo avrei già terminato.

Io spero per te che questa discussione ti aiuti a comprendere come la macchina risolve gli interrupt Hardware.;)

Link al commento
Condividi su altri siti

1 ora fa, Livio Orsini scrisse:

Non è assolutamente vero.

Leggiti il data sheet di qaulsiasi micro.

Perchè di qualsiasi micro, basta leggere quello giusto, visto che si parla di Arduino prendiamo l' AT328

A pagina 32 :

Quote

...

When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The
user software can write logic one to the I-bit to enable nested interrupts. All enabled interrupts can then
interrupt the current interrupt routine. The I-bit is automatically set when a Return from Interrupt
instruction – RETI – is executed.

 

Quindi : gli altri interrupt vengono disabilitati, ma possono venir riabilitati dal software, ergo, scusa se insisto, non dovrebbe essere necessario disabilitarli esplicitamente.

Pienamanete d'accordo con tutto il resto, comunque, anche se non sembra e se mi esprimo male, sono abituato a documentarmi sulle cose, che poi riesca a capirle tutte è un altro discorso...:).

 

Ma Roberto che fine ha fatto? Speriamo ci riporti un po' in topic...

 

Ciao, Ale.

Link al commento
Condividi su altri siti

21 ore fa, ilguargua scrisse:

 

Sei proprio un gran rumbpaball.:) Mi costringi a fare quello che non avrei voluto fare: scrivere molto.

 

Tra parentesi sono andato a vedere il tuo profilo. Se dici il vero sei di Livorno, quindi presumo che tu ti stia divertendo molto, però anchì'io son livornese per parte di padre (Castagneto Carducci e dintorni) quindi anch'io mi sto divertendo parecchio.;)

Spero si divertano anche gli altri lettori, se ce ne sono.

 

Partiamo "ab ovo".

I microprocessori, nella gestione degli interrupts, usano la strategia dell'ubi major minor cessat; ovvero un servizio ad un interrupt può sempre essere interrotto dall'arrivo di un interrupt di priorità superiore, a meno che sia stato esplicitamente disabilitato. Sempre che non si tratti di interrupts sempre abilitati (reset e trap, quando c'è).

Nei microcontrollori ad architettura semplificata (ARM) risulta più comodo nella microprogramamzione usare la strategia del "chi prima arriva meglio s'accomoda". Ovvero il primo interrupt che viene riconosciuto disabilita tutti gli altri (reset escluso).

Però quello che si è tenuto fuori dalla porta rientra dalla finestra.

Infatti l'istruzione RetI (return interrupt) deve riabilitare tutti gli interrupt.

Questo comporta due possibilità:

  1. Se ho un interrupt sensibile al livello e questo livello permane, non appena esco dal'interrupt ci ritorno immediatamente perchè sono ancora valide le condizioni di richbiamo.
  2. Se ho un interrupt sensibile ai fronti (caso corrente) e l'interrupt è legato al riconoscimento di stato di un contatto elettromenccanico che ha rimbalzi (sempre caso corrente) potrò avere numerosi interupts legati non al cambio di stato, ma ai rimbalzi dell'organo elettromeccanico.

L'unico modo per uscirne è usare l'istruzione "detachInterrupt(x);" in modo da inibire quel preciso interrupt per un determinato tempo.

L'errore nel mio esempio non è l'uso dell'istruzione detachInterrupt(0); bensì il fatto che l'attesa avvenga all'interno della routine di servizio.

La versione corretta prevede non un tempo di attesa all'interno della routine di servizio (che non funziona), ma si deve alzare un flag che segnalerà al main di ripristinare attchInterrupt(0); trascorso un detrminato tempo minimo.

Quando sarà eseguita l'istruzione RETI ci sarà l'automatica riabilitazione degli interrups, però l'interrpt in questione è disabilitato singolarmente e non avrà effetto.

 

Se non altro son stato obbligato a togliere un polvere accumulatasi in var decenni.:)

 

 

Link al commento
Condividi su altri siti

1 ora fa, ilguargua scrisse:

pensa se ti toccava un pisano quanto dovevi scrivere per fargli capire qualcosa!:roflmao:

 

Allora sei proprio livornese.:lol:

 

Comunque è sempre un piacere discutere di qualche cosa che è sempre stata la mia passione, anche s per qualche decennio è stata anche una professione.

 

Tornando all'argomento della discussione, concordo con te che usare un interrupt per gestire un pulsante è complicarsi la vita inutilmente, a meno che il pulsante non segnali un evento di elevatissima priorità.

Io però non ho mai incontrato casi in cui riconoscere un pulsante premuto intruducendo 10 ms di ritardo, nel caso pessimo, comporti problemi. quindi io leggo gli ingressi a tempo fisso usando un interrupts a 5ms (o 10 ms secondo applicazion) e, tramite vrifica del matenimento dello stato tra due successive letture, eseguo anche il dbouncing.

Link al commento
Condividi su altri siti

il 3/10/2017 at 11:05 , ilguargua scrisse:

Ma Roberto che fine ha fatto? Speriamo ci riporti un po' in topic...

Scusate ragazzi sono senza rete e non posso collegarmi da casa per qualche giorno, ora sono a lavoro e non ho provato ancora nulla leggero con calma il vostro dibattito e poi farò le prove con questo famoso pulsante a me serve per didattica e per fare esperienza. A volte le funzioni piu facili e scontate possono diventare difficili se non si conosce bene tutto parlo per me che non sono informatico

Link al commento
Condividi su altri siti

3 ore fa, gabri-z scrisse:

Ci sono , ci sono ! (almeno uno , non ho saltato una virgola :) )

 

E non ti sei annoiato?

Sei proprio stoico.:)

Link al commento
Condividi su altri siti

Certo che non mi sono annoiato , anzi ,oltre il tema della discussione ,ho scoperto questo aggettivo , stoico ;

 non l'avrei mai usato , avevo l'impressione che fosse una reminiscenza (nel mio cervello ) della lingua madre... 

Per me i forum danno aiuto non solo a chi lo chiede , ma anche a chi se lo sa trovare 'sto aiuto  :P .C'è sempre spazio nel cervello , magari potessimo utilizzarlo di più....

 Andate avanti con la '''' polemica '''' , a me sembra un vero fair-play ; chi perde , non lo so , io di sicuro , GUADAGNO .

 Grazie .

Link al commento
Condividi su altri siti

Si stoico deriva direttamente dal latino, individuava una corrente filosofica; uno degli esponenti più conosciuti di questa corrente fu Seneca, precettore di Nerone e da questi fatto "suicidare".

Oggi l'accezione di stoico sta ad indicare una persona che sopporta senza lamenti dolore ed avversità varie, tipo la lettura integrale dello scambio di opinioni tra me ed il guargua.:)

Link al commento
Condividi su altri siti

void setup()
{
  Serial.begin(9600);
  pinMode(pin, OUTPUT);
  attachInterrupt(0, blink,RISING);
}

void loop()
{
  Serial.println(state);
  tempo1=millis(); 
  if (tempo1-tempo>=50){
    tempo=millis();
 }
    
}

void blink()
{
  detachInterrupt(0);
  state = !state;
digitalWrite(pin,state);
delay(10);
attachInterrupt(0,blink,RISING);

}

 

 

non funziona...cosa sbaglio?

mi sa che è meglio lasciar perdere gli interrupt sul pulsante, meglio un semplice ritardo e memorizzare lo stato del pulsante su una variabile,

Livio mi puoi mettere il tuo codice dove  fai queste operazioni? non riesco a trovarlo tra le discussioni

il 3/10/2017 at 08:58 , Livio Orsini scrisse:

Io non dichiaro mai "volatile" una variabile ma non ho mai avuto alcun problema di sincronizzazione.

Se vai a vedere qualche sempio che ho messo in varie discussioni, noterai che solitamente creo un interrupt a tempo con timer1, con clock a 10ms. Uso l'interrupt per acquisire ingressi digitali ed analogici ed eseguire il debouncing degli ingressi digitali.

Il valore degli analogici lo uso regolarmente all'interno del main loop o di altre funzioni senza mai avere problemi di sincronizzazione.

 

Link al commento
Condividi su altri siti

9 ore fa, roberto8303 scrisse:

non funziona...cosa sbaglio?

 

La funzione blink() è chiamata all'interno della routine di interrupt quindi il delay non funziona.

 

 void loop()
{
  Serial.println(state);
  tempo1=millis(); 
   if flg_tempo == HIGH
    {
       if (tempo1-tempo>=50)
         {
            attachInterrupt(0,blink,RISING);
            flg_tempo = LOW;
          }
     }
 }
    
}

void blink()
{
  detachInterrupt(0);
  state = !state;
  digitalWrite(pin,state);
  flg_tempo = HIGH;
  tempo1=millis(); 
  tempo = tempo1;
} 

Devi dichiarare flg_tempo come boolean e mettere lo stato iniziale LOW.

Dovrebbe funzionare, anche se a quest'ora non sono ancora molto sveglio. Non son sicuro che funzioni

  tempo1=millis();
  tempo = tempo1;

nella routine di servizio interrupt. Nel caso non funzionasse devi fare questo lavoro solo la prima volta che entri nel codice che si esegue con flg_tempo == HIGH, quindi dovrai aggiungere un altro flag, ad esempio flg_primo, che alzi nella routine di blink e che abbassi nella routine di loop dopo la prima verifca che flg_tempo è alto; fai il set delle 2 variabili di tempo ed abbassi il flag di prima volta.

Se hai pazienza oggi o al massimo domani ti metto quelle 2 righe di codice.

Link al commento
Condividi su altri siti

Crea un account o accedi per commentare

Devi essere un utente per poter lasciare un commento

Crea un account

Registrati per un nuovo account nella nostra comunità. è facile!

Registra un nuovo account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...