IR protocol problems

I am using the IR protocol library here to recieve and decode IR commands from various remote controls: An Arduino universal remote: record and playback IR signals

However try as I might I cannot change the code to store more than one code at a time! Other than this the code works very well and allows me to receive and decode any remote I throw at it!

What I need to be able to do is store up to 10 remote commands and then be able to replay them later on. Could someone please point me in the right direction with this?

Thank you

Tom

Write the code for you? No.

Check out what you've written, and point out where it needs to be fixed? Sure.

I wasn't asking anyone to write the code for me, I was just looking for some pointers on where to start! I'll see what I can come up with and post the results.

However try as I might I cannot change the code to store more than one code at a time!

I was suggesting that you show us what you've tried. You are probably not that far off.

I had a quick scan of the code.
I think you'll need a fairly detailed rewrite of some of the library, either copying out the values from the raw buffer, or adding the ability to attach and detach different buffers.
Remember each raw buffer consumes over 150 bytes of SRAM, so the number of codes you'll be able to store is quite limited.

[edit]Re-read it - much simpler than that - look at the IRrecord.pde example - you just need to make "rawCodes" and "codeLen" into arrays, and add suitable indices in your sketch, though the ability to attach and detach user buffers would potentially save RAM[/edit]

Groove, I managed to come to the same conclusion as you this morning but got stuck on the rawCodes[RAWBUF] part. I eventually realised that I could make this into a 2D array and made it into rawCodes[RAWBUF][10]. I have altered the rest of the code (eg codeType[buttonNumber]) and the sketch has compiled successfully. Now to test it and see if I can get it saving codes again!
[edit]I have uploaded the code, but now the Arduino does nothing at all! It does not record code, does not respond to button presses and will not show anything in the serial monitor. The updated code is shown below:

#include <IRremote.h>

int RECV_PIN = 11;
int BUTTON_PIN = 12;
int STATUS_PIN = 13;

IRrecv irrecv(RECV_PIN);
IRsend irsend;

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
  pinMode(BUTTON_PIN, INPUT);
  pinMode(STATUS_PIN, OUTPUT);
}

// Storage for the recorded code
int codeType[10] = {-1}; // The type of code
unsigned long codeValue[10]; // The code value if not raw
unsigned int rawCodes[RAWBUF][10]; // The durations if raw
int codeLen[10]; // The length of the code
int toggle = 0; // The RC5/6 toggle state

// Stores the code for later playback
// Most of this code is just logging
void storeCode(decode_results *results, int buttonNumber) {
  codeType[buttonNumber] = results->decode_type;
  int count = results->rawlen;
  if (codeType[buttonNumber] == UNKNOWN) {
    Serial.println("Received unknown code, saving as raw");
    codeLen[buttonNumber] = results->rawlen - 1;
    // To store raw codes:
    // Drop first value (gap)
    // Convert from ticks to microseconds
    // Tweak marks shorter, and spaces longer to cancel out IR receiver distortion
    for (int i = 1; i <= codeLen[buttonNumber]; i++) {
      if (i % 2) {
        // Mark
        rawCodes[i - 1][buttonNumber] = results->rawbuf[i]*USECPERTICK - MARK_EXCESS;
        Serial.print(" m");
      } 
      else {
        // Space
        rawCodes[i - 1][buttonNumber] = results->rawbuf[i]*USECPERTICK + MARK_EXCESS;
        Serial.print(" s");
      }
      Serial.print(rawCodes[i - 1][buttonNumber], DEC);
    }
    Serial.println("");
  }
  else {
    if (codeType[buttonNumber] == NEC) {
      Serial.print("Received NEC: ");
      if (results->value == REPEAT) {
        // Don't record a NEC repeat value as that's useless.
        Serial.println("repeat; ignoring.");
        return;
      }
    } 
    else if (codeType[buttonNumber] == SONY) {
      Serial.print("Received SONY: ");
    } 
    else if (codeType[buttonNumber] == RC5) {
      Serial.print("Received RC5: ");
    } 
    else if (codeType[buttonNumber] == RC6) {
      Serial.print("Received RC6: ");
    } 
    else {
      Serial.print("Unexpected codeType ");
      Serial.print(codeType[buttonNumber], DEC);
      Serial.println("");
    }
    Serial.println(results->value, HEX);
    codeValue[buttonNumber] = results->value;
    codeLen[buttonNumber] = results->bits;
  }
}

void sendCode(int repeat, int buttonNumber) {
  if (codeType[buttonNumber] == NEC) {
    if (repeat) {
      irsend.sendNEC(REPEAT, codeLen[buttonNumber]);
      Serial.println("Sent NEC repeat");
    } 
    else {
      irsend.sendNEC(codeValue[buttonNumber], codeLen[buttonNumber]);
      Serial.print("Sent NEC ");
      Serial.println(codeValue[buttonNumber], HEX);
    }
  } 
  else if (codeType[buttonNumber] == SONY) {
    irsend.sendSony(codeValue[buttonNumber], codeLen[buttonNumber]);
    Serial.print("Sent Sony ");
    Serial.println(codeValue[buttonNumber], HEX);
  } 
  else if (codeType[buttonNumber] == RC5 || codeType[buttonNumber] == RC6) {
    if (!repeat) {
      // Flip the toggle bit for a new button press
      toggle = 1 - toggle;
    }
    // Put the toggle bit into the code to send
    codeValue[buttonNumber] = codeValue[buttonNumber] & ~(1 << (codeLen[buttonNumber] - 1));
    codeValue[buttonNumber] = codeValue[buttonNumber] | (toggle << (codeLen[buttonNumber] - 1));
    if (codeType[buttonNumber] == RC5) {
      Serial.print("Sent RC5 ");
      Serial.println(codeValue[buttonNumber], HEX);
      irsend.sendRC5(codeValue[buttonNumber], codeLen[buttonNumber]);
    } 
    else {
      irsend.sendRC6(codeValue[buttonNumber], codeLen[buttonNumber]);
      Serial.print("Sent RC6 ");
      Serial.println(codeValue[buttonNumber], HEX);
    }
  } 
  else if (codeType[buttonNumber] == UNKNOWN /* i.e. raw */) {
    // Assume 38 KHz
    irsend.sendRaw(rawCodes[buttonNumber], codeLen[buttonNumber], 38);
    Serial.println("Sent raw");
  }
}

int lastButtonState;

void loop() {
  // If button pressed, send the code.
  int buttonState = digitalRead(BUTTON_PIN);
  if (lastButtonState == HIGH && buttonState == LOW) {
    Serial.println("Released");
    irrecv.enableIRIn(); // Re-enable receiver
  }

  if (buttonState) {
    Serial.println("Pressed, sending");
    digitalWrite(STATUS_PIN, HIGH);
    sendCode(lastButtonState == buttonState, 1);
    digitalWrite(STATUS_PIN, LOW);
    delay(50); // Wait a bit between retransmissions
  } 
  else if (irrecv.decode(&results)) {
    digitalWrite(STATUS_PIN, HIGH);
    storeCode(&results, 1);
    irrecv.resume(); // resume receiver
    digitalWrite(STATUS_PIN, LOW);
  }
  lastButtonState = buttonState;
}

[/edit]

rawCodes[RAWBUF][10]

rawCodes[10][RAWBUF] would be more like it.

Also, not sure which processor you have, but 1500 bytes of buffer (plus the library's usage) is pushing it a bit for a device that may only have 1K bytes of RAM.

I am using the Atmega328 for this project, and the codes can be stored in EEPROM if need be as the unit will only need to learn them once.
I have changed the rawCodes to rawCodes[10][RAWBUF], but the program still does nothing on the Arduino. Could you offer a suggestion for debugging? In the past I have worked with VisualBasic where I could run the code 1 line at a time but obviousy can't do this on the Arduino!

Did you swap your subscripts too and check for consistency?
Debugging? Well, rather than 10, I'd start with 1.
#define N_CODES 1
Keep the 2d array, but with an initial dimension of [N_CODES][RAWBUF].
It should be easier to get that going, then simply increase "N_CODES" when it's working.

Don't forget EEPROM is only half the size of your SRAM.

I changed the code to add #define N_CODES 1 and updated the rest of the code to match. Works fine at 1 and 5, but not at 10. Found that I can define a max of 8 spaces in the arrays.

Is there another way I can work this? I need to be able to store 10 codes (numbers 0 to 9 on the remote).

You could print the sizes of the codes (codeLen), and maybe adjust RAWBUF down if they're not filling the buffer.
Lots of ways of doing it (run-length coding, variable-sized buffers...).
Just a matter of programming effort.

Adjusting the RAWBUF from 76 to 50 allows the code to run.I need to find out what size most raw protocols are to see if they will fit in EEPROM. If not I will need to find some form of external memory to store these codes in.

Thanks for your help guys!

More experimenting shows that lowering RAWBUF causes the system to show random output as it appears to overflow.
After the weekend I am going to try putting the variables into PROGMEM to see if this is a suitable solution. The results of the recorded code need to be stored in non-volatile memory anyway so PROGMEM may be the answer I need.

I will post after the weekend and let you know.