Libreria IRsend e NEC (comandare climatizzatori)

Ciao a tutti, sto usando questo sketch per leggere che tipo di codifica usa il mio telecomando del climatizzatore UNICAL e MITSUI (sorprendentemente i telecomandi sono intercambiabili, quindi… ho avuto una botta di c… ]:D).

#include <IRremote.h>

const int RECV_PIN = 11;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
  irrecv.blink13(true);
}

void loop() {
  if (irrecv.decode(&results)) {
    if (results.decode_type == NEC) {
      Serial.print("NEC: ");
    } else if (results.decode_type == SONY) {
      Serial.print("SONY: ");
    } else if (results.decode_type == RC5) {
      Serial.print("RC5: ");
    } else if (results.decode_type == RC6) {
      Serial.print("RC6: ");
    } else if (results.decode_type == UNKNOWN) {
      Serial.print("UNKNOWN: ");
    }
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value
  }
}

bene come risultato ho stabilito che è NEC. più precisamente mi viene restituito:

NEC: 3090000A quando accendo in una determinata modalità (HEAT)
NEC: 2090000A quando spengo da quella modalità (HEAT)

Una volta stabilito ciò ho fatto uno sketch di prova per inviare il segnale, che dovrebbe accendere il clima e dopo 10 secondi spegnerlo.

#include <IRremote.h>

IRsend irsend;

void setup()
{
  Serial.begin(9600);
}

void loop() {
  
  for (int i = 0; i < 3; i++) 
    {
      irsend.sendNEC(0x3090000A,32); // clima ON 
      delay(100);
    }
    delay(10000);
    
    for (int i = 0; i < 3; i++) 
    {
      irsend.sendNEC(0x2090000A,32); // clima OFF
      delay(100);
    }
    delay(10000);
    
  }

Il for l’ho messo perchè ho letto in giro che il send per il nec va ripetuto tre volte, ma potrei aver visto male… perchè non funziona…

Sono sicuro che il tutto sia giusto perchè Il tsop4838 mi rileva quello che il led IR invia ( legge sempre e regolarmente 3 3090000A e dopo 10 secondi 3 2090000A) e il telecomando del climatizatore allo stesso modo.
Ma il climatizzatore non vuole saperne di accendersi o spegnersi.
Suggerimenti?

Grazie

Anche a me sembra di aver letto di spedire 3 volte. Potrebbe essere un problema di distanza? Da che distanza mandi il segnale IR al clima? Anche se è la stessa distanza del telecomando, il segnale del telecomando potrebbe essere più "forte".

appena provato: da 20 , 10 cm dal condizionatore e anche attaccato al ricevitore.
Nada de nada. =( :zipper_mouth_face:

sto provando a fare la stessa cosa con tutti i telecomandi della casa.. Ho trovato un decoder che ha anch'esso il protocollo nec...

il codice del tasto spegnimento è questo AF559A6 E inviandolo solo una volta(non 3) funziona. se lo invio 3 volte spegne accendere e spegne :) Quindi va... il codice e il led funzionano...

Mi chiedo... non è che ci sia qualcosa di particolare o diverso per il condizionatore?

Secondo voi provare a leggere il RAW può cambiare qualcosa?

dr4gone: Mi chiedo... non è che ci sia qualcosa di particolare o diverso per il condizionatore?

Potrebbe essere ma non saprei di preciso.

dr4gone: Mi chiedo... non è che ci sia qualcosa di particolare o diverso per il condizionatore? Secondo voi provare a leggere il RAW può cambiare qualcosa?

Personalmente ritengo che il metodo raw è mooolto rognoso. Qui una piccola spiegazione di come usarlo: http://arduinostuff.blogspot.it/2011/05/receiving-and-sending-ir-with-arduino.html

Idea, potresti anche provare a modificare il secondo parametro, 32:

irsend.sendNEC(0x3090000A,32);

Per i NEC ho visto sempre usato 32, ma magari per il condizionatore ci va un altro valore. Ad esempio qui: http://alanarduinotools.googlecode.com/svn/trunk/Attiny2313/GuitarRodOfCommand/GuitarRodOfCommand.c nel codice ad un certo punto per un videoregistratore usa 1B (ovvero 27) invece di 20 esadecimale (ovvero 32 decimale) perciò mi vien da dire che non è fissa la regola del 32

Qui dice che il protocollo dei NEC è di 8+8+8+8 bit (perciò 32): http://techdocs.altium.com/display/ADRR/NEC+Infrared+Transmission+Protocol

