Reading IR signals.. Arduino is too SLOW??

To 1: On many comments of people.

Such as? I'm willing to bet you don't have anywhere near the qualifications to evaluate their validity of the comments these people are making. My guess is that your statement is based on the naive assumption that if you can buy a more powerful microcontroller than the mega168 from digikey for a few dollars more, that means you could easily make an Arduino around it for a few dollars more?

To 2: It seemed that on the net are good documentations on arduino, and as a beginner project it seemed appropriate.

It is appropriate for a beginner project. What you are asking for would not be. People getting started in microcontrollers don't need huge code space.

Look at it this way: you don't buy bicycle and then complain that you can't use it to go 80 mph down the highway. If you want an inexpensive, easy way to get around without walking, you buy a bike. If you want to go 80 mph down the highway, you buy a car. You definitely don't get pissed at the bicycle makers for not making cars. You picked the product you thought would serve your needs best. If you made the wrong choice, you have no one to blame but yourself. Don't try to make yourself feel better by playing the victim and saying that the Arduino sucks; the Arduino is great when used within its intended scope.

To 3:
Why should I need delays? pulseIn itself "has a delay", or not?
Edit: Well it works, somehow. But do not quite understand it yet...

How should I know why you need delays? This is where you actually go and troubleshoot your own application. Maybe there's a bug in pulseIn(), but that's hardly a reason to condemn the Arduino hardware or mega168 in general. More likely, you have no real understanding of how to use pulseIn() properly, and I'm guessing you don't really understand how your IR receiver works, either.

At any rate, you seem to be quite quick to blame everything but yourself for the problems you're having, which is a terrible attitude to have when you're trying to learn how to do something. You should approach things with an open mind and an attitude of "what am I doing wrong/how can I make this work" rather than "why doesn't this work, it must be broken/defective". If you had the former attitude I'd be much more likely to actually care about your problem and devote some time to trying to figure it out.

  • Ben

To 1: On many comments of people.

Such as? I'm willing to bet you don't have anywhere near the qualifications to evaluate their validity of the comments these people are making. My guess is that your statement is based on the naive assumption that if you can buy a more powerful microcontroller than the mega168 from digikey for a few dollars more, that means you could easily make an Arduino around it for a few dollars more?

Well...that point is technically valid. There's no actual reason the Wiring board (based on ATmega128) should cost 3 times more than a Diecimila. 10 bucks more for the chip, 5 bucks more for the extra PCB and headers, maybe. And the ATmega64 is only 3 more dollars and give you 64K of program space instead of 16K. Not really a big deal, I guess. Most people wanting more storage or power are fully capable of making their own board and using the normal development tools instead of Arduino. The Arduino team is just making things easy to use, not trying to hide the fact that more powerful microcontrollers are out there, or that most things done with an Arduino could be done with a $1.50 ATtiny.

How should I know why you need delays? This is where you actually go and troubleshoot your own application. Maybe there's a bug in pulseIn(), but that's hardly a reason to condemn the Arduino hardware or mega168 in general. More likely, you have no real understanding of how to use pulseIn() properly, and I'm guessing you don't really understand how your IR receiver works, either.

At any rate, you seem to be quite quick to blame everything but yourself for the problems you're having, which is a terrible attitude to have when you're trying to learn how to do something. You should approach things with an open mind and an attitude of "what am I doing wrong/how can I make this work" rather than "why doesn't this work, it must be broken/defective". If you had the former attitude I'd be much more likely to actually care about your problem and devote some time to trying to figure it out.

A few months ago, I did more-or-less what he seems to be trying to do. I got some IR remotes from a trivia game, reverse engineered their coding scheme and built a receiver for them to act like a jeopardy-style buzzer around the arduino.

I have a pretty good idea what he's trying to do, I used pulse-in statements in a similar way, it took me a while to get it working (I went through the stage where it looked like random pulses too). But I stuck with it and figured out what was going on.

His posts show a total ignorance of IR communication and embedded hardware, which alone is excusable and normally I'd be happy to explain it to him, but with his rude attitude, I just don't see why we should bother. All he's doing here is insulting the platform and the people who are taking the time to try and help him. He doesn't want to learn, he's so sure he's right he just want to complain.

As far as speed, the ATMEGA168 is many, many times more powerful than you need to read and decode IR signals. As far as processing power, my receive and decode functions take a couple of hundred bytes of program memory and maybe 10 bytes of working memory. Arduino gives you 14kB of program memory, so I really don't see the problem.

Fwiw, I've wanted a ATMEGA128 based Arduino for ages, but it has nothing to do with this post. You need 1 IO line for the IR module, and code space is not an issue for something this simple.

