Electronic Projects, forums and more.

Go Back   Electronic Circuits Projects Diagrams Free > Electronic Content > Electronic Projects


Electronic Projects A collection of small electronic circuits and projects you can build.

Reply
 
Tools Display Modes
Old 12th January 2009, 09:06 AM   #1 (permalink)
Default RS232 keypad with autorepeat and 2 key rollover.

This project uses a 12F508 (or 12F509) to read a keypad and send the results over RS232. It is most useful as an add-on to other pic projects that require some way to input numbers. This keypad acts the same way as your PC keyboard in that when a key is held down, it has the short delay before it repeats the key. Both the delay and repeat speed are settable in software just like your PC keyboard.

Many people will wonder what "2 key rollover" means. The best answer is with a little demonstration. Open your favourite text editor, hold down the "A" key and when it starts repeating press the "B" key. Even though 2 keys are now held down the keyboard sends the last key pressed. This is useful because many people will press the keys so fast that they inadvertently press two keys at once.

How does it work.
The Schematic,


The 12F508 only has 6 input/output (I/O) pins and we need 1 to send the serial data out which leaves only 5 left to read the keypad. The keypad has 4 rows and 3 columns which is too many for our little pic chip. The way we get around this problem is by using the same pins twice. You see the three resistors in the diagram, well they will make the three pic pins low by connecting them to ground. If we now make GP4 high the diode on row 1 will conduct and if any keys are pressed in row 1 then the corresponding pin GP0, GP1 or GP3 will also go high. We have successfully read row 1. We can repeat this with GP4 and read row 3.

Now comes the tricky part because the diodes on rows 0 and 2 are backward and so the only way to read those rows is by outputting a zero on GP4 and GP5 thus making the input pins low. But, wait a minute, they are already low due to those resistors and so we won't see any change. Luckily for us the pics have internal resistors that connect the (input) pins to the 5V line that we can turn on and off in software. These resistors have a value around 20k and so will overpower the 200k external ones and make the input pins 5V. So, with these internal resistors turned on we can make GP4 an output, set it low and any pins that are now low will indicate a key pressed on row 0. We can repeat this using GP5 to read row 2.

The board,


Closer,

The two sets of connectors are just for convenience, I added the second set to enable me to use it on a breadboard.

The finished article,


The code,
Code:
;*******************************************************************
;		Title	12F509 RS232 KeyPad
;		Author	Mike Webb
;		Date 	12th January 2009
;		Version	1.0
;*******************************************************************
;
	processor	12F509

	include	"p12f509.inc"

	errorlevel	-302
	radix	dec

	__CONFIG   _MCLRE_OFF & _CP_OFF & _WDT_OFF & _IntRC_OSC

;uncomment the following line to invert the RS232 signal.
;when inverted it can connect straight to a PC without a MAX232

;#define		Inverted

#define		GPIO0	0
#define		GPIO1	1
#define		GPIO2	2
#define		GPIO3	3
#define		GPIO4	4
#define		GPIO5	5

#define		b_GPIO0	GPIO,0
#define		b_GPIO1	GPIO,1
#define		b_GPIO2	GPIO,2
#define		b_GPIO3	GPIO,3
#define		b_GPIO4	GPIO,4
#define		b_GPIO5	GPIO,5


#define		RS232	2
#define		b_RS232Out GPIO,RS232

		cblock	07h
OutByte
Temp
Count
Key0
Key1
Old0
Old1
Edge0
Edge1
KeyCount
		endc

KeyDelay	equ	35	;delay in 100th second until repeat kicks in
KeyRepeat	equ	10	;delay between repeated keys


		org     0h

;********************************************************************
;	4 meg clock = 1.0 meg instructions


		org     0h
		movwf	OSCCAL		;write calibration value

start		movlw	0
		OPTION
	#ifdef	Inverted
		bcf	b_RS232Out	;ensure RS232 is high
	#else
		bsf	b_RS232Out	;ensure RS232 is high
	#endif
		movlw	b'11111111'-(1<<RS232)
		TRIS	GPIO		;all input except RS232 output


		call	Wait100th
		call	Wait100th