Qui invece il creatore della IRRemote spiega il protocollo Sony che di solito è a 12 bits (ma anche a 20 bits): http://www.righto.com/2010/03/understanding-sony-ir-remote-codes-lirc.html Qui http://www.mauroalfieri.it/elettronica/tutorial-arduino-come-trasmettitore-ir-o-come-telecomando.html una sendsony con secondo parametro 12, perciò il secondo parametro è quanti bit compongono il protocollo.

Potrebbe essere che quel condizionatore sia Nec ma non a 32 bit. Sapere però quanti non credo sia semplice. Solo supposizioni le mie.

EDIT: ulteriore annotazione "Each key on the remote has a particular code (typically 12 to 32 bits) associated with it, and broadcasts this code when the key is pressed. If the key is held down, the remote usually repeatedly broadcasts the key code. For an NEC remote, a special repeat code is sent as the key is held down, rather than repeatedly sending the code." Se tieni premuto lo stesso tasto normalmente i vari protocolli spediscono di continuo lo stesso codice, il NEC no, spedisce un tasto particolare. Magari spedire 3 volte al NEC richiede che ci sia in mezzo questo codice particolare.

Si quelle cose che hai detto le avevo viste, e sono sicuro che sia 32 bit perchè ho fatto il dump. guarda un po .. quello che è uscito con la raw.

Per il telecomando del decoder

AF5C837
Decoded NEC: AF5C837 (32 bits)
Raw (68): -24354 8900 -4300 600 -500 600 -500 600 -500 650 -450 650 -1550 600 -500 600 -1600 550 -550 600 -1600 550 -1650 600 -1600 550 -1650 650 -450 600 -1600 550 -550 550 -1650 600 -1600 550 -1650 550 -550 550 -550 600 -1600 550 -550 550 -550 550 -550 550 -550 550 -550 650 -1550 550 -1650 550 -550 550 -1600 600 -1600 600 -1600 650

Per il telecomando del condizionatore

3090000A
Decoded NEC: 3090000A (32 bits)
Raw (74): 22860 8950 -4400 650 -500 650 -550 650 -1600 650 -1700 600 -550 650 -550 650 -500 650 -550 600 -1650 650 -550 650 -500 650 -1650 650 -550 600 -550 650 -550 650 -500 650 -550 650 -500 650 -550 650 -500 650 -550 650 -550 650 -500 650 -550 650 -500 650 -550 650 -500 650 -550 650 -1600 650 -550 650 -1650 600 -550 650 -550 650 -1600 650 -550 650

Per quello che rigurada il codice di ripetizione è 0xFFFFFFF e basta non considerarlo. Ho gia fatto i test con il telecomando... La cosa strana è che con il condizionatore quel carattere non esce.... Quindi è qualcosa di un po diverso.... come si può notare anche dalla RAW...

Certo ora devo capire come interpretare queste differenze.

Non è tanto scontata la cosa :(

Bastardissima quella cosa, raw 68 e 74, c'e' una bella differenza :fearful:

:cold_sweat: :roll_eyes:

E lo so.. bisogna capire cosa cambia,,, se devo fare la raw di ogni comando... posso andare a spararmi... :D

Se non ho capito male dovrei: Leggere la raw, creare un array con tutti quei valori e spedirli con un irsend.RAW :fearful: Alla fine sto protocollo nec è una bufala :D Quello implemetato credo che sia quello con 68 valori.. questo sembra modificato e se non erro lo devo trattare come se fosse unknow :sweat_smile: Smentitemi vi prego!!! Per provare va bene... ma è un macello :D

HO provato con questo codice, ma non va… (anche se aveva senso)

#include <IRremote.h>
 
int RECV_PIN = 11;
 
IRrecv irrecv(RECV_PIN);
IRsend irsend;
 
boolean recording = true;
decode_results results;
 
void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}
 
void loop() {
  if (recording) {
    if (irrecv.decode(&results)) {
      Serial.println("IR code recorded!");
      //irrecv.resume(); // Receive the next value
      Serial.print("Recorded ");
      Serial.println(" intervals.");
      recording = false;
    }
  } else {
    // replay mode
    Serial.println("Sending recorded IR signal!");
    irsend.sendRaw((unsigned int*) results.rawbuf, results.rawlen, 38);
    delay(2000);
  }
}

Praticamente legge il codice raw e lo invia ripetutamente ogni 2 secondi.
Ma non va

cercando un po, ho trovato questo:

Ha i miei stessi codici!!

Chiedo l’aiuto del pubblico… ehm … :grin: di Pablos :grin:
Sempre che a lui funzioni! :wink:

