PDA

View Full Version : Matrix Keypad routine



mister_e
- 7th February 2006, 03:18
Here's a simple INCLUDE file wich allow to scan any matrix KeyPad format on any PORT you decide. Yeah i know, a bit code hungry but simple to use and it's free...

The defaults setings are
Keypad ROW are connected to PORTB<3:0>
Keypad COL are connected to PORTB<7:4>
Debounce delay = 200 mSec
No auto-repeat
Keypad type 4X4


Code example using the default setting


INCLUDE "KeyPad.bas"
myvar var byte

start:
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
goto start


NOT MUCH!
If you decide to change default settings, here's the DEFINEs list

DEFINE KEYPAD_ROW 4 ' 4 ROW keypad
DEFINE KEYPAD_ROW_PORT PORTB ' ROW port = PORTB
DEFINE KEYPAD_ROW_BIT 4 ' ROW0 = PORTB.4
DEFINE KEYPAD_COL 4 ' 4 COL keypad
DEFINE KEYPAD_COL_PORT PORTB ' COL port = PORTB
DEFINE KEYPAD_COL_BIT 0 ' COL0 = PORTB.0
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
DEFINE KEYPAD_AUTOREPEAT 1 ' use auto-repeat feature
When using the auto-repeat feature, the delay is the debounce delay (DEBOUNCEMS)

Code example #2: Using a 8X4 keypad


INCLUDE "KeyPad.bas"

'
' Hardware connection
' ===================
DEFINE KEYPAD_ROW 8 ' 8 row
define KEYPAD_ROW_PORT PORTB ' on PORTB
DEFINE KEYPAD_ROW_BIT 0 ' <7:0>
DEFINE KEYPAD_COL 4 ' 4 col
DEFINE KEYPAD_COL_PORT PORTA ' on PORTA
DEFINE KEYPAD_COL_BIT 0 ' <3:0>
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
define KEYPAD_AUTOREPEAT 1 ' use auto-repeat

'
' Serial Communication definition
' ===============================
DEFINE HSER_TXSTA 24h ' enable transmit, BRGH=1
DEFINE HSER_SPBRG 129 ' 9600 Bauds

'
' Variables definition
' ===================
myvar var byte

' ---------------------------------[Program Start]----------------------------------------------
start:
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
goto start


It set the according TRIS register for you everytime you call the MACRO.. kinda bullet-proof

Everything is explain in the attach file... don't forget to rename it :)

Squibcakes
- 24th April 2006, 11:16
Hi Steve,

What value do you use for the Pull Up resistors?

What value do you use for the series resistors?

Cheers
J

mister_e
- 24th April 2006, 14:47
Could be almost everything but usually i use 10K as pull-up, serie resistor could be remove but usualy 100-300 ohm is perfect.

Srigopal007
- 8th June 2006, 22:23
Hi Steve,

With the code that you have posted, Will this be able to recognize if the user presses more than one button at a time, or is it limited to only one button pushed at a time. If the later is true, then how can I implement a 4x4 matrix so that it allows multiple button pressed at one time .


Srig

mister_e
- 9th June 2006, 01:16
Hi Srig!

Long time we didn't heard from you :D

I do remember you asked that question awhile back but, sorry, only one button at the time for that one.

But as pushing two button exacty at the same time is an impossible human thing, we can modify the actual one and add some feature to. It will have to check once a button is press, wait few ms, set a flag, then RESCAN the whole keyboard and see if things changed. Not impossible.

I'll check what i can do with it somewhere next week. I have some project for some user here (those who pay for ;) ) and i promise to deliver by the end of this weekend... Mister_E rule#1 : always respect delay even if i must stop to sleep, avoid beer and ladies.

Sure i'll have an eye on it next week. See ya!

Leonardo
- 22nd June 2006, 01:54
Serious very good to publish an example with this code that is very interesting, when trying to compile the code "KeyPad.txt" it generates an error.

Greetings

Leonard



Here's a simple INCLUDE file wich allow to scan any matrix KeyPad format on any PORT you decide. Yeah i know, a bit code hungry but simple to use and it's free...

The defaults setings are
Keypad ROW are connected to PORTB<3:0>
Keypad COL are connected to PORTB<7:4>
Debounce delay = 200 mSec
No auto-repeat
Keypad type 4X4


Code example using the default setting


INCLUDE "KeyPad.bas"
myvar var byte

start:
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
goto start


NOT MUCH!
If you decide to change default settings, here's the DEFINEs list

DEFINE KEYPAD_ROW 4 ' 4 ROW keypad
DEFINE KEYPAD_ROW_PORT PORTB ' ROW port = PORTB
DEFINE KEYPAD_ROW_BIT 4 ' ROW0 = PORTB.4
DEFINE KEYPAD_COL 4 ' 4 COL keypad
DEFINE KEYPAD_COL_PORT PORTB ' COL port = PORTB
DEFINE KEYPAD_COL_BIT 0 ' COL0 = PORTB.0
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
DEFINE KEYPAD_AUTOREPEAT 1 ' use auto-repeat feature
When using the auto-repeat feature, the delay is the debounce delay (DEBOUNCEMS)

Code example #2: Using a 8X4 keypad


INCLUDE "KeyPad.bas"

'
' Hardware connection
' ===================
DEFINE KEYPAD_ROW 8 ' 8 row
define KEYPAD_ROW_PORT PORTB ' on PORTB
DEFINE KEYPAD_ROW_BIT 0 ' <7:0>
DEFINE KEYPAD_COL 4 ' 4 col
DEFINE KEYPAD_COL_PORT PORTA ' on PORTA
DEFINE KEYPAD_COL_BIT 0 ' <3:0>
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
define KEYPAD_AUTOREPEAT 1 ' use auto-repeat

'
' Serial Communication definition
' ===============================
DEFINE HSER_TXSTA 24h ' enable transmit, BRGH=1
DEFINE HSER_SPBRG 129 ' 9600 Bauds

'
' Variables definition
' ===================
myvar var byte

' ---------------------------------[Program Start]----------------------------------------------
start:
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
goto start


It set the according TRIS register for you everytime you call the MACRO.. kinda bullet-proof

Everything is explain in the attach file... don't forget to rename it :)

mister_e
- 23rd June 2006, 23:15
yeah.. read the last lines of my post...


... don't forget to rename it :)

so the .txt have to be renamed .bas

once it's done, i can't imagine it's not working. If so, let me know here!

Leonardo
- 24th June 2006, 01:12
Hello,

It already renames it but it is not allowed to compile because it shows an error, try to compile you the code "KeyPad.txt to KeyPad.bas" and that doesn't work.

Thank you
-------------------------------------------------------------------


Here's a simple INCLUDE file wich allow to scan any matrix KeyPad format on any PORT you decide. Yeah i know, a bit code hungry but simple to use and it's free...

The defaults setings are
Keypad ROW are connected to PORTB<3:0>
Keypad COL are connected to PORTB<7:4>
Debounce delay = 200 mSec
No auto-repeat
Keypad type 4X4


Code example using the default setting


INCLUDE "KeyPad.bas"
myvar var byte

start:
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
goto start


NOT MUCH!
If you decide to change default settings, here's the DEFINEs list

DEFINE KEYPAD_ROW 4 ' 4 ROW keypad
DEFINE KEYPAD_ROW_PORT PORTB ' ROW port = PORTB
DEFINE KEYPAD_ROW_BIT 4 ' ROW0 = PORTB.4
DEFINE KEYPAD_COL 4 ' 4 COL keypad
DEFINE KEYPAD_COL_PORT PORTB ' COL port = PORTB
DEFINE KEYPAD_COL_BIT 0 ' COL0 = PORTB.0
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
DEFINE KEYPAD_AUTOREPEAT 1 ' use auto-repeat feature
When using the auto-repeat feature, the delay is the debounce delay (DEBOUNCEMS)

Code example #2: Using a 8X4 keypad


INCLUDE "KeyPad.bas"

'
' Hardware connection
' ===================
DEFINE KEYPAD_ROW 8 ' 8 row
define KEYPAD_ROW_PORT PORTB ' on PORTB
DEFINE KEYPAD_ROW_BIT 0 ' <7:0>
DEFINE KEYPAD_COL 4 ' 4 col
DEFINE KEYPAD_COL_PORT PORTA ' on PORTA
DEFINE KEYPAD_COL_BIT 0 ' <3:0>
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
define KEYPAD_AUTOREPEAT 1 ' use auto-repeat

'
' Serial Communication definition
' ===============================
DEFINE HSER_TXSTA 24h ' enable transmit, BRGH=1
DEFINE HSER_SPBRG 129 ' 9600 Bauds

'
' Variables definition
' ===================
myvar var byte

' ---------------------------------[Program Start]----------------------------------------------
start:
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
goto start


It set the according TRIS register for you everytime you call the MACRO.. kinda bullet-proof

Everything is explain in the attach file... don't forget to rename it :)

mister_e
- 24th June 2006, 08:48
what are/is the error(s) message you get?

Leonardo
- 25th June 2006, 01:23
Hello Mister E,

I attach him the image of the error that generates when trying to compile, I have attempted it with several pics but with none it is allowed to compile.

Greetings

Leonard


what are/is the error(s) message you get?

Acetronics2
- 25th June 2006, 09:54
Hi, Leonardo

Just copiying and pasting Steve's code gives ( lower left ) the following message :

SUCCESS - 366 WORDS USED

So, I think the problem is in your computer ...

Alain

mister_e
- 25th June 2006, 11:30
probable cause.. there's 2 KeyPad.bas files opened in your editor as per your picture. It must be a MCS error... this 'feature' is not available in the MCSP version as i can't do it here... sorry.

Leonardo
- 26th June 2006, 13:49
Hello,

That version of PBP is using?.

Leonard




probable cause.. there's 2 KeyPad.bas files opened in your editor as per your picture. It must be a MCS error... this 'feature' is not available in the MCSP version as i can't do it here... sorry.

Leonardo
- 26th June 2006, 13:52
Hello Acetronis,

It can place an image of the code when it compiles it, the truth not you that to make since has the it finishes version of the PBP.

Greetings



Hi, Leonardo

Just copiying and pasting Steve's code gives ( lower left ) the following message :

SUCCESS - 366 WORDS USED

So, I think the problem is in your computer ...

Alain

Acetronics2
- 26th June 2006, 14:19
Hello Acetronis,

It can place an image of the code when it compiles it, the truth not you that to make since has the it finishes version of the PBP.

Greetings


Sorry, Leonardo

I do not understand anything in your sentence ... try to be a bit more explicit.

I opened Twice "keypad.bas" ... it compiles also ...

may also be Too many files opened ???

Alain

mister_e
- 26th June 2006, 16:14
i use PBP V2.46 but it should work with most previous one. MPASM version shouldn't be much of a problem.

<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=938&stc=1&d=1151334864">

Be sure the INCLUDE file is in the same directory of your project and it should compile as is. Unless add the path in the INCLUDE line.
<img src="http://www.picbasic.co.uk/forum/attachment.php?attachmentid=939&stc=1&d=1151335131">

