PDA

View Full Version : 10x4 matrix keyboard using only portB



aratti
- 15th November 2008, 17:37
A 40 keys keyboard matrix using Pic16F84A @ 4 MHz.

In this project I have used 40 keys but the system can be easily increased up to 60 keys (15 colums by 4 rows) with minor chance to the schematic and to the software (which is open source).

The default layout of the keyboard can be changed modifying the ascii array accordingly.

At startup characters are in upper case, they can be switched to lower case pressing key "Select". With the same key you can return to upper case.

You will find in the attached file, the schematics,the source code (copy and paste it into PICBASIC PRO) all well documented. But if something will result unclear, please don't hesitate to post your doubts.

Hope you will find the project useful.

Al.

mackrackit
- 15th November 2008, 18:14
Nice one !!!

T.Jackson
- 16th November 2008, 08:52
Great documentation, and I particularly like the diode schema. As the old saying goes: "a real engineer is someone who can build something for 50 cents that any other dam fool can do for $2"

Given the price of a diode these days Vs an integrated circuit-based equivalent solution, you my friend, place considerable emphasis on that old saying.

Trent Jackson

Ioannis
- 16th November 2008, 13:31
Hmm, the post is an excellent job on the matrix keyboard projects. I am just thinking to myself if it is worth to get in the trouble to built all these switch and wirings when a PC keybord has more keys, is very reliable and cost nothing!

Of course you cannot embed it in your own shell, but that is another story.

Just my thoughts, over a very nice project.

Ioannis

T.Jackson
- 16th November 2008, 16:15
I can see the schema being ideal for "custom membranes" ...

It is a popular trend for even low-volume manufactures of electronic equipment to get membrane switches tailored to suit their own enclosures. They're DEAD cheap, and easy-to-install.

Trent Jackson

aratti
- 17th November 2008, 22:51
During the weekend I came to the conclusion that the project should be for 60 keys.
The reason is that it is simpler to workout a smaller keypad from a larger one. (at least in this case)

Just remove the unnecessary switches and diodes and you have the keypad already designed.

The software has also been changed a bit in order to work around the fact that 16F84A could not accomodate an array of 61 bytes.
So with this new solution I had it at work reducing also the code work space.

Now the software works with all combination of keypad from 4x1 to 4x15 (Rows x Columns)

I am attaching the file with the new version (Hardware & Software) sure that this will make life easier.
Al.

Darrel Taylor
- 18th November 2008, 02:31
Hi Aratti,

You're doing a good job here, but there are a couple issues I'd like to bring up.
Don't shoot me. :)

While scanning the first row, you set PortB =16 which puts RB4 high and RB5-7 low.

<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=3010" /><!-- 3010 -->

If someone accidentally presses keys 1.1 and 2.1 at the same time, you have a dead short across RB4 and RB5. If you have a small power supply it won't last long because the PIC will reset as soon as the voltage drops low enough. But if you have a strong power supply, somethings likely to smoke.

The problem can be overcome a couple ways, either by adding ~100 ohm resistors in series with each Row's pin. Or you can manipulate the TRIS register in your program instead of PORTB, and only allow 1 Row at a time to be in OUTPUT mode.

And, it would be allot nicer to have the Outputs on the lower bits of PORTB, and the Inputs on RB4-7.

Then you would be able to use the PortB Change interrupts to monitor the keypad, and you wouldn't have to keep scanning it all the time. You would then place all outputs to HIGH and when you get an interrupt, scan the rows 1 by 1 like normal.

HTH,

aratti
- 18th November 2008, 02:48
Thank you Darel to have pointed out the problem, which I did noticed! I will modify the software to have only one output pin at the time on portB. The updated version will be posted tomorrow.

Thank againg for your promp notification.

Kind regards

Al.

aratti
- 18th November 2008, 05:00
Here the updated version of software and hardware.

It was necessary to pulldown the rows as well (4x5K resistors) in order to avoid floating inputs. It has been tested and it works.

