4x4
KEYPAD
P2 - Keypad Controller


There are many 4x4 Keypads on the market (including eBay) and some of them are less than $3.00
This makes them idea for inclusion in a project.
The only problem is interfacing them.
Almost all keypads have a "row and column" connection to the switches and this produces 8 lines.
If you are using a microcontroller with lots of in/out lines, you can directly connect the keypad to the micro.
But if you have a limited number of in-out lines, you need to devise a clever way to reduce the number of interface lines.
The cleverest interface can be done with a single line.
It uses a capacitor and a ladder of resistors to generate a "time delay" and the timing generates the correct key.
To get the timing correct, the value of the resistors and capacitor must be the same as the prototype we have produced because the program has pre-set time-delay values.
Resistor-values are very close to the specified value but capacitor-values can be 20% higher or lower. That's why the capacitor you use must be tested before-hand with a capacitance meter to make sure it is very close to 1n.
The circuit and program works like this:
The keypad is looked-at on a regular basis via a loop in the program and the input-output line is taken HIGH to charge the 1n capacitor. It is then turned into an input and after a delay of a few milliseconds, the line is looked-at to see if it is still HIGH. If a switch is pressed, the capacitor will have been discharged.
The program now knows if a switch is pressed, so the capacitor is charged again and looked-at every few microseconds to determine how long it takes to discharge.
The micro exits the sub-routine with the key-value.
We have also provided a separate "test-routine" that blinks a LED to indicate the number of the key. The LED flashes 5 times for key-5 etc.
Once you get the keypad working, you can add the sub-routine to your project by "copy-and-paste."
There are many different keypads on the market and we have included photos and prices of some from eBay, where the prices are the lowest and postage is FREE.
Ebay gives you a guarantee of quality (and receiving the item) and purchasing on eBay is only a few clicks of the mouse.  It is the fastest, most-convenient and cheapest way to buy things.

Switch 16 has a resistance of 47k, switch 15 has a resistance of 47k + 12k, switch 14 has a resistance of 47k + 12k + 12k, switch 13 has a resistance of 47k + 12k + 12k + 12k, switch 12 has a resistance of 47k + 47k etc.
You can see each switch has an increased resistance of either 12k or 11k. This resistance adds to the time to discharge the 1n capacitor and the sub-routine exits with the correct key.

INSTRUCTIONS TO SET THE KEY-VALUES
Turn the project OFF.
Push key16 and keep pressed.
Turn ON project.
Release key16.
Push key1  - LED will flash briefly
Push key2 to key16.
Push key1 and LED will flash slowly.
Turn project OFF.    Key-values are now in EEPROM.
Turn Project ON. Push key1 and LED will flash once.

 Here are two more 4x4 keypads:

 

 



 

Here is another 4x4 keypad with extra 4 red buttons that connect directly to the middle set of pins for extra functions in your project, plus a set of 8 LEDs that connect to the bottom set of pins. These LEDs can be used to indicate up to 8 different HIGH's from your project. 


Testing the 4x4 Keyboard on an "Experimental Board"


Close-up of the surface-mount components


The Interface board using through-hole components

To prove the effectiveness of automatically creating key-values, we made an interface board with through-hole components and a 1n capacitor. The detection worked perfectly.
Many keypad routines have been described on the web using a PIC based development system called BASIC STAMP,  Arduino and others using programming languages (including C) but none have added the feature of automatically detecting the key-values and that's why this program is so reliable. You can change the interface board and the program will still produce accurate results. Apart from that, we have shown how it is done. There is no mystery with hidden instructions and no high-level language to read and understand. You can take the instructions and add them to your own program to produce a more-complex design.     


 

The output for the 16 keys, 4 red LEDs and 8 LEDs:





