In attesa di iniziare il mio progetto stavo facendo qualche prova con gli infrarossi, utilizzando la libreria di Ken Shirriff e il circuito da lui consigliato.
Con questo sketch Arduino deve leggere un segnale di un telecomando sony e replicarlo dopo qualche secondo, ma si comporta in modo strano...
Quando premo un tasto viene riconosciuto il codice, viene inviato, ma dopo 3 secondi leggo sulla seriale una serie di caratteri incomprensibili.
Cosa può essere?
#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;
unsigned long val=0,oldval=0;
void setup()
{
Serial.begin(9600);
Serial.println("Inizio");
irrecv.enableIRIn();
}
void loop() {
if (irrecv.decode(&results)) {
val=results.value;
Serial.println(val,HEX);
if((val!=0)&&(val!=oldval)){
delay(3000);
inviaIR(val);
}
oldval=val;
irrecv.resume();
}
}
void inviaIR(unsigned long signal){
for (int i = 0; i < 3; i++) {
irsend.sendSony(signal, 12);
delay(100);
}
Serial.println("Ho inviato!");
irrecv.resume();
}
non vorrei dire baggianate ma se il led che usi per inviare e ricevere è los tesso, è facile che leggi quello che hai appena inviato (infatti 3 secondi è il tempo di delay), oppure si mette "in pausa" da solo finchè non gli dai irrecv.resume(); che però chiami 2 volte (una volta nella funzione loop(), l'altra in inviaIR() ) e crei macello.
sicuro di aver impostato nel serial monitor il baudrate a 9600?
per leggere il segnale non utilizzo un led ma un ricevitore a 38khz a 3 pin come indicato nello schema del primo post.
comunque la ricezione funziona correttamente.. con lo sketch che serve solo a leggere il segnale ottengo i risultati attesi.. e anche il serial monitor non da problemi perché é impostato a 9600.
per evitare la lettura del segnale inviato da Arduino utilizzo le variabili val e oldval e tramite un confronto mi assicuro di prendere solo il primo di una serie di segnali uguali.
Mi aspetto di leggere il codice ricevuto, oppure 0 se non premo nessun pulsante.
E in effetti funziona.. cioè leggo una serie di 0, e poi A90 che sarebbe il codice del pulsante di accensione.. poi viene inviato il codice A90 e immediatamente si blocca, cioè non legge nessun altro codice e ripete sempre A90.
Può sembrare che venga letto il valore riprodotto dal led e quindi si entri in questo circolo vizioso.. ma se così fosse dovrei visualizzare tante volte "Ho inviato". Per conferma ho anche controllato con una fotocamera e coperto il led con la mano.. e A90 viene inviato solo una volta.
Ho modificato un pò il codice seguendo anche il tuo consiglio:
#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
IRsend irsend;
decode_results results;
unsigned long val=0,oldval=0;
void setup()
{
Serial.begin(9600);
Serial.println("Inizio");
irrecv.enableIRIn();
}
void loop() {
if (irrecv.decode(&results)) {
val=results.value;
if((val!=0)&&(val!=oldval)){
//delay(3000);
Serial.println(val,HEX);
inviaIR(val);
}
oldval=val;
irrecv.resume();
}
}
void inviaIR(unsigned long signal){
for (int i = 0; i < 3; ++i) {
irsend.sendSony(signal, 12);
delay(100);
}
Serial.print("Ho inviato ");
Serial.println(val,HEX);
}
Se lo eseguo si comporta più o meno come prima.. cioè si blocca dopo che invia il primo valore.
Se invece commento "irsend.sendSony(signal, 12);" funziona perfettamente, a parte che ovviamente non invia!
Ho fatto altre prove.. se ricevo in loop funziona tutto, se invio in loop funziona tutto, se voglio ricevere e poi inviare funziona solo al primo ciclo!
Sto impazzendo ]
Si, ma come ho già detto ho fatto diverse prove e il segnale non viene neanche inviato una seconda volta... Se così fosse dovrei ricevere sulla seriale "Ho inviato".
no, quello che probabilmente avviene, più che un problema hardware, è un problema delle librerie, che (probabilmente) non son fatte per gestire un pin sia come in che come out. in pratica dopo aver fatto un out, dovresti reinizializzare la libreria input, etc..
Anche secondo me è un problema di libreria, ma non credo che sia legato al numero di pin.. perchè quello di input è specificato nel codice (11), mentre quello di output è di default il 3.
Come hai detto tu forse la libreria non prevede che si possa inviare e ricevere... ma non saprei come aggirare il problema. Ho dato anche un'occhiata ai sorgenti della libreria ma non sono riuscito ad individuare il problema..
Ho dato un'occhiata alla libreria. L'autore dice che per la trasmissione lui usa il PWM ma tu spedisci sul pin 12 (mi pare dal tuo codice) che non ha il PWM. Inoltre la trasmissione usa gli INT, e difatti l'autore usa per la trasmissione il pin 3, che è dotato non solo di PWM ma è anche agganciato all'int 1.
intanto grazie a tutti per i suggerimenti
comunque sto utilizzando il pin 3 come output.. quel 12 che vedi, da quello che ho capito indica il numero di bit da inviare (nel mio caso ad esempio a90 é rappresentato appunto in 3*4 bit)
supergiox:
Anche secondo me è un problema di libreria, ma non credo che sia legato al numero di pin.. perchè quello di input è specificato nel codice (11), mentre quello di output è di default il 3.
Come hai detto tu forse la libreria non prevede che si possa inviare e ricevere... ma non saprei come aggirare il problema. Ho dato anche un'occhiata ai sorgenti della libreria ma non sono riuscito ad individuare il problema..
quando fai IRrecv irrecv(RECV_PIN); la libreria effettua qualche tipo di inizializzazione sul pin, ovvero potrebbe impostare qualche valore particolare a livello di registri, che poi la chiamata di invio potrebbe modificare e quindi rendere non efficiente
leo72:
Ho dato un'occhiata alla libreria. L'autore dice che per la trasmissione lui usa il PWM ma tu spedisci sul pin 12 (mi pare dal tuo codice) che non ha il PWM. Inoltre la trasmissione usa gli INT, e difatti l'autore usa per la trasmissione il pin 3, che è dotato non solo di PWM ma è anche agganciato all'int 1.
Grazie leo per aver dato questa occhiata.
Quindi se anche IRrecv usa gli interrupt per leggere il segnale in ingresso (a livello registri), il fatto di attivate l'interrupt di lettura sullo stesso pin vuol dire che poi nascono casini tra i 2 interrupt di lettura e di scrittura. E' anche vero che il problema, se è stato preso in considerazione, è risolvibile via software.
Mi fa piacere che non sono l'unico ad avere questo problema... soprattutto se qualcuno l'ha risolto!
Se così non è, vorrei contribuire.. ma non ho mai usato gli interrupts (con Arduino).
Qualcuno sa consigliarmi una guida per capirci qualcosa? (oltre al playground)
Il codice usa i timer per leggere i dati e gli interrupt agganciati sempre ai timer per l'invio dei dati.
Di più non so, so però leggendo il codice che in fase di invio viene disattivata la lettura. Forse la libreria deve essere impostata in lettura, poi disattivata, poi reimpostata in scrittura e poi ridisattivata. Se resta aperta in ricezione, poi non trasmette e viceversa? Boh.
supergiox:
Mi fa piacere che non sono l'unico ad avere questo problema... soprattutto se qualcuno l'ha risolto!
Se così non è, vorrei contribuire.. ma non ho mai usato gli interrupts (con Arduino).
Qualcuno sa consigliarmi una guida per capirci qualcosa? (oltre al playground)
gli interrupt sono dei meccanismi che anche i PC utilizzano, quindi per capire il concetto puoi cercare qualche guida generica sugli interrupt. Su come usarli con arduino, a parte il playground e il datasheet at-mega, non credo esista molto. Magari scrivo qualche riga al proposito sfruttando il periodo di ponte.
Si conosco gli interrupt e li ho utilizzati su pc in assembler, vorrei capire come utilizzarli su arduino e quando conviene utilizzarli...
Ora cerco qualche esempio, ma ovviamente una tua guida sarebbe molto gradita e utile a molti