JP1 Remotes Forum Index JP1 Remotes


FAQFAQ SearchSearch 7 days of topics7 Days MemberlistMemberlist UsergroupsUsergroups RegisterRegister
ProfileProfile Log in to check your private messagesLog in to check your private messages Log inLog in

Arduino sketch to generate raw code for use with IR Scope
Goto page 1, 2, 3, 4, 5  Next
 
Post new topic   Reply to topic    JP1 Remotes Forum Index -> JP1 - Software
View previous topic :: View next topic  
Author Message
probono



Joined: 12 Aug 2012
Posts: 48

                    
PostPosted: Sun Aug 12, 2012 7:59 am    Post subject: Arduino sketch to generate raw code for use with IR Scope Reply with quote

I use the following Arduino sketch to generate raw code for use with IR Scope.

Materials used:
Arduino Nano Clone from eBay (12 EUR shipped)
38 kHz TSOP (Vishay IR detector module)

Library used:
http://www.pjrc.com/teensy/td_libs_IRremote.html

My sketch:
Code:

// If one keypress results in multiple codes being output, then
// change in IRremoteInt.h:
// #define _GAP 50000

#include <IRremote.h>

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

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

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
  }
}


This outputs:

Code:

1
For IR Scope:
+650 -2600 +600 -450 +550 -450 +600 -500 +650 -450 +600 -450 +600 -550 +500 -600 +500 -500 +600 -500 +550 -4200 +650 -2600 +550 -550 +600 -1000 +600 -350 +600 -600 +1050 -1050 +550 -550 +550 -400 +650 -500 +600
For Arduino sketch:
unsigned int raw[42] = {650,2600,600,450,550,450,600,500,650,450,600,450,600,550,500,600,500, 500,600,500,550,4200,650,2600,550,550,600,1000,600,350,600,600,1050,1050,550,550,550,400,650,500,600,};
irsend.sendRaw(raw,42,38);


I can plug the result into IR Scope, and I can use sendRaw in an Arduino sketch to send this command.

Extend IR Scope to interface with the Arduino directly, anyone?
Back to top
View user's profile Send private message
Barf
Expert


Joined: 24 Oct 2008
Posts: 1402
Location: Munich, Germany

                    
PostPosted: Sun Aug 12, 2012 12:22 pm    Post subject: Reply with quote

Hi probono,

thanx for drawing my attention to Arduino and the library. I will order mine later this evening Wink Any particular recommendations of models? I tend to an Ethernet model; I like Ethernet and socket programming...

I will likely integrate it into my IrMaster program directly. Sources (Java) are available.

But already with the released version 0.2.0 you can import your Arduino signals into IrMaster if you make a trivial change to your program ("sketch") in order to generate files in the so-called ict-format, that is the native export format of IrScope.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
probono



Joined: 12 Aug 2012
Posts: 48

                    
PostPosted: Sun Aug 12, 2012 4:52 pm    Post subject: Reply with quote

Hi Barf, cool. Finally some Arduino action Very Happy

I have both the Arduino Uno and a cheap Chinese Arduino Nano V3.0 clone. Personally I like the Nano better because it fits right onto a breadboard. Once my circuit is complete, I can even replace the Arduino with a bare ATmega: instructables.com

Together with a cheap ENC28J60-based Ethernet module we could even build a cheap GlobalCache like device... the possibilities are endless.
If you like wiring yourself, you could use something like http://goo.gl/eGPBp - otherwise there are ready made Ethernet shields available (in which case you should start with the Arduino Uno rather than the Nano to begin with).

Right now I am thinking about making a IR receiver/sender that receives, say, command "watch tv" and then plays complex custom macros (e.g., power on TV, set TV volume down 3x, power on cable box, set cable box volume to maximum, switch TV input to cable box, switch cable box to show EPG...). It will also control some RF power plugs...

Looking forward to your integration of the Arduino into your software.
Back to top
View user's profile Send private message
probono



Joined: 12 Aug 2012
Posts: 48

                    
PostPosted: Sun Aug 12, 2012 5:41 pm    Post subject: Reply with quote

Note to self:

To import into IrMaster, need to write a file in the following format and save it with the .ict extension.

