some pointers please???

Tim Vukman

New Member
The code below is for a "simple" clock that I wish to use a keypad to provide settings for.

Some of it seems to work great on it's own (displaying the digits if manually set) and fetching the hex values from the keypad, but I seem to have no consistent results when I try to put it together.

In this latest version (I'm too embarrassed to number them) I will capture the high on input to to fire the interrupt and I will get a result on the first run through the scan_keys. On the second run through scan_keys it may or may not recognize that a key is pressed.

Ideally I would like it to stop on interrupt, take four key presses and then process the information when I press "settime"; while echoing it to the display digits. I haven't started on the echo part yet as I can't seem to find a way to work through getting the four digits.

My keypad is returning what I expect although the scan_keys doesn't always start at the beginning.

I have single stepped my way through this and I'm not seeing the problem.

Any advice would be greatly appreciated.

Thanks

TimV

' picaxe 28x at 4mhz
' clock base code
' keypad wired with four rows attached to 28X outputs
' and four columns attached to inputs
' four input wires are tied low with 10k
' inputs also have diode leaving each of the four and joined at bar end
' from bar end of 4 diodes a single wire goes to Input Pin2
' which is also tied low with 10k
' set each output high and then interrupt for pin2 high meaning key press has happened

i2cslave %11010000, i2cslow, i2cbyte 'initialize rtc
pause 100
' ********output definitions***********

symbol dataout = 7 'output pin to 4 74LS595 latches
symbol clk = 6 'output pin to clock output to latches
symbol latchout = 5 'output pin to release latches

' ********variable definitions*********

symbol temp = b0
symbol key_pressed = b1
symbol bitcounter = b2 'used in display routine to count bits
symbol outbit = b3 'used to isolate bit in display routine
symbol outbyte = b4 'used to carry byte to latch
symbol outnibl = b5 'used to isolate value from rtc
symbol key_val = b6 'used to get hex value of key pressed
symbol minutes = b7 'used to represent minutes in program and rtc
symbol hours = b8 'used to represent hours in program and rtc
symbol temp2 = b9
symbol setnibl = b10 'used to hold hex value of key pressed
'symbol control = %00010000 'used for rtc if needed
symbol scans = b11 'used as counter in keypad scan module

main: 'start of program

minutes = $25 'arbitrary value used for BCD into rtc
hours = $01 'arbitrary value used for BCD into rtc
writei2c 1,(minutes) 'writes BCD Minutes value to rtc
writei2c 2,(hours) 'writes BCD Hours value to rtc
pause 2000 'gives rtc time to settle

loop:
setint %00000100, %00000100 'input pin2 will go high on key pressed
if Pin2 = 1 then Interrupt 'go to the interrupt routine (want next 4 keypresses)
pins = %00000010 'sets row 3 (top) high
pins = %00000100 'sets row 2 high
pins = %00001000 'sets row 1 high
pins = %00010000 'sets row 0 (bottom) high


scan_keys: 'called from interrupt rountine to read keys

key_pressed = 0 'starting point for row3
pins = %00000010 'set output 1 high to provide voltage to keypad col3
gosub key_test 'test the input pins for which column keypress is in
if key_pressed = 1 then Key_Value
if key_pressed = 2 then Key_Value
if key_pressed = 3 then Key_Value
if key_pressed = 4 then Key_Value


key_pressed = 4 'starting point for row2
pins = %00000100 'set output 2 high to provide voltage to keypad col2
gosub key_test 'test the input pins for which column keypress is in
if key_pressed = 5 then Key_Value
if key_pressed = 6 then Key_Value
if key_pressed = 7 then Key_Value
if key_pressed = 8 then Key_Value

key_pressed = 8
pins = %00001000 'set output 3 high to provide voltage to keypad col1
gosub key_test
if key_pressed = 9 then Key_Value
if key_pressed = 10 then Key_Value
if key_pressed = 11 then Key_Value
if key_pressed = 12 then Key_Value

key_pressed = 12
pins = %00010000 'set output 4 high to provide voltage to keypad col0
gosub key_test
if key_pressed = 13 then Key_Value
if key_pressed = 14 then Key_Value
if key_pressed = 15 then Key_Value
if key_pressed = 16 then Key_Value

if scans = 1 then hour10
if scans = 2 then hour01
if scans = 3 then minute10
if scans = 4 then minute01
setint %00000100, %00000100

return 'closes gosub to scan count from "setint" routine

key_test:
if pin1 = 1 then add1 ' to input for row3
if pin5 = 1 then add2 ' to input for row2
if pin6 = 1 then add3 ' to input for row1
if pin7 = 1 then add4 ' to input for row0
goto scan_keys

add4: key_pressed = key_pressed + 1 'id keys 13, 14, 15, 16
add3: key_pressed = key_pressed + 1 'id keys 9, 10, 11, 12
add2: key_pressed = key_pressed + 1 'id keys 5, 6, 7, 8
add1: key_pressed = key_pressed + 1 'id keys 1, 2, 3, 4

Key_Value: 'picks up hex value of key pressed
lookup key_pressed, ($00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $0A, $0B, $0C, $0D, $0E, $0F, $10), key_val
if key_val = $04 then settime 'special function key
if key_val = $08 then settime 'special function key
if key_val = $0C then alarmon 'special function key
if key_val = $0E OR key_val = $10 then snooze ' special function key

return 'closes gosub from interrupt: to key_value: via scan_keys:

settime: 'not written write time to rtc
High 7
return 'closes gosub from interrupt: to key_value: via scan_keys:

setalarm: 'not written hold alarm time to compare to rtc
Low 7
High 6
return 'closes gosub from interrupt: to key_value: via scan_keys:

alarmon: 'not written turn buzzer on / off
low 7
low 6
high 5
return 'closes gosub from interrupt: to key_value: via scan_keys:

snooze: 'not written add 9 minutes to alarm time but don't over write
High 7
return 'closes gosub from interrupt: to key_value: via scan_keys:

hour10:
temp = key_val
return 'closes gosub from interrupt: to key_value: scan loop

hour01:
temp2 = key_val 'b9 = b6
setnibl = temp & $000F 'b10 = b0 & $000F
hours = setnibl * $10 + temp2 'b7 = b1 * $10 + b9
return 'closes gosub from interrupt: to key_value: scan loop

minute10:

return 'closes gosub from interrupt: to key_value: scan loop

minute01:

return 'closes gosub from interrupt: to key_value: scan loop


readi2c 1,(b7) 'confirms value written to rtc from keypad
readi2c 2,(b8) 'same but for hours (minutes line above)

outnibl = b7 & $000F 'isolates right bit of minutes
gosub outdigit 'sends right bit to output routine

outnibl = b7 & $00F0 / 16 'isolates left bit of minutes
gosub outdigit 'sends left bit to output routine

outnibl = b8 & $000F 'isolate right bit of hours
gosub outdigit 'sends right bit to output routine

outnibl = b8 & $00F0 / 16 'isolates left bit of hours
gosub outdigit 'sends left bit to output routine

pulsout latchout, 1
goto loop

outdigit: 'handles getting four digits out in order
lookup outnibl, ($BE, $82, $DC, $D6, $E2, $76, $7E, $92, $FE, $F2, $FA, $6E, $3C, $DE, $7C, $78), outbyte

for bitcounter = 0 to 7
outbit = outbyte & 1
if outbit = 1 then outhi
low dataout
goto clkout
outhi: high dataout
clkout: pulsout clk, 1
outbyte = outbyte / 2
next bitcounter
goto loop 'closes gosub to outdigit: from loop:

Interrupt:
for scans = 0 to 4 'hoping to loop for four key presses
gosub scan_keys
next scans
return
 

Technical

Technical Support
Staff member
There is a fundamental flaw with all your conditional jumps and returns e.g.

if Pin2 = 1 then Interrupt

Interrupt is a sub procedure - ie ends with return. If you 'goto interrupt' as with this line, when the return is processed there will be no data for the return command to use and the program will crash.

Return must alway be paired with a gosub, not a goto type of command (as with if...then goto).

In the interrupt case you should not need to use this goto line at all - processing will jump autmatically to 'interrupt' label when the interrupt condition (as defined by setint) occurs.

In all other case you should correct your returns to gotos

Edited by - Technical on 10/06/2006 23:53:49
 

Tim Vukman

New Member
Thanks for taking the time to look through it. I started adding gotos when things didn't appear to be working properly on the returns.

That was likely caused by what you have pointed out.

I will answer back when I have cleaned it up to report on how it is working

Again
Thanks

Tim
 

Tim Vukman

New Member
Hi Technical
You were absolutely correct and if I single step the code, it is now working as intended.

If I let it run on the 28x, it will capture 1 keystroke and then it ignores anything I want to do.

I will try "pauses" in the keypad routine to give it a chance to capture my input.

The revised code is below and I did streamline the keypad routine.

Is there a way to make the code stop and wait for each keypress?

Thanks

TimV

' picaxe 28x at 4mhz
' clock base code
' keypad wired with four rows attached to 28X outputs
' and four columns attached to inputs
' four input wires are tied low with 10k
' inputs also have diode leaving each of the four and joined at bar end
' from bar end of 4 diodes a single wire goes to Input Pin2
' which is also tied low with 10k
' set each output high and then interrupt for pin2 high meaning key press has happened

i2cslave %11010000, i2cslow, i2cbyte 'initialize rtc
pause 100
' ********output definitions***********

symbol dataout = 7 'output pin to 4 74LS595 latches
symbol clk = 6 'output pin to clock output to latches
symbol latchout = 5 'output pin to release latches

' ********variable definitions*********

symbol key_pos = b0 'used to determine which digit is being processed
symbol key_pressed = b1 'used to determine which key on keypad was pressed
symbol bitcounter = b2 'used in display routine to count bits
symbol outbit = b3 'used to isolate bit in display routine
symbol outbyte = b4 'used to carry byte to latch
symbol outnibl = b5 'used to isolate value from rtc
symbol key_val = b6 'used to get hex value of key pressed
symbol minutes = b7 'used to represent minutes in program and rtc
symbol hours = b8 'used to represent hours in program and rtc
symbol setnibl = b9 'used to calculate tens digit
symbol time10 = b10 'used to hold hex value of 1st and 3rd key pressed
symbol time01 = b11 'used to hold hex value of 2nd and 4th key pressed

main: 'start of program

setint %00000100,%00000100
loop: 'main program loop
high 1 'set each row high in main loop so setint command will fire
high 2 'set next row high
high 3 'set next row high
high 4 'set next row high
goto display 'go update the display with rtc values
interrupt: 'break into display and process keypad scanning routines
goto scan_keys 'head to the scan_keys routine to capture time settings
setint %00000100,%00000100 'reset the interrupt routine
return
'go back to main loop from interrupt routing
scan_keys: 'figure out which keys on keypad are being pressed (loop for 5)
'first is tens of hour, then ones of hours, then tens of minutes
'then ones of minutes, then look for special functions like alarm set
'or alarm on / off
debug
key_pressed = 0 'starting point for row3
pins = %00000010 'set output 1 high to provide voltage to keypad col3
gosub key_test 'test the input pins for which column keypress is in

key_pressed = 4 'starting point for row2
pins = %00000100 'set output 2 high to provide voltage to keypad col2
gosub key_test 'test the input pins for which column keypress is in

key_pressed = 8
pins = %00001000 'set output 3 high to provide voltage to keypad col1
gosub key_test

key_pressed = 12
pins = %00010000 'set output 4 high to provide voltage to keypad col0
gosub key_test

goto loop 'once everything is done, return to main loop to head for display
'update and next request to use keypad

key_test:
if pin1 = 1 then add1 ' to get which key in row3
if pin5 = 1 then add2 ' to get which key in row2
if pin6 = 1 then add3 ' to get which key in row1
if pin7 = 1 then add4 ' to get which key in row0
return 'closes the GOSUB from scan_keys:

add4: key_pressed = key_pressed + 1 'id keys 13, 14, 15, 16
add3: key_pressed = key_pressed + 1 'id keys 9, 10, 11, 12
add2: key_pressed = key_pressed + 1 'id keys 5, 6, 7, 8
add1: key_pressed = key_pressed + 1 'id keys 1, 2, 3, 4

Key_Value: ' picks up hex value of key pressed
lookup key_pressed, ($00, $01, $02, $03, $04, $05, $06, $07, $08, $09, $00, $0B, $0C, $0D, $0E, $0F, $10), key_val
key_pos = key_pos + 1

if key_pos = 1 then hour10s 'go and get hex value for hours tens digit
if key_pos = 2 then hour01s 'go get ones and combine with tens for hour hex value for rtc
if key_pos = 3 then minute10s 'go and get hex value for minutes tens digit
if key_pos = 4 then minute01s 'go get ones and combine with tens for minute hex value to rtc
if key_pos = 5 then special_function 'go and look for special function like snooze or alarm on / off
key_pos = 0 'close out the setting function

goto loop 'and return to main loop for display

special_function:
if key_val = $04 then settime 'special function key
if key_val = $08 then setalarm 'special function key
if key_val = $0C then alarmon 'special function key
if key_val = $0E OR key_val = $10 then snooze ' special function key

goto loop 'return to main loop for display from special functions

hour10s: 'get hours tens digit
if key_val >2 then reset 'make sure digit is valid
time10 = key_val 'set tens digit to variable for later processing
goto scan_keys

hour01s:
key_val = key_val - 1
time01 = key_val
setnibl = time10 & $000F
hours = setnibl * $10 + time01
writei2c 2,(hours)
pause 200
time01 = $00
time10 = $00
setnibl = $00
goto scan_keys

minute10s:
key_val = key_val - 1
if key_val >5 then reset
time10 = key_val
goto scan_keys

minute01s:
key_val = key_val - 1
time01 = key_val
setnibl = time10 & $000F
minutes = setnibl * $10 + time01
writei2c 1,(minutes)
pause 200
time01 = $00
time10 = $00
setnibl = $00
goto scan_keys

reset:
key_pos = 0
high 6
high 7
pause 100
low 6
low 7
pause 100
high 6
high 7
pause 100
low 6
low 7
pause 100
high 6
high 7
pause 100
low 6
low 7
pause 100
goto loop

settime: 'not written write time to rtc
'High 7
goto loop

setalarm: 'not written hold alarm time to compare to rtc
'Low 7
'High 6
goto loop

alarmon: 'not written turn buzzer on / off
'low 7
'low 6
'high 5
goto loop

snooze: 'not written add 9 minutes to alarm time but don't over write
'High 7
goto loop

display:
readi2c 1,(b7) 'confirms value written to rtc from keypad
readi2c 2,(b8) 'same but for hours (minutes line above)

outnibl = b7 & $000F 'isolates right bit of minutes
gosub outdigit 'sends right bit to output routine

outnibl = b7 & $00F0 / 16 'isolates left bit of minutes
gosub outdigit 'sends left bit to output routine

outnibl = b8 & $000F 'isolate right bit of hours
gosub outdigit 'sends right bit to output routine

outnibl = b8 & $00F0 / 16 'isolates left bit of hours
gosub outdigit 'sends left bit to output routine

pulsout latchout, 1
goto loop

outdigit: 'handles getting four digits out in order
lookup outnibl, ($BE, $82, $DC, $D6, $E2, $76, $7E, $92, $FE, $F2, $FA, $6E, $3C, $DE, $7C, $78), outbyte

for bitcounter = 0 to 7
outbit = outbyte & 1
if outbit = 1 then outhi
low dataout
goto clkout
outhi: high dataout
clkout: pulsout clk, 1
outbyte = outbyte / 2
next bitcounter
return
 

Technical

Technical Support
Staff member
setint %00000100,%00000100
loop:
....
goto loop

interrupt:
goto scan_keys
*****
setint %00000100,%00000100
return

scan_keys: 'figure out which keys on keypad
...
goto loop

See the problem?...

The last line of the summarised code is not correct. You need to go back to the point marked ***** rather than loop.
 

Tim Vukman

New Member
Hi Technical

interrupt:
goto scan_keys
*****
setint %00000100,%00000100
return

scan_keys: 'figure out which keys on keypad
...
goto loop

See the problem?...

The last line of the summarised code is not correct. You need to go back to the point marked ***** rather than loop.

It would seem by where you have indicated the program should return to that I should use Gosub Scan_Keys rather than Goto. That would dicatate using a Return rather than the goto loop in the Scan_Keys module.

I shall try that now and reply again

Thanks

Tim
 

Tim Vukman

New Member
Hi Technical

setint %00000100,%00000100
loop: 'main program loop
high 1
high 2
high 3
high 4
gosub display
goto loop

display:
.....
return

scan_keys:
.....
return

interrupt:
gosub scan_keys
.....
setint %00000100,%00000100
return

Once downloaded, the interrupt fired and I chose to hold button 3, knowing that it would be invalid.
Program control went to the reset routine as expected.

I did a hard reset on the 28x. My first keypress is being correctly captured and it does get displayed correctly as the tens digit of hours whether I press 1 or 2.

After that, it is out of my control. No further key presses register while the clock will run and update the time properly.

The interrupt routine will not fire even though the output pins are high (I have leds on them so I can see).

I obviously have something wrong in the keypad area and the interrupt is not being reset. Since the time is updating on the display, the program hasn't crashed.

I will print the code and try to follow it through by hand.

Should I be expecting the program to wait for me to press the next key? I see nothing to indicate that it would

Thanks

TimV
 

hippy

Ex-Staff (retired)
If program execution has entered the 'display' routine, and is in the 'outdigit' routine within that, when the interrupt occurs, entering the interrupt routine, calling 'scan_keys' which also calls 'key_test' will exceed the maximum depth of subroutines which are permitted.

With the maximum subroutine depth ( four deep ) having been exceeded, program execution will be compromised and the program will not execute as expected.

There are three solutions (*); disable interrupts while the 'display' or 'outdigit' routines are executing, re-write the code so the maximum subroutine call stack depth is not exceeded, or use the interrupt routine to only set an indicator that the key scanning needs to be done ( although that's possibly not a lot better than polling ).

That's not the only problem you have though. There's an issue of altering variables while in the interrupt routine which are expected to be unchanged, consider ...<code><pre><font size=2 face='Courier'>display:
readi2c 1,(b7) 'confirms value written to rtc from keypad
readi2c 2,(b8) 'same but for hours (minutes line above)
outnibl = b7 &amp; $000F 'isolates right bit of minutes
gosub outdigit 'sends right bit to output routine </font></pre></code> If an interrupt occurs immediately after 'readi2c 2,(b8)', when the interrupt execution completes, 'b7' and 'b8' may have been altered within the interrupt routine, which will then mangle what you intend to display. This wouldn't be a problem if interrupts were disabled while the 'display' routine were being called.

These are potential problems, and may not be the actual problem you are suffering from. There could be other things I haven't spotted.

<i>(*) There is a fourth solution which is to implement your own subroutine handling, but that's an advanced technique which is not easy to explain nor do. </i>

Edited by - hippy on 12/06/2006 02:15:07
 

Tim Vukman

New Member
Hi Hippy

Thanks for looking

&quot;If program execution has entered the 'display' routine, and is in the 'outdigit' routine within that, when the interrupt occurs, entering the interrupt routine, calling 'scan_keys' which also calls 'key_test' will exceed the maximum depth of subroutines which are permitted.&quot;

I am pretty certain that this is happening.

&quot;With the maximum subroutine depth ( four deep ) having been exceeded, program execution will be compromised and the program will not execute as expected.&quot;

I thought the 28X could go deeper. Program editor has an option for 256 ?

&quot;There are three solutions (*); disable interrupts while the 'display' or 'outdigit' routines are executing, &quot;

That leaves me a pretty small window of opportunity in the main program loop to fire the interrupt. Perhaps I should stretch my window with Pause values?

&quot;re-write the code so the maximum subroutine call stack depth is not exceeded, &quot;

That is my preference, but it seems a little beyond my current abilities.

&quot;or use the interrupt routine to only set an indicator that the key scanning needs to be done ( although that's possibly not a lot better than polling ).&quot;

I had a suggestion in another post about using a 74C922 decoder for the keypad. I think it has merit but I was unable to buy one at my local electronics place. He said he could order it, but it would take two weeks. MAybe it is worth the wait?

&quot;That's not the only problem you have though. There's an issue of altering variables while in the interrupt routine which are expected to be unchanged, consider ...

display:readi2c 1,(b7) 'confirms value written to rtc from keypadreadi2c 2,(b8) 'same but for hours (minutes line above)outnibl = b7 &amp; $000F 'isolates right bit of minutesgosub outdigit 'sends right bit to output routine
If an interrupt occurs immediately after 'readi2c 2,(b8)', when the interrupt execution completes, 'b7' and 'b8' may have been altered within the interrupt routine, which will then mangle what you intend to display. This wouldn't be a problem if interrupts were disabled while the 'display' routine were being called.&quot;

Yes, you have made a very good observation that I had not considered. I can see it quite clearly now. I have been very linear in my thinking and would have been surprised when that happened.

&quot;These are potential problems, and may not be the actual problem you are suffering from. There could be other things I haven't spotted.&quot;

Thanks for what you have spotted. I pieced this together by working and testing one module at a time.

Perhaps someone would be kind enough to post some pseudo code for me to work from that would help me put the modules together properly. I'm obviously missing some key structural understanding.

Thanks Hippy
I will make the modifications you have suggested. I think the one that is most within my skill set is to disable the interrupt while outside of the main loop.
I put the high x statements there when I realized the interrupt would never fire as I would never get a high on pin2 until I started the keypad scanning which was called from the interrupt. Rather impossible to get there, really.

Regards

TimV

 

andrewpro

New Member
Regarding the gosub depth: What hippy was referring to was nesting a gosub within another gosub. This can only go as deep as 4.

The total number of gosubs in the program, all together, is what your setting in the program editor.

A nested gosub would be soemthing like this:


main:
line of code
gosub part2


part2:
line of code
gosub part3
return


Part3:
line of code
return


By putting a &quot;gosub in a gosub&quot;, this is what's called nesting, and can only go so deep (4 I suppose!) and if you use interrupts, your using a gosub. So if you nested 4 deep, then used interrupts...no worky worky. In order to use the interrupts, you could only nest 3 deep, then youd be in the clear.

--Andy P
 

wilf_nv

Senior Member
Consider using the keyboard interface circuit at
<i>http://www.user.dccnet.com/wrigter/picaxe/12keyencoder.gif

<A href='http://www.user.dccnet.com/wrigter/picaxe/12keyencoder.gif' Target=_Blank>External Web Link</a>

The 3x4 keypad encoder uses 4 NPN transistors, 5 resistors (in a single resistor network) and requires just 5 picaxe input pins.

This encoder circuit can simplify the keyboard service routine as no keypad scanning is required.

The 4 rows of the 3x4 key pad encoded in binary by the 4 transistors and are output as a 2 bit value while the 3 columns are not encoded. One of the three column lines goes active low when any key is pressed.

Any key down can be detected with an interrupt generated on the falling edge using a logic OR interrupt mask on the 3 column bits.

After contact debounce, the 5 keyboard bits can be used to point to the decoded key value in a lookup table.

There is no harm in pressing more than one key. Multiple active columns can be detected but errors of multiple active rows are not detected .

The method can be easily extended to a 4x4 keypad.

wilf </i>
 

Tim Vukman

New Member
AndyPro
&quot;nesting a gosub within another gosub&quot;
Thanks for the explanation. I understand. There is no way my code can run the way it is. I will have to think this through very carefully to see if I can self contain the modules and avoid the exit gosubs from inside the modules.

wilf_nv
Thanks for pointing out the circuit. I will have a look at it this morning (Canada). It sounds very promising.

Regards

TimV
 

Tim Vukman

New Member
Hi Wilf

I have looked at the circuit that you linked to. Am I correct in thinking that all I need to do is add another resistor (ie another row) and two more transistors to handle the four columns for the added row?

When you mention (resistor network) is that different than attaching one end of the resistor to the column pin and the other end to Vcc?

I think this would be a good circuit to implement as it would remove my polling requirement and likely simplify the program quite a bit

Thanks

Tim
 

wilf_nv

Senior Member
A 16 contact matrix encoder circuit is shown here:

<A href='http://www.user.dccnet.com/wrigter/picaxe/16keyencoder.gif' Target=_Blank>External Web Link</a>

Compared with the 12 contact matrix keypad, the 16 contact keypad requires one more discrete resistor (or a resistor network with one more resistor) and one more PicAxe input.

This version is shown with discrete resistors but component count can be reduced by using a (7x10K with single common) resistor network.

wilf
 

Tim Vukman

New Member
Thanks Wilf

I now understand what a resistor network is. I know them as resistor banks, but they are the same thing. I have four 7 segment CCs looking like prime targets :)

Thanks for updating the keypad matrix for me. I will put that together over the next day or so and connect it into my circuit.

Confirmation request please
&quot;One of the column lines goes active low when any key is pressed.

Any key down can be detected with an interrupt generated on the falling edge using a logic OR interrupt mask on the 3 column bits. &quot;

The inputs I have been using are currently tied low via 10K and go high when the key in the row that is high is pressed.

From looking at the circuit, I think I should remove these resistors. Please confirm

Thanks

Tim

 

wilf_nv

Senior Member
You may as well use pull down resistors instead of pull up resistors. Just change the transistors to PNPs and change the supply connections as shown here:
<A href='http://www.user.dccnet.com/wrigter/picaxe/16keyencoder2.gif' Target=_Blank>External Web Link</a>

The added advantage for this application is that the logic levels of the encoder outputs will now be true (not inverted).

wilf

 

Tim Vukman

New Member
Thanks Wilf

That is ideal for me.

On the 28X, can I use the analog inputs for this?

I lose 2 inputs for the rtc for i2c and I have been keeping input0 for Mike Collier's simulator. He's given me a version that communicates with the picaxe hardware and it allows me to see everything that is going on as it displays all the software stuff and drives the picaxe hardware.

I would be 1 input short unless I give up the simulator. I would prefer not to.

Please advise

Tim
 

wilf_nv

Senior Member
Hi Tim,
Hi again Tim,

For this clock application, you may consider using this scanless 15 key matrix encoder.

Wastes one contact of a hex keypad but frees up two PicAxe input pins in the process.

The columns and rows are now binary encoded outputs with complemented and true values respectively.

Any key press causes at least one of the 4 bits to change that can be detected with the PicAxe interrupt mask.

<A href='http://www.user.dccnet.com/wrigter/picaxe/15keyencoder2.gif' Target=_Blank>External Web Link</a>

With a slightly more complex circuit it is possible to interface this 15 key encoder with just 3 I/O pins. heheh!

wilf
 

Tim Vukman

New Member
Hi Wilf.

Thanks for the creativity.

My keypad is sealed with the rows each connecting to a single pin and the columns the same way.

I can't access any of the individual switches.

I drew up a truth table for the last schematic that you sent so I have the keys identified for conversion to hex.

While this will solve my issues caused from polling, I don't think it will help me with my gosub challenge.

I was sent a link to a document that showed a 16 pin keypad where each row and each column had a resistor of a different value attached. The feed is Vcc at one end and a single output at the other. The single output is attached to one of the analog inputs and the &quot;key pressed&quot; is determined by the voltage read on the input.

On that basis, I think I could use the same input to fire the interrupt and then capture the keystrokes.

The keypad would not be used all that often and certainly not a data input terminal speed.

I'm going to take some time later today or tomorrow to do some calculations.

All input welcome

Tim
 

Tim Vukman

New Member
Hi Wilf:

I fired up the keypad with the 4 3906 transistors. Row1 and Row2 work perfectly, but I am not seeing anything on the analog pins.

If I remove the 10k to ground (I have 4, 1 to each analog input, but I have the other ends together to a single wire to ground), my whole board shuts down as if there is a short.

I'll recheck my wiring tomorrow and see if I find anything out of place.

Thanks

tim
 

Tim Vukman

New Member
Hi Wilf:

I have checked all my wiring and taken readings with a voltage meter.

After the transistors, I am delivering 5.02 volts to the analog input pins. In reading each pin with a meter, each one is a different row and that is all working fine.

loop:

if porta pin0 = 1 then zero
if porta pin1 = 1 then one
if porta pin2 = 1 then two
if porta pin3 = 1 then three
goto loop
zero:
high 7
pause 100
low 7
goto loop

one:
high 6
pause 100
low 6
goto loop

two:
high 5
pause 100
low 5
goto loop

three:
high 4
pause 100
low 4
goto loop


does absolutely nothing.

Everything I have read says that all I need to do is an IF test as above, so I don't understand why the analog pins aren't going high.

Thanks

Tim
 

Tim Vukman

New Member
Hi All:

I found a previous post answer from Hippy that was helping someone with READADC.

I can confirm, Wilf, that your circuit is working just fine.

I set up a different variable for each analog pin and I can watch them change with each button pressed. I also notice than Pins and PinsC are giving me a consistent number as each input pin goes high.

I can build a lookup table that will spit out the hex value that I want to feed to the rtc after I add the last two binary digits (row) from the transistors into the column values for my uniqeu key press values.

Thanks Wilf / Hippy. This has been highly educational and benficial for me.

Regards

Tim
 
Top