sto sperimentando gli interrupt e cercando di leggere 4 bit sulla porta D con questo codice ...
int LED = 12;
volatile int state = LOW;
int VALUE;
int intPIN = 0; //interrupt 0 ---> pin digitale 2
int codice_dtmf;
void setup ()
{
Serial.begin(115200);
pinMode(LED, OUTPUT);
DDRD = B00000000;
attachInterrupt(intPIN, leggiDTMF, CHANGE);
}
void loop ()
{ digitalWrite(LED, state);}
void leggiDTMF()
{
state = !state;
VALUE = PIND & B01111000;
Serial.print("\n codice: ") ; Serial.print (VALUE);
}
se attivo la serial.print, cioè se invio dati sulla seriale, lo script funziona alcune volte poi si blocca...... a volte fuunziona solo due volte, a volte 10/15 volte;
se disattivo lìinvio di dati nella seriale .. allora funziona sempre .. cioè ad ogni cambio di stato sul pin PD2 il led accende o spegne... cioè funziona.
non capisco come mai con l'invio di dati sulla seriale si blocca... naturalemnete sul pin 0 e 1 della porta D non ho connesso nulla...
Succede perchè la serial usa gli interrupt e li accende e spegne globalmente all'occorrenza.
Nelle routine di interrupt non usare codice che costa troppo in termini di tempo di esecuzione, se hai necessità di stampare, riempi un buffer con quello che vuoi stampare e poi nel loop leggi il buffer invii e pulisci il buffer così è pronto per la prossima operazione.
Buffer termine generico per indicare un array o string array, ma volendo può essere qualunque cose che mantiene un insieme di dati. Nel caso mantiene un solo byte si tratta di una variabile.
La seriale è implementata via interrupt, sia in trasmissione che in ricezione su IDE 1.0. Se chiami un Serial.print dall'interno di una ISR il micro si intorta.
in realtà sto solo provando. L'invio alla seriale lo facevo per vedere i bit letti... ma non è necessario...
la variabile VALUE (che viene posta uguale PIND bitwise AND con B01111000) è un buffer ... no?
perchè e necessario svuotarla dopo averla letta o stampata?.... non è sufficiente sovrascriverla alla prossima esecuzione della funzione di interrupt???
quindi se faccio così l'invio in seriale avviene solo quando non cè interrupt?
int LED = 12;
volatile int state = LOW;
int VALUE;
int intPIN = 0; //interrupt 0 ---> pin digitale 2
int codice_dtmf;
void setup ()
{
Serial.begin(115200);
pinMode(LED, OUTPUT);
DDRD = B00000000;
attachInterrupt(intPIN, leggiDTMF, CHANGE);
}
void loop ()
{ digitalWrite(LED, state);
Serial.print("\n codice: ") ; Serial.print (VALUE);
}
void leggiDTMF()
{
state = !state;
VALUE = PIND & B01111000;
}
@Paolo:
Mauro ha parlato di buffer ad array. Una singola variabile la puoi sovrascrivere.
Il buffer ad array ha un indice che punta l'ultimo elemento presente e da cui si può quindi risalire a quanti elementi contiene il buffer e quanti elementi vuoti restano. Per "svuotamento" si intende un ciclo che via via decrementa il puntatore e estrae il valore dell'elemento puntato. Quando l'indice è a zero, hai "svuotato" il buffer.
La seriale è implementata via interrupt, sia in trasmissione che in ricezione su IDE 1.0. Se chiami un Serial.print dall'interno di una ISR il micro si intorta.
hi hi hi, si intorta.
Il mio micro si impasticcia ma il risultato è uguale.
in realtà sto solo provando. L'invio alla seriale lo facevo per vedere i bit letti... ma non è necessario...
Certamente le prove che fai si chiamano debug e servono a verificare che il codice fa quello che volevamo.
Con il termine buffer si indica genericamente una porzione di memoria che può contenere più di un dato.
Il buffer poi può essere gestito dal software in tanti modi FIFO LIFO ecc, ma a te non serve al momento e per fare debug basta una variabile.
la variabile VALUE (che viene posta uguale PIND bitwise AND con B01111000) è un buffer ... no?
No, è una variabile e basta.
Salvare il valore in una variabile è una operazione che non conivolge gli interrupt e dura 1 ciclo di clock quindi rapidissima, mentre la funzione membro print ecc di Serial impiegano più cicli di clock per essere esguita ed è più lenta, ma il problema principale e quello che ho spiegato all'inizio. Vale sempre comunque il consiglio di mettere nelle funzioni di interrupt operazioni che si completano in pochi cicli di clock, cioè per assurdo è meglio non fargli fare niente nella funzione, ma dal momento che ci serve fargli fare qualcosa questo deve essere molto simile al non fargli fare niente in termini di costo di cicli di clock.
Posso dire ancora che nelle interrupt si deve prendere nota di ciò che è accaduto e basta, poi nel loop() si fanno delle cose in base a ciò di cui è stato preso nota prima.
Però questo vale solo inizialmente quando ancora non si ha esperienza e non si è pienamente coscienti
di cosa accade nel dettaglio.
ok... per la 'leggerezza' della funzione associata all'nterrupt ...
in effetti io devo solo leggere "fotografare" i bit presenti sui pin PD3, PD4, PD5 , PD6 .... nel momento in cui il livello di PD2 (interrupt 0) sale da LOW a HIGH.
in sostanza, credi che sia eccessivo fare eseguire una istruzione tipo "VALUE = PIND"; cioè leggere i bit presenti sulla porta D .. poi potrei analizzarla nella loop... cosa ne pensi?
in sostanza, credi che sia eccessivo fare eseguire una istruzione tipo "VALUE = PIND"; cioè leggere i bit presenti sulla porta D .. poi potrei analizzarla nella loop... cosa ne pensi?
Già risposto così:
Salvare il valore in una variabile è una operazione che non conivolge gli interrupt e dura 1 ciclo di clock quindi rapidissima,
l'operazione con AND ed in genere con i bitwise sono rapidissime quindi va bene come l'hai scritta.
ho spostato la serial print nel loop... ma adesso la seriale riceve solo bestemmie.... al posto di caratteri intellegibili...
il baud rate e corretto ma non riceve nulla ,
dichiara la variabile VALUE come volatile e prova nuovamente lo sketch.
cioè scambiando attachinterrupt con Serial.begin... ho anche aumentato i delay fino a 3000 ...
cosa succede:
quando apro la finestra di serial monitor non funge, cioè riceve caratteri senza senso, poi resetto con il tastino e da qui in poi funziona bene, decodifica bene etc...
credo sia un problema di interferenza tra interrupt e serial ... se è così.. qual'è la soluzione????
anzi.. ho verificato che è casuale che alla prima apertura della finestra serial monitor riceva regolarmente oppure oppure no. però anche quando non funziona resetto e la ricezione dei dati riprende in modo corretto...
Prova impostando lo stato dei pin prima di attaccare l'interrupt.
Siccome usi la modalità CHANGE, forse impostandoli su INPUT causano un cambiamento di stato leggibile dall'interrupt: ricorda che all'avvio i pin sono flottanti (senza stato).
al pin due è collegata una resistenza da 10 k collegata al GND, giusto per forzare il livello su LOW. L'interrupt l'attivo portando su HIGH il livello del pin2 con un filo connesso al + 5 V.
si ho provato con diversi baudrate e la situazione non cambia;
Uso Luigino come board, il micro ha il bootloadr UNO;
per leo:
provato!!! ..... la stessa identica cosa ......
naturalmente tutti i 4 pin, di cui leggo il valore, sono connessi stabilmente con R da 10 K a GND....
bho!!! provo a cambiare micro controllore sulla board?
lo stao HIGH funziona regolaremnete perchè c'è il led che inverte il suo stato (acceso|spento) ogni volta che interviene l'interrupt.... il problema riguarda solo l'invio dei dati alla seriale nel primo avvio, perchè dopo il primo reset tutto funziona bene... e qualche volta funzina bene anche al primo avvio ...
In effetti, poichè a me i dati inviati in seriale non servono, magari và già bene così. Solo che volevo capire perchè si verifica questo fenomeno.
Un'altra cosa che ho notato, di diverso dagli altri schech, e che all'upload si blocca con la spia rx accesa fissa, poi con un reset prosegue regolarmente con esito positivo...
intanto adesso provo un altro microcontrollore .... giusto per vedere se il comportamento è lo stesso ...