Code:
irscope 0
carrier_frequency 38000
sample_count 4
+650,25
-2600
+600,23
-450
...

The Arduino sketch can be easily changed to output that indeed.
Back to top
View user's profile Send private message
cauer29



Joined: 03 Feb 2010
Posts: 236

                    
PostPosted: Sun Aug 12, 2012 9:02 pm    Post subject: Reply with quote

Ideally you should use a raw IR sensor rather than a demod version like the TSOP series. The demod sensors are not all that accurate with respect to precise timing. That may or may not be critical. We have seen some protocols that require more precise timing than can be gotten from a TSOP. A raw IR sensor sees each individual pulse and does not make any assumption about the carrier frequency.

A.A.
Back to top
View user's profile Send private message
probono



Joined: 12 Aug 2012
Posts: 48

                    
PostPosted: Sat Aug 18, 2012 10:45 am    Post subject: Reply with quote

Indeed, I would prefer to see the individual pulses (in order to measure rather than to guess the carrier frequency).

What would be the best sensor to do this, and what circuit would you recommend to hook up to the Arduino's pins?
The QSE159 or an infrared LED used as the sensor?
Back to top
View user's profile Send private message
probono



Joined: 12 Aug 2012
Posts: 48

                    
PostPosted: Sat Aug 18, 2012 11:43 am    Post subject: Reply with quote

And here is the counterpart, a generic IR sender that receives IR timings over the serial line and outputs to an IR LED.

To switch PACE box (ruwido r-step 56 kHz protocol) on, send the following command over the serial line:
4,56,250,500,250,250,500,500,500,250,250,250,250,500,250,250,250,250,250,250,250,250,250,250, 250,250,250,250,250,250,250,250,500,500,500,250,250,500,250;
4 = "Send IR" command
56 = 56 kHz
Rest = "pulse on", "light off" timings in microseconds (starting with on)

Code:


/*

 irCommander
 by probono 2012-08-18
 
 Sends arbitrary infrared remote commands with the Arduino
 (independent of IR protocols, since using raw IR timing information)
 
 Tested with 38 kHz (Blaupunkt, NEC1) and 56 kHz (ruwido r-step) protocols
 
 To switch Blaupunkt TV (Grundig protocol) program 1 on, send the following command over the serial line:
 4,38,550,2600,550,550,500,500,600,500,550,500,550,500,550,550,500,550,500,550,550,500,550,20600,550,2600, 550,500,600,1000,550,550,550,500,1050,1050,550,500,550,550,500,550,500;
 4 = "Send IR" command
 38 = 38 kHz
 Rest = "pulse on", "light off" timings in microseconds (starting with on)
 
 To switch PACE box (ruwido r-step 56 kHz protocol) on, send the following command over the serial line:
 4,56,250,500,250,250,500,500,500,250,250,250,250,500,250,250,250,250,250,250,250,250,250,250,250,250,250, 250,250,250,250,250,500,500,500,250,250,500,250;
 
 */

#include <CmdMessenger.h> // https://github.com/dreamcat4/cmdmessenger - IMPORTANT: change "#define MESSENGERBUFFERSIZE 256" in CmdMessenger.h
#include <Streaming.h> // http://arduiniana.org/libraries/streaming/
#include <IRremote.h> // http://www.pjrc.com/teensy/td_libs_IRremote.html - IMPORTANT: change "#define _GAP 50000” in IRremoteInt.h

IRsend irsend;

char field_separator = ',';
char command_separator = ';';

CmdMessenger cmdMessenger = CmdMessenger(Serial, field_separator, command_separator);

enum
{
  kCOMM_ERROR    = 000,
  kACK           = 001,
  kARDUINO_READY = 002,
  kERR           = 003,
  kSEND_CMDS_END,
};

messengerCallbackFunction messengerCallbacks[] =
{
  sendraw // 4
};