Loop		Call	Wait100th	;needed for timing and debounce
		movfw	Key0
		movwf	Old0		;keep copy of previous keys
		movfw	Key1
		movwf	Old1
		call	ReadKeys	;read the key matrix into Key0 and Key1
		movfw	Key0
		iorwf	Key1,W		;any key pressed
		btfsc	STATUS,Z
		goto	Loop
		movfw	Key0		;get key state
		xorwf	Old0,W		;keep changed bits (pressed and released)
		andwf	Key0,W		;keep only new presses
		btfss	STATUS,Z
		goto	NewKeyDown
		movfw	Key1
		xorwf	Old1,W
		andwf	Key1,W
		btfsc	STATUS,Z
		goto	KeySame	
NewKeyDown	movlw	KeyDelay	;start key delay
		movwf	KeyCount	
		movfw	Key0		;edge = (key^old)&key
		xorwf	Old0,W
		andwf	Key0,W
		movwf	Edge0		;edges contains a 1 for each new key press
		movfw	Key1
		xorwf	Old1,W
		andwf	Key1,W
		movwf	Edge1
		goto	HaveKey
KeySame		decfsz	KeyCount,F	;key delay
		goto	Loop
		movlw	KeyDelay	;if KeyDelay is zero
		iorlw	0		;then no repeat allowed
		btfsc	STATUS,Z
		goto	Loop
		movlw	KeyRepeat
		movwf	KeyCount
HaveKey
;	having got to here then a key is pressed for the first time
;	or the repeat time is up and so it needs repeating.
;	Edge0 or Edge1 contain the key pressed.

		movfw	Edge0		;does edge0 have a bit set
		btfsc	STATUS,Z
		goto	IsEdge1		;no so must be edge1
		movwf	Temp
		movlw	255		;set count to -1
		goto	CountBits
IsEdge1		movfw	Edge1		;move edge1 
		movwf	Temp		;into temp and
		movlw	7		;count to 7
CountBits	movwf	Count
		bsf	STATUS,C	;ensure it can't get stuck in loop
CountBitsL	incf	Count,F		;increment counter
		rrf	Temp,F		;until we find a set bit
		btfss	STATUS,C
		goto	CountBitsL
		movfw	Count		;W=key number 0-15
		Call	Bit2Key		;convert to key character
		call	Send		;send key via RS232
		goto	Loop



ReadKeys	movlw	0<<NOT_GPPU		;   WPUs ON
		OPTION
		movlw	b'11111111'-(1<<GPIO5)-(1<<RS232)
		tris	GPIO			;make I/O 5 output
		bcf	b_GPIO5			;and make it low
		call	BitDelay		;avoid RMW
		clrf	Key0			;will hold key state
		btfss	b_GPIO0			;if I/O 0 low then key pressed
		bsf	Key0,0			;so set the bit
		btfss	b_GPIO1			;repeat
		bsf	Key0,1			;for
		btfss	b_GPIO3			;other
		bsf	Key0,2			;keys
		movlw	b'11111111'-(1<<GPIO4)-(1<<RS232)
		tris	GPIO			;make I/O 4 output
		bcf	b_GPIO4			;and make it low
		Call	BitDelay
		btfss	b_GPIO0			;read next row
		bsf	Key0,4
		btfss	b_GPIO1
		bsf	Key0,5
		btfss	b_GPIO3
		bsf	Key0,6
		movlw	1<<NOT_GPPU		;WPUs OFF
		OPTION
		movlw	b'11111111'-(1<<GPIO5)-(1<<RS232)
		tris	GPIO			;make I/O 5 output
		bsf	b_GPIO5			;and make it high
		call	BitDelay
		clrf	Key1
		btfsc	b_GPIO0			;I/O 0 will be pulled low by
		bsf	Key1,0			;220k resistors unless key pressed
		btfsc	b_GPIO1
		bsf	Key1,1			;same for rest of row
		btfsc	b_GPIO3
		bsf	Key1,2
		movlw	b'11111111'-(1<<GPIO4)-(1<<RS232)
		tris	GPIO			;make I/O 4 output
		bsf	b_GPIO4			;and high
		call	BitDelay
		btfsc	b_GPIO0
		bsf	Key1,4			;read next row
		btfsc	b_GPIO1
		bsf	Key1,5
		btfsc	b_GPIO3
		bsf	Key1,6
		retlw	0
		
Bit2Key		andlw	15
KeyTable	addwf	PCL,F
		retlw	'7'
		retlw	'8'
		retlw	'9'
		retlw	'x'
		retlw	'1'
		retlw	'2'
		retlw	'3'
		retlw	'x'
		retlw	'*'
		retlw	'0'
		retlw	'#'
		retlw	'x'
		retlw	'4'
		retlw	'5'
		retlw	'6'
		retlw	'x'

	#ifdef	Inverted