Here is what I've been using for Sony remotes. It works fine.
Perhaps there's something else to learn in it. :sunglasses:

int getIRKey() { // used by get_remote() reads IR & converts Sony keys *V2* 
  int duration, irCode, mask;
  do {                                 // wait for start bit
    duration = pulseIn(ir_pin, LOW);
  } 
  while (duration < 2160 || duration > 2640);//Wait for a start bit look for
  irCode = 0;                        //  2200ms pulse.
  mask = 1;                        // set mask to bit 0
  for (int idx = 0; idx < 7; idx++) {      // get only 7 of the 12 bits
    duration = pulseIn(ir_pin, LOW);   // measure the bit pulse
    if (duration >= 1080)             // > 1000uS it is a 1
      irCode |= mask;                     // yes, update ir code
    mask <<= 1;                             // shift mask to next bit
  }
  irCode = irCode +1;                  // convert raw return to actual digit values
  if (irCode == 10) irCode = 0;        // special case for zero key
  return irCode;
}

BTW PulseIn now has a timeout escape which was not used in the above.

By the way, I'm not in any way opposed to the idea of a more powerful Arduino, such as one based on a mega644 or 128, but I think it's fairly disrespectful to the Arduino team to claim that they could easily produce one for $5 more. Supporting a significantly different microcontroller with the Arduino environment would not be a trivial undertaking, nor would routing an entirely new board capable of providing convenient access to the larger number of I/O lines and hardware peripherals (e.g. the mega644 has 12 more digital I/O lines than the mega168 if you are using an external crystal). The board would need to be bigger with more headers, which would mean greater production and component costs, and I think it would be quite difficult (if not impossible) to make the board compatible with existing shields. If you want to be able to offer compelling pricing to distributors, you basically need to retail at quadruple your costs, so you'd probably be looking at something like a $15 - $20 increase at a minimum to go along with quite a bit of design and support work.

In short, I think people need to show some respect for the complexity of the processes used to create these things that are often taken for granted. Any time you find yourself asking "hey, why don't they just do ...", you probably need a reality check. People much more knowledgeable than you have probably already considered your idea and most likely have a very good reason for not acting on it. I'm not saying you shouldn't wonder why something is the way it is, nor am I saying that you might come up with an idea that others haven't yet considered, I'm just saying you should not have an air of "man, these guys are so stupid for doing it this way when it would be so easy for them to do it better."

This kind of thing reminds me of a story I heard about a conversation between a friend and one of his acquantances. They were standing near a monorail track and the acquantance said, "those tracks are so ugly, why don't they just remove every other post so that the tracks are less intrusive on the scenery?" This shows a startling lack of respect for the engineers who built the tracks. Furthermore, it shows a lack of respect for the physics involved in suspending a many-ton rail and train above the earth. You can't just knock out every other support and expect that the system will be just fine! These complex devices and structures we see around us aren't magical; they operate according to very real and restrictive constraints that need to be balanced. You have to trade performance in one area to boost it in another. In the end you select those features that arrive at what you think to be the best balance.

  • Ben

The only person I can thank for his or her post is BroHogan.
Thank you very much. But I already got it working with Sony Ir Remotes. Because their "HIGH" and "LOW" values differ very much from each other.
But I am trying to use a small IR Remote Control (RM-1500) from Creative. It values if I use Serial.print() are 200 to 400 for LOW values, and 650 to 710 for HIGH values.

I was under the assumption:
that pulsein() waits until the signal changes from HIGH to LOW.
so if I have a loop:
for(){ pulsein(); OTHERCODE }
And the value returned from pulsein() is higher than it is supposed to be, the "OTHERCODE" had to delay the processing that the very short signals could not be detected because they already went trough the ir receiver without pulling their value with pulsein() or the other way around. (vice versa)

It would be great if someone could tell me why it's working with sony ir remotes and not with this ir remote. It really seemed for me because the pulses are much shorter arduino can not handle them. As a beginner to microcontroller I think this is an valid conclusion. Maybe wrong, but comprehendable.

AND:
It IS very easy to say that it's my fault. It's the very same case with my statement of arduino being better if spending 5 bucks more on it and you claiming otherwise and claiming that it is unfounded. Your statements are untill now also UNFOUNDED!!
I am not expecting a working code example just an explanation why it does not work the way I want it to work.

EDIT:
I searched the forum again and I found not code example containing a delay(). Why? Becaus all of them use an ir remote with long pulses, and only I one with very short pulses. And arduino has a bug? being not able to deal with these kind of ir remotes?

