prefered method of checking digital input pins

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

Is there a preferred method to check and process Digital input pins?

I have to check 4 pins, 3 on PORTE one on PORTD. All pins start at high and I scan for a low. the pins are connected to switches rather than button and I know I still have to de-bounce.

if ((PINE & 0x10)==0)  //switch 1
	{
		// do something
	}
	
	if ((PINE & 0x20)==0)  //switch 2
	{
		// do something
	}
	
	if ((PINE & 0x40)==0)  //switch 3
	{
		// do something
	}

at present I check each pin individually but presume there is a better/faster method.

So far I have managed but wonder if there is a preferred way to check the port pins for changes?

Nigel

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

nigelf wrote:
Is there a preferred method to check and process Digital input pins?

I have to check 4 pins, 3 on PORTE one on PORTD. All pins start at high and I scan for a low. the pins are connected to switches rather than button and I know I still have to de-bounce.

at present I check each pin individually but presume there is a better/faster method.

So far I have managed but wonder if there is a preferred way to check the port pins for changes?

Nigel

If each pin must initiate a separate action (i.e. different "// do something"s), then what you have is fine. Although, the compiler may or may not handle your tests optimally. I also would suggest avoiding magic numbers. Use the device macros. I might suggest:
if (!(PINE & (1<<PE4)))  //switch 1
{
  // do something
}
  
if (!(PINE & (1<<PE5)))  //switch 2
{
  // do something
}
  
if (!(PINE & (1<<PE6)))  //switch 3
{
  // do something
}

Although frankly, I would expect the compiler to generate the same code for both.

If you simply need to know that any pin has gone low:

if ((PINE & ((1<<PE6)|(1<<PE5)|(1<<PE4))) != ((1<<PE6)|(1<<PE5)|(1<<PE4))){
  // do something
}

This has the advantage of sampling all pins at the exact same instant. With only three pins, it may not be faster than checking each pin in sequence, but it might be faster if in the case of more pins.

Compile several examples and compare the assembled output.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

I would not combine the reading of the switches and the processing of the switches, the way you have. I would have a read_switches function, followed by a process_switches function. Encode the switches as individual bits in an unsigned value (8,16 or 32 bits, depending on how many switches). Once encoded that way, you can check for individual switches with a 1-bit mask, or 1-of-N switches or keys with an N-bit mask

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

For switches it probably doesn't matter but sometimes you need to take an instantaneous snapshot of all inputs so don't use:

if (!(PINE & (1<<PE4)))  //switch 1
{
  // do something
}
 
if (!(PINE & (1<<PE5)))  //switch 2
{
  // do something
}
 
if (!(PINE & (1<<PE6)))  //switch 3
{
  // do something
} 

but something like:

uint8_t buttons = !PINE;
if (buttons & (1<<PE4))  //switch 1
{
  // do something
}
 
if (buttons & (1<<PE5))  //switch 2
{
  // do something
}
 
if (buttons & (1<<PE6))  //switch 3
{
  // do something
} 

This also has the advantage that the volatile source (PINE) is only read once so the compiler doesn't have to generate three sets of identical code to read it (as volatile requires) so the code is shorter/faster/more efficient. You also get to do the ! inversion once at the top and the following logic is easier to read as the tests are positive not negative.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
uint8_t buttons = !PINE; 

But that's either 0 or 1. You mean

uint8_t buttons =  ~PINE; 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
if (stripped(door) == PINE)
  {
  repaint(door);
  }

Four legs good, two legs bad, three legs stable.

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

Quote:

But that's either 0 or 1. You mean

uint8_t buttons =  ~PINE;


There's something you don't see very often. Cliff with pants down... :D

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

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

Only one coffee so far this morning - clearly more caffeine needed here :oops:

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

John_A_Brown wrote:

if (stripped(door) == PINE)
  {
  repaint(door);
  }


if (PINE == for_the_fjords) {
  cli();
  wdt_enable(WDTO_15MS);
  while(1) {}
}

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

Ut oh. A limerick may be just around the corner.

The largest known prime number: 282589933-1

It's easy to stop breaking the 10th commandment! Break the 8th instead. 

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

I typically "gather" my inputs/buttons/switches from the various ports and pins and enter into the parallel debounce rountine. See "key_fetch" in this link, and related/supporting in other forum search results for "key_fetch".

https://www.avrfreaks.net/index.p...

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

joeymorin wrote:
I also would suggest avoiding magic numbers. Use the device macros. I might suggest:
if (!(PINE & (1<<PE4)))  //switch 1
{
  // do something
}
  
if (!(PINE & (1<<PE5)))  //switch 2
{
  // do something
}
  
if (!(PINE & (1<<PE6)))  //switch 3
{
  // do something
}

Although frankly, I would expect the compiler to generate the same code for both.

To me, PE4 is as magic as 4.

I would use my macros for handling port bits by name, e.g.
"if(pval(LIGHT_SWITCH)) { ... }" or "if(pval(MOTOR_SWITCH)) { ... }".
Their uses would be preceded by definitions like
#define LIGHT_SWITCH_LET E
#define LIGHT_SWITCH_BIT 4
#define MOTOR_SWITCH_LET E
#define MOTOR_SWITCH_BIT 6
The definition of pval is left as an exercise for the reader.

As this involves debouncing,
I might instead have subsystems that debounce the switches attached to ports E and D.
The parameters distinguishing the subsystems would be a port letter and a mask.
I'd use macros to give the switches names,
but the subsystems would not know them.

"Demons after money.
Whatever happened to the still beating heart of a virgin?
No one has any standards anymore." -- Giles

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

Wow thanks guys, You know I now have to go read loads more... im not sure I have sufficient room left in my noggin!

I think I may have to use a mix and match of methods from above. using good names within some defines looks good. I have just started to use them!

regards
Nigel