Interfacing a 3X4 keypad with attiny2313

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

Hey guys,

I have been working on this for a few days straight now and have looked at several examples but I can't seem to figure out how to get the keypad polling right. I can detect colum (input) okay but can't seem to get it to read the output pin. I am using Pins: D0-D2 for input(columns) and D3-D6 for output (rows).
Here is my most recent attempt at a getColoumn function(used to have one getKey function but figured this would help me isolate the value. It defaults to the last conditional in the function so I must be reading the output value incorrectly:

int getCol1()
{

_delay_ms(250);
keyval = 0;

_delay_ms(250);
PORTD&=~(0x80>>1);
         _delay_ms(250);
		 
		 _delay_ms(250);
		if(bit_is_clear(PIND, PD0))
		{
        //blinkEm(2);
		if(bit_is_clear(PIND, PD3))
		  keyval = 1;
		
        if(bit_is_clear(PIND, PD4))
			keyval = 4;

        if(bit_is_clear(PIND, PD5))
			keyval = 7;

    	if(bit_is_clear(PIND, PD6))
			keyval = 10;		 
		}
		return keyval;

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

I am assuming that you are grounding each column, and reading the rows ( which have pull-ups on them ).

So:

col = 6;                   // you wanted to column #6
PORTD &= ~(1 << col);       // ground the column
rows = PIND & 0b00001111; // read all the rows

I am always happier with positive logic, so I would prefer to invert PIND.

rows = (PIND ^ 0b00001111) & 0b00001111; // read all the rows

Then you can abort if no keys are pressed, or select your keyval in an easier manner.

David.

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

Example code for 4*4 keypad:

#include 

typedef unsigned char  u8;
typedef unsigned short u16;
#define NOP();  asm volatile("nop"::);


#define KEY_PIN         PINB
#define KEY_PORT        PORTB
#define KEY_DDR         DDRB


u8 keyscan( void )
{
  u8 col = 0, row = 0;

  KEY_PORT = 0xFF;
  KEY_DDR = 0xF0;
  KEY_PORT = 0x0F;
  NOP();                        // wait until input stable
  if( ~KEY_PIN & 1<<0 )
    col = 4;
  if( ~KEY_PIN & 1<<1 )
    col = 3;
  if( ~KEY_PIN & 1<<2 )
    col = 2;
  if( ~KEY_PIN & 1<<3 )
    col = 1;
  row = col;
  if( col ){
    KEY_PORT = 0xFF;
    KEY_DDR = 0x0F;
    KEY_PORT = 0xF0;
    NOP();
    if( ~KEY_PIN & 1<<4 )
      row = 5;
    if( ~KEY_PIN & 1<<5 )
      row = 9;
    if( ~KEY_PIN & 1<<6 )
      row = 13;
    if( ~KEY_PIN & 1<<7 )
      row = 17;
  }                             // 0 = no key
  return row - col;             // 1..16 = key
}

Peter

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

i think in this way you are wasting your i/o.
try using an adc input that read the keypad.
just on pin to read 12 keys!

I love Digital
and you who involved in it!

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

Quote:

i think in this way you are wasting your i/o.
try using an adc input that read the keypad.
just on pin to read 12 keys!

Multi keys and a resistor chain on an ADC is all very well until you need to cope with multi-button detection.

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

Neat code, thanks.
I also thought of the analogue approach, and agree, the downside is that the key-push resistance is in the area of 150 to 190 ohms (within the 200 Ohm maximum according to the spec-sheet), and I imagine the variation will get worse over time. But it's worthwhile trying if you only have 8 keys :-)

I shall go with danni's approach, its just missing anti key-mashing logic. Will I need de-bounce like when using tact switches (its the conductive rubber-stuff type) shown here http://www.accordia.com.tw/html/metal/index.htm?

Conrad Braam - www.softcircuitry.blogspot.com - www.plcsimulator.org
Always start off poorly, that way when you finally figure it out, you can get a few surprise hits in.

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

Zaphodikus wrote:
I shall go with danni's approach, its just missing anti key-mashing logic.

Its only the key reading.
For debounce you should call it e.g. every 20ms (timer interrupt).
And if two consecutive samples are equal, then accept it.

Peter

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

danni wrote:
Zaphodikus wrote:
I shall go with danni's approach, its just missing anti key-mashing logic.

Its only the key reading.
For debounce you should call it e.g. every 20ms (timer interrupt).
And if two consecutive samples are equal, then accept it.

Wow, Peter, hiding your light under a basket? :twisted:

Peter wrote a very nice key-debounce routine and posted it here (read to the bottom where he posted both C and assembly versions). Combine that code with the suggestions above and you should have knock-out keypad code!

I like to keep track of things like that...

Stu

Engineering seems to boil down to: Cheap. Fast. Good. Choose two. Sometimes choose only one.

Newbie? Be sure to read the thread Newbie? Start here!

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

stu_san wrote:
Wow, Peter, hiding your light under a basket? :twisted:

You can combine both, but you need to convert the key number to a bit mask.

Following an example code (ATtiny26), which use the ADC-approach to read a 3*4 matrix:

http://www.mikrocontroller.net/a...

And the schematic:

http://www.mikrocontroller.net/a...

Peter

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

Quote:
You can combine both, but you need to convert the key number to a bit mask.

Same this ?

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