Short press vs long press - IR Remote

Hi, Im using IR Remote 4.1.2 + arduino micro.

Im looking how to solve problem - one button of remote control for 2 function, separate for short click + separate for long click (hold).

Maybe something like this:

click button on remote > software is checking if code isnt changed between 200ms , if not make function for short press, if yes and we have repeat 0x0 code (like it is in NEC) then make function for long press?

Maybe someone has already made this function?

Well, you have posted a good description of the logic. Why not code it and post actual code?

Else, please explain the specific difficulty that you are having in programming it.

You have to acknowledge and handle the repeat codes that the remote sends when the button is held down...

A simple logic would be, register a code, if the next code is a repeat code, it is a long press, otherwise it's a short press.

2 Likes

Some remotes send the same code repeatedly for some keys.
Some remotes send a 'repeat' code after the initial code for some keys.
Unless the key you are using has a repeat feature you won't be able to tell when the key is no longer pressed.

3 Likes

Hi ,

Johnwasser, yes I know. RC5 sends still same code, NEC (for example Apple) is sending first code and then as repeat 0xFFFFFFFF (in IRRemote 4.1.2 it is 0x0)

aarg


const unsigned long interval = 2000;

void loop()
{
unsigned long currentMillis = millis();

 if (IrReceiver.decode()) {

    if (IrReceiver.decodedIRData.protocol == APPLE) {
   currentButtonCode = IrReceiver.decodedIRData.decodedRawData;

      if (currentButtonCode == 0) {
        currentButtonCode = lastButtonCode;
        lock= 0;
        count= count+ 1;
      } else {
        lastButtonCode = currentButtonCode;
        lock= 1;
      }

//this one works for NEC for code repeat//
      if (currentButtonCode == ApplePrawo && lock== 0 ) {
        sel_change = 1;
        sel++;
        if (sel >= 3) sel = 3;
      }

      if (currentButtonCode == AppleSrodek) {
previousMillis = currentMillis;
AppleSrodekPressed=1;
      }



  if ((currentMillis - previousMillis < interval) && AppleSrodekPressed==1 )
  {
        //short press//
  }

  if ((currentMillis - previousMillis >= interval) && AppleSrodekPressed==1 )
  {
        //long press//
  }
}
}

Did you mean

  if ((currentMillis - previousMillis < interval) && AppleSrodekPressed==1 )
  {
        //short press//
  }
  else
  {
        //long press//
  }

?

aarg

Hmmm. That is my name but you said nothing at all about the code you posted.

yes, but it is not working. if I press down button for more than 2sec its always made function for short press.

how do you know that? the code you posted takes no action on any key press.. you only put comment lines there...

I dont know what it will change, but anyway:


const unsigned long interval = 2000;

void loop()
{
unsigned long currentMillis = millis();

 if (IrReceiver.decode()) {

    if (IrReceiver.decodedIRData.protocol == APPLE) {
   currentButtonCode = IrReceiver.decodedIRData.decodedRawData;

      if (currentButtonCode == 0) {
        currentButtonCode = lastButtonCode;
        lock= 0;
        count= count+ 1;
      } else {
        lastButtonCode = currentButtonCode;
        lock= 1;
      }

//this one works for NEC for code repeat//
      if (currentButtonCode == ApplePrawo && lock== 0 ) {
        sel_change = 1;
        sel++;
        if (sel >= 3) sel = 3;
      }



if (currentButtonCode == AppleSrodek) {
previousMillis = currentMillis;
AppleSrodekPressed=1;
      }

  if ((currentMillis - previousMillis < interval) && AppleSrodekPressed==1 )
  {
             MuteState = !MuteState;
      digitalWrite(K7, MuteState);
  }
  else
  {
      enc_change = 1;
      enc = 40;
  }
}
}

it always work like short press (mutestate change), second function is made it self. after pressing some button it goes to enc=40

I have added AppleSrodekPressed=0 (if not pressed). Now it works better, first part for short press is working, but long press is not working, and also is not working by it self.

if (currentButtonCode == AppleSrodek) {
previousMillis = currentMillis;
AppleSrodekPressed=1;
      }
      else
      {
        AppleSrodekPressed=0;
      }

  if ((currentMillis - previousMillis < interval) && AppleSrodekPressed==1 )
  {
             MuteState = !MuteState;
      digitalWrite(K7, MuteState);
  }
  else
  {
      enc_change = 1;
      enc = 40;
  }



maybe better will be function like this:

  • one press > software is checking if there will be new command (more clicking) between for example 200-500ms if not make function for short press, if there will be more clicking (code from remote will change) make function for long press. I need to store last value and check it with new ir results.

but I dont know how to do it properly.

This will always excute

When you keep pressed a button on ir remote for long time. It sends "FFFFFFFF" instead of actual code.
So if (currentButtonCode == AppleSrodek) is no longer true. Which means else { AppleSrodekPressed=0; } will be excuted and long press won't work

I have noticed one bad thing.

Apple remote (first gen) sends as repeat 0x0 on all buttons, but code works only for:

  • left,
  • right,
  • up,
  • down,
  • menu

not work for "ok" (center) and play/pause.

I have replaced code in "left" function (if held (0x0) make sel++ (input selector up by 1)) which work without problem for button center or playpause and... it didnt work.

in IRRemote dump all buttons works in same way. I dont know why it doesnt work for center and play/pause.

Short press for center or play/pause works, but I have no idea why it isnt work for repeats

Please see:

how to upload .txt file with log from IR Remote dump?

if (IrReceiver.decodedIRData.protocol == APPLE) {


      boolean isARepeat=false;

      currentButtonCode = IrReceiver.decodedIRData.decodedRawData;

      if (currentButtonCode == 0) {
        currentButtonCode = lastButtonCode;
        isARepeat=true;
      } else {
        lastButtonCode = currentButtonCode;
        isARepeat=false;
      }


if (currentButtonCode == AppleSrodek && isARepeat==1)
{
          enc_change = 1;
        enc=40;
}

if (currentButtonCode == ApplePrawo && isARepeat==1)
{
          enc_change = 1;
        enc=45;
}

ApplePrawo works without problem, but ApplePlay is not working.

I have also switched variable to code like below:

//play
if (currentButtonCode == 0xFA5E87EE && isARepeat==1)
{
          enc_change = 1;
        enc=40;
}

//prawo
if (currentButtonCode == 0xFA0787EE && isARepeat==1)
{
          enc_change = 1;
        enc=30;
}


and still its only work for "appleprawo"

#define MARK_EXCESS_MICROS 20 - also original
//#define RECORD_GAP_MICROS 12000 // Default is 5000 - its original value - 5000
IR receiver TSOP34438 and others, same result (always 38kHz)

Dump for both buttons ->

I dont see any differences between both codes. In both example there is 1 code then repeat as 0x0, but I dont know why, its not working

Also I have second remote control (also like Apple 1gen) but not original (first one is original) and situation is same. up, down, left, right, menu is working good when holding, but ok/center and play pause is not working when Im holding

Or, it sends nothing, as pointed out in reply #3.

OK, Im coming with some news.

Finally after a lot of tests I have working all butons for long press (repeat 0xffffff)

Im using flag from IR Remote:

(IrReceiver.decodedIRData.flags == IRDATA_FLAGS_IS_REPEAT)

but with this flag there was also problem with ok and playpause button - they was only in one state (I have tested function if repeat turn on led, if not just press turn off).

After adding delay 50ms before resume IR receiver it works good.

But still I have problem how to detec if it was short press or long press.

Maybe function if code wasnt changed between 200ms make it for short press if its changed and flag is repeat then make function for long press.

its easy to tell about, but its harder for me to make it works in arduino (programing :slight_smile: )

maybe somone can help?

also I have problem with RC5 buttons, from one press I get in same time 2 codes.I cant add delay about 150-200ms because I have connected 7seg LCD which will unusable with this delay:

16:06:44.527 -> uint16_t address = 0x0;
16:06:44.527 -> uint16_t command = 0xC;
16:06:44.527 -> uint32_t rawData = 0x180C;

16:06:44.651 -> uint16_t address = 0x0;
16:06:44.651 -> uint16_t command = 0xC;
16:06:44.651 -> uint32_t rawData = 0x180C;

its from IR Remote dump, from ONE SINGLE CLICK, as you can see about 100-200ms and here it is second code from one click.

I have problem like this > single press "right" (input++ by 1), again single press "right" (input++ by 1) , then single press on "left" , it should decrease input by 1, but it still goes like it was pressed "right" button and its going input++, second press of "left" is going finally down with decreasing input by 1.

I think that arduino is storing value, which he dont make in one loop, then next press is making last code. so its still problem that Im recording 2 same codes at same time.

I dont know how to block IR or make in software some lock to make one time one function. If I got 2 codes, just make one of them, second go to hell :slight_smile:

In NEC/Apple there is no problem. But when I got in RC5 power button, one click sends 2 codes I will never turn off something :slight_smile:

Now code for long press looks:

      if (IrReceiver.decodedIRData.flags == IRDATA_FLAGS_IS_REPEAT) {
        currentButtonCode = lastButtonCode;
        blokadaPilot = 0; //lock
        LiczDlugie = LiczDlugie + 1; //Im counting how many times it was repeated
        if(LiczDlugie>5)LiczDlugie = 0; //If higher than 5, reset and go to 0
      } else {
        lastButtonCode = currentButtonCode;
        blokadaPilot = 1; //lock
      }


        if (currentButtonCode == AppleSrodek && blokadaPilot == 0 && LiczDlugie == 2) {
 enc_change = 1;
      enc = 40;
      }

but now I need to add for same button new function, but for short press.

maybe something like this (for ok button):

 if ((currentMillis - previousMillis > interval) && IrReceiver.decodedIRData.decodedRawData == AppleSrodek && currentButtonCode == AppleSrodek )
  {
        //short press//
  }

else { 
// long press// 
}

or else if (IrReceiver.decodedIRData.flags == IRDATA_FLAGS_IS_REPEAT)
{
//long press//
}

currentButtonCode = saved last press
IrReceiver.decodedIRData.decodedRawData - new code (if received)

so in this variant should work

interval is set to 500ms. is not working as I would like to work :slight_smile: short press - its ok, long press is not working, always code is making first function for short press. if I will double click on button it start function for short press, then make for long press.

repeat - flag if its repeat code (0xfffff) = 1, if not repeat = 0

 if (IrReceiver.decodedIRData.decodedRawData == AppleSrodek  )
{
  if((currentMillis - previousMillis > interval) &&  repeat==0 && currentButtonCode==AppleSrodek)
{
  previousMillis = currentMillis;
        MuteState = !MuteState;
      digitalWrite(K7, MuteState);
      digitalWrite(learnLED,1);

}
else if(repeat==1)
{
   enc_change = 1;
      enc = 40;
      digitalWrite(learnLED,0);
}
}

May be this will work

if (IrReceiver.decode()) {

if (IrReceiver.decodedIRData.protocol == APPLE) {
   currentButtonCode = IrReceiver.decodedIRData.decodedRawData;

if(currentButtonCode != 0Ă—FFFFFFFF)
{ precode = currentButtonCode;
}
while ( IrReceiver.decodedIRData.decodedRawData ==AppleSrodek ;){
Pre=millis();
 }
while (IrReceiver.decodedIRData.decodedRawData == 0Ă—FFFFFFFF && precode == AppleSrodek){ tillpressed =millis();
if( tillpressed - pre >interval)
{ 
Serial.println ("long press");
}
}
if ( tillpressed - pre < interval && precode == AppleSrodek){ 

Serial.println( " short press");
}
}

Hi, loop while freezes arduino. (long/short press)