void sendraw()
{
  Serial.println("");
  cmdMessenger.sendCmd(kACK,"sendraw cmd recieved"); // Increase MESSENGERBUFFERSIZE if we get "unknown message" instead
  unsigned int raw[60] = {
    '\0'    }; // Maximum 60 parts, increase if this is not enough
  int i = -1;
  int freq = 38; // The first part is the frequency in kHz
  while ( cmdMessenger.available() )
  {
    char buf[8] = {
      '\0'        };
    cmdMessenger.copyString(buf, 8);
    if(buf[0]){
      unsigned int part;
      // TODO: remove non-digit characters such as " ", "+", and "-"
      part = (unsigned int) atoi(buf);
      if (i > -1) {
        raw[i] = part;
      }
      else {
        freq = part;
      }
      i++;
    }
  }

  irsend.sendRaw(raw,sizeof(raw)/sizeof(int),freq);

  Serial.println("");
  Serial.print("Carrier frequency ");
  Serial.print(freq);
  Serial.println(" kHz;");

  for (int i=0; i<(sizeof(raw)/sizeof(int)); i++) {
    Serial.print((unsigned int)raw[i]);
    Serial.print(" ");
  }
  Serial.println("");   

  arduino_ready();
}

void arduino_ready()
{
  cmdMessenger.sendCmd(kACK,"Ready");
}

void unknownCmd()
{
  cmdMessenger.sendCmd(kERR,"Unknown command");
}

void attach_callbacks(messengerCallbackFunction* callbacks)
{
  int i = 0;
  int offset = kSEND_CMDS_END;
  while(callbacks[i])
  {
    cmdMessenger.attach(offset+i, callbacks[i]);
    i++;
  }
}

void setup()
{
  Serial.begin(9600);
  cmdMessenger.attach(kARDUINO_READY, arduino_ready);
  cmdMessenger.attach(unknownCmd);
  attach_callbacks(messengerCallbacks);
  arduino_ready();
}

void loop()
{
  cmdMessenger.feedinSerialData();
}


It should be pretty trivial to communicate with this device via software.
Back to top
View user's profile Send private message
Barf
Expert


Joined: 24 Oct 2008
Posts: 1402
Location: Munich, Germany

                    
PostPosted: Sat Aug 18, 2012 2:00 pm    Post subject: Reply with quote

Quote:
And here is the counterpart, a generic IR sender that receives IR timings over the serial line and outputs to an IR LED.

Cool. Should be straightforward, using e.g. the RXTX Java library, to access it from a program such as IrMaster. Using a TCP-socket instead of the serial port is probably not too hard ("left to the reader as an excercise"?).

Actually, your program sends an IR-Signal exactly once. What we need is a three part IR signal, one intro sequence always sent, a repeat sequence sent n times (n is a parameter given with the send command) or until a stop-command arrives, and finally an ending sequence sent after the repeats. (Comparatively seldom non-empty, and neither the Pronto form nor the GlobalCache supports it.) Correspondingly, we need a stop-ir command.

My Auduino Uno + Ethernet Shield has arrived; unfortunately I will not have time to play with it in the short time span.

Quote:
Indeed, I would prefer to see the individual pulses (in order to measure rather than to guess the carrier frequency).

You should check out the work of Kevin Timmerman, for example from this thread and the contained links.

There are some dedicated "IR Detectors" like the QSE159 you mentioned, but they seem to be almost impossible to locate these days. I did some googling, Vishay seem to have a replacement, e.g., TSMP58138, which also seems impossible to get (Mouser: no stock, order 850 of them and they deliver in 20 weeks if I recall correctly). The brand new TSMP72000 and TSMP600 are designed for 3d shutter glasses, but seem to be usable and available. Disadvantages: SMD-measures and somewhat high price. Kevin possibly knows more.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
probono



Joined: 12 Aug 2012
Posts: 48

                    
PostPosted: Sun Aug 19, 2012 9:09 am    Post subject: Reply with quote

Barf wrote:
Using a TCP-socket instead of the serial port is probably not too hard ("left to the reader as an excercise"?)

Maybe I'll try that once my Ethernet shield arrives, so far I am using my embedded debian box (to be replaced by a Raspberry Pi soon).

Barf wrote:
Actually, your program sends an IR-Signal exactly once. What we need is a three part IR signal, one intro sequence always sent, a repeat sequence sent n times (n is a parameter given with the send command) or until a stop-command arrives, and finally an ending sequence sent after the repeats. (Comparatively seldom non-empty, and neither the Pronto form nor the GlobalCache supports it.) Correspondingly, we need a stop-ir command.