THE PROGRAM
The program detects key16 first as it takes the shortest time to discharge the 1n capacitor.
When the program comes to detecting key 1, any slight increase or decrease in the value of the capacitor will be multiplied 16 times and key 1 will not be detected. That's why the capacitor must be exactly 1,000p (1n).
Another way to explain the problem is this:
You are looking through a hole in a wall that is 16 bricks from the ground. You pile-up 16 bricks from a different suppler but these bricks are not quite the same. When it comes to the 16th brick, the pile is less than the bricks in the wall.
Let's explain it a bit more accurately.
The program detects key1 after about 40 loops of a 6uS delay when using our 1n capacitor, but if a 1n capacitor with a slightly higher reading will take 41 or 42 loops.
That's why you need to produce a table of timing values that apply to the capacitor and resistor-ladder you have selected.
To prevent the keys being incorrectly detected, the program automatically produces a value for each key from the components you have used, and holds it in EEPROM memory.
These values are download each time the micro is turned ON and loaded into locations 50h to 5Fh, (at the top-end of the General Purpose Register's  - GPR's).
The program also shows how to access EEPROM for writing and reading.
When the micro is first turned ON, the EEPROM is empty.
To place key-values in EEPROM, press key16 and turn the project ON. The indicator LED will flash once.
Now press key1 for 0.5 seconds, then key 2, 3, 4, 5  . . . etc to key 16.
Each time the key is pressed and released, the key-value is placed in a set of temporary files and the indicator LED flashes. After key16, press key1 and the indicator LED keeps flashing at a low rate.
Now switch the project OFF and ON again. It is now ready to detect the keys.
We have added another "test" routine that will need to be deleted when you add sub-routines.
The test routine produces flashes to correspond to the key number.
Simply turn the project ON and press key1. The LED will flash once. Push key16 and it will flash 16 times.
The program is obviously much larger than a simple key-detect routine because it needs to do a lot of things in the process of creating automatic key-values.
This program becomes the basis of any project requiring a 4x4 keypad and you simply add sub-routines to what we have already produced. After adding a few lines of code, give the program a new name so you can go back to older versions if a mistake is made.

The files:
4x4.asm
4x4.txt
4x4.hex

		
;*******************************
;4x4 Keypad.asm
;KEYPAD DEMONSTRATION PROGRAM
;Tests 4x4 keypad and flashes LED to indicate key number
;Keypad does not control any devices 
;  13-6-2013 
;*******************************


	list	p=12F629
	radix	dec
	include	"p12f629.inc"
	
	errorlevel -302	; Dont complain about BANK 1 Registers during assembly

	__CONFIG _MCLRE_OFF & _CP_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT  

;_MCLRE_OFF  - master clear must be off for gp3 to work as input pin 

;****************************************************************
; variables - names and files
;****************************************************************

	Cblock  20h
temp1	    	;used in delays
temp2		;used in delays
temp3		;used in delays
temp16          ;16 keys
flashes		;LED flashes to indicate key number
loops 
SwFlags      

        endc

;****************************************************************
;Equates
;****************************************************************
status		equ	0x03
rp1		equ	0x06
rp0		equ	0x05
GPIO 		equ 	0x05
			

status		equ	03h
option_reg	equ 	81h


	; bits on GPIO
				
pin7		equ	0	;GP0  LED - flashes to indicate key number
pin6	 	equ	1	;GP1  
pin5		equ	2	;GP2  
pin4		equ	3	;GP3  
pin3		equ	4	;GP4  
pin2		equ	5	;GP5  4x4 Keypad switches   
 

	;bits
				
rp0		equ	5	;bit 5 of the status register




;****************************************************************
;Beginning of program
;****************************************************************
	org	0x00
	nop
	nop
	nop
	nop
	nop			
