Increasing declared variable makes the code hang ? (IR receiver)

am trying to read the IR pulses from a Pioneer IR remote.
the code already works (for the most part) with another simpler remote but wasn’t getting consistent results leading me to believe (perhaps wrongly) that it was “just a cheap component”.

i had already established connection with this Pioneer remote and read it’s pulses properly, except i realised it was sending longer pulses, 70+ compared with the 36-40 of the previous remote.

so i’m thinking i “just” have to increase the number of NUMPULSES from 50 to 70 and it should work, right ?

it doesn’t - the code hangs, and almost always never even gets past the setup() section, when it does it prints;

H³ªV?åto decode IR!

instead of

Ready to decode IR!

any idea what i’m doing wrong ?

or what part of the code is “unhappy” with 50 becoming 70 - i can’t figure out why that should be, unless there’s some limitation that has been breached.

okay then, here’s the code !

/* Raw IR commander
 
 This sketch/program uses the Arduno and a PNA4602 to decode IR received. 
 It then attempts to match it to a previously recorded IR signal
 Code is public domain, check out www.ladyada.net and adafruit.com for more tutorials! 
*/

// We need to use the 'raw' pin reading methods
// because timing is very important here
// and the digitalRead() procedure is slower!
//uint8_t IRpin = 2;
// Digital pin #2 is the same as Pin D2 see
// http://arduino.cc/en/Hacking/PinMapping168 for the 'raw' pin mapping
#define IRpin_PIN      PIND
#define IRpin          2

// the maximum pulse we'll listen for - 65 milliseconds is a long time
#define MAXPULSE 65000
//#define NUMPULSES 50 (need to increase for Pioneer remote)
//                     BUT WHY IT FAILS TO WORK THEN !! ??
#define NUMPULSES 70

// what our timing resolution should be, 
// larger is better as its more 'precise' 
// - but too large and you wont get accurate timing
#define RESOLUTION 20 

// What percent we will allow in variation to match the same code
#define FUZZINESS 20

// we will store up to 100 pulse pairs (this is -a lot-) 
uint16_t pulses[NUMPULSES][2];  // pair is high and low pulse 
uint8_t currentpulse = 0; // index for pulses we're storing

#include "ircodes.h"

// to switch DEBUG mode on(1) or off (0)
//#define DEBUG // it's not boolean, it's whether defined AT ALL !

void setup() {
  Serial.begin(9600);
  Serial.println("Ready to decode IR!");
}

void loop() {
//  int numberpulses;  
  //numberpulses = listenForIR();
    int numberpulses = listenForIR();

  Serial.print("Heard ");
  Serial.print(numberpulses);
  Serial.println("-pulse long IR signal");
  
  if (IRcompare(numberpulses, pioneerUP,sizeof(pioneerUP))) {
    Serial.println("UP");
  }
  else if (IRcompare(numberpulses, pioneerDN,sizeof(pioneerDN))) {
    Serial.println("DOWN");
  }
  else if (IRcompare(numberpulses, pioneerLF,sizeof(pioneerLF))) {
    Serial.println("LEFT");
  }
  else if (IRcompare(numberpulses, pioneerRT,sizeof(pioneerRT))) {
    Serial.println("RIGHT");
  }
  else if (IRcompare(numberpulses, pioneerSTOP,sizeof(pioneerSTOP))) {
    Serial.println("STOP");
  }
  else  {
    Serial.println("Code NOT recognised");
  }
  delay(500);
}

//KGO: added size of compare sample. Only compare the minimum of the two
  
boolean IRcompare(int numpulses, int Signal[], int refsize) {
  int count = min(numpulses,refsize);
  Serial.println("");  // should just use ESC code in the next line ! forgot what tho : \n ??
  Serial.print("ENTERingIRcompareFUNC=> count set to: ");
  Serial.println(count);
  for (int i=0; i< count-1; i++) {
    int oncode = pulses[i][1] * RESOLUTION / 10;
    int offcode = pulses[i+1][0] * RESOLUTION / 10;
    
#ifdef DEBUG    
    Serial.print(oncode); // the ON signal we heard
    Serial.print(" - ");
    Serial.print(Signal[i*2 + 0]); // the ON signal we want 
#endif   
    
    // check to make sure the error is less than FUZZINESS percent
    if ( abs(oncode - Signal[i*2 + 0]) <= (Signal[i*2 + 0] * FUZZINESS / 100)) {
#ifdef DEBUG
      Serial.print(" (ok)");
#endif
    } else {
#ifdef DEBUG
      Serial.print(" (x)");
#endif
      Serial.print("Variance in ON");
      // we didn't match perfectly, return a false match
      return false;
    }
        
#ifdef DEBUG
    Serial.print("  \t"); // tab
    Serial.print(offcode); // the OFF signal we heard
    Serial.print(" - ");
    Serial.print(Signal[i*2 + 1]); // the OFF signal we want 
#endif    
    
    if ( abs(offcode - Signal[i*2 + 1]) <= (Signal[i*2 + 1] * FUZZINESS / 100)) {
#ifdef DEBUG
      Serial.print(" (ok)");
#endif
    } else {
#ifdef DEBUG
      Serial.print(" (x)");
#endif
      Serial.print("Variance in OFF");
      // we didn't match perfectly, return a false match
      return false;
    }
    
#ifdef DEBUG
    Serial.println();
#endif
  }
  // Everything matched!
  return true;
}

int listenForIR(void) {
  currentpulse = 0;
  
  while (1) {
    uint16_t highpulse, lowpulse;  // temporary storage timing
    highpulse = lowpulse = 0; // start out with no pulse length
  
//  while (digitalRead(IRpin)) { // this is too slow!
    while (IRpin_PIN & (1 << IRpin)) {
       // pin is still HIGH

       // count off another few microseconds
       highpulse++;
       delayMicroseconds(RESOLUTION);

       // If the pulse is too long, we 'timed out' - either nothing
       // was received or the code is finished, so print what
       // we've grabbed so far, and then reset
       
       // KGO: Added check for end of receive buffer    ME: REMOVED - revert to Original Tutorial code - AND THEN REVERTED coz DIDN'T WORK !!
       if (((highpulse >= MAXPULSE) && (currentpulse != 0))|| currentpulse == NUMPULSES)  {
       //if ((highpulse >= MAXPULSE) && (currentpulse != 0))  {
         return currentpulse;
       }
    }
    // we didn't time out so lets stash the reading
    pulses[currentpulse][0] = highpulse;
  
    // same as above
    while (! (IRpin_PIN & _BV(IRpin))) {
       // pin is still LOW
       lowpulse++;
       delayMicroseconds(RESOLUTION);
        // KGO: Added check for end of receive buffer  ME: same as above for 'highpulse'
        if (((lowpulse >= MAXPULSE)  && (currentpulse != 0))|| currentpulse == NUMPULSES) {
        //if ((lowpulse >= MAXPULSE) && (currentpulse != 0))  {
         return currentpulse;
       }
    }
    pulses[currentpulse][1] = lowpulse;

    // we read one high-low pulse successfully, continue!
    currentpulse++;
  }
}

and a sample array which is in ircodes.h

/*********** THE codes ***********/

 
int pioneerUP[] = {	   
// ON, OFF (in 10's of microseconds) 
838,416,	   
50,158,	   
56,152,	   
52,52,	   
52,52,	   
50,52,	   
54,156,	   
50,54,	   
52,156,	   
52,50,	   
54,52,	   
52,154,	   
54,156,	   
52,156,	   
54,52,	   
52,154,	   
54,52,	   
54,152,	   
54,52,	   
50,52,	   
52,158,	   
50,158,	   
52,52,	   
50,52,	   
54,156,	   
50,52,	   
54,156,	   
52,156,	   
54,50,	   
52,50,	   
54,156,	   
52,156,	   
54,52,	   
50,2496,	   
832,420,	   
50,156,	   
54,154,	   
54,156,	   
52,156,	   
52,52,	   
52,156,	   
54,52,	   
50,156,	   
54,52,	   
50,52,	   
52,52,	   
54,50,	   
52,156,	   
54,50,	   
52,156,	   
54,52,	   
50,52,	   
52,158,	   
50,52,	   
52,52,	   
54,154,	   
54,156,	   
50,158,	   
52,156,	   
52,156,	   
52,52,	   
52,158,	   
50,156,	   
54,52,	   
50,52,	   
52,52,	   
54,50,	   
52,0};

could a faulty IR-receiver also be a possible cause ?

i did already try the shiriff IRremote-library but was getting inconsistent feedback, which is why i ended up trying the Adafruit way, a bit more complex but a lot more learned in the process !

for what it’s worth, with the shiriff Library “IRrecvDemo” i got extraneous data like;

FD8877
FFFFFFFF
FFFFFFFF
FFFFFFFF
6F5974BD
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
FFFFFFFF
6F5974BD
FFFFFFFF

and

DEE522C1
FFFFFFFF
DEE522C1
FD08F7
DEE522C1
FD08F7
FFFFFFFF
FD
FFFFFFFF
FD
FFFFFFFF

the HEX codes in Blue being the relevant ones.
could that indicate faulty hardware ?

Look at where the name that you changed the associated value for is used:

// we will store up to 100 pulse pairs (this is -a lot-) 
uint16_t pulses[NUMPULSES][2];  // pair is high and low pulse

You’ve gone from 100 2 byte values to 280 bytes. Given that the Arduino only has 2048 bytes of SRAM, it is likely that you’ve now used more than that.

  Serial.println("Ready to decode IR!");

This string literal also takes space (unnecessarily) in SRAM.

Serial.println(F(“Ready to decode IR!”));
This string literal does not. Hey, there’s 17 bytes freed.

  Serial.print("Heard ");
  Serial.println("-pulse long IR signal");

More opportunities…

And there are plenty more after that.

hello again, Paul.

thanks for the tip on the F() macro, i've seen a few threads mention them - will study it to see the savings.

looks like my initial thread was on the right track, it was an issue with the variable uint16_t which i'm still not quite familiar with.

PaulS:
Look at where the name that you changed the associated value for is used:

// we will store up to 100 pulse pairs (this is -a lot-) 

uint16_t pulses[NUMPULSES][2];  // pair is high and low pulse



You've gone from 100 2 byte values to 280 bytes. Given that the Arduino only has 2048 bytes of SRAM, it is likely that you've now used more than that.

a bit more slowly please - 100 2 bytes = 200 bytes ?
and now, you're saying it's 280 bytes... total ?

how do i know what uses up that 2048 bytes, the code gets compiled to more than that in many cases.

could you point me to a good reference on SRAM usage ?

this is starting to go away from Arduino - Home isn't it ?
looks like i have to start venturing out of the newbie backyard....

a bit more slowly please

50 * 2 = 100
100 * 2 = 200

70 * 2 = 140
140 * 2 = 280

A uint16_t is two bytes.

how do i know what uses up that 2048 bytes

Lots of things do. The stack. The heap. All of your variables. All of your string literals (unless wrapped by the F() macro). All the variables used by other classes that you use.

You can use the tips/techniques here to see how much memory you are not using:
http://playground.arduino.cc/Code/AvailableMemory

this is starting to go away from Arduino - Home isn't it ?
looks like i have to start venturing out of the newbie backyard....

That covers the sharp point on the tip of the iceberg.

PaulS:

a bit more slowly please

50 * 2 = 100
100 * 2 = 200

70 * 2 = 140
140 * 2 = 280

A uint16_t is two bytes.

ok, so that's "only" a difference of 80 bytes.
or, almost a 50% increase in usage, and 3% alone of the 2K of SRAM.

it does seen quite a big jump from byte to int.
2^8=256 to 2^16=65536
if we know the value range won't go past 10 or 11-bits, is there no other (more efficient) data type one could use ?

PaulS:

how do i know what uses up that 2048 bytes

Lots of things do. The stack. The heap. All of your variables. All of your string literals (unless wrapped by the F() macro). All the variables used by other classes that you use.

You can use the tips/techniques here to see how much memory you are not using:
Arduino Playground - AvailableMemory

this is starting to go away from Arduino - Home isn't it ?
looks like i have to start venturing out of the newbie backyard....

That covers the sharp point on the tip of the iceberg.

thanks for that link, i think i'm ready to "get into that".

i discovered(!) the Foundations page http://arduino.cc/en/Tutorial/Foundations and really should've grasped that fully first.
as it happens, there were just the two items on that page that i wasn't yet comfortable with, Memory and Libraries - that's up next for "study"

Thanks again, as always.

ok, so that’s “only” a difference of 80 bytes.

But if you were close to the limit because of all the strings in your prints, serial input buffers etc, then those “only” 80 bytes could push you over the edge.

it does seen quite a big jump from byte to int.
2^8=256 to 2^16=65536
if we know the value range won't go past 10 or 11-bits, is there no other (more efficient) data type one could use ?

Yes it is a big jump, but since we don't have a ten- or 11-bit machine, it's kind of what we're stuck with. There are two possibilities I can think of, though I don't know if you have time to do it as the bytes come in, as I am not familiar with the IR bitstream..

  1. Compression. If you use only bytes, rather than ints, and use half-bytes to store parts of each pair of values, you can save 1/4 of the RAM usage. Example: assume you have a values for the first three pairs of:

838,416,50,158,56,152
Or in hexadecimal,
0x0346, 0x01A0, 0x0032, 0x009E, 0x0038, 0x0098

Then, you can store them in an array of bytes, something like this:
High and low bytes of int are shown with H and L.
Value numbers under the H and L line

// 46 31 A0 32 00 9E 38 00 98
// LL HH LL HH LL HH LL HH LL
// 00 01 11 22 23 33 44 45 55
  1. You could resolve each pair into a bit, or each N bits into a byte on the fly, as they coma in. As I said, I don't know enough about the IR remore bit stream to know if that's feasible.

Anyway, just a couple of ideas, to keep you from having to go to a micro with a larger RAM.

lar3ry:

it does seen quite a big jump from byte to int.
2^8=256 to 2^16=65536
if we know the value range won't go past 10 or 11-bits, is there no other (more efficient) data type one could use ?

...
...

  1. Compression. If you use only bytes, rather than ints, and use half-bytes to store parts of each pair of values, you can save 1/4 of the RAM usage. Example: assume you have a values for the first three pairs of:

838,416,50,158,56,152
Or in hexadecimal,
0x0346, 0x01A0, 0x0032, 0x009E, 0x0038, 0x0098

Then, you can store them in an array of bytes, something like this:
High and low bytes of int are shown with H and L.
Value numbers under the H and L line

// 46 31 A0 32 00 9E 38 00 98

// LL HH LL HH LL HH LL HH LL
// 00 01 11 22 23 33 44 45 55




2. You could resolve each pair into a bit, or each N bits into a byte on the fly, as they coma in. As I said, I don't know enough about the IR remore bit stream to know if that's feasible.

Anyway, just a couple of ideas, to keep you from having to go to a micro with a larger RAM.

Thanks for the idea, certainly a thought exercise.
i was also thinking along the lines of high-byte/low-byte storage.
incidentally, i think this here;

// 46 31 A0 32 00 9E 38 00 98
// LL HH LL HH LL HH LL HH LL
// 00 01 11 22 23 33 44 45 55

you mean;

// 46 31 A0 32 00 9E 38 00 98
// LL HH LL LL HH LL LL HH LL
// 00 01 11 22 23 33 44 45 55

right ?

it does seem like a good possibilty, 3 bytes per high/low pulse pairing.

not sure i understand what you mean by;

You could resolve each pair into a bit, ...

i'm very poor in knowing the proper terminology.

also, i'm not sure how a value of 838 would be read into a byte var ?

incidentally, i think this here;

// 46 31 A0 32 00 9E 38 00 98

// LL HH LL HH LL HH LL HH LL
// 00 01 11 22 23 33 44 45 55




you mean;



// 46 31 A0 32 00 9E 38 00 98
// LL HH LL LL HH LL LL HH LL
// 00 01 11 22 23 33 44 45 55




right ?

No. let's look at the first two values in your test array only: 838 and 416. They both take two bytes to store them as int. So instead of storing them in an array of int, we want to reduce the storage requirement, so we will READ them as int, then fiddle with them to compress them into 12 bits.

The first int is 838, or 0x346
So, we take the low order byte and store it in the first byte of a byte array,
Byte 0 = 0x46
Then we store the lower 4 bits of the high order byte in the high 4 bits of second byte of the array
Byte 0 = 0x46
Byte 1 = 0x30 (the 3 is in the upper 4 bits of the int, and we will use the lower 4 bits (currently 0) of the byte to store the high order byte of the next value (416 or 0x1A0))
Byte 0 = 0x46
Byte 1 = 0x31
and the next byte has the low order byte of the int (0xA0)
Byte 0 = 0x46
Byte 1 = 0x31
Byte 2 = 0xA0

We continue in this way until we are finished filling the array, the order of bytes and partial bytes is exactly as I showed.
There are some helpful ways of specifying things like ints, that allow us to see them as bytes, and vice versa.

not sure i understand what you mean by;
You could resolve each pair into a bit, ...

I am assuming that a pair of values signifies a single bit. I'll look it up as soon as I can get the time, though. But if you can determine from the length of of high and low levels, what a bit should be, all you need to do is to store that bit, or to collect that bit and every 8 bits, store it in a byte.

also, i'm not sure how a value of 838 would be read into a byte var ?

You can't, but you CAN store 24 bits into 3 bytes, which is what the fiirst example was trying to show. Once you have the data, you can extract it from the compressed form and reduce it to single bytes.

lar3ry:
...
...
No. let's look at the first two values in your test array only: 838 and 416. They both take two bytes to store them as int. So instead of storing them in an array of int, we want to reduce the storage requirement, so we will READ them as int, then fiddle with them to compress them into 12 bits.

The first int is 838, or 0x346
So, we take the low order byte and store it in the first byte of a byte array,
Byte 0 = 0x46
Then we store the lower 4 bits of the high order byte in the high 4 bits of second byte of the array
Byte 0 = 0x46
Byte 1 = 0x30 (the 3 is in the upper 4 bits of the int, and we will use the lower 4 bits (currently 0) of the byte to store the high order byte of the next value (416 or 0x1A0))
Byte 0 = 0x46
Byte 1 = 0x31
and the next byte has the low order byte of the int (0xA0)
Byte 0 = 0x46
Byte 1 = 0x31
Byte 2 = 0xA0

We continue in this way until we are finished filling the array, the order of bytes and partial bytes is exactly as I showed.

yes, and if you continue, i think you'll see what my question was getting at; it's 2 "low bytes" and 1 "high byte" for every pulse pair, sol LL HH LL, then LL HH LL again, right ?

lar3ry:
There are some helpful ways of specifying things like ints, that allow us to see them as bytes, and vice versa.

and these would be... ?
are you referring to typecasting ?

lar3ry:

not sure i understand what you mean by;
You could resolve each pair into a bit, ...

I am assuming that a pair of values signifies a single bit. I'll look it up as soon as I can get the time, though. But if you can determine from the length of of high and low levels, what a bit should be, all you need to do is to store that bit, or to collect that bit and every 8 bits, store it in a byte.

woah, slow down a bit(!!), please - that first bit is referring to the pulse bit and the second bit, is referring to it being stored as data - which would be in 8-bits ?...

lar3ry:

also, i'm not sure how a value of 838 would be read into a byte var ?

You can't, but you CAN store 24 bits into 3 bytes, which is what the fiirst example was trying to show. Once you have the data, you can extract it from the compressed form and reduce it to single bytes.

that's where you've lost me i'm afraid, i have no idea what they look like in comparison, the uncompressed and "compressed form"

yes, and if you continue, i think you’ll see what my question was getting at; it’s 2 “low bytes” and 1 “high byte” for every pulse pair, sol LL HH LL, then LL HH LL again, right ?

Oops… of course! You are right.

and these would be… ? are you referring to typecasting ?

Not typecasting. More like unions, or in some cases, you can use pointers to look through the same memory as two different data types. I haven’t had much success using pointers this way, but that’s probably just because I haven’t figured out how to assign, say, an address of an int array to a byte pointer.

Here’s an example of using a union to look at the same data as both int and byte. When you run it, note the order of the bytes. ints are stored low-order, high-order, in successive memory addresses.

int testdata[] = {838,416,50,158,56,152};

union ints_n_bytes {
  int val[6];
  byte bytes[12];
} valpairs;

void setup() {
  for (int i = 0; i < 6; i++) {
    valpairs.val[i] = testdata[i];
  }
  Serial.begin(115200);
  Serial.println("ints\n-------");
  for (int i=0; i < 6; i++) {
    Serial.println(valpairs.val[i],HEX);
  }
  Serial.println("bytes\n------");
  for (int i = 0; i < 12; i++) {
    Serial.println(valpairs.bytes[i],HEX);
  }
}

void loop() {
}

Note that this is just a way of showing you the layout of the memory, and will take just as much memory. The better way is to read a pair of values into two int variables, then store three bytes in a byte array.

All that being said, you probably have enough time to decode and store the IR stream as it comes in.

woah, slow down a bit(!!), please - that first bit is referring to the pulse bit and the second bit, is referring to it being stored as data - which would be in 8-bits ?.

Yes, the IR stream consists of bursts of 38KHz (or, I think 40KHz in the case of Pioneer). The on/off times of the 40 KHz carrier determine the code.after the lead-in, each pair of values (on-time, off-time), indicates a single bit. If you read two values, you can tell if that bit is a 0 or a 1. At that point, you can store the bit. The best way to store a bit, of course, is in a byte, and you can 8 of them in one byte. You can store them using bitWrite() or bitSet().

Have a look around for Arduino libraries that do the decoding for you. I saw a multi-protocol library a while back. You’ll want one that handles Pioneer, which is the same as NEC2 except for freqency>

“union”, huh ?
thanks for the tip, something else to learn up on then.

yes, there is the more “popular” IRremote library by Ken Shiriff which looks really simple to use, but i had problems getting HEX values that looked strange, “FFFFFFFF” among others and happened upon the Adafruit tutorial on IR-sensors which showed more of the “nitty gritty” going on - ie. actually seeing the code that reads the high pulse, and then the low pulse - as well as printing all that raw data to an array - really learned a lot from that.

that gave me more “consistent” data - being simply raw streams - and i continued with (fumbling with) that method.