io avevo fatto questo per replicare i comandi sul nec, non uso più arduino da 6 mesi quindi non posso provare nulla, ma lo accendevo e spegnevo in base al codice raw

#define TOPBIT 0x80000000
//#define NEC_HDR_MARK      9000
//#define NEC_HDR_SPACE     4500
//#define NEC_BIT_MARK       560
//#define NEC_ONE_SPACE     1690
//#define NEC_ZERO_SPACE     560
#define NEC_BITS 32

// 8E700210 spegne
#define NEC_HDR_MARK      9100 //9100
#define NEC_HDR_SPACE     4400 //4400
#define NEC_BIT_MARK       500 //500
#define NEC_ONE_SPACE     1660 //1650
#define NEC_ZERO_SPACE     500 //500

#define DUTY_CYCLE         1/3       // Carrier duty cycle
#define PERIOD             26       // 38kHz, 1/38kHz =~ 26us
#define ACTIVE_HIGH       (PERIOD * DUTY_CYCLE)
#define ACTIVE_LOW        (PERIOD - (PERIOD * DUTY_CYCLE))

int IR_LED = 4;
unsigned long power = 0x9C000210   ;    // BenQ Projector Power code

void setup()
{
  pinMode(IR_LED, OUTPUT);
  Serial.begin(9600);
}

void mark(long time)
{
  for(int i = 0; i < (time / PERIOD); i++)
  {
    digitalWrite(IR_LED, HIGH);
    delayMicroseconds(ACTIVE_HIGH - 4); // digitalWrite() takes 4us
    digitalWrite(IR_LED, LOW);
    delayMicroseconds(ACTIVE_LOW - 4); // digitalWrite() takes 4us
  }  
}

void sendNEC(unsigned long data)
{
    // Leader code
    mark(NEC_HDR_MARK);
    delayMicroseconds(NEC_HDR_SPACE);
  
    for (int i = 0; i < NEC_BITS; i++)
    {
      mark(NEC_BIT_MARK);
      if (data & TOPBIT)
  	delayMicroseconds(NEC_ONE_SPACE);
      else
  	delayMicroseconds(NEC_ZERO_SPACE);
  
      data <<=1;
    }
    
    // stop bit
    mark(NEC_BIT_MARK);
}  
  
void loop()
{  
  // power = 2658140688  ;

  // send power IR signal to Projector every 5 seconds
  Serial.println(power);
  delay(2000);
  sendNEC(power);
}

Al momento sto sviluppando un paio di sketch per la decodifica del segnale ir sia per la ricezione del singolo impulso che per la pressione prolungata (perché alcune codifiche hanno un bit che serve per far capire se è premuto più volte di fila o se è una pressione prolungata) con relativo sketch di trasmissione appunto perché nella libreria mancano delle decodifiche....è ancora in fase di sviluppo o meglio è funzionante ma molto grezzo ho fatto solo un paio di prove...non aspettarti il codice perché è da sistemare e devo ancora verificare delle cose... posso dirti che il telecomando del clima ogni volta manda tutti i comandi tipo: - posizione delle alette per muovere l'aria - velocità ventola - temperatura - caldo o freddo- deumidificatore ecc ecc non funziona come quello della tv che manda solo l'impulso del tasto premuto. -non so se la portante è la stessa dei telecomandi tv ma mi pare che sia più bassa dei 38KHz

P.S. finché facevo delle prove avevo notato che tra il mio codice e quello del tizio della libreria (non mi ricordo mai il nome) lui imposta come predefinite (tra le tante altre cose) le pause di trasmissione tra un segnale e l'altro in base alle decodifiche che lui ha precaricato....per esempio segnale sony nella decodifica RAW di tizio il segnale parte con -45000, o una cosa del genere, mentre in realtà la pausa è messa a fine codice tra un treno di bit e l'altro e dovrebbe essere anche più breve di quella da lui scritta (ma come ti dicevo devo ancora fare dei test sul codice). Andando a logica ed in teoria se tu decodifichi con la funzione RAW della libreria diversi tasti del telecomando tv/decoder (non ho ancora fatto la prova) e noti che tutti i segnali partono con il segno meno allora vuol dire che non decodifica correttamente il segnale del clima o che non è riconosciuto nella libreria....ripeto andando a logica.

P.S. 2 i dati definiti "RAW" sono già parzialmente rielaborati basta che guardi sono tutti risultati "tondi" e uguali mentre i ricevitori, se non sbaglio, dovrebbero avere una tolleranza massima sui 200uS più o meno...forse un po meno.