np123
- 14th September 2006, 00:08
I am new to PIC programming,, have been fiddling with BLINK.Bas
and managed to make the LCD show a message "LED Blinking"
just before the LED blinks.

I am using the MCS PICBasic Pro for the sake of compiling and am using the
DIY K149 Pic Micro Programmer to program my PIC16F877A.

Now I was wondering how would I be able to use the Keypad as an input
and display things on the LCD.

I am sure my question is very newbie, but if someone could explain me
how I could manage my inputs and storing into registers and then output
it to whatever port pin etc., then it would be of great help.

Thank you!

precision
- 14th September 2006, 03:43
Hello Mister E
Great works for newbie, Thanks again.

I config. keypad on portd of 877a, becoz portb is allready config on my dev. board V3(metrixmultimedia) for LCD rutine.

its working fine for me.


INCLUDE "KeyPad.bas"
INCLUDE "MYLCD.BAS"
myvar var byte

start:
@ READKEYPAD _myvar
lcdout $fe,1
lcdout " Key Value = ",DEC2 myvar
goto start



Thanks

mpardinho
- 18th October 2006, 21:10
the file keypad.txt not download ... error in forum server

need the file to text my keypad code

can i help me?

mister_e
- 19th October 2006, 00:07
seems to be a server problem since this morning (october 18/2006)

drop me your e-mail address on my PM.

mpardinho
- 19th October 2006, 15:20
keypad complied 100%,
but in terminal i receive many keys without press any key

my test:




Include "modedefs.bas"
INCLUDE "KeyPad.bas"

DEFINE KEYPAD_ROW 4 ' 4 ROW keypad
DEFINE KEYPAD_ROW_PORT PORTB ' ROW port = PORTB
DEFINE KEYPAD_ROW_BIT 4 ' ROW0 = PORTB.4
DEFINE KEYPAD_COL 3 ' 3 COL keypad
DEFINE KEYPAD_COL_PORT PORTB ' COL port = PORTB
DEFINE KEYPAD_COL_BIT 1 ' COL0 = PORTB.1
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
DEFINE KEYPAD_AUTOREPEAT 0 ' use auto-repeat feature

Serial_Saida Var PORTC.2 'Pic 13 - > Max232 10
myvar var byte

Inicio:
@ READKEYPAD _myvar
Serout Serial_Saida, T2400, [#myvar, 13, 10]
goto Inicio




Terrminal:



Received: 15
Received: 15
Received: 1
Received: 3
Received: 15
Received: 15
Received: 3
Received: 2
Received: 3
...... withou press any key

mister_e
- 19th October 2006, 16:08
seems you forgot to add external pull-ups....

i don't know wich pic you are using but try

OPTION_REG.7=0

mpardinho
- 20th October 2006, 16:21
i use 16f628a with pull-ups ..... for test

in circuit row and col have voltage around 0,5 to 3,5v (oscillating ... i don't know why)

than i press one button, 2 pins have 0,0v

Ioannis
- 20th October 2006, 21:24
Hi. While testing Steve's routine, I get many fatal errors. The attached Screen Capture gives the state. Steve if you can have a look...

Includes are OK about names and paths.

Ioannis

mister_e
- 20th October 2006, 22:02
Ioannis,
You have to compile with MPASM, not PM.

mpardinho,
You probably miswired something. with your exact program it works fine here. Also.. there's no PORTC on PIC16F628 but you should already know that.

i used this line for my config fuses


@ __CONFIG _INTRC_OSC_NOCLKOUT & _MCLRE_OFF & _LVP_OFF & _WDT_OFF & _PWRTE_ON & _BODEN_ON

Did you tried with OPTION_REG.7=0 without resistor?

wich value of pull-up?

Ioannis
- 23rd October 2006, 07:52
Ioannis,
You have to compile with MPASM, not PM.


Ohh! dear....

Thanks,
Ioannis

charudatt
- 14th February 2007, 19:21
Hello Steve,

Any idea in getting your code to work (compile) with PM. ?

That would be a big help.

thank you for the shareing the code.

regards

mister_e
- 14th February 2007, 19:58
Nope, i have no idea and no plan to do it.

I NEVER use PM, it really don't worth to use it anyways... sorry :(

Darrel Taylor
- 14th February 2007, 22:53
I know of NO reason why anyone should still be using PM.

If you don't use ASM then it'll handle PBP just fine. But if you do use ASM, PM will cause nothing but problems. I never use it anymore either.

However, before I found out how much better MPASM is, I used PM for a year or 2, and am probably more familiar with it than Steve.

So here's Steve's Kepad.bas, modified to work with PM.exe

This version will NOT work with MPASM

Don't forget to remove the .txt extension.

HTH,

T.Jackson
- 9th May 2007, 12:54
Looks good Steve. Worth a vote *****

mister_e
- 9th May 2007, 13:22
i has the advantages to be 'user configurable' and support many matrix Keypad type... up to 8X8.

Can be used in a Timer interrupt as well, so you can read from it when you want, etc etc.

Enjoy!

T.Jackson
- 9th May 2007, 13:34
It looks quite comprehensive.

I tend to base most of my algorithms around direct logic - boolean algebraic structures - rather than continuous mathematics, i.e calculations. PIC's are not as well equipped for calculations.

mister_e
- 12th May 2007, 23:33
If that was true... ASM additions, substraction, bit shifting functions and few STATUS register bits wouldn't exist...(carry/Borrow, Z)

charudatt
- 13th May 2007, 05:57
I know of NO reason why anyone should still be using PM.

If you don't use ASM then it'll handle PBP just fine. But if you do use ASM, PM will cause nothing but problems. I never use it anymore either.

However, before I found out how much better MPASM is, I used PM for a year or 2, and am probably more familiar with it than Steve.

So here's Steve's Kepad.bas, modified to work with PM.exe

This version will NOT work with MPASM

Don't forget to remove the .txt extension.

HTH,

Thanks Darrel.

Unfortunately I still use PM and maybe I am facing all problems because of that. I shall shift over to MPASM and see the difference.

Today my biggest problem is to get a 16F628A to sleep and wake it on INT on Change B4...B7. This is in conjuction with a keypad rotuine I am working on for a keylock project.

I think I must change over and see (experience) the difference myself

Thank you steve for this wonderful thread.

regards

T.Jackson
- 13th May 2007, 06:45
If that was true... ASM additions, substraction, bit shifting functions and few STATUS register bits wouldn't exist...(carry/Borrow, Z)

So, you believe that a PIC performs on par with: A = (100 / I) + (J * 2) Vs IF B = 1 THEN A = 120 ?
Huge amount of work for the PIC to do something like this: A = (100 / I) + (J * 2)
100 x the num of clock cycles perhaps?

mister_e
- 13th May 2007, 08:56
Trent, If your example was right i could agree with some part of it... programming method and code optimization is an endless story... i'm not going to argument on which is better, which is worst... it's not what the actual thread is about anyway.

100X ??? NAH, i don't think so. Depending the Value of I, few times maybe... but not 100 for sure. and * 2, is just a Byte shifting, one position to the left... not much... 1-2 cycle not much.
-----------------------------

Charudatt,
before going in sleep mode, make sure those PINs are set to input (with pull-up) and the others are set LOW and OUTPUT (or input but with pull-down resistor). Once you'll press a key, RB<7:4> should see the LOW signal... which should wake your PIC, then you call the keypad scan.

paul borgmeier
- 13th May 2007, 20:17
I tend to base most of my algorithms around direct logic - boolean algebraic structures - rather than continuous mathematics, i.e calculations. PIC's are not as well equipped for calculations.

Huh? Lookups have their place (and I love them when needed) but to say PICs are not equipped for calculations is just plain silly.

For all your projects (that you have posted), was time of the issue or code space? (answer = the latter). With your example equation, which one takes less code space? Which one is faster for larger I? (answer = calculation based approach).



' Calculation based equation A = 100/I +J*2
If I > 100 then
A = J<<1
ELSE
A = 100
FOR X = 1 to 100
A = A – I
IF A < I then OUT
NEXT X
OUT:
A = X+ J<<1
ENDIF

or


' lookup based equation A = 100/I +J*2
IF I = 1 then A = 100+J<<1
If I = 2 then A = 50 +J<<1
If I = 3 then A = 33+J<<1
If I = 4 then A = 25+J<<1
...
' (a bunch more if-thens)
...
if I =100 then A = 1+J<<1
If I > 100 then A = J<<1

CluckShot
- 22nd May 2007, 17:57
I know the Pull up Resistor attaches to Vss but where does it go else wise? Also... What happens to other test programs etc by its presence?

Paul

Ioannis
- 23rd May 2007, 07:58
To port B.

As for the programs, what programs? Depends on what are the programs doing... Usually the port B with PU enabled, reads as all 1s.

Ioannis

T.Jackson
- 23rd May 2007, 09:25
Huh? Lookups have their place (and I love them when needed) but to say PICs are not equipped for calculations is just plain silly.


I didn't say not equipped - I said not as well equipped. And, I'm more so referring to something that's more so "hard coded" over calculations. When I say hard coded I'm talking about something that's direct as in (a = 100) Vs (a = b x 10 / 2) No prizes for guessing which is faster and uses less resource.

mackrackit
- 23rd May 2007, 12:59
I didn't say not equipped - I said not as well equipped. And, I'm more so referring to something that's more so "hard coded" over calculations. When I say hard coded I'm talking about something that's direct as in (a = 100) Vs (a = b x 10 / 2) No prizes for guessing which is faster and uses less resource.

If a is hard coded to equal 100, then I would guess b and c would be hard coded too. If I understand you correctly this is what the PIC a good for. If this was all I had to do I good do it on paper once and would not have to bother with all of this programing and such. In my world variables change.

In you opinion, what should we all be using?

T.Jackson
- 23rd May 2007, 13:36
(b & c) are variables that will only be hard coded if assigned with a fixed value. In Discrete mathematics, if we were to say, a(x) means something - then this is effectively a predicate since the variable x can take on many different forms. On the other hand, if we say A = 100 and it's a "real number", it is said to be a proposition because there is obvious truth in it. Clearly 100 is a real number.



In you opinion, what should we all be using?

Short answer is, in my opinion - use whatever works best for you. Focus on your strengths and if it gets the job done, call it a day :D

mackrackit
- 23rd May 2007, 14:00
(b & c) are variables that will only be hard coded if assigned with a fixed value. In Discrete mathematics, if we were to say, a(x) means something - then this is effectively a predicate since the variable x can take on many different forms. On the other hand, if we say A = 100 and it's a "real number", it is said to be a proposition because there is obvious truth in it. Clearly 100 is a real number.


Short answer is, in my opinion - use whatever works best for you. Focus on your strengths and if it gets the job done, call it a day :D

I was being sarcastic.

T.Jackson
- 23rd May 2007, 14:37
I think what I'm really trying to say here is that, if we want (a) to equal 100, and we can predict this value, then why use a formula? (It's unnecessary maths)



Public Function DrawLCD()
'-----------------------------------------------------------------------------
'// 2 Line 16 LCD_Chrs 5x7 matrix '
'-----------------------------------------------------------------------------
Dim i As Long 'General working var for nested loops
Dim j As Long '^
Dim k As Long '^
Dim f As Long '^
Dim e As Long '^
Dim h As Long '^

'// Draw display matrix with all segs off '
For LCD_Row = 0 To 1 '2 lines
For LCD_Chrs = 0 To 15 '16 chrs per line
For f = 0 To 7 'Matrix row
For k = 0 To 4 'Matrix col
For j = 0 To Draw_Scale - 1 'Ea seg is (dscale x dscale) pixels
For i = 0 To Draw_Scale - 1 '^
SetPixelV LCD.hdc, 2 + i + k * (Draw_Scale + 1) + (LCD_Chrs * Draw_Scale * 6) + (LCD_Chrs * 4), 3 + j + (f * (Draw_Scale + 1)) + (LCD_Row * Draw_Scale * 9) + LCD_Row * 7, vbGreen
Next
Next
Next
Next
Next
Next


I'm forced into using calculations with the above code because we can't easily predict the values of the variables without making things even more complex than they already are. So there's plenty of valid reasoning behind this predicate arrangement. But if we can predict what we want, and it's feasible to do so, why not hard code it???
<hr/>

T.Jackson
- 23rd May 2007, 14:48
If Total_Frames <> 0 Then
For i = 0 To 31
'// Test to see if this LED is already on the screen (don't blit again if so)
If LED(Frame_Data(Current_Frame, i)) <> LED(Frame_Data(Last_Blitted_Frame, i)) _
Or Not Run_ROM Then
BitBlt Tree_PCB.hDC, Tree_X(i), Tree_Y(i), 22, 22, LED_Mask.hDC, 0, 0, MergePaint
BitBlt Tree_PCB.hDC, Tree_X(i), Tree_Y(i), 22, 22, LED(Frame_Data(Current_Frame, i)).hDC, 0, 0, SrcAnd
End If
Next
End If

Tree_X(0) = 162
Tree_Y(0) = 2
Tree_X(1) = 190
Tree_Y(1) = 42
Tree_X(2) = 218
Tree_Y(2) = 82
Tree_X(3) = 180
Tree_Y(3) = 83
Tree_X(4) = 203
Tree_Y(4) = 123
Tree_X(5) = 226
Tree_Y(5) = 163
Tree_X(6) = 249
Tree_Y(6) = 203
Tree_X(7) = 205
Tree_Y(7) = 204
Tree_X(8) = 230


The above procedure relies mostly on a hard coded arrangement. The two single dimension arrays Tree_X() & Tree_Y() contains all fixed values that actually saves a lot of calculating. Hard coding is definitely a worth while consideration. So instead of making the PIC do (2 + 2), why not just assign 4 to the variable. (Anyhow this is my final comment about this, it's completely off topic) Sorry :(

passion1
- 14th June 2007, 13:50
Steve

Thank you for your keypad routines! I implemented and it works with no compilation errors.
However, I do have a minor problem:
In my logic, the call to

@ READKEYPAD _myvar

is part of a larger loop that performs some other functions.
Now my program will not continue with the rest of the loop until a key on the keypad was pressed?
What must I do so that it will read the keypad but if no key was pressed it will simply continue as normal?

Initially the myvar variable continuously returned random key values and I was then advised by you to use the
OPTION_REG.7=0
command so that the routine will only register a value when a key was actually pressed. Adding the OPTION_REG.7=0 command solved that problem but now the program flow does not continue until a key was pressed.

Thank you in advance.

Here is the definitions I used:

DEFINE KEYPAD_ROW 4 ' 4 ROW keypad
DEFINE KEYPAD_ROW_PORT PORTC ' ROW port = PORTC
DEFINE KEYPAD_ROW_BIT 4 ' ROW0 = PORTC.4
DEFINE KEYPAD_COL 4 ' 4 COL keypad
DEFINE KEYPAD_COL_PORT PORTB ' COL port = PORTB
DEFINE KEYPAD_COL_BIT 4 ' COL0 = PORTB.4
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
DEFINE KEYPAD_AUTOREPEAT 1 ' use auto-repeat feature

PAUSE 500
LCDOUT $FE,1,"Initializing ...."
Pause 1000

INCLUDE "KeyPad.bas"

OPTION_REG.7=0

---------------------------------------------

Steve

I just looked at your code again.
Can I simply remove the

repeat

until key!=0

lines, because this seems to force the loop to be repeated until a key was pressed?

mister_e
- 14th June 2007, 20:41
OK NO NEED FOR THAT ;)

i've attach the latest version... which i thought i had posted here :(
http://www.mister-e.org/Pics/DOH

So the only thing you will have to do, is to add this simple line

DEFINE SCAN_ONCE 1

And this should cure the problem.

I have added this feature once i needed to scan a keypad with a timer interrupt... which is certainly the way to go for any Push-Button/Keypad entry anyways.

Enjoy!

passion1
- 14th June 2007, 20:52
Steve

EXCELLENT!! Now everything works 100%!

One last question:
What is the debounce and autorepeat functionality as set by

DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
DEFINE KEYPAD_AUTOREPEAT 1 ' use auto-repeat feature

Thanks again!

mister_e
- 14th June 2007, 20:57
Let's say the user press on a specific key for awhile, the AUTOREPEAT feature should allow to scan/give you the Keypad scan each 200mSec.. handy? Not sure of it :( In your case, of course not.

Debounce delay will be the delay the software will wait after a key have been pressed before to go out and giving you the right Key. On most tact-switch keypad, 100 mSec is more than enough, but.. the best way to know it, is to test it.

Glad to know it's working now!

passion1
- 14th June 2007, 21:08
Steve

Thus, am I right in saying that if I want the keypad scanner to interfere the least with the rest of the program execution, then I must switch the AUTOREPEAT OFF?

mister_e
- 15th June 2007, 03:51
If you don't define AutoRepeat, the program will spin in round until you release the keys.

To make a short story ;) Use AutoRepeat and SCAN_ONCE... i should have written that routine in a different way...

Ioannis
- 15th June 2007, 08:24
Maybe using Darrel's Instant Interrupts? Just an idea...

When I have some spare time I'll try it to have a true multitasking keyboard scanner.

Ioannis

CluckShot
- 16th June 2007, 11:50
I have noted this discussion on Pull Up resistors. I am running the PIC18F series chip and it in the documentation says it supports a weak pull up setting internally in the chip. Could I get any discussion of this relative to the pull up resistors on Vcc. Also Pull Ups as I understand their function is to bring the voltage on the pin up a little so that when the transistor in the chip is triggered only slightly the pin will appear digitally to have tripped.

As such what values do you think these resistors should be generally?

If the support is internal, does this mean we still have to place the external resistors?

Thanks to all.

skimask
- 16th June 2007, 18:28
I have noted this discussion on Pull Up resistors. I am running the PIC18F series chip and it in the documentation says it supports a weak pull up setting internally in the chip. Could I get any discussion of this relative to the pull up resistors on Vcc. Also Pull Ups as I understand their function is to bring the voltage on the pin up a little so that when the transistor in the chip is triggered only slightly the pin will appear digitally to have tripped.
As such what values do you think these resistors should be generally?
If the support is internal, does this mean we still have to place the external resistors?
Thanks to all.

Generally, a pullup resistor (or a pulldown) is used to keep a pin from 'floating', which basically happens when nothing is driving the pin. The pin's voltage floats around due to induced voltages from traces around it, the weather, humidity, your hand, etc.etc...
Another reason is that the pin might be an 'open drain' ('open collector' for older school types). This means that the pin only has a switching transistor to pull it low, and not high. So you connect a resistor of about 4.7K to Vcc across it. This provide a couple of mA (@ 5v) at most to keep the pin high.
The internal pullups are valued at around 100K, which means they'll only provide about 50uA of current to hold it high. If you connect a load of much more than 50uA to that pin (a load resistance of much more than 100K), you'll be able to draw that pin low.
Most likely, even though you're using the internal pullups, sometimes, depending on the outside circuitry, yes, you'll have to add a small pullup resistor.
Generally speaking, a pullup resistor's value is either 4.7K or 10K, depending.
Make the resistance too low, and you draw unneccessary current and it won't allow external circuitry to pull the pin low.
Make the resistance too high, and you might not have enough current to pull the pin high like you wanted in the first place.
Stick with 4.7K, and you should be fine.

CluckShot
- 18th June 2007, 00:26
How do we determine what the pullup should be? I mean 100 to 300 ohms or 10 K ohms doesn't exactly give me the data I need. (Does it vary with the circuit being driven for example?) I really want to trigger the circuit with a minimum of time so I want the pullup fast so that my transistors (Nice NPN's for switching) with about 4.7 K ohms lead in resistance trigger off pretty much as fast as any current comes on the pin to signal it.

I will be pushing a signal in the switch of the NPN transistor so that there is some current to pull a MOSFET fast. I need some current to move like NOW.

In any case since I just cooked a $15 chip and an X1 Board , I really want to know some answers. (I just burned up some money) I need to know what voltage appears on the pins of the chip when we set for example a PORTA.2 =1. or PORTA.2 = 0 Is it on PORTA.1 = 1 a positive or negative voltage. It was logic testing that cooked this equipment.

All advice will be appreciated.

Well I got a cross of a posting that occurred between my post and an answer.

The issue of Pullups seems to be a feature of the pin to cause it to draw some current to make it pull down a few thousandths of an ampere so that the circuit stays logic stable. I would think that if I am driving a transistor as I am the obvious value to use is about 10K because the transistor will have a 4.7 K or so leading out of the logic pin into the transistor Emitter. Or does this 4.7 to Vss draw down enough power so that the transistor needs no other resistor on the emitter?

Generally a 5 VDC to emitter of a switching transistor with logic state high would take a 4.7 K ohm in the way of the signal feeding into the emitter (P of the NPN). If you take a 5 VDC state with a 10 K ohm to Vss and the positive voltage on the pins as high logic state then a 4.7 to the emitter should keep enough current to the transistor to open the gate so I am guessing based upon the previous answer that a 10 K ohm is in order (???)

When we change from an input drain state as in the keyboard to an output control state, I would suspect that we add a current to bring the pin near switch on state but just below in order to logically control things, Is this so?


Thanks

mister_e
- 18th June 2007, 01:07
For Switchs, Keypad the Pull-up value is not really important. 10K is common, that's what i use. They can be higher... but i stick with 10K.

For switches and Keypad, yes you could use the internal one without having too much problem.

If you don't use any, this will cause you some problem as the internal gate don't see a logic level... it will see noise, so it will react weird. It has nothing to do with the Output driver, as the pin is set as Input. And BTW, if you enable ALL internal pull-up, they will be disabled on all Output configured I/O.

<hr>PORTA.x = 1 = 5Volt
PORTA.x = 0 = 0Volt<hr>

To drive a transistor (NPN/PNP) you need a resistor in serie with the base, unless you will burn the I/O. Roughly, if you don't insert a resistor in serie with the transistor base, the i/O will see only a diode, as there's no current limiting resistor the current will be infinite. I=E/R, I=Vdd/0 :eek: hence some obvious damage to the PIC which can't provide more than 25mA by I/O, and x/PORT.

The base resistor will have to be calculated. But you need to know how much current your transistor will drive and the transistor Hfe. The base resistor have to be higher than Vdd/25mA to avoid burning the I/O and few time lower than the calculated one to ensure proper switching.

rb=Vdd-0.7/(Ic/Hfetyp)

HTH

passion1
- 19th June 2007, 07:27
Steve

Does the same apply to driving a n-channel power mosfet?
I would like to drive a IRFP250N n-channel mosfet.
(for this mosfet the static drain-to-source on-resistance Rds(on)=0.075ohm,
drain-to-source leakage current Idss = 25-250uA)
Do I also need a resistor inbetween the mosfet and the output pin?
If so, should I use the same calc as above to determine the ohm value of the resistor?

mister_e
- 19th June 2007, 08:34
in theory, you don't need any resistor in between as the gate impedance and their gain(not the right term but.. ) is quite large . BUT if you worry of a Gate to Source short, or else weird stuff, you should use a resistor in serie to 'protect' the PIC.

Ioannis
- 19th June 2007, 08:51
... you should use a resistor in serie to 'protect' the PIC.

If your concern is speed then
this res should be as low as possible, 0-470 Ω.
Else
use larger one about 1K
Endif

Ioannis

mister_e
- 19th June 2007, 09:35
I tend to not use any resistor. If i need to drive high current, i sure use something else in between...

passion1
- 19th June 2007, 11:25
Thank you Steve & Ioannis.

Steve, what do you mean with:
"If i need to drive high current, i sure use something else in between..."

Ioannis
- 19th June 2007, 11:58
Another transistor or other driver I suppose.

Microchip has such Mosfet drivers (either for high or los side)

Ioannis

passion1
- 22nd June 2007, 14:58
Ioannis / Steve

I would like to drive a 220V circuit with a power mosfet.
Do you think an optocoupler is a MUST or will I be able to get away with a diode to protect my pic?
If so, what diode or alternative protection would you recommend?

mister_e
- 22nd June 2007, 16:22
:eek: it's up to you. Everything will depend of what the whole beast will do, and how the enclosure design is done. But to me, as long as there's room to fit a transformer and optocoupler and keep away the AC line away of the user... i feel better and sleep all night without any problem.

What do you need to drive?

Ioannis
- 22nd June 2007, 20:07
...

But to me, as long as there's room to fit a transformer and optocoupler and keep away the AC line away of the user... i feel better and sleep all night without any problem.



I double that. Even if the end user is well isolated from the circuit, YOU are not trying to make it work. You will have to debug the circuit while alive and sure put your life in danger.

How many pcs are you going to sell? If it is say low quantity, for sure you will be paid by your time to develop the system. That money should be more than enough to let you put that transformer without second thought.

In my country people say that coward's mother will never cry over the grave! Of course it sounds more elegant in greek than the awkard translation!!!

Ioannis

passion1
- 22nd June 2007, 22:37
Ioannis / Steve

Thank you for the wise advice!! I agree 100%.

bill12780
- 22nd June 2007, 23:47
Hello all,

I have to ask because I have NEVER seen it done any other way. But is it not just plain good design practice to current limit with series resistors and pull up or down ALL digital I/O's?

And as far as driving your 220AC device. You should ALWAYS use some sort of isolation device to protect your DC circuits AND the poor person that is trying to use them!

But back to the thread....

Tell me if I am missing something here and if this would work at all:

if doing a keypad scan could you not use portb 0-2 and portb 3-7 for a 3x4 keypad. then use a look up table to get the actual key pressed? If you could do this it would be easy to add "secret" key combinations to do special functions in the project.

I am just getting started here and learning lots by reading. I have spent quite some time looking over the Keypad code posted here and its VERY complex more so then I would have thought. am I missing something here?
(I am not saying anything bad about the code. I could just be ignorant to what it takes to actually do this. So please don't be insulted.)

Also, I see no accomidation in the keypad for compairing the input from the keypad to stored values for say "pin access" or the such. Or is this code ment to be only the keyscan?

Just asking?

;Smart A** Programing Joke starts here
cls
Print "Best Regards,"
Print "Bill12780"
end

Darrel Taylor
- 23rd June 2007, 05:23
Hi Bill,

It's not that it really takes that much code to scan a keypad. You can write your own that's much simpler, (Except that YOU actually have to write it). And then it will probably only work with that one set of hardware that you wrote it for.

But mister_e's keypad module was written to work with Everybody's program. With lots of options to allow the user to customize it to work with whatever hardware they are using, and with different modes such as Auto Repeat, and Scan Once, or Modal modes. Without the user having to do much at all.

It looks complicated on the inside, but that's the part you don't need to worry about. All you have to deal with is the actual useage of the module. Which is really easy. Define your pins and desired features, use an @ READKEYPAD _KeyVar, and you're done.

It's just like when you use PicBasic Pro itself. You don't care how the code works inside the compiler. You just want to say LCDOUT "Hello World" and have it show up on the LCD display.

Also, I see no accomidation in the keypad for compairing the input from the keypad to stored values for say "pin access" or the such. Or is this code ment to be only the keyscan?

Correct. Just reads the keypad.
For some sample code that can recognize a sequence of key presses. This might help.

Combinaton Gate access
http://www.picbasic.co.uk/forum/showthread.php?t=5695

charudatt
- 3rd July 2007, 07:47
Hello,

I remember seeing an idea of connecting multiple (more than 1) switches on a single Port(analog) pin and working with the adc val.

Cannot find this anymore on the forum.

Any help on this topic/idea.

regards

Ioannis
- 3rd July 2007, 11:52
I don't remember where is the link, but you can do it easily just like that.

From the analog port put some resistors in series to 5V. t the joints of the resistors put switch to ground. So every switch will result in different voltage at the ADC input. No switch pressed, the ADC will read 255 or 1023 (8 or 10 bit result).

Ioannis

Pic_User
- 3rd July 2007, 13:06
Hi charudatt,

Hello,

I remember seeing an idea of connecting multiple (more than 1) switches on a single Port(analog) pin and working with the adc val.

Cannot find this anymore on the forum.

Any help on this topic/idea.

regards
TIP #5 Scanning Many Keys With One Input
EDIT: TIP #7 4x4 Keyboard with 1 Input

Microchip’s Tips ‘n Tricks (DS40040C)
http://ww1.microchip.com/downloads/en/DeviceDoc/40040C.pdf

Hope this helps,
-Adam-

charudatt
- 3rd July 2007, 20:18
Thank you Adam and Ioannis.

That was exactly what I was looking for.

regards

RussMartin
- 10th July 2007, 01:05
How do we determine what the pullup should be? I mean 100 to 300 ohms or 10 K ohms doesn't exactly give me the data I need. (Does it vary with the circuit being driven for example?)

I was taught, back in the "old days", to figure for about 1 ma to flow in the pullup (or, when needed, pulldown). Thus for 5-volt TTL, 4.7K; for 12-volt CMOS logic, 10K. I still use these values without thinking, and everything still works.

RussMartin
- 10th July 2007, 01:12
I have to ask because I have NEVER seen it done any other way. But is it not just plain good design practice to current limit with series resistors and pull up or down ALL digital I/O's?

This is what I was taught back in the "old days", but there are lots of circumstantial exceptions--there were circumstantial exceptions, then, too, but probably not as many of them!

RussMartin
- 10th July 2007, 01:17
How do we determine what the pullup should be? I mean 100 to 300 ohms or 10 K ohms doesn't exactly give me the data I need. (Does it vary with the circuit being driven for example?)

I was taught, back in the "old days", to figure for about 1 ma to flow in the pullup (or, when needed, pulldown). Thus for 5-volt TTL, 4.7K; for 12-volt CMOS logic, 10K. I still use these values without thinking, and everything still works.

Darrel Taylor
- 10th July 2007, 04:29
I think that's for a standard 10 TTL loads.

But a PIC pin is only 1 load. So you can be fine with 40K, which is somewhere around the range of the internal weak pull-ups.
<br>

RussMartin
- 10th July 2007, 19:22
I think that's for a standard 10 TTL loads.

But a PIC pin is only 1 load. So you can be fine with 40K, which is somewhere around the range of the internal weak pull-ups.
<br>

I'm sure you're correct, Darrel. As I wrote, that was a long time ago. My feeble point was, I still automatically use that thumb rule and those values and the circuits still work. (Probably kind of like driving a tack with a sledgehammer . . . )

Darrel Taylor
- 11th July 2007, 00:37
Or shooting Quail with a Deer slug. :eek:

But keep in mind we're talking keypads here.
For something like high speed communication with I2C, lower values are required to overcome any capacitance that might cause a Slew Rate.

In which case 4.7K is the perfect value.

I'd say, just keep doing what you're doing, and you should be fine.
<br>

RFsolution
- 14th October 2007, 09:41
Hi Steve,

Some time ago you modified your code for pbp243 (if you remember)
Meanwhile I have updated to 2.50

After playing with your code I have a strange behavior
If I want to serout something in the main loop it is not working
any idea how to fix this



INCLUDE "KeyPad.bas"
myvar var byte

start:
Hserout ["test",10,13] 'does not do anything
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
if myvar =1 then
Hserout ["test2",10,13] 'does work if button 1 pressed
endif
goto start




Here's a simple INCLUDE file wich allow to scan any matrix KeyPad format on any PORT you decide. Yeah i know, a bit code hungry but simple to use and it's free...

The defaults setings are
Keypad ROW are connected to PORTB<3:0>
Keypad COL are connected to PORTB<7:4>
Debounce delay = 200 mSec
No auto-repeat
Keypad type 4X4


Code example using the default setting


INCLUDE "KeyPad.bas"
myvar var byte

start:
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
goto start


NOT MUCH!
If you decide to change default settings, here's the DEFINEs list

DEFINE KEYPAD_ROW 4 ' 4 ROW keypad
DEFINE KEYPAD_ROW_PORT PORTB ' ROW port = PORTB
DEFINE KEYPAD_ROW_BIT 4 ' ROW0 = PORTB.4
DEFINE KEYPAD_COL 4 ' 4 COL keypad
DEFINE KEYPAD_COL_PORT PORTB ' COL port = PORTB
DEFINE KEYPAD_COL_BIT 0 ' COL0 = PORTB.0
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
DEFINE KEYPAD_AUTOREPEAT 1 ' use auto-repeat feature
When using the auto-repeat feature, the delay is the debounce delay (DEBOUNCEMS)

Code example #2: Using a 8X4 keypad


INCLUDE "KeyPad.bas"

'
' Hardware connection
' ===================
DEFINE KEYPAD_ROW 8 ' 8 row
define KEYPAD_ROW_PORT PORTB ' on PORTB
DEFINE KEYPAD_ROW_BIT 0 ' <7:0>
DEFINE KEYPAD_COL 4 ' 4 col
DEFINE KEYPAD_COL_PORT PORTA ' on PORTA
DEFINE KEYPAD_COL_BIT 0 ' <3:0>
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
define KEYPAD_AUTOREPEAT 1 ' use auto-repeat

'
' Serial Communication definition
' ===============================
DEFINE HSER_TXSTA 24h ' enable transmit, BRGH=1
DEFINE HSER_SPBRG 129 ' 9600 Bauds

'
' Variables definition
' ===================
myvar var byte

' ---------------------------------[Program Start]----------------------------------------------
start:
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
goto start


It set the according TRIS register for you everytime you call the MACRO.. kinda bullet-proof

Everything is explain in the attach file... don't forget to rename it :)

RFsolution
- 26th February 2008, 07:49
Hi MisterE

Using with succes your keypadroutine on a 4x2 keypad

I was wondering if it would be possible to jump out the keypadroutine if no key is pressed
in order to handle the main loop

I need to receive some serial commands by HSERIN, but when a key is pressed
it should go to a label and then return to the main loop checking Hserin

Now it waits for a keypress

Thanks

RFsolution
- 27th February 2008, 08:49
I found this solution which was already in the forum, thanks


OK NO NEED FOR THAT ;)