If you have downloaded the file from the previuos post please discard them and download the updated file from this post.

Thank you again to Darel, and sorry for the inconvenience to all the members of the forum that have visited my post.

Al.

mister_e
- 18th November 2008, 05:07
I like the concept, good job!

Darrel Taylor
- 18th November 2008, 06:14
Awwwwww! No RBC Interrupts. :(

Such a nice little keypad scheme.
If only it would ....
<br>

aratti
- 18th November 2008, 11:26
Darel be patient next release will be with "PORTB change interrupts". For that I need to build a new hardware prototype and it will take few days.
I had to fix the bug you pointed out quickly, otherwise I could not sleep!

Regards

Al.

falingtrea
- 18th November 2008, 20:10
If I am looking at this correctly, the one drawback to this design is that you can't detect multiple keypresses in the sam row, right? In fact, holding two keys down in the same row could cause the wrong character code to be generated. Like holding down 1,1,and 1,8 gives you the code for 1,9, right? Not trying to nitpick. Just wanted to make sure I understood the advantages and disadvantages to the design.

aratti
- 19th November 2008, 02:59
Yes Tim, this is the price you have to pay for the extra keys!

If the spacing of the keypad is done properly than chances to press two contiguous keys at the same time are really rare, but since number of keys available is no more an issue, you can dedicate one key to delate the possible unwanted input.

Al.

T.Jackson
- 19th November 2008, 07:35
I believe that a protocol is possible to detect simultaneous key presses, BUT it would fail if both keys were pressed at exactly the same time (incredibly unlikely though). However, if it did occur -- the procedure would return the key that equated to the binary sum of the two keys held down.

You would only need microseconds of a difference between the keys being pressed to come up with something that works.

Trent Jackson

Ioannis
- 19th November 2008, 08:40
Since we are talking about mechanical switch, that micro seconds might be to short time in my opinion. Debouncing is needed to read the switch correctly.

Ioannis

T.Jackson
- 19th November 2008, 08:43
Moreover ...

I think if the columns were each given a unique, physical delay, say using an RC circuit -- you'd eliminate the possibility of two keys ever being processed as one.

aratti
- 20th November 2008, 09:10
Following T.Jackson suggestion, I removed the auto-repeat, now multiple keys have to close exactly at the same time to be decoded as the sum. This has been accomplished introducing a WHILE WEND which detect when you release the key.

To follow the code.

Al.


'************************************************* ***************
'* Name : 60 Keys_Kpad.BAS *
'* Author : [a.ratti] *
'* Notice : Copyright (c) 2008 *
'* : All Rights Reserved *
'* Date : 20/11/2008 *
'* Version : 2.2 *
'* Notes : Micro used: Pic 16F84a *
'* : The software will decode any matrix keypad 4 x n *
'* : where n is any columns number from 1 to 15 *
'************************************************* ***************

TrisA = %00000000
TRISB = %11111111

Define OSC 4

'--- EEprom ASCII code assignment to define keys response ---------

'------------------- First Row --------------------
Eeprom 1,[49,50,51,52,53,54,55,56,57,48,43,40,94,91,27]' (1,1)-(1,15)

'--------------------Second Row --------------------
Eeprom 16,[65,66,67,68,69,70,71,72,73,74,45,41,37,93,26]' (2,1)-(2,15)

'--------------------- Third Row ------------------
Eeprom 31,[75,76,77,78,79,80,81,82,83,84,47,64,36,60,62]' (3,1)-(3,15)

'--------------------- Fourth Row ------------------
Eeprom 46,[85,86,87,88,89,90,46,58,59,61,42,35,38,32,13]' (4,1)-(4,15)
'------------------------------------------------------------------



'--------------------------- Set variables and pins --------------------

LED VAR PortA.0 ' Heart beating led
Buz var PortA.1 ' got character acknowledgement
Tx var PortA.2 ' Serial out
RTS var portA.3 ' Ready to sent when low
T9600 con 2 ' baud rate = 9600

UCase var byte
KeyFlag var byte
KbOut var Byte [2] ' Buffer Array

high Tx ' purge serial line (True Mode)
High RTS ' disable RTS
low Buz ' Bepper off

KeyFlag = 0 ' reset variable
Ucase = 0 ' set uppercase


'-------------------------- Main program -------------------------------

Loop:
if KeyFlag>0 then 'If <> 0 then Tx ASCII character and Beep
Low RTS 'RTS flag enabled
pause 20

if KbOut[1]=26 then Loop 'Skip ascii code 26

If KbOut[1]=>65 then 'Skip ascii code <> character
KbOut[0] = KbOut[1] + UCase 'If UCase = 0 then UpperCase
else
KbOut[0] = KbOut[1]
endif

'---------------------------------------------------------------------
Serout Tx,T9600,[KbOut[0]] ' Tx ascii character
'----- Choose one of the two serout comand DON'T SELECT BOTH !!! -----
'Serout Tx,T9600,[#KbOut[0]] ' Tx ascii code
'---------------------------------------------------------------------

High RTS ' RTS flag disabled
high buz ' Beep on
pause 30 ' time duration of the beep
low Buz ' Bepper off
pause 150
endif
pause 50 ' Heart beating frequency
toggle Led ' Heart beating

while KeyFlag>0 ' stop auto repeat
KeyFlag = PortB
KeyFlag=KeyFlag & %00001111
wend

'----------------------------- KeyScan routine ------------------------

KeyFlag=0 ' reset flag variable

'------------------------ First Row - keys from 1 to 15 --------------
TRISB = %11101111
PortB =16
If PortB>16 then ' one key of the first row has been pressed
KeyFlag=PortB
KeyFlag=KeyFlag & %00001111 ' decode to which column the key belongs
Gosub GetChar
goto Loop
endif

'------------------------ Second Row - keys from 16 to 30 -------------
TRISB = %11011111
PortB =32
If PortB>32 then ' one key of the second row has been pressed
KeyFlag=PortB
KeyFlag=KeyFlag & %00001111
KeyFlag = KeyFlag +15 ' decode to which column the key belongs
gosub GetChar
goto Loop
endif

'----------------------- Third Row - keys from 31 to 45 ---------------
TRISB = %10111111
PortB =64
If PortB>64 then ' one key of the third row has been pressed
KeyFlag=PortB
KeyFlag=KeyFlag & %00001111
KeyFlag = KeyFlag +30 ' decode to which column the key belongs
gosub GetChar
goto Loop
endif

'------------------------ Fourth Row - keys from 46 to 60 -------------
TRISB = %01111111
PortB =128
If PortB>128 then ' one key of the fourth row has been pressed
KeyFlag = PortB
KeyFlag=KeyFlag & %00001111
KeyFlag = KeyFlag +45 ' decode to which column the key belongs
gosub GetChar
endif

goto Loop

'------------------------ End of keyscan routine ----------------------


'----------------------------------------------------------------------
'---------------- Select Uppercase or LowCase letters -----------------
'------ (Ucase = 32 then lowerCase) (UCase = 0 then UpperCase) -------
'----------------------------------------------------------------------
GetChar: ' Read ASCII code from eeprom & set UCase or LCase
Read KeyFlag, KbOut[1]
If KbOut[1]=26 then
If UCase=0 then
Ucase=32
else
UCase=0
endif
endif
return


end

falingtrea
- 3rd April 2009, 21:12
I found this reference on another forum that was very interesting. I had never heard of Charlieplexing (http://en.wikipedia.org/wiki/Charlieplexing) before but this is really cool. It not only applies to multiplexing outputs, but inputs as well. Since the guy that came up with this works at Maxim, there are even some Maxim parts that use charlieplexing to drive LEDs. It looks like aratti's design may be a variant of charlieplexing.

ChrisMicro
- 16th November 2011, 10:39
Just Brilliant