short/long IR remote control press

Go To Last Post
9 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

I was thinking about this for a couple of days, please look at it as a request to discuss possible codes for this request. Is there a bullet proof way to enable a project using, for example RC5 or SIRC, let's mainly say SIRC, and be able to distinguish between long and short press? I saw the button debouncing code by perter danninger, and he did quite nice job there. Is there a way to apply this for IR remote control, such that there is the possibility to detect short, long presses as he has done for switches.

In TV sets, we can turn on/off the TV using the same button, how is this correctly handled in code?

For example:

get_code_long(12)
get_code_short(56)
get_code_rpt(32)

this would be real nice way to handle tons of IR streaming code while pressing the button on the remote control set.

The problem with RC5 toggle bit is that it is not reliable. Suppose I press, then press again with my hand on the TX, then press again, the MCU has saved the first toggle bit, missed the second, and then when it sees the third toggle bit, it will see it unchanged.

Signature: We need more peripherals in DIP packages. Namely, USB, 12-bit ADC, 16-bit timer, cheaper tool as a programmer/debugger coz STK600 is expensive! Atmel Studio 5/6 sucks! coz it brings MS visual studio crap to AVR world..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Think of your remote control like a keyboard.
Each button produces a different code.
Most buttons are one-off.
Some buttons may repeat if you hold them down.

You handle them much the same way as your typewriter keyboard. i.e. you detect a keypress, debounce it, detect a key-release, debounce it.

This is not really very horrific. The 'same' value for 30ms or so means debounced. 'Held down' for 500ms or so means repeat.

For your TV you probably don't want auto-repeat like this. Instead you repeat sooner.

The TV looks at a continuous '2' and chooses channel #2 and not #2222.
The TV looks at a continuous 'volume-up' and chooses several 'up' operations until the signal ceases.

No, I have never studied the human-timing of a TV remote. You just need to make it seem 'normal' to the average punter.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You keep a count of the received codes. if the current code is the same as the previous, you increment the count. You then have a timeout so when no codes are received for a given time, then you report the code that was previously received and the number of times you received that code. Therefore for a short press you would be presented with
count = 1
for a long one,
count = 5 or whatever.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

metal wrote:
Is there a bullet proof way to enable a project using, for example RC5 or SIRC, let's mainly say SIRC, and be able to distinguish between long and short press?

A way, yes, certainly possible. A bullet proof way, never if signal is too weak and already comes out corrupted from IR receiver module.

Both RC5 and SIRCS keep transmitting the same data stream repeatedly until you release the button, so that is when the data stream stops. When you receive a code, flip a flag bit on which means a button is currently pushed. Count time and count number of IR transmissions received. If there is a gap longer than should be the time between transmissions, you see this timeout and flip the button is currently pushed bit off.

metal wrote:

The problem with RC5 toggle bit is that it is not reliable. Suppose I press, then press again with my hand on the TX, then press again, the MCU has saved the first toggle bit, missed the second, and then when it sees the third toggle bit, it will see it unchanged.

And what is the problem? That is the way it just works when your code looks at the toggle bit. Accept the behavior, or just make your code ignore the toggle bit and it will work like SIRCS and other remotes that do not have a toggle bit at all.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually I solved it, and it is bullet proof:

Inside rc5 code handler, provided a correct code is received, I added this code to handle buttons I need, on/off button code is 12. rc5_valid indicates if the received code is valid or not, if RC5 reception failed it will simply be set to 0 by some other code not shown here, if OK will be set to 255 according to the conditions by code below, rc5_timeout is simply used to prevent toggling while the button is pressed and held, the idea is to count 241ms after the first rc5_code == 12 has been received and serviced, hence rc5_timeout is set to 255 inside the main while loop to allow counter to start counting, and as long as the button is being held after the timer starts counting, it will reset the counter rc5_rpt_cnt to 0, once released, it increments the counter till 240, this way no more rc5_code == 12 are serviced as long as the button is pressed and held:

//rc5.c
unsigned int rc5_rpt_cnt = 0;
unsigned char rc5_timeout = 0;

if(rc5_code == 12 && !rc5_timeout)
{
	rc5_valid = 255;
}
else if(rc5_code != 12)
{
	rc5_valid = 255;
}
else
{
	rc5_valid = 0;
	rc5_rpt_cnt = 0;
}

Inside main while loop, where the on/off function is handled:

//main.c
if(rc5_valid && (rc5_code == 12))
{
      rc5_valid = 0;
      rc5_timeout = 255;
	  // the rest of handling code
	  .
	  .
	  .
	  .
}

Inside timer 0 overflow handler, 1ms overflows.
After receiving the first rc5_code == 12, the timer will not start incrementing rc5_rpt_cnt until it has been serviced, if during the next 241ms another rc5_code == 12 is not received, rc5_timeout is set to 0 allowing code inside rc5_handler to handle new rc5_code == 12 and set rc5_valid to 255.
Note that rc5_rpt_cnt is being set to 0 above after receiving the first rc5_code == 12 and will still be set to 0 as long as rc5_code == 12 steam is being received, once rc5_rpt_cnt == 240, rc5_timeout will be set to 0 allowing the processing of new rc5_code == 12, I am able to prevent processing of further rc5_code == 12 by keeping rc5_valid set to 0 in the main while loop after it was serviced, and as long as rc5_timeout is 255, RC5 handling code will not not set rc5_valid to 255:

//timer.c
if(rc5_timeout)
{
	if(rc5_rpt_cnt < 240)
		rc5_rpt_cnt++;
	else
	{
		rc5_rpt_cnt = 0;
		rc5_timeout = 0;
	}
}

The idea is tricky, it was a result of long time thinking, trial and error and understanding of which variables to modify inside and outside an interrupt, it will take some time to be understood, if there is something unclear, please ask me.

Signature: We need more peripherals in DIP packages. Namely, USB, 12-bit ADC, 16-bit timer, cheaper tool as a programmer/debugger coz STK600 is expensive! Atmel Studio 5/6 sucks! coz it brings MS visual studio crap to AVR world..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The RC5 code contain a toggle bit.
If you press a key longer, then you get several identical readings.
But if you press a key two times, then the toggle bit changes.

Peter

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I could use that, but I wanted to write something I can use for other codes as well, such as SIRC.

Signature: We need more peripherals in DIP packages. Namely, USB, 12-bit ADC, 16-bit timer, cheaper tool as a programmer/debugger coz STK600 is expensive! Atmel Studio 5/6 sucks! coz it brings MS visual studio crap to AVR world..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hoq does your technique differ to what i described?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

read code and description and compare

Signature: We need more peripherals in DIP packages. Namely, USB, 12-bit ADC, 16-bit timer, cheaper tool as a programmer/debugger coz STK600 is expensive! Atmel Studio 5/6 sucks! coz it brings MS visual studio crap to AVR world..