My thought was that the firmware itself should be as generic as possible (protocol agnostic). I was thinking that the carrier frequency plus the on, off time durations are sufficient to describe any command in any protocol. So I would prefer the repetitions, stop codes etc. to be sent to the device from the software. Or do you think this is a bad idea?

Which of the existing serial gadgets has the simplest ("dumbest"?) interface, so that we could try to make a compatible Arduino drop-in replacement?

Barf wrote:
There are some dedicated "IR Detectors" like the QSE159 you mentioned, but they seem to be almost impossible to locate these days

Too bad. Maybe the Arduino is fast enough to detect the pulse length? Maybe we could use a IR LED as the sensor? After all, it is fast enough to generate even 56 kHz signals.

Next up: A way to power "high power" IR LEDs so that I can operate all devices in the room.
Back to top
View user's profile Send private message
Barf
Expert


Joined: 24 Oct 2008
Posts: 1402
Location: Munich, Germany

                    
PostPosted: Sun Aug 19, 2012 2:29 pm    Post subject: Reply with quote

Quote:
My thought was that the firmware itself should be as generic as possible (protocol agnostic). I was thinking that the carrier frequency plus the on, off time durations are sufficient to describe any command in any protocol. So I would prefer the repetitions, stop codes etc. to be sent to the device from the software. Or do you think this is a bad idea?

How about the use case when the user presses a repeating button, say Vol+, and intends to keep it pressed until the desired volume (of his TV/Amplifier/whatever) has been reached, and then release it? If you study the API of GlobalCache, LIRC, IrTrans, you will see that all implement repeats, GC implements a stopir command, LIRC implements it but quite silly (I have submitted a patch, but it seems not to have made it), IrTrans does not implement it at all (AFAIK). There is no way to know in advance how many repetitions are needed.

Quote:
Which of the existing serial gadgets has the simplest ("dumbest"?) interface, so that we could try to make a compatible Arduino drop-in replacement?

I am not sure I understand that question. I think it is reasonable to distinguish between two use cases: No a priori knowledge. Then probably a Kevin-type receiver is a good bet. Some a priori knowledge, e.g. protocol roughly known. Then a suitable demodulator (not universal!) is probably just as good as anything.

But the "learning" usecase is overrated anyhow, in particular in "Logitech-like" communities. In principle, we need just one person to decode the commands, then upload it to some sensible data base. In theory.... ... Wink
Back to top
View user's profile Send private message Send e-mail Visit poster's website
cauer29



Joined: 03 Feb 2010
Posts: 236

                    
PostPosted: Sun Aug 19, 2012 4:33 pm    Post subject: Reply with quote

Barf wrote:

There are some dedicated "IR Detectors" like the QSE159 you mentioned, but they seem to be almost impossible to locate these days. I did some googling, Vishay seem to have a replacement, e.g., TSMP58138, which also seems impossible to get (Mouser: no stock, order 850 of them and they deliver in 20 weeks if I recall correctly). The brand new TSMP72000 and TSMP600 are designed for 3d shutter glasses, but seem to be usable and available. Disadvantages: SMD-measures and somewhat high price. Kevin possibly knows more.


On the first try, I located only 29,288 QSE159s ready for immediate shipment:

http://www.digikey.com/product-search/en?lang=en&site=us&KeyWords=QSE159

A.A.
Back to top
View user's profile Send private message
probono



Joined: 12 Aug 2012
Posts: 48

                    
PostPosted: Sun Sep 02, 2012 12:58 pm    Post subject: Reply with quote

Simplified sketch for sending.

This time without using any IR library.

Code:
/*
# Blaupunkt TV ch- (works)
send 38 550 2600 550 500 550 500 600 500 550 500 550 500 550 550 500 550 500 550 550 500 550 20600 550 2600 550 550 550 450 600 1050 1050 1050 1050 1050 550 500 550 550 500
*/

#include <SerialCommand.h> // #define SERIALCOMMAND_BUFFER 256 - 512 erratic on ATMega168, works with ATMega368

SerialCommand sCmd;

int IRledPin = 8;

