Wow, I just realised I created this project back in May 2008… I think the principal and technique used for the keypad is worth explaining however so I’m publishing it now.
When my local repeater GB3PY started providing Echolink access my shack radio was an Icom IC-910 which does not support DTMF to control Echolink. This meant I was unable to connect to nodes or disconnect nodes.
The answer for me was to build my own DTMF keypad, and this was a good excuse to learn how to interface a keypad into a PICAXE.
The schematic was below shows I used a PICAXE-20M which ‘scanned’ the keypad and when an input was detected enabled the PTT via Q2 then generated the DTMF tones using an HT9200B chip.
There are a couple of methods to read a keypad input, I used the ‘scanning’ method but a simpler way might be using ADC.
Keypad Scanning
Explaining the scanning method is harder than it actually is, but lets give it a go. The keypad us divided into ROWs and COLUMNS, in a HEX keypad (those with *, # and A-D) there are 4 of each
If we pressed the ‘0’ key then it would create a connection between ROW4 with COL2 which is a unique ROW/COL combination we can use to identify which key is pressed. An issue arises though when it comes to reading this same unique combination using a PIC we need to read a voltage, but on the ROW or COL line?
Lets say we supply a voltage to all ROWs so when a key is pressed a voltage appears on the corresponding COLUMN (you can swap COLUMNs and ROWs around in hardware implementation if you wish but you will see one way works better than the other), if we pressed the ‘6’ key then we would get the ROW2 +5v voltage on COL3. But wait a minute, we would also get +5v on COL3 if we pressed keys ‘3’, ‘6’, ’9’ or ‘B’. This is no use now is it!
The solution is quite simple in fact. The voltage supplied to each ROW comes from an output of the PIC and so can be ‘scanned’ when an input is detected. The code in the PIC sits with all outputs high so all ROWs have +5v on them waiting for any key to be pressed, when it detects a key has been pressed, as a voltage will appear on a COL line, it switches the outputs off and then turns each one on individually in turn until it finds which COLUMN has the voltage on it. This means means we know only one ROW has a voltage on it and which COL the key has connected it to and therefor the button pressed, this is how the scanning works. Additionally we connect the ROW voltage to the higher bits of the PIC inputs meaning we can add the ROW bit to the COL bit to create a unique value, as using just the 4 COL inputs means we can only have 4 values, bits 1, 2, 4 & 8 (pins 1, 2, 3 & 4) but adding the ROW also gives us bits 16, 32, 64, 128 (pins 5, 6, 7 & 8 ) to add meaning key 6 (COL3& ROW2) gives 4+32 (36). The PIC can then assign a value to the key, it can convert 36 to 6 using a lookup table.
Keypad ADC
The other method is to use a bunch of resistors and the supply voltage to create a unique voltage (ADC value) for each key press;
This can simplify the method but adds much more components to the BOM and will also be less accurate, poor switch contact resistance for instance will result in the wrong key value being read. Also as this is a project designed to be used in an RF environment, the RF could induce voltage into the keypad causing the ADC to read a wrong value for the key pressed.
The PIC will still need to translate the detected value into the real key value, but the advantage is only one PIC input is needed to read all 16 keys. 4 outputs and 8 inputs are needed for the ROW and COL scanning method.
The Project Goals
When I planned this project I wanted it to have 2 modes, one mode would send DTMF and the other CAT or CI-V frequency control. Pressing something like the ‘A’ for 3 seconds would toggle modes. I never did implement the CI-V aspect into this project but the DTMF worked fine.
PICAXE Code
'Define Inputs and Outputs and Registers ' 'Inputs 'Logic Use Physical 'In 0 Keypad Row 4 3 'In 1 Keypad Row 3 4 'In 2 Keypad Row 2 5 'In 3 Keypad Row 1 6 'In 4 Keypad Column 4 7 'In 5 Keypad Column 3 8 'In 6 Keypad Column 2 9 'In 7 Keypad Column 1 10 ' ' 'Outputs 'Logic Use Physical 'Out 0 In 7 & DTMF D0 18 'Out 1 In 6 & DTMF D1 17 'Out 2 In 5 & DTMF D2 16 'Out 3 In 4 & DTMF D3 15 'Out 4 DTMF Enable 14 'Out 5 Serial TX 13 'Out 6 PTT 12 'Out 7 **Unused 11 ' ' 'Registers 'Register Use 'B10 Key_Value 'B11 Row Scan 'B12 TX Timer 'B13 Mode (1 for DTMF and 2 for CAT) SYMBOL key_value = B10 SYMBOL row_scan = B11 SYMBOL Tx_timer = B12 SYMBOL Mode = B13 SETFREQ M8 EEPROM 0,("123A456B789*0#D") 'Load 16 keypad real numbers/chracters into memory Mode = 1 pause 2000 start: high 4 If Mode = 1 then goto DTMF_Mode If Mode = 2 then goto CAT_Mode DTMF_Mode: if Tx_timer = 0 then low 6 else dec Tx_timer endif 'debug Tx_timer gosub check_keys if key_value = 0 then goto start 'debug ROW_SCAN 'debug key_value pins = key_value Tx_timer = 50 high 6 low 4 pause 1000 key_value = 0 goto start CAT_Mode: goto start check_keys: row_scan = 1 'if row 1 key value will be between 1 and 4 high 2 'set to high to provide voltage to keypad row1 gosub check_column low 2 row_scan = 4 'if row 2 key value will be between 5 and 8 high 3 'set to high to provide voltage to keypad row2 gosub check_column low 3 row_scan = 7 'if row 3 key value will be between 9 and 12 high 1 'set to high to provide voltage to keypad row3 gosub check_column low 1 row_scan = 11 'if row 4 key value will be between 12 and 16 high 0 'set to high to provide voltage to keypad row4 gosub check_column low 0 'test the input pins for which column the key is in return check_column: if pin0 = 1 then gosub first'column if pin1 = 1 then gosub second'column if pin2 = 1 then gosub third'column if pin3 = 1 then gosub forth'column return first:'column key_value = row_scan 'No addition required, column number [1] return second:'column key_value = row_scan + 1 'This is row number + column number [2] return third:'column key_value = row_scan + 2 'This is row number + column number [3] return forth:'column if row_scan = 1 then key_value = 13 else endif if row_scan = 4 then key_value = 14 else endif if row_scan = 7 then key_value = 15 else endif if row_scan = 11 then key_value = 0 else endif 'key_value = row_scan + 4 'This is row number + column number [4] return