Scusate ancora non ho provato il codice di pablos, prima voglio capire bene come funziona la cosa..

ZG84: posso dirti che il telecomando del clima ogni volta manda tutti i comandi tipo: - posizione delle alette per muovere l'aria - velocità ventola - temperatura - caldo o freddo- deumidificatore ecc ecc

Si questo l'ho già notato infatti il mio condizionatore cambia i primi due esadecimali, cioè il primo byte in base alla configurazione se caldo o freddo o deumidificatore e in base ai gradi.. questa cosa già l'ho mappata. Ma il problema principale non è questo. Ora basta prendere un comando qualsiasi, Tipo accensione 25 gradi caldo in modalità auto... (che è quello che ho preso) e vedere se si accende,,, tutto qui, per il momento non serve altro.

Partendo da questa base, e guardando dentro la libreria di Ken Shirrifs ho fatto i seguenti ragionamenti:

inviando il segnale esce questo:

Decoded NEC: 3090000A (32 bits)
Raw (74): 
28610 9000 -4350 

700 -450 700 -500 700 -1550 700 -1600 
700 -500 700 -450 750 -450 700 -500 
700 -1550 700 -500 650 -500 700 -1600 
700 -450 700 -500 700 -450 700 -500 
700 -500 650 -500 700 -500 650 -500 
700 -500 700 -450 700 -500 700 -450 
700 -500 650 -550 700 -450 750 -450 
700 -1550 700 -500 700 -1550 700 -500 
700 -450 750 -1550 700 -450 750

Quindi nell'ordine: 1) il primo valore nella libreria viene ignorato (non so perchè) ma nell'altro telecomando nec che mi da Raw(68) esce anche, viene ignorato... e comunque funziona..... quindi assumo che si possa ignorare. 2) 9000 è HDR_MARK 3) -4350 è HDR_SPACE 4) il valore positivo tra il 650 e il 750 è il BIT_MARK 5) i valori negativi sui 400/500 rappresentano gli zeri... e i valori tra 1550/1600 rappresentano gli uno.

Quindi ripulendo ho: Decoded NEC: 3090000A (32 bits) 9000 = HDR_MARK -4350 = HDR_SPACE

tolgo tutti i BIT_MARK e ottengo

-450 -500 -1550 -1600 
-500 -450 -450 -500 
-1550 -500 -500 -1600 
-450 -500 -450 -500 
-500 -500 -500 -500 
-500 -450 -500 -450 
-500 -550 -450 -450 
-1550 -500 -1550 -500 
-450 -1550 -450

Quindi tradotto è

0011 = 3
0000 = 0
1001 = 9
0000 = 0
0000 = 0
0000 = 0
0000 = 0
1010 = A
010   = ?

avanza questo
010 
che credo debba essere considerato 
0010 = 2
oppure 
0100 = 4

Se non erro qui sta il problema... Lui invia 32 bit, ma in realtà sono 4*8+3=35 (36 rappresentati in esadecimale)

alla fine si dovrebbe provare a inviare 0x3090000A2 o 0x3090000A4

Vi convince questo ragionamento?

Niente non funziona. Non funziona nemmeno il codice postato da pablos.

Quello comunque non va bene per fare la prova di spedire più di 32 bit. Sono un po sconfortato.. :~

scusa ma lo fai il set in output del pin che usi per l'infrarosso? nel primo post che hai messo nei 2 sketch non vedo nel setup pinMode(pin, OUTPUT);

il circuito che usi per ricevere il segnale è corretto? rischi di leggere un numero sbagliato e di rispedire l'errore hai provato con un altro apparato, magari con codici più semplici?

ciao

pablos: scusa ma lo fai il set in output del pin che usi per l'infrarosso?

Il pin di invio del led è il 3 ed è incluso già nella libreria apposta non l'ho dichiarato. Ovviamente ho testato quello che invio. Ho messo anche il ricevitore per leggere quello che faccio inviare al led, e legge lo stesso comando che gli arriva dal telecomando.

quando ho usato il codice che hai postato, ovviamente l'ho definito.. sempre il 3, ho cambiato il valore (power) con quello del mio telecomando e i valori dei define come mi escono dalla raw (ho provato anche quelli del tuo codice). Dopo di che ho visto che nel serial print che hai messo nel loop, cioè questo;

  Serial.println(power);
  delay(2000);
  sendNEC(power);

Mi stampa in decimale il valore che io avevo definito prima in power... Ma non invia niente passandolo come argomento a sendNEC()