Send		movwf	OutByte
		bsf	b_RS232Out
		call	BitDelay
		bsf	STATUS,C
SendLoop	rrf	OutByte,F
		movfw	OutByte
		btfsc	STATUS,Z
		goto	EndTransmit
		bsf	b_RS232Out
		btfsc	STATUS,C
		bcf	b_RS232Out
		call	BitDelay
		bcf	STATUS,C
		goto	SendLoop
EndTransmit	bcf	b_RS232Out
		call	BitDelay
		call	BitDelay
		retlw	0

	#else

Send		movwf	OutByte
		bcf	b_RS232Out
		call	BitDelay
		bsf	STATUS,C
SendLoop	rrf	OutByte,F
		movfw	OutByte
		btfsc	STATUS,Z
		goto	EndTransmit
		bcf	b_RS232Out
		btfsc	STATUS,C
		bsf	b_RS232Out
		call	BitDelay
		bcf	STATUS,C
		goto	SendLoop
EndTransmit	bsf	b_RS232Out
		call	BitDelay
		call	BitDelay
		retlw	0

	#endif


; at 1 meg instructions and 2400 baud
; delay is 1,000,000/2400 = 416 cc
; the calling loop and the call/return = 13
; therefore delay needs to be 403 cycles

; to change to 9600 baud
; delay needs to be 104 - 13 = 91
; which would be (3*30)-1 = 89 + 2 = 91

BitDelay	movlw	30	;134	change back to 134 for 2400 baud
		movwf	Temp
DelayLoop	decfsz	Temp,F;		(3*134)-1 = 401 + 2 = 403
		goto	DelayLoop
		retlw	0

Wait100th	clrf	Count
		movlw	13
		movwf	Temp
Delay100L	decfsz	Count,F;	(256*3)-1 = 767
		goto	Delay100L
		decfsz	Temp,F;		(13*(767+3))-1 = 10009 + 3 = 10012
		goto	Delay100L
		retlw	0

		END
A video.


Note, this will not work with newer pic chips as they don't have the WPU on I/O 3.

<edit>Somethings I forgot,
The connections from left to right are GND, RS232 out and 5V.
The output is TTL and so can be connected straight to a pic RX pin without a MAX232 chip.
If you want an inverted signal to connect to a PC then uncomment the #define inverted line in the source.
You can change the repeat delay and repeat rate in the source.
</edit>

Mike.
Attached Thumbnails
RS232 keypad with autorepeat and 2 key rollover.-board-b-w.pngW.png
Views:	42
Size:	18.8 KB
ID:	25272  

Last edited by Pommie; 12th January 2009 at 10:49 AM.
Pommie is online now  
Old 12th January 2009, 09:53 AM   #2 (permalink)
Default

Wow what a smooth functioning same like a PC keyboard.

Again a very nice compact project.Nicely done
__________________
Gayan

My Website
http://gsmicro.blogspot.com/
Gayan Soyza is offline  
Old 12th January 2009, 10:04 AM   #3 (permalink)
Default

Excellent report Pommie, a pleasure to view, and very informative.
bassnut is offline  
Old 12th January 2009, 10:51 AM   #4 (permalink)
Default

Quote:
Originally Posted by Gayan Soyza View Post
Wow what a smooth functioning same like a PC keyboard.
Hi Gayan,

It behaves exactly like a PC keyboard. You can even set the repeat delay and repeat speed the same as a PC keyboard.

Mike.
Pommie is online now  
Old 12th January 2009, 02:49 PM   #5 (permalink)
Default

Mike, you're posting these interesting projects too fast.

I'm still studying the rom search algorithm in your DS18x20 project code (grin).

Regards, Mike
Mike, K8LH is online now  
Old 12th January 2009, 03:02 PM   #6 (permalink)
Default

Quote:
Originally Posted by Mike, K8LH View Post
Mike, you're posting these interesting projects too fast.
I actually wrote this code about 2 years ago and have just gotten around to posting it and so you'll probably have a few years to study these two before there is any more.

As far as I am aware I think this is the first charlieplexed(ish) keypad code/circuit around. It reads 12 keys with 5 I/O pins so not quite n*(n-1).

Mike.
Pommie is online now  
Old 12th January 2009, 10:48 PM   #7 (permalink)
Default

I dismissed the idea of using a standard multiplexed keypad in a Charlieplexed matrix a long time ago because of the "float" pin wiring. I never thought of using an additional pin to get around the problem.

