IRremote ha improvvisamente smesso di funzionare

Niente, la libreria si era aggiornata alle versione 3 e quindi c'era bisogno di cambiare qualche riga di codice. Ora, sfrutto l'occasione per chiedere un'altra cosa: questo "telecomando seriale" usa un piccolo programma fatto in C# su Visual Studio per comunicare, il tutto è connesso tramite USB al PC. Questo programma scrive nella porta seriale dei numeri, ad esempio "1" oppure "2", poi l'Arduino alla ricezione di questi numeri dovrebbe inviare un segnale alla TV tramite led IR... Il problema è che le prime volte questa comunicazione seriale funziona, ma dopo un po' di tempo (o scrivendo "1", "2" ripetutamente) smette di funzionare. L'Arduino riceve i dati seriali, ma è come se il codice dentro l'if non funzionasse. Se aspetto 30 secondi/1 minuto, poi, la comunicazione sembra andare bene. Sembra un po' casuale... La mia domanda è: c'è un cooldown per il numero di dati inviati tramite porta seriale? Oppure è una limitazione di Arduino o altro?
Questo è il mio codice:

#include <IRremote.h>
#define SAMSUNG_BITS  32
IRsend irsend(3);

void setup()
{
  Serial.begin(9600);
  irsend.enableIROut(38);
}

void loop()
{ 
 if(Serial.read() == '1') {
    const unsigned int S_1[68]={4650,4300,700,1550,700,1550,650,1550,700,400,700,400,700,400,700,450,700,400,700,1500,700,1500,700,1550,700,450,650,400,700,450,650,450,700,400,700,400,700,450,650,1550,700,400,700,400,700,400,700,450,650,450,650,1550,700,1500,700,450,650,1550,700,1550,650,1550,700,1500,700,1550,650};
  irsend.sendRaw(S_1,68,38);
  delay(500);
  Serial.write("0");
  } else if(Serial.read() == '2') {
    const unsigned int S_2[68]={4600,4350,650,1550,700,1500,700,1550,700,400,700,400,700,450,650,450,700,400,700,1500,700,1500,700,1550,700,400,700,450,650,450,700,400,700,400,700,1500,700,400,700,1550,700,400,700,400,700,450,650,450,700,400,700,400,700,1550,650,450,700,1500,700,1550,650,1550,700,1500,700,1550,650};
  irsend.sendRaw(S_2,68,38);
  delay(500);
  Serial.write("0");
  }
}

Mi sa che senza vedere lo sketch è difficile fare ipotesi.

Benvenuto, essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con MOLTA attenzione tutto il su citato REGOLAMENTO ... Grazie. :slight_smile:

nid69ita

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione, nessuno ti potrà rispondere, quindi ti consiglio di farla al più presto. :wink:

Hai ragione! Ho creato un nuovo account dato che non riuscivo ad accedere al vecchio, ovviamente dimenticandomi di ripresentarmi... :sweat_smile: Ho subito rimediato.

Semplice, la Serial.read() legge il byte dal buffer togliendolo. Tu devi mette un solo Serial.read() dentro al loop memorizzando il valore in una variabile e quindi usare la variabile per capire cosa hai letto. Poi le costanti è inutile metterle dentro alla funzione, piazzale in testa al codice che così diventa anche più semplice da leggere. E, per finire, quando hai un valore che deve determinare il codice da eseguire in base ad ogni valore, usa la "switch()".
Una cosa di questo tipo:

const unsigned int S_1[68]={4650,4300,700,1550,700,1550,650,1550,700,400,700,400,700,400,700,450,700,400,700,1500,700,1500,700,1550,700,450,650,400,700,450,650,450,700,400,700,400,700,450,650,1550,700,400,700,400,700,400,700,450,650,450,650,1550,700,1500,700,450,650,1550,700,1550,650,1550,700,1500,700,1550,650};
const unsigned int S_2[68]={4600,4350,650,1550,700,1500,700,1550,700,400,700,400,700,450,650,450,700,400,700,1500,700,1500,700,1550,700,400,700,450,650,450,700,400,700,400,700,1500,700,400,700,1550,700,400,700,400,700,450,650,450,700,400,700,400,700,1550,650,450,700,1500,700,1550,650,1550,700,1500,700,1550,650};
...
void loop()
{ 
  char car = Serial.read();
  switch (car) {
    case '1':
      irsend.sendRaw(S_1,68,38);
      delay(500);
      Serial.write("0");
      break;
    case '2':
      irsend.sendRaw(S_2,68,38);
      delay(500);
      Serial.write("0");
      break;
  }

Grazie per la spiegazione! Le costanti le ho messe dentro alla funzione perché sono 12 e quindi non c'è abbastanza memoria (sto usando un Arduino Nano). Per quanto riguarda la Serial.read()... A questo punto posso anche togliere Serial.write("0"), dato che già il byte è stato tolto in precedenza dal Serial.read(), giusto?

Hm, mi sfugge come delle costanti interne ad una funzione possano occupare meno spazio di quelle globali...

Sono due cose diverse, non è che fare Serial.write() significhi mettere quei caratteri nel buffer, ma semplicemente che quello "0" verrebbe inviato al PC (non sapendo se si trattasse di un qualche carattere di conferma per il programma che scrive su seriale, non l'ho rimosso).
Quindi si, se non ti serve che il PC riceva conferma del carattere riconosciuto ossia del tasto da inviare, puoi rimuoverlo.

Per curiosità, ma che cosa fa il programma su PC esattamente?
E poi sicuro che ti servano i codici raw? Cosa devi comandare? Vedo una costante (che non usi) che parla di SAMSUNG, se è un protocollo di quelli riconosciuti dalla libreria ti basta un valore per indicare un tasto..

Da quello che ho capito le costanti globali vengono immagazzinate nella RAM (che è troppo piccola per contenere queste costanti), mentre mettendole dentro ad una funzione le forzo a rimanere dentro alla memoria flash. Così non occupano meno spazio, ma semplicemente sono dentro a una memoria più grande.

È un programma scritto in C# che ha gli stessi tasti di un telecomando e grazie a lui posso comandare la mia TV direttamente dal PC. Praticamente scrive sulla porta seriale dei numeri o delle lettere e l'Arduino, leggendole, manda il segnale corrispondente alla TV.

Mi servono i codici raw perché non so i valori HEX e non so convertirli... la costante che non uso era solo una prova, per vedere se funzionassero i codici HEX trovati su internet.

non credo proprio,
semmai è dichiararle const globali che le forza a essere messe in una memoria non scrivibile, ma non credo sia il caso di Arduino, abbiamo già provato e sembra che comunque vadano in RAM, addirittura anche costanti letterali (stringhe scritte nel testo del programma) vengono allocate in RAM, pur se il K&R esplicitamente le da come allocabili in memoria non accessibile in scrittura
in arduino per fare questo lavoro invece si può usare il modificatore PROGMEM, che io non ho mai usato ma sembra fare esattamente quello che cerchi

1 Like

Ma se hai i codici raw immagino che tu abbia usato "IRrecvDumpV2" (che trovi tra gli esempi della libreria IRremote, io ho usato una WeMos quindi è la libreria per ESP ma è derivata direttamente -a proposito, esattamente che versione di libreria hai?-) e che ti mostra la codifica rilevata per ognuno dei tasti che premi: ti ha mostrato "UNKNOWN", ossia non ha riconosciuto la codifica? Te lo chiedo perché, sebbene io non abbia fatto molte prove con vari modelli di TV, per le marche più note (qual è il tuo, Samsung?) a me riconosceva quasi sempre le codifiche, cosa che permette di tenere 4 byte del codice tasto invece di 68 interi per ogni tasto quindi se hai 10 tasti (ma per un telecomando in genere se ne usano di più) sono 1360 byte! L'unica eccezione era il telecomando di MySkyHD, per il quale sono stato costretto a usare i raw) ma per tutti gli altri che ho in casa erano codifiche note (Sony, RC5, RC6, Panasonic...).
Verifica bene cosa ti risponde IRrecvDump, magari posta qui il suo output.

E comunque se proprio dovessi per forza usare i RAW, studia il comando PROGMEM che già ti hanno consigliato.

Io ho fatto una cosa simile, ma il comando arriva da un altro WeMos che invia tramite WiFI (un pacchetto UDP) il tasto da trasmettere, ma in sostanza è una cosa molto simile.

Purtroppo non ho un ricevitore IR, quindi mi sono dovuto arrangiare con ciò che ho trovato su internet. Essenzialmente ho tenuto conto di quello che c'è su questo sito e ho fatto un piccolo script in JavaScript per convertirmi tutti i valori RAW in codici leggibili dalla libreria.
Per chi volesse, lascio qui il codice dello script:

Script converti valori
var readline=require("readline");

function askQuestion(query) {
    const rl = readline.createInterface({
        input: process.stdin,
        output: process.stdout,
    });

    return new Promise(resolve => rl.question(query, testo => {
        rl.close();
        resolve(testo);

        var array=[];
var hexarray=[];
var toarray=testo.split(",");
for(i=0;i<toarray.length;i++) {
    var int=parseInt(toarray[i]);
    array.push(int);
}

for(u=0;u<array.length;u++) {
    if(array[u]>4000) {
        array.splice(u, 1);
    }
    if(array[u]<1000) {
        if(array[u+1]>1000) {
            array[u]=1;
            array.splice(u+1, 1);
        } else if(array[u+1]<1000) {
            array[u]=0;
            array.splice(u+1, 1);
        }
    }
    if(u===array.length) {
        array.splice(u, 1);
    }
}

var stringarray=array.toString();
var nocomma=stringarray.replace(/,/g, "");
var nospace=nocomma.replace(/ /g, "");
var bytes=nospace.match(/.{1,4}/g);
for(x=0;x<bytes.length;x++) {
    var hex=parseInt(bytes[x], 2).toString(16);
    hexarray.push(hex);
}
var hexarraystring=hexarray.toString();
var withNAN=hexarraystring.replace(/,/g, "");
var output=withNAN.replace(/NaN/g, "");
console.log("\n-> 0x"+output);

    }))
}
const testo = askQuestion("Inserisci il codice RAW. ");
console.log(testo);

Mentre per il codice di Arduino, questa è la versione modificata:

Codice arduino
#include <IRremote.h>
#define SAMSUNG_BITS  32
IRsend irsend(3);
#define POWER 0xe0e040bf
#define CH1 0xe0e020df
#define CH2 0xe0e0a05f
#define CH3 0xe0e0609f
#define CH4 0xe0e010ef
#define CH5 0xe0e0906f
#define CH6 0xe0e050af
#define CH7 0xe0e030cf
#define CH8 0xe0e0b04f
#define CH9 0xe0e0708f
#define CH0 0xe0e08877
#define SOURCE  0xe0e0807f
#define EXIT    0xe0e0b44b
#define VDOWN   0xe0e0d02f
#define VUP     0xe0e0e01f
#define MUTE    0xe0e0f00f
  
void setup()
{
  Serial.begin(9600);
  irsend.enableIROut(38);
}

void loop()
{   
  char car = Serial.read();
  switch (car) {
    case 'p':
    irsend.sendSAMSUNG(POWER, SAMSUNG_BITS);
    delay(500);
    irsend.sendSAMSUNG(POWER, SAMSUNG_BITS);
    break;
    case '1':
      irsend.sendSAMSUNG(CH1,SAMSUNG_BITS);
      break;
    case '2':
      irsend.sendSAMSUNG(CH2,SAMSUNG_BITS);
      break;
    case '3':
      irsend.sendSAMSUNG(CH3,SAMSUNG_BITS);
      break;
    case '4':
    irsend.sendSAMSUNG(CH4,SAMSUNG_BITS);
      break;
      case '5':
    irsend.sendSAMSUNG(CH5,SAMSUNG_BITS);
      break;
      case '6':
    irsend.sendSAMSUNG(CH6,SAMSUNG_BITS);
      break;
      case '7':
    irsend.sendSAMSUNG(CH7,SAMSUNG_BITS);
      break;
      case '8':
    irsend.sendSAMSUNG(CH8,SAMSUNG_BITS);
      break;
      case '9':
    irsend.sendSAMSUNG(CH9,SAMSUNG_BITS);
      break;
      case 'b':
    irsend.sendSAMSUNG(CH0,SAMSUNG_BITS);
      break;
      case 's':
    irsend.sendSAMSUNG(SOURCE,SAMSUNG_BITS);
      break;
      case 'u':
    irsend.sendSAMSUNG(VUP,SAMSUNG_BITS);
      break;
      case 'd':
    irsend.sendSAMSUNG(VDOWN,SAMSUNG_BITS);
      break;
      case 'e':
    irsend.sendSAMSUNG(EXIT,SAMSUNG_BITS);
      break;
      case 'm':
    irsend.sendSAMSUNG(MUTE,SAMSUNG_BITS);
      break;
  }
}

Non capisco in che modo quel progetto sia in relazione col tuo, ma in ogni caso se non hai i dati dei codici del TUO esatto telecomando la vedo difficile. Certo, se per caso prima ti ha funzionato (non ho capito se è così o meno) quei codici raw sono quelli del tuo telecomando, ma a me sembra tutto eccessivamente "farraginoso"...

Quindi io ti consiglierei, non solo per capire meglio cosa stai facendo ma anche per permetterti di personalizzare questo progetto o altri in futuro, di prendere un paio di ricevitori IR da eBay (costano pochi Euro, ma puoi anche rimediarli da qualche apparecchio da "cannibalizzare", come un vecchio TV o videoregistratore o qualche ripetitore di telecomandi), e con lo sketch della libreria leggi quali sono i tasti che vuoi riprogrammare. A quel punto sono quasi certo che la codifica sia ben nota, e quindi potrai usare forse 2 o 4 byte per ogni tasto, dandoti piena libertà di azione in termini anche di memoria.

Ho usato quel sito per convertire tutti i valori RAW che avevo prima in valori HEX (penso che siano HEX). Ad esempio, questi valori RAW: 4650,4300,700,1550,700,1550,650,1550,700,400,700,400,700,400,700,450,700,400,700,1500,700,1500,700,1550,700,450,650,400,700,450,650,450,700,400,700,400,700,450,650,1550,700,400,700,400,700,400,700,450,650,450,650,1550,700,1500,700,450,650,1550,700,1550,650,1550,700,1500,700,1550,650 li ho convertiti (grazie a quello che c'è scritto su quel sito) in questo valore: 0xe0e020df. I valori RAW li ho trovati su REMOTECENTRAL, e quindi penso siano dei valori globali che sono compatibili con tutte le TV Samsung.
Inoltre comprerò dei ricevitori IR, così potrò controllare meglio in questo caso e fare progetti futuri.

Beh non è che quel sito mi sia molto chiaro, entra in alcuni casi in dettagli dei quali puoi tranquillamente fare a meno, ed in altri non spiega in modo chiaro quello che espone (le due cose poi spesso coincidono).

Per dire, quel valore che hai indicato non è propriamente la "conversione" dei codici RAW che di fatto indicano una sequenza, la durata in microsecondi di ogni impulso low o high ossia presenza o assenza di portante, ma è un codice che rappresenta un certo tasto/comando che a sua volta corrisponde ad una sequenza "standard".

Se vuoi lavorare con gli infrarossi ti conviene lasciar perdere le cose "trovate in giro sul sito X" e che non capisci: rimedia o comprati un paio di ricevitori IR (direi TSOP4838 o VS1838, costano pochissimi Euro, il secondo link te ne dà 2 per 1 Euro, più 2.50 di spedizione purtroppo ma fai finta che li stai pagando poco più di 1.70€ l'uno..) e usando gli esempi della libreria sarai in grado non solo di capire meglio il tutto, ma anche di personalizzare correttamente tutto ciò che ti occorre fare.
Inutile proseguire "a tentoni", vai sul concreto. :slight_smile:

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.