i've attach the latest version... which i thought i had posted here :(
http://www.mister-e.org/Pics/DOH

So the only thing you will have to do, is to add this simple line

DEFINE SCAN_ONCE 1

And this should cure the problem.

I have added this feature once i needed to scan a keypad with a timer interrupt... which is certainly the way to go for any Push-Button/Keypad entry anyways.

Enjoy!

Darrel Taylor
- 1st August 2008, 00:33
This is an update to the PM version of Steve's Matrix Keypad routine.

Steve added a SCAN_ONCE option after I converted it for PM.exe. And someone recently asked for an update to it. It took me so long to do it, I forget who asked. :o

Note: This is for PM only. It will not work with MPASM.

HTH,

earltyso
- 25th August 2008, 19:52
T. Jackson & Mr. E,

Nice work to both of you regarding Matrix Keypads!

I have used Trents example with great success, I plan on trying out Mr. E's with a handheld Wireless panel/LCD I put together for work. I want to add a 4x4 matrix keypad to the front of the reciever case and upgrade my TXM/RSM LR LINX modules to the new LT tranciever type. I really think having the matrix keypad will expand (the crap out of) the types of commands I can send.....wall mounted reciever, robot, whatever....

earltyso
- 25th August 2008, 21:00
Hello,
Just an hour ago I tried to include Mr. E's Keypad.bas file in pbp folder and my local "pic_programs" folder. I DID rename the txt file and saved it to .BAS file.
Here is the code....


INCLUDE "KeyPad.bas"
myvar var byte


start:
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
'LCDOUT 254,ROW1,"COMMAND", DEC MYVAR
goto start


Won't compile....
I keep getting lots of "opcode expected instead of....'kb_row','kb_col', 'debounce_delay' " errors. I did read the thread about the errors found when you don't save as a .BAS file but I must not be seeing something obvious, happens to me alot on this forum.

Mr. E could you lend a hand,

I am using version 2.50A & PM assembler

Darrel Taylor
- 25th August 2008, 21:31
With Steve's version, you have to use MPASM.

For PM, use the version I recently uploaded to Post#82

hth,

Kalind
- 1st October 2008, 15:43
I'm doing a temperature control system. Pretty new to PIC programming. I have managed to display temperature on the LCD using an LM35 sensor and a 16 x 2 lcd with a 16F873. I want to add on a 4 x4 matrix keypad so that i can set setpoints to switch a relay and a low warning buzzer I have no idea how to program for the above mentioned add-ons. Please could someone help me. below is my code which will obviously need additions and a scematic of my circuit is attached . Please could somebody help me with this!!

' Define LCD registers and bits

Define LCD_DREG PORTB
Define LCD_DBIT 0
Define LCD_RSREG PORTB
Define LCD_RSBIT 5
Define LCD_EREG PORTB
Define LCD_EBIT 4
dEFINE LCD_BITS 4
DEFINE LCD_LINES 2

adval var word ' Create adval to store result
temp var word ' Create temp to store result
temp1 var word ' Create temp1 to store result

TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %10000010 ' Set PORTA analog and RIGHT justify result
ADCON0 = %11000001 ' Configure and turn on A/D Module
Pause 100 ' Wait 0.1 second


loop: ADCON0.2 = 1 ' Start Conversion

AGAIN: Pause 1
If ADCON0.2 = 1 Then AGAIN ' Wait for low on bit-2 of ADCON0, conversion finished

adval.highbyte = ADRESH ' Move HIGH byte of result to adval
adval.lowbyte = ADRESL ' Move LOW byte of result to adval

Lcdout $fe, 1 ' Clear screen
temp=50*adval ' Conversion to Degrees
temp=temp/100
Lcdout "TEMP = ",DEC temp,$DF,"C" ' Display the value of temp
temp1 = temp*18 ' Conversion to Fahrenheit
temp1 = temp1+320
temp1 = temp1/10
lcdout $FE,$C0, "TEMP = ",dec temp1,$DF,"F" ' Display the value of temp
Pause 1000 ' Wait 1 second

Goto loop ' Do it forever
End

skimask
- 1st October 2008, 15:47
I'm doing a temperature control system. Pretty new to PIC programming. I have managed to display temperature on the LCD using an LM35 sensor and a 16 x 2 lcd with a 16F873. I want to add on a 4 x4 matrix keypad so that i can set setpoints to switch a relay and a low warning buzzer I have no idea how to program for the above mentioned add-ons. Please could someone help me. below is my code which will obviously need additions and a scematic of my circuit is attached . Please could somebody help me with this!!
Schematic for keypad connection to a PIC is talked about at the beginning of this thread. If you need a schematic, draw it up... Shouldn't be that difficult at all...dontcha think?

As far as the code goes, you've gotten this far (or have you? Ctrl-C/Ctrl-V)...
Why not write some code, doesn't even have to be real code, just talk yourself thru it, and type it out as you talk. After you see it written down, you just might be able to write the code yourself.

Kalind
- 1st October 2008, 15:54
i have written this code. its just that im really confused and lost as to how to begin with the keypad. i kinda figured out how to hook up the keypad though. i just need help as to how to go about doing the code

skimask
- 1st October 2008, 16:00
i have written this code. its just that im really confused and lost as to how to begin with the keypad. i kinda figured out how to hook up the keypad though. i just need help as to how to go about doing the code

I am HELPING. No need for whiney PM's.
Key word here is HELPING...not DOING.
I think you'll find a whole lot of people around here willing to HELP...some might even be willing to DO.
Write some code, in fact, don't even write code, just write a sequence of thoughts of how you think the program should operate. The code will follow. That's how it works. You think about something and it happens eventually.
As far as your keypad goes, what's wrong with the code that's provided earlier in the thread? I use it...works great for me.

Kalind
- 1st October 2008, 16:05
well, i was thinking that when i push "Button A" of the keyapd, the upper setpoint will be displayed, "Button B" = Lower limit, "Button C" = Backspace, "Button D" = OK , "Button *" = alarm on/off, "Button #" = Main screen

skimask
- 1st October 2008, 16:06
well, i was thinking that when i push "Button A" of the keyapd, the upper setpoint will be displayed, "Button B" = Lower limit, "Button C" = Backspace, "Button D" = OK , "Button *" = alarm on/off, "Button #" = Main screen
Ok, so you've defined the FUNCTIONs of the buttons...now how to you act on those functions.
In fact, do yourself a favor and just work on adding one button at a time...

Kalind
- 1st October 2008, 16:12
thats my point. I have no idea where to begin...i was thinking maybe scan keypad first, check if A or B was pressed and if so then act upon it by prompting the user to enter a desired setpoint. once that's done, press ok and return to the main display screen. the alarm can be set on for the desired lower setpoint and once the upper setpoint has been reached, the relay should switch on. vice versa

skimask
- 1st October 2008, 16:14
thats my point. I have no idea where to begin...i was thinking maybe scan keypad first, check if A or B was pressed and if so then act upon it by prompting the user to enter a desired setpoint. once that's done, press ok and return to the main display screen. the alarm can be set on for the desired lower setpoint and once the upper setpoint has been reached, the relay should switch on. vice versa

Then write some code and see how it works!
If it doesn't work, post the code, and I'm sure somebody will help you figure it out.

Archangel
- 1st October 2008, 17:50
The first thing to do is open Mr. E's Keypad.bas and read the instructions he wrote for you.

RFsolution
- 2nd October 2008, 07:41
Well the answeris in mister E's code, it works very well give it a true it is very well documented and easy to use

Walter



I'm doing a temperature control system. Pretty new to PIC programming. I have managed to display temperature on the LCD using an LM35 sensor and a 16 x 2 lcd with a 16F873. I want to add on a 4 x4 matrix keypad so that i can set setpoints to switch a relay and a low warning buzzer I have no idea how to program for the above mentioned add-ons. Please could someone help me. below is my code which will obviously need additions and a scematic of my circuit is attached . Please could somebody help me with this!!

' Define LCD registers and bits

Define LCD_DREG PORTB
Define LCD_DBIT 0
Define LCD_RSREG PORTB
Define LCD_RSBIT 5
Define LCD_EREG PORTB
Define LCD_EBIT 4
dEFINE LCD_BITS 4
DEFINE LCD_LINES 2

adval var word ' Create adval to store result
temp var word ' Create temp to store result
temp1 var word ' Create temp1 to store result

TRISA = %11111111 ' Set PORTA to all input
ADCON1 = %10000010 ' Set PORTA analog and RIGHT justify result
ADCON0 = %11000001 ' Configure and turn on A/D Module
Pause 100 ' Wait 0.1 second


loop: ADCON0.2 = 1 ' Start Conversion

AGAIN: Pause 1
If ADCON0.2 = 1 Then AGAIN ' Wait for low on bit-2 of ADCON0, conversion finished

adval.highbyte = ADRESH ' Move HIGH byte of result to adval
adval.lowbyte = ADRESL ' Move LOW byte of result to adval

Lcdout $fe, 1 ' Clear screen
temp=50*adval ' Conversion to Degrees
temp=temp/100
Lcdout "TEMP = ",DEC temp,$DF,"C" ' Display the value of temp
temp1 = temp*18 ' Conversion to Fahrenheit
temp1 = temp1+320
temp1 = temp1/10
lcdout $FE,$C0, "TEMP = ",dec temp1,$DF,"F" ' Display the value of temp
Pause 1000 ' Wait 1 second

Goto loop ' Do it forever
End

Kalind
- 4th October 2008, 10:38
ok, now that i have e's keypad code, how do i implement the idea that i mentioned in #90?

mackrackit
- 4th October 2008, 12:48
ok, now that i have e's keypad code, how do i implement the idea that i mentioned in #90?
Do you have the code working?
What happens when "A" is pressed now?