SetUp	bsf	status, rp0 	;Bank 1			
       	movlw	b'11001000'	;Set TRIS GP0,1,2,4,5 out   GP3 not used
	movwf	TRISIO	
	bcf	status, rp0	;bank 0
	movlw   07h         	;turn off Comparator ports
        movwf   CMCON       	;must be placed in bank 0  
	clrf 	GPIO       		;Clear GPIO of junk			
	movlw	4Fh             ;start of GPR's
	movwf	fsr
	call    NoKey           ;see if a switch is pressed
	btfss   SwFlags,1       ;test bit1 for switch pressed
	goto    SetUp2          ;load 50h to 5Fh from EEPROM
	call    GenKeyvalue     ;to see if key16 is pressed before start-up.
	movlw   0Ch             ;Put a value into W and perform SUBWF
	subwf   loops,1         ;Carry flag is CLEAR if W is greater than file value 
        btfsc   03,c            ;Test carry flag 
	goto    SetUp2		
	movlw   .16
	movwf   temp16          ;for 16 keys
		
	call    NoKey           ;test bit1 for switch pressed 
	btfsc   SwFlags,1       ;detect no key pressed for debounce	
	goto    $-2
	bsf     gpio,0          ;flash LED briefly
	call    _10mS
	bcf     gpio,0
	call    _10mS
		
	call    NoKey           ;test bit1 for switch pressed 
	btfss   SwFlags,1       ;detect key pressed for debounce	
	goto    $-2
			
	call    GenKeyvalue     ;get number of loops 
					
    	incf	fsr,f	        ;fsr starts at file 50h   Store 16 key-values
	movf    loops,w         ;move number of loops into w
	movwf	indf	        ;put loops into file 50h to 5Fh
	decfsz	temp16,f
	goto    $-.15
		
	call    toEEPROM        ;put 16 values into EEPROM
	
	bsf     gpio,0          ;added
	call    _500mS
	bcf     gpio,0
	call    _500mS
	goto    $-4            ;keeps flashing - turn off project        
		
		 

         ;load files 50h to 5Fh with key values from EEPROM
         

SetUp2  
	bsf	status,rp0	;select bank1	
	clrf	eeadr		;start EEPROM at location 0		
	bcf	status,rp0	;select bank0		
	movlw   .16
	movwf   temp16      ;for 16 keys
	movlw	4Fh         ;start of GPR's
	movwf	fsr
	incf	fsr,f	    ;fsr starts at file 50h	
	bsf	status,rp0							
	bsf	EECON1,0	;starts EEPROM read operation storing result in EEDATA
	movf	EEDATA,w	;move read data into w
	bcf	status,rp0				
	movwf	indf	    ;put EEPROM data into file 50h to 5Fh
	bsf	status,rp0	;select bank1	
	incf	eeadr,1						
	bcf		status,rp0	;select bank0
	decfsz	temp16,f
	goto	$-.10
	goto    Main		
		


;********************************
;* Delays 			*
;********************************

_uS     goto	$+1        
_uS_1   goto	$+1	
        goto	$+1 
        retlw   00



_1mS	movlw   80h
        movwf   temp1
	nop
	decfsz 	temp1,f
        goto 	$-2			
	retlw 	00	
		
		
		
_10mS	movlw	0Ah
	movwf	temp2
_10	nop
	decfsz 	temp1,f
	goto 	_10
	decfsz 	temp2,f
	goto 	_10	
	retlw 	00		
		


_100mS	movlw	.100
	movwf	temp2
_100	nop
	decfsz 	temp1,f
	goto 	_100
	decfsz 	temp2,f
	goto 	_100	
	retlw 	00	
		
		

		
_500mS	movlw   5			
	movwf   temp3
	call	_100mS		
	decfsz  temp3,1
	goto    $-2
	retlw   00

;****************************************
;* Sub Routines 			*
;****************************************
	
	
  
        ;detect key16 at start-up to generate key-loops for storage in EEPROM
	;this sub-routine also detects a pressed-key and
	;returns with a value in "loops"
			