pablos: il circuito che usi per ricevere il segnale è corretto? rischi di leggere un numero sbagliato e di rispedire l'errore hai provato con un altro apparato, magari con codici più semplici?

Sono sicuro che è corretto, i codici di un altro telecomando nec (di un decoder) li leggo e li riproduco normalmente con arduino.

Il problema di fondo secondo me sta nel fatto che quel telecomando nec del decoder quando leggo la raw ha 68 valori, quello del condizionatore ne ha 74. Ma anche a te dava 74. Ma tu dici che a te funzionava, abbiamo lo stesso identico telecomando. Quindi sto sbagliando qualcosa evidentemente.

Finalmente ci sono riuscito!!! ]:slight_smile: ]:D:grin: :grin: :grin: :grin: ]:slight_smile: ]:smiley:

HO con il dump presente negli esempi della libreria ho ottenuto la raw.
Poi ho eliminato il primo valore, costruito un array di interi( molto importante è togliere i meno, prima non funzionava per questo) e poi usare semplicemente questo codice:

#include <IRremote.h>
IRsend irsend;

unsigned int powerOn[74] = {
                             8900,4450,650,500,650,550,650,1600,650,1600,650,550,650,500,650,550,650,500,650,1650,600,550,650,500,650,1650,650,500,650,550,650,500,650,550,600,550,650,550,600,550,650,500,650,550,650,500,650,550,650,500,650,550,650,500,650,550,650,500,650,1600,650,550,650,1600,650,550,650,500,650,1650,600,550,650};

void setup()
{
  Serial.begin(9600);
}

void loop()
{
    irsend.sendRaw(powerOn,74,38); //irsend.sendRaw(array,lunghezza raw, khz) 
     delay(2000);
  }

Ovviamente era solo per test…
MA FUNZIONA!!!

Ora non mi resta che mappare tutto nel modo più intelligente possibile… e via!
Grazie dei suggerimenti! :wink: :wink:

E grazie a te dei vari test che hai fatto. Se un giorno dovrò fare gestione raw di telecomandi strani dovrò ricordarmi di queto thread. :D

:) mi fa piacere.. Ora cerco di fare una cosa smart che dalla lettura della raw crei direttamente l'array senza meno e con le virgole al posto degli spazi per poterlo copiare direttamente nel codice che poi servirà per i comandi.

Ho notato però che con il condizionatore a più di 1 metro a volte non prende il segnale... Dopo aver mappato i comandi, passerò alle prove per aumentare il raggio d'azione del led se è possibile! Ma se ne parla con l'anno nuovo mi sa :D l'importante era capire come funzionasse!

La cosa spettacolare è che così sono riuscito a mappare anche a leggere l'ON/OFF di tutti i TV samsung che ho in casa... Finalmente! Non puoi quanto sia contento :D A volte basta poco :D Mi sono fatto un bel regalo di natale :grin:

a chi potesse servire, ho trovato il codice che già fa quello che avevo scritto nel post precedente.

#include <IRremote.h> 

int RECV_PIN = 11; 
IRrecv irrecv(RECV_PIN); 
decode_results results; 

void setup() 
{ 
  Serial.begin(9600); 
  irrecv.enableIRIn(); 
} 

int c = 1; 

void dump(decode_results *results) { 
  int count = results->rawlen; 
  Serial.println(c); 
  c++; 
  Serial.println("For IR Scope: "); 
  for (int i = 1; i < count; i++) { 
    
    if ((i % 2) == 1) { 
      Serial.print("+"); 
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC); 
    } 
    else { 
      Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC); 
    } 
    Serial.print(" "); 
  } 
  Serial.println(""); 
  Serial.println("For Arduino sketch: "); 
  Serial.print("unsigned int raw["); 
  Serial.print(count, DEC); 
  Serial.print("] = {"); 
  for (int i = 1; i < count; i++) { 
    
    if ((i % 2) == 1) { 
      Serial.print(results->rawbuf[i]*USECPERTICK, DEC); 
    } 
    else { 
      Serial.print((int)results->rawbuf[i]*USECPERTICK, DEC); 
    } 
    Serial.print(","); 
  } 
  Serial.print("};"); 
  Serial.println("");  
  Serial.print("irsend.sendRaw(raw,"); 
  Serial.print(count, DEC); 
  Serial.print(",38);"); 
  Serial.println("");  
  Serial.println(""); 
} 

void loop() { 
  if (irrecv.decode(&results)) { 
    dump(&results); 
    irrecv.resume(); // Receive the next value 
  } 
}

Tanti auguri! :slight_smile: