Arduino Universal Remote Case Statement Help

I am making a web based universal remote for my TV, satellite receiver, receiver, and Mac mini. I am using an Adruino Uno with an ethernet shield. I have used jquery mobile to create my web interface which sends a command (1-40) to the Arduino. The Arduino interprets that command (1-40) as an IR signal.

unsigned int TVPowerCode[68] = {4450,4450,600,1650,550,1650,600,1650,600,500,600,550,600,500,600,550,550,550,600,1650,550,1650,600,1650,600,550,550,550,600,500,600,550,550,550,600,500,600,1650,600,550,550,550,600,500,600,550,550,550,600,500,600,1650,600,550,550,1650,600,1650,600,1650,600,1600,600,1650,600,1650,550};
                  
                  switch (selectedValue) {
                      case 1:
                      irsend.sendRaw(TVPowerCode,68,38);
                      break;
                  }

All of that works when I have about 15 commands in my switch statement. When I have all 40 commands in my switch statement my IR LED does not get its signal and the URL does not finish loading (ie URL http://192.168.0.9/9/1). Because it will work with a limited number I believe the issue is in the switch statement but I am not seeing it.

So my two questions are:

  1. what is wrong with my switch statement that it will not work with all 40?

  2. I would love to be able to move all of the code variables (is ReceiverPowerCode) and the case statement to the sever hosting the query mobile page. But to be able to do this I would need to be able to pass IR siginal to the Arduino. Does anybody know of a way to make this work:

http://192.168.0.9?2450,500,1250,550,650,550,1250,550,650,550,1250,550,600,550,650,550,650,550,1250,550,650,550,1250,550,1250

I would need to be able to send a variable length argument that would have commas.

This is the code I am currently using. I have put my case statement in other projects for testing but got the same results.

Code was to long so I attached file.

RESTduino.ino (17.8 KB)

unsigned int ReceiverPowerCode[68] = {2450,500,1250,550,650,550,1250,550,650,550,1250,550,600,550,650,550,650,550,1250,550,650,550,1250,550,1250,550,600,600,1200,550,650,550,650,550,650,550,1250,550,1250,550,1200};
                  unsigned int ReceiverVolumeUpCode[68] = {9000,4450,600,1600,650,500,600,1650,600,500,600,500,650,500,600,500,650,1600,600,1650,600,500,600,1650,600,1600,650,500,600,1650,600,1600,650,1600,650,1600,600,500,650,500,600,500,650,450,650,1600,600,1650,600,500,650,500,600,1600,650,1600,650,1600,600,1650,600,500,650,450,650,1600,650};
                  unsigned int ReceiverVolumeDownCode[68] = {9000,4450,600,1650,600,500,600,1650,600,500,600,500,650,500,600,500,650,1600,600,1650,600,500,600,1650,600,1650,600,500,600,1650,600,1600,650,1600,650,500,600,500,600,500,650,500,600,500,600,1650,600,1650,600,500,600,1650,600,1600,650,1600,650,1600,600,1650,600,500,600,500,650,1600,650};
                  unsigned int ReceiverAUXCode[68] = {9000,4450,600,1650,600,500,600,1650,600,500,600,500,650,500,600,500,650,1600,600,1650,600,500,600,1650,600,1600,650,500,600,1650,600,1600,650,1600,650,1600,600,500,650,1600,600,1650,600,500,650,1600,600,1650,600,500,650,450,650,1600,650,500,600,500,600,1650,600,500,600,500,650,1600,650};
                  unsigned int ReceiverDirectTVCode[68] = {9000,4450,600,1600,650,500,600,1650,600,500,600,500,650,500,600,500,650,1600,600,1650,600,500,600,1650,600,1600,650,500,600,1650,600,1600,650,1600,650,500,600,500,600,500,650,500,600,1600,650,1600,650,1600,600,500,650,1600,600,1650,600,1650,600,1600,650,500,600,500,650,450,650,1600,650};
                  unsigned int ReceiverBluRayCode[68] = {9000,4450,600,1600,650,500,600,1650,600,500,600,500,650,500,600,500,600,1650,600,1600,650,500,600,1650,600,1600,650,500,600,1600,650,1600,650,1600,650,1600,600,1650,600,500,600,1650,600,500,600,1650,600,1600,650,500,600,500,650,500,600,1600,650,500,600,1650,600,500,600,500,650,1600,600};
                  unsigned int ReceiverAirPlay[68] = {9000,4450,600,1650,600,500,650,1600,600,500,650,450,650,500,600,500,650,1600,600,1650,600,500,650,1600,600,1650,600,500,650,1600,600,1650,600,1600,650,500,600,1600,650,1600,650,500,600,1600,650,1600,650,1600,600,500,650,1600,600,500,650,500,600,1600,650,500,600,500,650,500,600,1600,650};
                unsigned int DirectTVUpCode[68] = {6000,1200,1200,1200,600,600,600,600,1200,550,650,550,650,1150,1250,550,1250,1150,650};
    unsigned int DirectTVListCode[68] = {6050,1150,1250,1150,650,550,650,550,1250,550,1250,500,1250,550,650,550,1250,550,650};
    unsigned int DirectTVLeftCode[68] = {5950,1250,1250,1150,650,550,650,550,1200,600,600,600,1200,1150,1250,1150,650,1150,650};
    unsigned int DirectTVRightCode[68] = {6050,1150,1250,1150,650,550,650,550,1250,550,650,1150,650,550,1250,1150,650,1150,600};
    unsigned int DirectTVDownCode[68] = {6000,1200,1250,1150,650,550,650,550,1250,550,600,600,1200,600,1200,1200,600,550,650};
    unsigned int DirectTVExitCode[68] = {6050,1150,1250,1150,650,550,650,550,1250,500,650,1150,1250,550,1250,1150,1250,1150,650};
    unsigned int DirectTVMenuCode[68] = {6000,1200,1250,1150,650,550,650,550,1250,550,650,550,650,550,1250,550,1250,550,650};
    unsigned int DirectTVChannelUpCode[68] = {6050,1150,1250,1150,650,550,650,550,600,600,1200,1150,650,1150,1250,550,1250,550,650};
    unsigned int DirectTVChannelDownCode[68] = {6050,1150,1250,1100,650,550,650,550,650,550,1250,1150,1250,550,1250,550,1250,1150,650};
    unsigned int DirectTVPlayCode[68] = {6000,1150,1250,1150,650,550,650,550,1250,1150,650,550,650,550,1250,1150,1250,1150,650};
    unsigned int DirectTVPauseCode[68] = {3050,1150,1250,1150,650,550,650,550,1250,1150,650,550,1200,550,650,550,650,1150,650};
    unsigned int DirectTVRewindCode[68] = {6050,1150,1250,1150,650,550,650,550,1250,1150,650,550,1250,1150,650,550,1250,550,650};
    unsigned int DirectTVFastforwardCode[68] = {6000,1150,1250,1150,650,550,650,550,1250,1150,650,1150,650,550,650,550,1250,550,650};
    unsigned int DirectTVMuteCode[68] = {6050,1150,1250,1150,650,550,650,1150,650,1150,1250,550,650,1150,650,550,1250,1100,650};
    unsigned int DirectTV1Code[68] = {6000,1200,1200,1150,650,550,650,550,650,550,650,550,650,1150,650,550,650,1150,650};
    unsigned int DirectTV2Code[68] = {6050,1150,1250,1150,600,550,650,550,650,550,650,550,1250,550,650,550,1250,550,650};
    unsigned int DirectTV3Code[68] = {6050,1150,1250,1150,650,550,650,550,650,550,600,600,1250,1100,650,550,1250,1150,650};
    unsigned int DirectTV4Code[68] = {6050,1150,1250,1150,650,550,650,550,650,550,650,1150,650,550,600,600,1200,1150,650};
    unsigned int DirectTV5Code[68] = {6000,1150,1250,1150,650,550,650,550,650,550,650,1150,650,1150,650,1150,650,550,650};
    unsigned int DirectTV6Code[68] = {6000,1150,1250,1150,650,550,650,550,650,550,650,1150,1250,550,650,1150,650,1150,650};
    unsigned int DirectTV7Code[68] = {5950,1200,1250,1150,650,550,650,550,650,550,650,1150,1250,1150,650,1150,1200,600,650};
    unsigned int DirectTV8Code[68] = {5950,1250,1250,1150,650,550,600,600,650,550,1200,600,600,600,600,1200,1200,550,650};
    unsigned int DirectTV9Code[68] = {5950,1250,1250,1150,650,550,650,550,600,600,1200,600,600,1150,650,1150,1250,1150,650};
    unsigned int DirectTV0Code[68] = {6000,1200,1250,1150,650,550,650,550,600,1200,600,600,600,1200,600,1200,1200,550,650};
    unsigned int DirectTVRecordCode[68] = {6000,1200,1250,1150,650,550,650,550,1200,1150,650,1150,650,1150,650,550,1250,1150,650};
    unsigned int DirectTVEnterCode[68] = {5950,1250,1250,1150,650,550,650,550,650,1150,650,550,1200,1200,1200,600,600,550,650};
    unsigned int DirectTVPowerCode[68] = {6000,1150,1250,1150,650,550,650,550,650,1150,650,550,650,550,650,1150,650,1150,600};
    unsigned int DirectTVGuideCode[68] = {3000,1150,1250,1150,650,550,650,550,1250,550,1250,550,650,550,600,600,600,550,650};

That looks to be well taking up well over the amount of SRAM that the Uno has...

Is there an easy way to check that? When I was compiling the project I was watching the bottom where it tells you the size and it is currently at 28,094 of 32,256.

andyboutte: Is there an easy way to check that? When I was compiling the project I was watching the bottom where it tells you the size and it is currently at 28,094 of 32,256.

Program memory and SRAM are different. The Uno has 2K SRAM, and any variables not explicitly told to be stored in the program memory will be stored in SRAM. The quick way to check for it is to count all those 68 sized array, multiply the number by 68 to get the number of ints and multiply that by 2 to get the number of bytes the arrays are taking up. I count 35 so

35 * 68 * 2 = 4760 taken up by just those array, which is twice what the Uno has available total, not even taking account the space needed for the stack and heap.

Thanks for the info. That really helps!

So that leaves me with no choice but to find a way to move all that to the server hosting my web interface. You know of anyway to have the Arduino receive a web request like this:

http://192.168.0.9?2450,500,1250,550,650,550,1250,550,650,550,1250,550,600,550,650,550,650,550,1250,550,650,550,1250,550,1250

and make it do this:

unsigned int DirectTVListCode[68] = {2450,500,1250,550,650,550,1250,550,650,550,1250,550,600,550,650,550,650,550,1250,550,650,550,1250,550,1250};

andyboutte: Thanks for the info. That really helps!

So that leaves me with no choice but to find a way to move all that to the server hosting my web interface. You know of anyway to have the Arduino receive a web request like this:

http://192.168.0.9?2450,500,1250,550,650,550,1250,550,650,550,1250,550,600,550,650,550,650,550,1250,550,650,550,1250,550,1250

and make it do this:

unsigned int DirectTVListCode[68] = {2450,500,1250,550,650,550,1250,550,650,550,1250,550,600,550,650,550,650,550,1250,550,650,550,1250,550,1250};

There are plenty of examples on how to read get?= information from webserver requests, you just need a small char array to store each of the tokens. When you get a ',', null terminate the array and send it to atoi(). Stuff it in your array and continue to your next value.

Another option would be to upgrade to a beefy microcontroller and store all those codes in the program's memory, or get an external memory chip. I'm curious, though, as to why you are creating arrays with 68 elements if you are not filling those arrays?

    unsigned int DirectTV1Code[68] = {6000,1200,1200,1150,650,550,650,550,650,550,650,550,650,1150,650,550,650,1150,650};

There are hardly 68 entries here, as Arrch said. How about:

    unsigned int DirectTV1Code[] = {6000,1200,1200,1150,650,550,650,550,650,550,650,550,650,1150,650,550,650,1150,650,0};

Then stop when you hit zero (assuming zero isn't a valid code).

Plus you can put this stuff into program memory (look up the PROGMEM directive).

Then it can stay in the 32 Kb of PROGMEM not the 2 Kb of SRAM.

Thanks guys. The 68 was what I had originally copy / pasted from an example and I never got around to fixing it.

I will look into both of your suggests.

Thanks!

You also have 1k EEPROM.

This is the code I ended up going with if any body stumbles across this in the future.

#include <SPI.h>
#include <Ethernet.h>
#include <IRremote.h>
IRsend irsend;
#include <string.h>

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192,168,0,9);

EthernetServer server(80);
String command="";
char charBuf[300];
char c;
int i=0;
int index=0;
unsigned int angle[300];
char delimiters[] = ",";
char* valPosition;

void setup() {
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
  Ethernet.begin(mac, ip);
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

void loop() {
  EthernetClient client = server.available();
  if (client) {
      while (client.connected()) {
      while (client.available()) {
        client.read();
        
        for(int i=0; i<4; i++) //This removes the unneeded data before the command
            {
               client.read(); 
            }
            
          client.read(); // removes the first / in the argument
          
          while ( c != '\n' && c != '/') // This removes everything from the header execept the arguments
          {
             c = client.read();
             charBuf[index++] = c;
             Serial.print(c);  
          }
          
          charBuf[index]=' ';//This removes the second / at the end of the argument

          valPosition = strtok(charBuf, delimiters); //fist trun of strtok
        
          while(valPosition !=NULL){ //converts all numbers between commas into int
            angle[i] = atoi(valPosition);
            valPosition = strtok(NULL, delimiters);
            i++;
          }
       
          irsend.sendRaw(angle,68,38); // sends infred command

          index=0; // resets variables so universal remote buttons can be pushed again
          c=' ';
          i=0;

          delay(1);
          client.stop();
      }    
      delay(1);
      client.stop();
      Serial.println("client disonnected");
    } 
  }
}
        client.read();
        
        for(int i=0; i<4; i++) //This removes the unneeded data before the command
            {
               client.read(); 
            }
            
          client.read(); // removes the first / in the argument

It’s not a good idea to throw away data the might not be what you assume it is. There is no reason not to store these 6 characters, and check them against a string that contains what you think these 6 characters are supposed to be.

Besides, client.available() may not have reported that there are 6 characters to read, yet you read 6 anyway.

Then, you read a whole bunch more, store them in charBuf and then check whether they should be stored. Fail!

          while ( c != '\n' && c != '/') // This removes everything from the header execept the arguments
          {
             c = client.read();
             charBuf[index++] = c;
             Serial.print(c);  
          }
          
          charBuf[index]=' ';//This removes the second / at the end of the argument

          valPosition = strtok(charBuf, delimiters); //fist trun of strtok

charBuf is NOT a string. Do NOT pass non-strings to functions that expect strings.

Your assignment now is to determine why charBuf is not a string, and what to do to make it one. It is a fundamental part of string processing.

If charBuf was a string, the strtok() function returns a token, not a position. Meaningful names are important.

String command="";

Why link in the whole String library for one useless statement?