IR to Ethernet duplicate commands help

Hello Guys,

I am building an IR reciever to ethernet so I can send IR signals to a computer to be processed. I have it all working see my code below, however the command is being sent twice even though the button is only pushed once on the remote. Does anyone have any ideas how to fix this? I am so stumped! Oh also I modified the sample code for the client connect so it could re-establish a connection if the server dies :sunglasses:

#include <SPI.h>
#include <Ethernet.h>
#include <IRremote.h>
#include <IRremoteInt.h>

int statusLEDPin=13;
int val=0; //global var
int irLocation = 1;  //assign a room code to each device;
char irLocationMessage;

// Enter a MAC address and IP address for your controller below.
byte mac[] = {  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,168,90 };
byte server[] = { 192,168,168,50 }; //target server
Client client(server, 3000); // Initialize the Ethernet client library

//setup the IR stuff
int RECV_PIN = 9;  //set up the IR pin
IRrecv irrecv(RECV_PIN);
decode_results results;

void setup() {
  Ethernet.begin(mac, ip);   // start the Ethernet connection:
  Serial.begin(9600);  // start the serial library:
  
  // initialize the digital pin as an output:
  pinMode(statusLEDPin, OUTPUT);
  delay(1000); // give the Ethernet shield a second to initialize:
  
  Serial.println("Shield Fired up... About to try connecting");
  
  //try to connect to server
  if (client.connect()) {
    Serial.println("connected");
    //send some data to the server so we can get things rolling
    client.println("Connecting");
    client.println();
  } else {
    client.stop();
    Serial.println("connection failed");
  }
  
  irrecv.enableIRIn(); // Start the receiver
}

void loop()
{
  //if the connection is available then listen for IR signals
  /*
  if (client.available()) {
      char c = client.read();
      Serial.print(c);
      
      sendIRMessage();
  }
  */
  
  // if the server's disconnected, stop the client, but try to reconnect
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    
    connectToServer();    //call the function to try to re-connect to the server
  } else {  //we have a connection try to get IR stuff
    sendIRMessage();
  }
}

void sendIRMessage() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);  //print out our debug to the serial port

    client.println("IRLocation_1");  //send the location message first
    client.println(results.value);  //send the IR message to the server
    irrecv.resume(); // Receive the next value
    digitalWrite(statusLEDPin, HIGH);
    delay(400);
  }
  
  digitalWrite(statusLEDPin, LOW);
}

void connectToServer() {  //attempt re-connect to the server
  delay(5000);  //for debug only wait 5 seconds, 60 for final

  if (client.connect()) {
    Serial.println("connected");
    client.println("Connecting");
    client.println();
  } else {
    client.stop();
    Serial.println("connection failed");
  }  
}

Any ideas how to get rid of or suppress the duplicate command? Is it coming from the remote or from the arduino???

Thank you ahead of time

Oh one more question I haven't been able to figure out. My main language is a scripting language so this is kinda confusing to me. In PHP if you want to combine a string with a variable you can do something like this:

$irLocationMessage = "IRLocation" .$irLocation;

but when I try that in arduino like this:

client.println("IRLocation".irLocation);

It doesn't work? What is the proper syntax to make this work?

duplicate command

Depending on the remote and depending on the particular protocol, commands may be sent more than once. Some protocols specify that each command will be sent three times (not all remotes comply exactly with a given protocol.) This may happen no matter how sharply you "jab" the button on the remote control.

Anyhow...

A typical way of accommodating repeated codes might be implemented with something like the following:

1. Define a timeout interval, say 500 milliseconds.

2. Define a static variable that stores the value of millis() whenever a commmand is received, and define a static variable that stores the value of a command when it is received. Call these variables something like old_time and old_value or some such things.

Then...

3. When a new command is received within the timeout interval (and if the new command is equal to the old command), ignore the new command. In other words: If it is a different command or if the current millis() value is greater than old time plus the timeout interval, process the new command.

4. Set old command value equal to the newly received command and set old receive time equal to the current millis() value.

Regards

Dave

Footnote:
You may have to experiment with the timeout interval. If you are pushing buttons manually, half a second will (probably) suffice.

At least IWFMYMMV. (It Works For Me; Your Mileage May Vary)

That makes sense to use a old vs new command time interval to avoid the duplicate command. Only question with the millis is it sounds like that is a time counter from the when the arduino actually turns on. This device is going to be part of an automated house install so it will be on for weeks/months at a time without needing to rest. Won't the millis number get massive?

Let "now", "old_time" and "timeout_interval" be unsigned long ints (uint32_t)

In your sketch, now will be set to millis() whenever a new code is received.

The test goes like this:

// Do the following if a new code has been received and it's the same as the old code
    // New code has been received do something if it has timed out
    now = millis();
    if ((now - old_time) > timeout_interval)
    {
         // do something when the timeout has elapsed
    }
    // Maybe there is an 'else' and maybe not
    old_time = now; // Set old time for next time through the loop

The millis() rollover will take care of itself unless the time between key presses is something over 19 or 20 days.

With this simple test, here's the deal:

If it has been a month or so since the last key press, you may (or may not) have to press it twice. But the main thing is that duplicates that happen close together will be filtered.

If you need something more sophisticated, it's not much more work, but I am a believer that "less is more." Give a specific requirements statement, then do whatever is good enough to satisfy that specification.

Regards,

Dave

Ok after some playing around with the millis thing turns out that using a millis logic like you posted just delays the amount of time between each command :frowning:

The only thing I could figure out is between the lines where it sends the IR command and it gets told to listen for the next command to put a delay see the code below. This solved the problem and now I only get each button press once.

if (irrecv.decode(&results)) {
      Serial.println(results.value, HEX);  //print out our debug to the serial port
      client.println("IRLocation_1");  //send the location message first
      client.println(results.value);  //send the IR message to the server
      digitalWrite(statusLEDPin, HIGH);
      
      delay(300);  //delay getting the next value and delay so the statusLED lights up
      digitalWrite(statusLEDPin, LOW);
      irrecv.resume(); // Receive the next value    
  }

Well, I guess the important thing is that you now know that your remote control sends commands more than once.

For my application, I couldn't stand having a delay every time it detected a keypress from the remote, so I used the timeout scheme that I indicated.
It looks something like this:

#include <DavesIRremote.h>
#include <DavesIRremoteInt.h>


//const int RECV_PIN = 9; //For breadboard
const int RECV_PIN = 2; // For Gadget Shield
IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
    Serial.begin(9600);
    Serial.println("Daves IRrecvDemo");
    Serial.println();
    irrecv.enableIRIn();        // Start the receiver
    irrecv.blink13(true);
}

unsigned long last = 0;
const unsigned long delay_before_repeat = 400;

void loop()
{
    char buffer[30];
    if (irrecv.decode(&results)) {
        unsigned long now = millis();
        if ((now - last) > delay_before_repeat) {
            if (results.decode_type == SONY) {
                sprintf(buffer, "0x%03x", results.value);
                Serial.print(buffer);

                // A lookup routine that converts a value to a "string"
                const char *b = getSonyButton(results.value);
                if (b) {
                    sprintf(buffer, " (%s)", b);
                    Serial.print(buffer);
                }
                Serial.println();
                last = now;
            }
        }
        irrecv.resume();        // Receive the next value
    }
    // Do lots of other stuff  (Can not tolerate delay of hundreds of ms)
}

// My function for getSonyButton goes here.

My IRremote stuff is based on Ken Shirriff's IRremote library, with a few tweaks. Class and functions have same user API. Reference: A Multi-Protocol Infrared Remote Library for the Arduino

Regards,

Dave