Even the code from David Cuartielles (http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1176098434) does not work. All values are about 670. I know that there a different protocols, but still I have to be able to receive all signals as they are? Unchanged? Like a bitstream from a pc, without knowing the decoding scheme, but still I get everytime the same bitstream. This has to be possible too with ir signals...

At any rate, you seem to be quite quick to blame everything but yourself for the problems you're having, which is a terrible attitude to have when you're trying to learn how to do something. You should approach things with an open mind and an attitude of "what am I doing wrong/how can I make this work" rather than "why doesn't this work, it must be broken/defective". If you had the former attitude I'd be much more likely to actually care about your problem and devote some time to trying to figure it out.

  • Ben

Amen :slight_smile:

Seems like the admin itself can't figure it out... very sad :cry:

I hope you can PROVE me WRONG....

Nobody did it yet. I am trying to debug it for hours, and you all claim to know the solution but still won't share it with me or people who eventually will face the same problem. I uploaded over 50 times different code trying to solve this bug. Soon my arduino won't work anymore I fear. Because you only can upload x000 times your code and then it's over, isn't it?

US Style Disclaimer: This is my own opinion and does not reflect the opinion of the Arduino project in any form or shape

Dear the millennium

The nice thing about an open source project is that I get to decide how much effort I put in replying to people.
Attitude is a big factor , IMHO, in getting help from people.
On one hand you're a beginner and on the other hand you start complaining before you even start explaining your problem

is it a work related problem? you can hire somebody here to help you
is it a school project? you should have a tutor at school that can help you.
is it your personal project? be nice and the answer will be handed to you on a silver plate.

If you tell us where in the world you live we might be able to point you to some people locally that can help you.

Less whining and more working...

massimo

Reading my first post again I realise that I started off in a wrong direction. And I am sorry for that.

But I was so frustrated. I tried to debug the problem for 5-6 hours. I am a person who does not like asking other people for help. The more disappointed was I when noone understood my frustration and only showing me cold shoulders and accusing me of criticizing in a moment of frust their "holy" arduino board. Arduino is a very nice microcontroller you can get started easily. But only trying to figure out which ir signals each of the buttons on the creative rm-1500 ir remote control sends, so that I can detect if Button 1, Button 2, or the Volume Buttons, or Play Button was pressed and then start a specific function (switching a LED on,...) .... does not work untill now (except for my sony ir remote) and I am spending more than 10 hours on it without any kind of success....
If I knew the protocol which creative uses for their ir remotes it would be a piece of cake, i just wait for the start signal, wait the starttime (from the protocol) and then read every "specific time" (also from the protocol) with digitalread() if the value is 1 or 0.

But I can't figure out how to receive the ir signals as they are to be able to find out what the start time and the "specific time" is. Or how it is decoded in general. So far I only know with certainty that the start bit is about 9000 microseconds long)

Arduino is not holy

Arduino gets you started really quickly, the problem is that some user might mistakely think they magically became electronics engineers overnight... this is not the case with any discipline..

The Arduino approach is: "I have to work on a IR remote project and I am not an expert prorgrammer of micrcontroller then I google the playground and look for work by somebody else (there is a lot) and pick one of those remotes"

In your case what you need is to use an digital oscilloscope to measure the pulses and make sure you understand the protocol very well. (documentation is always misleading)

then you read all about the timers and the interrupts on the avr chip, this gives you the solution you need. it's all in the datasheets.

People have implemented the whole USB protocol in the same microcontroller that arduino uses and it works beautifully... they slice and dice 1.5 million bits per second all in software... Christian Starkjohann is clearly a jenius but it demonstates everything can be done..

massimo

If I knew the protocol which creative uses for their ir remotes it would be a piece of cake, i just wait for the start signal, wait the starttime (from the protocol) and then read every "specific time" (also from the protocol) with digitalread() if the value is 1 or 0.

You could figure out the protocol quite easily with an oscilloscope, though in my case I just used the Arduino since it's relatively simple to do looking at pulse times, and I was dealing with a very simple protocol. But it's not enough to just look at the low pulses as you seem to do be doing.

And once you understand the protocol, you absolutely do not want to use digitalRead() to see what the input is, you will still use pulseIn. Again, you are completely misunderstanding how to do IR, and as a hint it is tied into why you seem to think you're getting random numbers.

It's REALLY important to know what the protocol is. They vary a lot. Sometimes you have the bits encoded in the length of pulses, other times you have the bits encoded as the time between pulses (and all the pulses are the same length). There are protocols that look at rising and falling edges depending on preceding bits.

Check this site for an explanation of a lot of IR remote protocols: http://www.sbprojects.com/knowledge/ir/ir.htm

only showing me cold shoulders and accusing me of criticizing in a moment of frust their "holy" arduino board

You should note that I've never even used an Arduino, so it most certainly isn't "holy" to me, and comments like this further justify my initial assessment of your poor attitude. My entire issue is your attitude, which sucks, and the unfounded assumptions you were willing to make to justify your problems (e.g. "the Arduino is too slow"). Frustration is not an excuse to ask for help in the manner you did, at least not if you expect people to actually want to help you. It causes you to come off as somewhat whiny, lazy (e.g. it's easy to compute how fast the mega168 can carry out instructions), and petulant, and it makes it seem like you are not looking for a solution but rather for someone to help you assign blame. In general, if you're going to ask people to take their time to help you with your problem, show some respect, humility, appreciation, and desire to get to the root of the problem. Otherwise exactly what incentive to people have to drop what they're doing to try to learn what they need to know to understand your project better than you?

I truly believe this is a case of your calling working code faulty for not conforming with an erroneous assumption about the protocol of your IR device. You were willing to make incorrect assumptions about the mega168, which makes it not unreasonable to think you are doing the same with other components of your device. If you want to really test your program and you suspect that pulseIn() isn't working, write your own pulse-measuring routine (it's not hard). Ideally, do as Massimo and Oracle suggested and look at the signal with an oscilloscope to see what's really going on and how that correlates to what you measure with your Arduino.

And note that I didn't suggest that adding delays would make things work, I only pointed out that the case you said worked was special in that it had long delays built into the loop. I believe the case you assumed was working was in fact not, and the cases you thought weren't working in fact were. My exact words were that you should try adding delays to see if it made things work in the way you expected, which is not the same as saying it would make things work correctly.

  • Ben

TheMillenium:

You could take a look at this info in Arduino Playground. Using this program and gnuprot you could find out how your remote control encodes information.

gnuprot

I assume you mean gnuplot, just in case the OP wants to Google it? :slight_smile:

--Phil.

Yes Phil, you are right. It is gnuplot.

Let's get back to the original question... You have a IR remote control that speaks an unknown protocol, and have been unsuccessful decoding it (or, detecting differences between the buttons?) using assorted combinations of pulseIn() function. You spent a long time trying different things, mostly based on the assumption that the Arduino was too slow to get correct results in your previous attempt... So:

  • The arduino is NOT too slow to do this, and in particular, array index addressing is quite fast. I know it can be particularly frustrating to have spent a lot of time chasing the wrong bug, but it happens, and you need to start over too.
  • You said that the example that used Serial.Print() was "working", while I and a number of other posters have mentioned that Serial.Print() introduces long and somewhat variable delays into your code (on the order of 1ms per output character at 9600bps) What exactly is your definition of "working" here? You seem to expect relatively short pulses (<400us), but elsewhere you say you're not sure what the protocol is. Is it just that the serial-printing code gave you variability of timing, while the array-based code didn't?
  • Aside from the Sony Protocol, the most common IR protocol is Philips RC5 protocol, which you seem to be expecting based on the size of your arrays, but it uses a basic bit time of 1778 us, (always half high and half low, with the direction of change indicating 0 or 1), so I'm not sure why you're expecting short pulses. For that matter, it's not clear to me that measuring pulse durations for only high or low state is very helpful for decoding RC5...
  • The first step is to get a better picture of what the protocol actually looks like. It seems you tried to do that with your Serial.print() code, but perhaps were led astray by the delays introduced by serial.print. Start over storing pulse times in an array, and measuring both high and low times. (I checked, pulseIn(x,LOW) WILL measure the remaining time if the pin is already low, so you should be able to get to reasonable places with code similar to that shown below, though I haven't actually tried it.) There will be errors introduced by the start of function and such, but they should be small compared to the multi-hundred us pulse times expected for most IR protocols.
  • I saw an interesting scheme for IR decoding suggested once that consisted essentially of sampling for a certain amount of time at a certain sample interval known to me much smaller than the bit times involved, and calculating a CRC-like value from the samples. You don't necessarily need to know what the format is to recognize just a few distinct keys, and it takes very little storage...
for (i=0; i<50; i+=2) {
  times[i] = pulsein(pin, LOW, 5000);
  if (times[i] ==0) break;
  times[i+1]=pusein(pin, HIGH,5000);
  if (times[i+1] ==0) break;
}
for (i=0; i<50; i++) {
  Serial.println(times[i]);
     if (times[i] ==0) break;
}