void pulseIR(int freq, long microsecs) {
  unsigned int delayTime = (1000/freq/2)-3;
  cli();  // this turns off any background interrupts
  while (microsecs > 0) {
    digitalWrite(IRledPin, HIGH);  // takes about 3 microseconds
    delayMicroseconds(delayTime);
    digitalWrite(IRledPin, LOW);   // takes about 3 microseconds
    delayMicroseconds(delayTime);
    microsecs -= (2*delayTime)+6;
  }
  sei();  // this turns them back on
}

void sendCode() {
  long aNumber;
  char *arg;
  unsigned int raw[128] = {
    '\0'                      }; // increase if this is not enough
  int i = 0;
  int freq = 0;
  while(1){
    arg = sCmd.next();
    if (arg != NULL) {
      if (i==0)  freq = atoi(arg);
      else raw[i-1] = atoi(arg);
      i++;
    }
    else {
      break;
    }
  }

  Serial.print("Length: ");
  Serial.print(i-2);
  Serial.println(" parts");
  Serial.print("Frequency: ");
  Serial.print(freq);
  Serial.println(" kHz");

  for (int n=0; n<(i-1); n++) {
    if(n % 2 == 0) {
      pulseIR(freq, raw[n]);
    }
    else {
      delayMicroseconds(raw[n]);
    }
  }

  Serial.print("Sequence:");
  for (int n=0; n<(i-1); n++) {
    if(n % 2 == 0) Serial.print(" +");
    else Serial.print(" -");
    Serial.print(raw[n]);
  } 
  Serial.println(" ");
  Serial.println("OK");
}

void unrecognized(const char *command) {
  Serial.println("What?");
  Serial.println("OK");
}

void setup() {
  pinMode(IRledPin, OUTPUT);
  digitalWrite(IRledPin, LOW);
  Serial.begin(56700);
  sCmd.addCommand("send", sendCode);
  sCmd.setDefaultHandler(unrecognized);
  Serial.println("Ready");
}

void loop() {
  sCmd.readSerial();
}
Back to top
View user's profile Send private message
Barf
Expert


Joined: 24 Oct 2008
Posts: 1402
Location: Munich, Germany

                    
PostPosted: Wed Sep 05, 2012 2:05 pm    Post subject: Reply with quote

Cool. Razz I wish I soon get some time to play with my new Arduino, which has not yet seen electrical power... Embarassed

Have you, or someone considered calling it from LIRC? Not that I am in love with LIRC (I am not!) but there is a hardware "API" so that if you have a LIRC (send- and/or receive) driver your stuff will be more readily usable. Like supporting the mode2 LIRC interface for receiving? For example, I would be interesting in supporting more hardware from IrMaster, but I am reluctant to write n drivers for n different pieces of hardware.
Back to top
View user's profile Send private message Send e-mail Visit poster's website
probono



Joined: 12 Aug 2012
Posts: 48

                    
PostPosted: Sat Sep 08, 2012 3:08 am    Post subject: Reply with quote

Yes, I thought about that briefly, but LIRC seems to be additional unneeded overhead. Also I read on http://www.harctoolbox.org/lirc_ccf.html that LIRC doesn't send arbitrary commands "out of the box", and I am pretty much interested in sending arbitrary commands from the software.

As for the receiving, I would probably go down this route
http://forums.adafruit.com/viewtopic.php?t=4890
using an IR LED as the receiver, in order to be able to measure the frequency.
Back to top
View user's profile Send private message
probono



Joined: 12 Aug 2012
Posts: 48

                    
PostPosted: Sat Sep 15, 2012 3:10 pm    Post subject: Reply with quote

http://imageshack.us/photo/my-images/19/img01373201209152153.jpg/
This is an ultra-cheap (significantly under 10 USD) bare-bones selfmade Arduino replacement:
  • Mini Breadboard
  • Prolific USB to Serial adapter with connector cable (betemcu.cn)
  • ATmega168 microcontroller with Arduino LilyPad bootloader
  • IR LED
The parts can be ordered from China on eBay.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic       JP1 Remotes Forum Index -> JP1 - Software All times are GMT - 5 Hours
Goto page 1, 2, 3, 4, 5  Next
Page 1 of 5

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


 

Powered by phpBB © 2001, 2005 phpBB Group
Top 7 Advantages of Playing Online Slots The Evolution of Remote Control