GenKeyvalue				
	clrf    loops      	
	bsf	status, rp0 	;Bank 1	    	
	bcf 	TRISIO,5	;clear bit GPIO,5 as output to charge cap.
	bcf	status, rp0	;bank 0
	bsf	gpio,5		;make pin2 HIGH to charge cap. 
	call	_10mS           ;charge cap
	bsf	status, rp0 	;Bank 1			
       	bsf 	TRISIO,5	;set TRIS GP0,5 to detect discharged cap
	bcf	status, rp0	;bank 0			
	call	_uS		
	incf    loops,1
	btfsc   gpio,5
	goto	$-3           
	retlw   00              ;return with value in loops
		
	;NoKey - detect no key pressed 
	
	
NoKey	bcf     SwFlags,1
	bsf	status, rp0 	;Bank 1	 (see if switch is pressed)    	
	bcf 	TRISIO,5	;clear bit GPIO,5 as output to charge cap.
	bcf	status, rp0	;bank 0
	bsf	gpio,5		;make pin2 HIGH to charge cap. 
	call	_10mS           ;charge cap		
	bsf	status, rp0 	;Bank 1			
       	bsf 	TRISIO,5	;set TRIS GP0,5 to detect discharged cap
	bcf	status, rp0	;bank 0					
	call	_1mS		
	btfsc   gpio,5
        retlw	00		;no switch pressed
        bsf     SwFlags,1
	retlw	00	        ;key pressed - bsf SwFlags,1
		
		
	;ShowKey shows the key value via LED flashes
ShowKey		
	bsf     gpio,0          ;
	call    _500mS
	bcf     gpio,0
	call    _500mS
	decfsz  flashes,1
	goto    $-5            ;
	goto    Main
		
		
	;TestKeys is a test routine that flashes the key number
		
TestKeys	
        clrf   loops
	clrf   flashes
	incf   flashes,1
	call   GenKeyvalue
	movf   loops,w   ;
	xorwf  50h,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  51h,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  52h,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  53h,w
	btfsc   03,z		
	goto   ShowKey	
	incf   flashes,1
	movf   loops,w   ;
	xorwf  54h,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  55h,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  56h,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  57h,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  58h,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  59h,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  5Ah,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  5Bh,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  5Ch,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  5Dh,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  5Eh,w
	btfsc   03,z		
	goto   ShowKey		
	incf   flashes,1
	movf   loops,w   ;
	xorwf  5Fh,w
	btfsc   03,z		
	goto   ShowKey		
	retlw  00
		    
		
	;after 16 keys  . . . .
	;put number of loops in 50h to 5Fh into EEPROM	
				
		
toEEPROM
	bsf	status,rp0	;select bank1	
	clrf	eeadr		;start EEPROM at location 0
	bcf	status,rp0	;select bank0		
	movlw   .16
	movwf   temp16      ;for 16 keys
	movlw	4Fh         ;start of GPR's
	movwf	fsr
	incf	fsr,f	    ;fsr starts at file 50h
	movf	indf,w	    ;retrieve data in file 50h to5Fh
	bsf	status,rp0	;select bank1	
	movwf	eedata		; 
	bcf	status,rp0	;select bank0
	call 	write
	bsf	status,rp0	;select bank1	
	incf	eeadr,1						
	bcf	status,rp0	;select bank0
	decfsz	temp16,f
	goto	$-10
	retlw   00
		
		
write	bsf	status,rp0	;select bank1	
	bsf	eecon1,wren	;enable write		
	movlw	55h 		;unlock codes
	movwf	eecon2
	movlw	0aah
	movwf	eecon2
	bsf	eecon1,wr	;write begins
	bcf	status,rp0	;select bank0		
writeA	btfss	pir1,eeif	;wait for write to complete
	goto	writeA
	bcf	pir1,eeif
	bsf	status,rp0	;select bank1
	bcf	eecon1,wren	;disable other writes
	bcf	status,rp0	;select bank0	
	retlw	00			
		
	

;************************
;* Main 		*
;************************

Main	
	call   TestKeys		
	goto   Main	
				
					
							
	END
		


For the next project in this series, using the 4x4 KeyPad, go to:
KeyPadController

ooo00000oooo

11-7-2013