Archangel
- 5th October 2008, 06:25
well, i was thinking that when i push "Button A" of the keyapd, the upper setpoint will be displayed, "Button B" = Lower limit, "Button C" = Backspace, "Button D" = OK , "Button *" = alarm on/off, "Button #" = Main screen


InterruptHandler:
@ READKEYPAD _MyVar
resume
'now your key reading is stored in MyVar


most 16 key keypads are laid out 123A 456B 789C *0#D, so 1=1 2=2 3=3 A=4 4=5 . . . .
You can use this as is or use a lookup routine to alias the actual port reading to what
you want, like so:


lookup MyVar,[0,"123A456B789C*0#D"],MyOtherVar

now your key information stored in myOtherVar will mirror your keypad.
so . . .


If myothervar = A then gosub Uppersetpoint
if MyOtherVar = b then gosub . . . .easy

chrisshortys
- 20th November 2008, 16:06
Hay guys and girls. I've been playing around with this coding this afternoon and i keep getting errors and when i dont nothing going as i thought it should so any chance somone could point out whats wrong please or point me in the right dirrection at least!

My main coding:


TRISA=%00000011
TRISB=%00000000
TRISC=%11111110
ADCON0=%11000000
ADCON1=%00000111
INCLUDE "KeyPad.bas"

'
' Hardware connection
' ===================
DEFINE KEYPAD_ROW 8 ' 8 row
define KEYPAD_ROW_PORT PORTc ' on PORTB
DEFINE KEYPAD_ROW_BIT 0 ' <7:0>
DEFINE KEYPAD_COL 4 ' 4 col
DEFINE KEYPAD_COL_PORT PORTc ' on PORTA
DEFINE KEYPAD_COL_BIT 0 ' <3:0>
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
define KEYPAD_AUTOREPEAT 1 ' use auto-repeat
' LCD Display
' -----------
' Adjust these to suit your chosen LCD pinout
'
DEFINE LCD_DREG PORTb 'Define PIC port used for LCD Data lines
DEFINE LCD_DBIT 4 'Define first pin of portb connected to LCD DB4
DEFINE LCD_RSREG PORTb 'Define PIC port used for RS line of LCD
DEFINE LCD_RSBIT 3 'Define Portb pin used for RS connection
DEFINE LCD_EREG PORTb 'Define PIC prot used for E line of LCD
DEFINE LCD_EBIT 0 'Define PortB pin used for E connection
DEFINE LCD_BITS 4 'Define the 4 bit communication mode to LCD
DEFINE LCD_LINES 2 'Define using a 2 line LCD
DEFINE LCD_COMMANDUS 2000 'Define delay between sending LCD commands
DEFINE LCD_DATAUS 50 'Define delay time between data sent.

'
' Serial Communication definition
' ===============================
DEFINE HSER_TXSTA 24h ' enable transmit, BRGH=1
DEFINE HSER_SPBRG 129 ' 9600 Bauds

'
' Variables definition
' ===================
myvar var byte

' ---------------------------------[Program Start]----------------------------------------------
start:
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
gosub lcddisp
goto start

lcddisp:
LCDOUT $FE, 1, myvar
pause 60
return
end


The modified Keypad code

TRISA=%00000011
TRISB=%00000000
TRISC=%11111110
ADCON0=%11000000
ADCON1=%00000111
INCLUDE "KeyPad.bas"

'
' Hardware connection
' ===================
DEFINE KEYPAD_ROW 8 ' 8 row
define KEYPAD_ROW_PORT PORTc ' on PORTB
DEFINE KEYPAD_ROW_BIT 0 ' <7:0>
DEFINE KEYPAD_COL 4 ' 4 col
DEFINE KEYPAD_COL_PORT PORTc ' on PORTA
DEFINE KEYPAD_COL_BIT 0 ' <3:0>
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
define KEYPAD_AUTOREPEAT 1 ' use auto-repeat
' LCD Display
' -----------
' Adjust these to suit your chosen LCD pinout
'
DEFINE LCD_DREG PORTb 'Define PIC port used for LCD Data lines
DEFINE LCD_DBIT 4 'Define first pin of portb connected to LCD DB4
DEFINE LCD_RSREG PORTb 'Define PIC port used for RS line of LCD
DEFINE LCD_RSBIT 3 'Define Portb pin used for RS connection
DEFINE LCD_EREG PORTb 'Define PIC prot used for E line of LCD
DEFINE LCD_EBIT 0 'Define PortB pin used for E connection
DEFINE LCD_BITS 4 'Define the 4 bit communication mode to LCD
DEFINE LCD_LINES 2 'Define using a 2 line LCD
DEFINE LCD_COMMANDUS 2000 'Define delay between sending LCD commands
DEFINE LCD_DATAUS 50 'Define delay time between data sent.

'
' Serial Communication definition
' ===============================
DEFINE HSER_TXSTA 24h ' enable transmit, BRGH=1
DEFINE HSER_SPBRG 129 ' 9600 Bauds

'
' Variables definition
' ===================
myvar var byte

' ---------------------------------[Program Start]----------------------------------------------
start:
@ READKEYPAD _myvar
hserout ["Key=",dec myvar,13,10]
gosub lcddisp
goto start

lcddisp:
LCDOUT $FE, 1, myvar
pause 60
return
end




forgot to put the error code

Executing: "C:\Program Files\Microchip\MPASM Suite\MPAsmWin.exe" /q /p16F876A "KEYPADTE.ASM" /l"KEYPADTE.lst" /e"KEYPADTE.err"
Error[113] C:\PBP\PBPPIC14.LIB 2784 : Symbol not previously defined (PORTb)
Error[113] C:\PBP\PBPPIC14.LIB 2785 : Symbol not previously defined (PORTb)
Error[113] C:\PBP\PBPPIC14.LIB 2789 : Symbol not previously defined (PORTb)
Error[113] C:\PBP\PBPPIC14.LIB 2790 : Symbol not previously defined (PORTb)
Error[113] C:\PBP\PBPPIC14.LIB 2800 : Symbol not previously defined (PORTb)
Error[113] C:\PBP\PBPPIC14.LIB 2871 : Symbol not previously defined (PORTb)
Error[113] C:\PBP\PBPPIC14.LIB 2889 : Symbol not previously defined (PORTb)
Error[113] C:\PBP\PBPPIC14.LIB 2913 : Symbol not previously defined (PORTb)
Error[113] C:\PBP\PBPPIC14.LIB 2920 : Symbol not previously defined (PORTb)
Error[113] C:\PBP\PBPPIC14.LIB 2928 : Symbol not previously defined (PORTb)
Error[113] C:\PBP\PBPPIC14.LIB 2934 : Symbol not previously defined (PORTb)
Error[113] C:\PBP\KEYPADTE.ASM 100 : Symbol not previously defined (PORTc)
Error[113] C:\PBP\KEYPADTE.ASM 103 : Symbol not previously defined (PORTc)
Error[113] C:\PBP\KEYPADTE.ASM 125 : Symbol not previously defined (PORTc)
Error[113] C:\PBP\KEYPADTE.ASM 136 : Symbol not previously defined (PORTc)
Halting build on first failure as requested.
BUILD FAILED: Thu Nov 20 16:00:57 2008

mister_e
- 20th November 2008, 18:13
YUP, that's what happen when you don't check the spelling of your DEFINEs. DEFINEs are case sensitive. So PORTb have to be written PORTB, and so on with all others.

chrisshortys
- 20th November 2008, 18:35
;) Cheers, so any clues as to whats wrong now? i dont get any reaction on the LCD and i get several ports flash high then low

mister_e
- 20th November 2008, 18:46
well...


DEFINE KEYPAD_ROW 8 ' 8 row
define KEYPAD_ROW_PORT PORTc ' on PORTB
DEFINE KEYPAD_ROW_BIT 0 ' <7:0>
DEFINE KEYPAD_COL 4 ' 4 col
DEFINE KEYPAD_COL_PORT PORTc ' on PORTA
DEFINE KEYPAD_COL_BIT 0 ' <3:0>


looking at your schematic bellow
http://www.picbasic.co.uk/forum/attachment.php?attachmentid=3016&d=1227197183
There's some problems there for sure... You don't use a 8X4 keypad ;)



DEFINE KEYPAD_ROW 4
DEFINE KEYPAD_ROW_PORT PORTC
DEFINE KEYPAD_ROW_BIT 0

DEFINE KEYPAD_COL 3
DEFINE KEYPAD_COL_PORT PORTC
DEFINE KEYPAD_COL_BIT 4

chrisshortys
- 20th November 2008, 19:34
Thanks yet again mister_e! You should move in with me, that way i wouldnt have to use the net to bother yo every other day :p

and yes i put the dec2 myvar on the lcdout command so all works now :)

time to play with it some more!

da_cure_4_u
- 31st March 2009, 18:13
I would like to scan a 4x4 keypad to use as a calculator on PIC16F88.

anyone can help please???

mister_e
- 1st April 2009, 04:49
Try something by yourself first.
Download the Keypad Include file,
Find LCDOUT in your manual,
Use the example I gave in POST #1 and you're almost half done if you replace HSEROUT with LCDOUT.

Dennis
- 18th November 2009, 22:18
Hi all

Please would somebody be so kind as to shed some light on the problem I am experiencing.

I am busy re-kindling my hobby and interest in PIC programming, I think these forums are an excellent resource, somehow all roads lead back here after many a google search and reading post after post and numerous articles.
After 3 weeks of late nights and sore eyes and a lot of reading later I have finally gotten to a stage where I have a functional (perhaps a very under-utilized PIC 18F4530).
After having blinked LED's and read switches and getting my LCD working I would like to implement a keypad as opposed to a bank of dip switches.

