## Reading the state of a keymatrix into an array

13 posts / 0 new
Author
Message

Hi,
So Im quite new to masks but I get the jist. I've written the following to read the state of a 64 key keymatrix into an array. I use the mask to set PORTK LOW and then if PINH is not 255 then I read the state into a byte in the array.
I can later go and process it to find out exactly which button(s) were pressed:

```void KeyMatrix::pollKeys() {
static uint8_t map[8] = { 0 };
uint8_t count = 0;
PORTK = ~mask; //low one col with all others pull-up

if ((PINH != 0xFF)) {
map[count] = PINH;
}
count++;
}
}
```

To me everything looks good, except i printed out the contents when i was pressing only one button down and got this:

```serial.printf("pin high: % d : % d\n", count, PINH);
displayed:

pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
pin high: 1 : 247
pin high: 0 : 247
```

That to me says that that is storing the value in 2 rows?
What have I messed up?

Quote:

PORTK = ~mask; //low one col with all others pull-up

if ((PINH != 0xFF)) {

A couple things...

When I do a matrix keypad, I usually read one row at say 1ms interval after setting the column strobe. In your example sequence, the read is done like a microsecond or less after setting the new configuration. A quick test would be to insert e.g. 1ms before the PINH read.

As you always appear to get 247, is that one bit "stuck"?

After you get going, remember the buttons bounce. So in my stodgy old way I'd read a column every 1ms or 1.25ms and store all the results and then enter all (every 10ms or so) into a debounce sequence, 3x to 5x. Bob G. will say it isn't necessary. ;)

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.

No thats the value of PINH due to me pressing the button, the first number is the position in the mask, the problem is that numer is changing from 0-1 which suggests its being read on two positions in the mask.

Do you have pullups enabled on PINH? As Lee suggests, you want some delay - there's stray capacitance coupled with high impedances so that means things can change slower than you expect.

mask += mask; most of us would just mask<<=1; It probably makes no difference to the compiler, but us bit twiddlers expect a shift.

You do realise you can just set PORTK = 0; and twiddling the DDRK bits is sufficient.

I second Lee's advice - I would just have a timer tick scan the array as well as other time based duties.

theusch wrote:
After you get going, remember the buttons bounce. So in my stodgy old way I'd read a column every 1ms or 1.25ms and store all the results and then enter all (every 10ms or so) into a debounce sequence, 3x to 5x. Bob G. will say it isn't necessary. ;)

Bob frequently says that if you have a sufficiently long delay between each time you read the state of the buttons, there is no need to debounce them.

If we are certain that noise will never affect the state of the input, he is right.

Those who disagree with Bob never mention debouncing as a way to deal with noise - it's always about dealing with the switch bounce. Bob's thinking works perfectly in that respect.

Sid

Life... is a state of mind

Lots of 'ifs' there.

I'm not sure what you are saying. There have been lots of discussions of debouncing here. Just Google 'debounce site:avrfreaks.net'

Are you recommending NOT debouncing?

Smiley

Sid, seems you haven't read my tutorials! I discuss debouncing and the effect of noise on inputs. For any input that comes from the 'real world' whether it bounces or not, you really want to read it as many times as possible to statistically lessen the chance of a false read due to transients etc. As to how many times you read depends on the application and the signal.

Last Edited: Wed. Feb 20, 2013 - 06:04 AM

Smiley,

What do you mean "lots of ifs" ? There are only two of them. One of them comes from Bob, the other one comes from me.

I am well aware that there are many threads about debouncing. I am pointing out that Bob is right with regards to what people usually discuss in those threads. There is no need to debounce buttons to deal with switch bounce. I can elaborate on that if you want me to, although it probably won't sink in because nobody seems to have understood what Bob is saying and he has said it a lot of times.

However, I am not recommending not debouncing. The main reason for that is what I already said, i.e. noise could play a part in this. If you had an input changing state for a short time due to noise, the debouncing scheme would take care of that and Bob's idea would not address it properly. I don't know enough about electronics to say that that is important - or not important - so I play it safe and debounce my buttons.

Somehow, that part seems to have escaped all the "experts" that pretty much insinuate Bob is wrong.

Sid

Life... is a state of mind

Kartman wrote:
Sid, seems you haven't read my tutorials! I discuss debouncing and the affect of noise on inputs. For any input that comes from the 'real world' whether it bounces or not, you really want to read it as many times as possible to statistically lessen the chance of a false read due to transients etc. As to how many times you read depends on the application and the signal.

Kartman,

You are right - I didn't read your tutorial and you are obviously not one of those I was talking about. On the contrary, you just confirmed that my thinking is spot on.

Sid

Life... is a state of mind

I've seen the effect of not 'debouncing' inputs many times - mainly in industrial settings. Most PLCs implement as a default will multiple sample inputs. Some even have some response settings and specifically state on high speed inputs to be aware of the issues. However, when I see people use microcontrollers (as opposed to a PLC which is microcontroller based anyway), they don't take into account the possibility of transients upsetting the operation. There was a turntable that randomly stopped midway. The proximity sensors worked perfectly, but the odd transient fooled the microcontroller into thinking the turntable had hit a limit when it hadn't. Multiple sampling ( or debouncing) solved this problem.

i think Gannsle covered this and spoke about some even going to the lengths of testing input with the various mains frequencies etc to validate the robustness as sampling at a fixed rate means that different frequencies are detected differently.

Well, like they say, sometimes a bit of integration helps you differentiate :)

(OK, OK! No need to shove. I was just about to leave anyway.)

Quote:

However, when I see people use microcontrollers (as opposed to a PLC which is microcontroller based anyway), they don't take into account the possibility of transients upsetting the operation.

There is a current thread that will boil down to this (IMO): "Strange behavior of Tiny828 when in sleep mode". If I had to guess the transient (perhaps static) caused a wakeup via pin-change, but a scan of the input bank showed no bits made and the program didn't know how to handle that and didn't go back to sleep.

I have deep-sleep apps with pin-change wakeup as well. But then I start the normal scan/debounce sequence to verify the "made" signal(s).

Anyway...

Quote:

As Lee suggests, ...

OP seems oblivious to the capacitance/delay needed in this type of setup. In a lashup there may be ringing on the lines and the like. Generally IME this is short--much shorter than switch bounce--and (say) 1.25ms or 2.5ms per column works well.

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.