Be careful Mike, there are moments when you could be mistaken for a bloomin' genius (grin).

Nice job. I look forware to studying the code, as always.

Mike, K8LH
Mike, K8LH is online now  
Old 13th January 2009, 08:48 AM   #8 (permalink)
Default

Quote:
Originally Posted by Pommie View Post
Note, this will not work with newer pic chips as they don't have the WPU on I/O 3.
I have tried all kind of external hardware tricks trying to provide a HIGH to the GPIO3 pin to mimic missing WPU so your code can also be used for newer 8-pin PICs like 12F629, 12F635 or 12F675 but so far all my efforts failed.

It is so d*** hard to do just that.
__________________
L.Chung
eblc1388 is offline  
Old 13th January 2009, 09:23 AM   #9 (permalink)
Default

Quote:
Originally Posted by eblc1388 View Post
I have tried all kind of external hardware tricks trying to provide a HIGH to the GPIO3 pin to mimic missing WPU so your code can also be used for newer 8-pin PICs like 12F629, 12F635 or 12F675 but so far all my efforts failed.

It is so d*** hard to do just that.
Believe me I've tried. I wanted to make a combination lock with one of the newer 8 pin chips and store the code in EEPROM. Alas, it's not doable because of that missing WPU.

Doing a combination lock with a fixed code would be doable with the above code but that wouldn't be much use, or would it?

Mike.
Pommie is online now  
Old 13th January 2009, 09:28 AM   #10 (permalink)
Default

What about using 1 wire keypad & measure the AD Value to detect which key has pressed like (Kifo) did his keypad thing?Never tried auto repeat feature with that method.May be a good project
__________________
Gayan

My Website
http://gsmicro.blogspot.com/

Last edited by Gayan Soyza; 13th January 2009 at 09:32 AM.
Gayan Soyza is offline  
Old 11th April 2009, 12:57 PM   #11 (permalink)
Default

what type capacitor u use??

Last edited by zedy22; 11th April 2009 at 12:58 PM.
zedy22 is offline  
Old 15th April 2009, 10:46 PM   #12 (permalink)
Default

nice project
camelush is offline  
Old 1st June 2009, 11:20 AM   #13 (permalink)
Default

good project
red light is offline  
Old 2nd June 2009, 10:07 AM   #14 (permalink)
Default

Quote:
Originally Posted by Pommie View Post
Believe me I've tried. I wanted to make a combination lock with one of the newer 8 pin chips and store the code in EEPROM. Alas, it's not doable because of that missing WPU.
Don't give up so soon! There's more ways to skin this cat. For the cost of an extra resistor you can remove all pullups.

Or use 4 I/O lines, 3 resistors and 3 capacitors for the keypad.

Or use 1 I/O line, 5 resistors & 3 caps...

See attached schems for examples. I'm sure there's more ways that I haven't thought of..

Quote:
Originally Posted by Pommie View Post
Doing a combination lock with a fixed code would be doable with the above code but that wouldn't be much use, or would it?
Of course it would. The single fixed code could be the 'master reset' code, which could be entered to set the other code(s). So long as power is never interrupted (e.g. it's on batteries), then the code(s) remains. If the pic's in sleep most of the time, battery changes may not be for years.
Attached Files
File Type: pdf MATRIX_DEC.PDF (33.4 KB, 23 views)
dougy83 is online now  
Old 2nd June 2009, 12:58 PM   #15 (permalink)
Default

I don't like any scheme that involves analogue voltages or timed RC solutions as it really messes up the simple debounce and 2 key rollover code. However, the third diagram is interesting. Can you explain how you read this matrix?

Mike.
Pommie is online now  
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Title Starter Forum Replies Latest
Lizard PIC16F628A LCD, 4x4 keypad, relay, buzzer RS232 William At MyBlueRoom Electronic Projects Design/Ideas/Reviews 0 13th October 2006 04:19 PM
keypad help... jrz126 Micro Controllers 6 8th November 2005 11:47 PM
keypad in a RC car dukeoverl General Electronics Chat 1 14th December 2004 06:33 PM
rs232 to rs232 data logger with 1meg buffer -help needed ccaammaaccaazzii Electronic Projects Design/Ideas/Reviews 11 20th October 2004 09:43 PM
Keypad ? lil_sti Electronic Projects Design/Ideas/Reviews 2 6th March 2004 02:31 PM



All times are GMT. The time now is 02:17 AM.


Electronic Circuits  |  Learning Electronics
eXTReMe Tracker