I am trying to implement the keypad.bas file submitted by mister_e (Thanks mister e ... your code looks fantastic, I'm dying to use it properly :-)

So here's where I'm at now....

I am trying to connect a 4 x 4 matrix keypad to my 18F4520 PIC.

Ultimately I would like to be able to be able to type in a number, end it with a # to signify completed input and then transmit the inputted number to another pic either wired or wireless.

The keypad layout is as follows.
my keypad matrix

1 2 3 A
4 5 6 B
7 8 9 C
* 0 # D


I have connected the keypad to the pic as follows.

Keypad PIC

Column 0 PortA.0
Column 0 PortA.1
Column 0 PortA.2
Column 0 PortA.
Row 0 PortC.0
Row 1 PortC.1
Row 2 PortC.2
Row 3 PortC.3

10K pullups set on column inputs
100 Ohm resistors in series with rows

When I have the above configured my LCD just produces blocks

If I remove either the pullups and/or the series resistors I just get "Key Value" 20 continuously appearing on the LCD and if I press a key on the keypad I get the "key Value" changing on the LCD but it is not the correct value according to my keypad.

I could also use the whole of Port A but when I tried it but had the same results :-(

Initially I tried to connect on PortB and had the same results, so I assumed it was because I was getting inputs from pin 39 and pin 40 of the pic where the PICkit 2 is connected for ICSP.

I have attached my code below.

Please could someone advise as to where I am going wrong or what I could look at to fix the problem !

I think it could be a possible CONFIG problem or coding issue in my code.

Any help would be greatly appreciated.

Kind regards

Dennis



'*************************************
'LCD code for 16 X 2 HD4x lcd
'*************************************

'Ocsillator selections here
OSCCON = $70 'Int CLK 8MHz
OSCTUNE.6 = 1 'PLL 4x
ADCON1= %00001111 '$0F = disable A/D converter
'END of oscillator selections


'Port IO directions and presets for port pins begin here
'TRISA = %11111111 'All pins are outputs
TRISA.0 = 1
TRISA.1 = 1
TRISA.2 = 1
TRISA.3 = 1
TRISB = %00000000
'TRISC = %00000000
TRISC.0 = 1
TRISC.1 = 1
TRISC.2 = 1
TRISC.3 = 1

TRISD = %00000000
TRISE.0 = 0
TRISE.1 = 0
TRISE.2 = 0
'End of Port IO directions and presets for port pins begin here

'timer/oscillator defines
DEFINE OSC 32 '4x 8MHz
'END of timer/oscillator defines

'variables begin here
myvar var byte

'LCD defines begin here
DEFINE LCD_BITS 4 'defines the number of data interface lines (4 or 8)
DEFINE LCD_DREG PORTD 'defines the port where data lines are connected to
DEFINE LCD_DBIT 4 'defines the position of data lines for 4-bit interface (0 or 4)
DEFINE LCD_RSREG PORTD 'defines the port where RS line is connected to
DEFINE LCD_RSBIT 2 'defines the pin where RS line is connected to
DEFINE LCD_EREG PORTD 'defines the port where E line is connected to
DEFINE LCD_EBIT 3 'defines the pin where E line is connected
DEFINE LCD_RWREG 0 'defines the port where R/W line is connected to (set to 0 if not used)
DEFINE LCD_RWBIT 0 'defines the pin where R/W line is connected to (set to 0 if not used)
DEFINE LCD_COMMANDUS 2000 'defines the delay after LCDOUT statement
DEFINE LCD_DATAUS 200 'delay in micro seconds
'END of LCD DEFINES

'KEYPAD 4x4 defines begin here
DEFINE KEYPAD_ROW 4 ' 4 ROW keypad
DEFINE KEYPAD_ROW_PORT PORTC ' ROW port = PORTB
DEFINE KEYPAD_ROW_BIT 0 ' ROW0 = PORTB.4
DEFINE KEYPAD_COL 4 ' 4 COL keypad
DEFINE KEYPAD_COL_PORT PORTA ' COL port = PORTB
DEFINE KEYPAD_COL_BIT 0 ' COL0 = PORTB.0
DEFINE KEYPAD_DEBOUNCEMS 200 ' debounce delay = 200 mSec
DEFINE KEYPAD_AUTOREPEAT 1 ' use auto-repeat feature
'End of KEYPAD defines

'*********************Includes******

include "C:\PBP\SAMPLES\KeyPad.bas"
'Includes end here

'Code begins here
Pause 500 ' Wait for LCD to startup

start:
@ READKEYPAD _myvar
lcdout $fe, 1
lcdout " Key Value = ",DEC2 myvar
goto start

Dennis
- 21st November 2009, 13:50
My problem in the previous post here is now solved.
The keypad is working.

But I now am trying to solve 2 more problems

1. I need the keypresses to reflect the correct label
My matrix is
1 2 3 A
4 5 6 B
7 8 9 C
* 0 # D

At the moment I get the following 1,2,3,4 as opposed to 1,2,3,A

2. I would like to capture a number of keystrokes as I type them in for example 135 completing input with a #
So the number stored will be the number decimal 135

Any help or suggestions will be most appreciated.

Kind regards

Dennis
For example keypress1

Ioannis
- 23rd November 2009, 08:42
An idea would be to use the lookup command for your translation from numbers to numbers-ASCII conversion.

Now about the numbers to assebly in a byte. What is the range of your input?

0-255 or 0-999?

Ioannis

Dennis
- 23rd November 2009, 14:24
Hi Ioannis

Thanks for the reply :-)
Lookup is already implemented and working .

My range would be anything really (inifinity ??) but I guess I could use 0 to 999

It's like dialling on a phone ... you dial the numbers and then press the dial button :-)

I want to type numbers in and then press the # key and * to backspace or clear last entry ...

Kind regards

Dennis

Ioannis
- 23rd November 2009, 20:56
Well, if you go for the 999 then a 0-65535 is possible as the final result needs a word variable.

One idea untested is this:



array var byte[5]
index var byte
i var byte
word_v var word

'Get keypress
index=0

loop:
gosub key_read
if mykey=32 then loop 'No key press returns 32
array[index]=myvar
index=index+1
if index=5 then calculate_result
goto loop
...

caculate_result:
word_var=0:mult=10000
for i=index-1 to 0 step -1
word_var=word_var*mult+array[i]
mult=mult/10
next i
index=0
goto display_result


As there is the index counter, there is no need to press '#'. Numbers must be entered in 5 digit format, e.g. 00123.

Also there is no filter if the user keys in a number greater than 65535, in which case result will be of course wrong due to overflow.

Ioannis

Dennis
- 23rd November 2009, 21:37
Hi Ioannis

Thank you for the code example... I'm just thinking that perhaps it would indeed be more practical to use 255 as the max number, in which case I would need to declare a byte as opposed to a word ...not so ?

Kind regards

Dennis

Ioannis
- 24th November 2009, 08:14
Yes, that is correct. Rest applies of course.

But don't be afraid of the word variable!

Ioannis

Dennis
- 7th January 2010, 23:29
Hi all

The keypad code has been working very well ! Thanks mister_e!

Initially I had to wire alter the wiring to the keypad to the PIC to get things working now in order to match the header pins for PORT B on a dev board I am building I need to alter the include file somehow to match my keypad.
I was hoping someone could point me in the right direction for this or tell me where to change the code to match the desired pin configuration.
Here is what I have now:

EXISTING CONFIG (WORKING)
-------------------------

Columns Rows
______________ _____________
Keypad 7 6 5 4 3 2 1 0

PIC B4 B5 B6 B7 B0 B1 B2 B3

Here's what I would like to be
DESIRED CONFIG
--------------

Columns Rows
______________ _____________
Keypad 7 6 5 4 3 2 1 0

PIC B7 B6 B5 B4 B3 B2 B1 B0



I would appreciate any help/info

Kind regards

Dennis

Dennis
- 7th January 2010, 23:38
Check the attached file

Dennis

Darrel Taylor
- 8th January 2010, 04:36
Steve's keypad routines won't let you reverse the orders like that.
But you can re-map the keys to whatever you want.

By reversing both the columns and rows, I think it would come out like this ...

@ READKEYPAD _myvar

; original keys 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
LOOKUP myvar,[0,16,15,14,13,12,11,10,9,8, 7, 6, 5, 4, 3, 2, 1],myvar
Which should also work like this ...
myvar = 17 - myvar
If they don't line up right, you can change the LOOKUP to a pattern that matches.

hth,

Dennis
- 8th January 2010, 20:38
Thanks Darrel

Will give it a shot and feedback results here :-)

Dennis

Dennis
- 8th January 2010, 21:41
Hi Darrel

Thanks for the assistance :-)
The LOOKUP change was the easiest solution !

originally I had this

@ READKEYPAD _myvar 'read keypress variable and place in myvar

LOOKUP myvar,[0,"123A456B789C*0#D"],myvar 'use lookup table to diplay proper keypress


And I just changed the line to this


@ READKEYPAD _myvar 'read keypress variable and place in myvar
LOOKUP myvar,[0,"D#0*C987B654A321"],myvar


Thanks a million , it saves me having to redo my dev board design or re-wiring the keypad :-) YAY

Kind regards
Dennis

boroko
- 17th January 2010, 11:37
HI all,
I have been playing with this wonderful piece of code for many hours. Really cool code. I was having problems with one row of the keypad but the rest was working enough for me to proceed filling in the gaps and learning the lessons from the thread. I bring this up because I have been caught on it before, you would have thought I'd have learned....

The row in question would freeze the operation of the circuit. Upon looking closely at the datasheet, I my eye caught the LOW VOLTAGE PROGRAMMING option. A faint voice in my head reminded me that we were not friends (the option, not the voice). Yep, that was it. Disabled it in meLabs programmer and... you guessed it... runs just like it was suppose to. Who'd a thought it?

Hope that this saves someone else some head banging. Some gotchas I have to keep reminding myself about.
Bo

boroko
- 23rd January 2010, 09:41
Hi all,

I have managed to get Steve's (Mister E) KeyPad.bas to remap and do what I would like to accomplish. Thanks again Steve for writing it and you others for explaining it. Really handy!

Here's the question: Where in KeyPad.bas would you insert the "LOOKUP myvar,... " so that you only had to do it once and not burn up a bunch of space? In my case, I would save the original, and rename the converter custom version to something appropriate.

From what I can decipher, (which is embarrassingly meager), the include file sets up a macro if you choose to use "@ READKEYPAD _YourVar". It gets the result from the subroutine "KeypadScan".

Am I right that the "LOOKUP..." would go just before the "ReadCol:"
subroutine to allow the remapping to occur each time you look for a key?

Thanks
Bo

boroko
- 23rd January 2010, 10:27
I'm sorry to the list....

After I posted that last question, it hit me like a brick... That was being really immature... I knew what I wanted to happen, but I hung when I saw a bit of code that was confusing to me. I had an idea what might work but instead of trying to test it myself, I defaulted to asking the list. Very poor.. I should have at least tried something and done some of my own work first instead of asking others to do it for me.

My feeble assumption proved so far to be correct, by adding the LOOKUP into what I now call KeyPadRM.bas (the RM for ReMap), and making sure to save it as a .bas, I can eliminate many redundant lines of code. The edit is at the end of Steve's code:
......
until row>(KB_ROW-1)
if (single_scan=0) AND (KEY=0) then ScanKeypad ; Row scan finished?
LOOKUP Key,[0,1,2,3,10,4,5,6,11,7,8,9,12,15,14,16,13],Key ; ReMap Edit
RETURN ; any key pressed?
ReadCol:
KeyTemp=kb_col_PORT>>kb_col_Bit ; Read Column state
KeyTemp=KeyTemp & kEYMASK ; Keep only wanted bits
return

JumpOverKeyScan:

Any corrections of my understanding are welcome.
Bo

Dennis
- 23rd January 2010, 17:09
I think that's fantastic :-)

Thank you !

I'm not sure why you're running yourself down like that , you should give yourself a pat on the back !

I think that the list is a great place for when you get to the point of confusion and whether or not someone replies at least you have jotted down your thoughts either for tohers to give advice or give you a different angle or even you realising that there is another angle on a problem or solution :-)

I have also had the same issues, having to reload the same code or think about more efficient ways to change my bits of code to use the results from the keypad routine more efficiently.

Now .. a quick question .. did you just add the lookup line in the place you have pointed out in the code stub you posted ? So the 'looked-up' keypress now is held in MYVAR ?

Kind regards

Dennis

boroko
- 25th January 2010, 00:29
Hi Dennis
I'm really not putting myself down as much as it sounds, more like venting so that others can see the process. I feel strongly that one should close the loop when something is learned. Otherwise, no one can gain from it. I get very frustrated when I run into an open loop never get to find out what was resolved. The main point on my thoughts were the realization that I could have written a snippet and tested my idea quicker than I could have written up the question. That's pretty sad. Time to start moving from milk to meat..

In answer to your question, the snippet of code that I posted is exactly what I used. The variable was converted in that line and returned just as if that line was never inserted.

Bo

fratello
- 3rd February 2012, 18:01
I made a simple schematic for testing my remote control stalk near the steering wheel, from Renault.
I use "KeyPad_2.bas" , addapted to my hardware :

;
; Default settings
; ================
KB_ROW = 2 ; 2 ROW keypad
KB_ROW_PORT = PORTB ; Keypad ROW on PORTB
KB_ROW_BIT = 0 ; ROW0 = PORTB.0
KB_COL = 3 ; 3 COL keypad
KB_COL_PORT = PORTA ; Keypad Col on PORTA
KB_COL_BIT = 0 ; COL0 = PORTA.0
DebounceDelay = 0x41 ; debounce delay 41mSec
SINGLE_SCAN = 0 ; Scan ;till a key is pressed
KEYPAD_AUTOREPEAT = 1

The code it's verry simple :

@ DEVICE pic16F628A, XT_OSC, WDT_OFF, PWRT_OFF, BOD_OFF, MCLR_OFF, LVP_OFF

Define OSC 4 ' 4MHz
CMCON = 7 ' Disable on-chip comparator, PORTA in digital mode
OPTION_REG.7=1

include "c:\pbp\MYKEY.BAS" ' see http://www.picbasic.co.uk/forum/showthread.php?t=3250

main:
gosub keypadscan
gosub check
goto main


check:
select case key
CASE 1
portb.2 = 1
pause 5000
portb.2 = 0

case 2
portb.3 = 1
pause 5000
portb.3 = 0

case 3
portb.4 = 1
pause 5000
portb.4 = 0

case 4
portb.5 = 1
pause 5000
portb.5 = 0

case 5
portb.6 = 1
pause 5000
portb.6 = 0

case 6 ; track +
portb.7 = 1
pause 5000
portb.7 = 0

end select
Return


But....
Allways LED's on PortB.2 and PortB.3 are ON ! What I am doing wrong ?!? Thanks in advance for reply !

fratello
- 6th February 2012, 11:43
Problem solved...by moving ALL rows and columns to PortB ...

; Default settings
; ================
KB_ROW = 4 ; 4 ROW keypad
KB_ROW_PORT = PORTB ; Keypad ROW on PORTB
KB_ROW_BIT = 0 ; ROW0 = PORTB.0
KB_COL = 4 ; 4 COL keypad
KB_COL_PORT = PORTB ; Keypad Col on PORTB
KB_COL_BIT = 4 ; COL0 = PORTB.4
DebounceDelay = 0x200 ; debounce delay 200mSec
SINGLE_SCAN = 0 ; Scan ;till a key is pressed

longpole001
- 1st February 2014, 21:36
Hi Guys ,

Well this keyboard matrix routine has been here a while and works well.

but if you need to place a 1 row or column port pin on another port out of sequence then you have a problem.

I face this as i changed from 16f1947 to 18f67k22 on the pcb , where the 16f1947 has portF.0 , and 18f67k22 does not
as you guessed a row pin was on Portf.0

PORTF.0 -3 was row ,portb 0-3 was column , so no problem with the column port , but row0 wont work on an non existent port
so the new row0 port was connected to a spare pin at portG.4

PortG.4 TRES direction was set to output prior to keypad.bas include used , but could have been set in in the keypad.bas section of code after the asm that sets the TRES for the colume and row ports assigned


I used the port offset value to point portG.4 , when it was selecting row0 , and set the POrtG.4 =1 prior as per steves comments
the offset value 12 is worked out 12 port locations past portF0

i also did not care if portF.0 TRES were set to output as per steves routine , but if this was an issue , removing the ASM code that sets the TRES in keypad.bas and do it as per normal would have been ok


I hope this helps someone that has a similar problem

cheers

Sheldon

Code section prior to change
=====================




ScanKeypad:
key=0 ; no key is press
row=0 ; begin scan @ ROW0
col=0 ; and COL0

kb_row_PORT=kb_row_PORT | InitialState ; set all ROW bits to 1 using bitwise OR
repeat


ROWBIT=ROW+KB_ROW_BIT ; point to a ROW bit
kb_row_PORT.0[RowBit]=0 ; clear actual ROW bit


after code change
==============



ScanKeypad:
key=0 ; no key is press
row=0 ; begin scan @ ROW0
col=0 ; and COL0
PORTG.4 = 1 ; Setup row-0 = 1

kb_row_PORT=kb_row_PORT | InitialState ; set all ROW bits to 1 using bitwise OR
repeat

if row = 0 then
Rowbit = 12 ; offset amount for row 0 from PortF.0 to point to PortG.4
else
ROWBIT=ROW+KB_ROW_BIT ; point to a ROW bit
endif
kb_row_PORT.0[RowBit]=0 ; clear actual ROW bit

longpole001
- 30th March 2014, 22:33
handy key fifo for this routine to keep 5 key strokes deep




if key >0 then

for Key_count = 4 to 1 step - 1
Key_value(Key_count) = Key_value( Key_count - 1)
next Key_count

Key_Value(0) = Key

endif

fratello
- 12th July 2015, 17:51
How can I use this include for something like this ???


main:
@ READKEYPAD _myvar
gosub check
goto main

check:
select case myvar

case 1
porta.0 = 1 ; WHILE CASE 1 PORTA.0 = 1, THEN PORTA.0 = 0

Thanks !

HenrikOlsson
- 12th July 2015, 17:56
CASE 1
Porta.0 = 1
WHILE myVar = 1
@ READKEYPAD _myvar
WEND
PortA.0 = 0


/Henrik.

fratello
- 12th July 2015, 18:22
Thank You!

LE : But don't work.
Press button 1 of matrix ; led 1 = OFF ; end pressing button 1 ; led 1 = ON untill press ANOTHER button ...say button 2.
But pressing button 2 don't turn ON led2 ; just another press and release of button 2 turn correspondent led (2) ON.

HenrikOlsson
- 12th July 2015, 19:05
In your first post you indicated that you wanted PortA.0 high while the myVar was equal to 1 - is that not what's happening with the code?
How do you want it to work and what does the code look like?

fratello
- 12th July 2015, 19:18
Thanks for support , Mr.Henrik !
What I want :
- porta.x = ON while correspondent button.x is pressed.
How work :
- press button x ; do nothing ; release button x - porta.x=ON ; remain ON while press ANOTHER button(say y) ...But this new button(y) don't turn correspondent porta.y ON ; just turn OFF previous porta.x ; only after the release of the second press turn on correspondent porta.y...

HenrikOlsson
- 12th July 2015, 19:57
Hi,
1) The documentations for the keypad routine says that myVar should be a BYTE, you have it declared as a WORD. Don't think it matters but ....
2) There's no RETURN at the end of the Check subroutine.
3) The routine has some sort of AutoRepeat feature, I don't know if that is perhaps messing with you - I've never used the routine myself.
4) The filename for the INCLUDE file says Keypad1, have you modifed it in any way?
5) Do you have your LED's wired as in the schematic? Ie PortA.1 = 1 does actually turn on the LED?

Which device?

/Henrik.

fratello
- 12th July 2015, 20:12
1.I (re) declared myVar as byte .
2.I added Return at the end of check.
3.I use this in my keypad include :
" SINGLE_SCAN = 0 ; Scan ;till a key is pressed
KEYPAD_AUTOREPEAT = 1 "
4.No, just portb allocation
5.Yes.
No change in how the code work ...

Thanks again !

LE : "SINGLE_SCAN" must be set to "1" for acting like I wish ...
Thanks ! Regards !

cesar35
- 17th September 2022, 11:02
HI
ABOUT THE ROUTINE WRITTEN BY MR MISTER_E.
I NEED HELP HOW TO MAKE THE NUMBERS ARE IN SERIES EXAMPLES 12345566
AND THEN PRESS THE BUTTON # SEND VIA SERIAL A SEQUECIA.

#CONFIG
__config _HS_OSC & _WDT_OFF & _PWRTE_OFF & _CP_OFF & _LVP_OFF & _WRT_OFF
#ENDCONFIG

DEFINE OSC 4

TRISA=%00000011
TRISB=%00000000
TRISC=%11111110
ADCON0=%11000000
ADCON1=%00000111
INCLUDE "KeyPad2.bas"

'
' Hardware connection
' ===================

DEFINE KEYPAD_ROW 4
DEFINE KEYPAD_ROW_PORT PORTC
DEFINE KEYPAD_ROW_BIT 0
DEFINE KEYPAD_COL 3
DEFINE KEYPAD_COL_PORT PORTC
DEFINE KEYPAD_COL_BIT 4
DEFINE KEYPAD_DEBOUNCEMS 200 'debounce delay = 200 mSec
define KEYPAD_AUTOREPEAT 1 'use auto-repeat

' LCD Display
' -----------
' Adjust these to suit your chosen LCD pinout
'
'----DEFINIR LCD--------------------------------------------------------------
DEFINE LCD_DREG PORTB ' LCD data port
DEFINE LCD_DBIT 4 ' LCD data starting bit
DEFINE LCD_RSREG PORTB ' LCD register select port
DEFINE LCD_RSBIT 2 ' LCD register select bit
DEFINE LCD_EREG PORTB ' LCD enable port
DEFINE LCD_EBIT 3 ' LCD enable bit
DEFINE LCD_BITS 4 ' LCD data bus size
DEFINE LCD_LINES 2 ' Number lines on LCD
DEFINE LCD_COMMANDUS 5000 ' Command delay time in us
DEFINE LCD_DATAUS 50 ' Data delay time in us

mykey VAR BYTE
myvar var byte
array var byte[5]
index var byte
i var byte
word_v var word

LCDOUT $FE,1, " FONTE DIGITAL "
PAUSE 1000
LCDOUT $FE,1
' ---------------------------------[Program Start]----------------------------------------------
start:
@ READKEYPAD _myvar
gosub lcddisp
goto start

lcddisp:
LCDOUT $FE,$C0,DEC4 myvar
pause 60
return
end

Ioannis
- 18th September 2022, 20:30
You may add the keypresses to an array using an index and then send the array over the serial port.

Not tested but you get the idea:



string var byte[9]
index1 var byte

start:
For index1=0 to 8
@ READKEYPAD _myvar
string[index1]=myvar
next index1

if myvar="#" then hserout [STR string\8]

goto start


Ioannis