-
Re: New approach to Rotary Encoder
Try GOSUB Encoder and put a RETURN at the end of the subroutine. Currently you GOTO Encoder and then you run off into never never land. I'm not saying that will make it work but that's one possible problem.
Also, make sure that have the "wiper" of the roller connected to 5V, verify that you get signals on the actuall pins of the PIC when you rotate the encoder/roller.
-
1 Attachment(s)
Re: New approach to Rotary Encoder
I think the hardware must be build in this way (since the rest of buttons are allready connected as matrix). I wonder if "KeyPad.bas" of Mr.Mister-e can be addapted to read the increment/decrement of roller, by "including" somehow the code for encoder ....
Brrrrrr...it's beyond of my intellectual capacities :( .
-
Re: New approach to Rotary Encoder
Hi,
I don't have any experience with that routine but provided everything else works the way you want why don't you just set the pin which is common to the encoder (RB5 ?) high, read the port, and return the pin low.
GOSUB ScanMatrix 'Or whatever
PortB.5 = 1
GOSUB Encoder
PortB.5 = 0
Finally, in the first code you posted you had the encoder to RB7-5 so I based my code on that. Now, in your latest schematic, you have it on RB2-0 which means that my code (if that's what you're trying) definitely won't work without modifying it since it expects the three "switches" in the encoder to be on RB7-5.
-
Re: New approach to Rotary Encoder
What I do wrong ?!
I adapted "keypad.bas" to my hw :
Code:
KB_ROW = 3 ; 3 ROW keypad
KB_ROW_PORT = PORTB ; Keypad ROW on PORTB
KB_ROW_BIT = 3 ; ROW0 = PORTB.3
KB_COL = 3 ; 3 COL keypad
KB_COL_PORT = PORTB ; Keypad Col on PORTB
KB_COL_BIT = 0 ; COL0 = PORTB.0
DebounceDelay = 0x80 ; debounce delay 41mSec
SINGLE_SCAN = 0 ; Scan ;till a key is pressed
KEYPAD_AUTOREPEAT = 1
and I wrote this pice of code :
Code:
@ DEVICE pic16F628A, XT_OSC, WDT_OFF, PWRT_ON, BOD_OFF, MCLR_ON, LVP_OFF
Define OSC 4 ' 4MHz
CMCON = 7 ' Disable on-chip comparator, PORTA in digital mode
include "alldigital.pbp"
include "C:\PBP\enc_KEY.BAS"
TrisA = %00000000
PortA = %00000000
PortB = %00111000
TrisB = %00011000
oldState VAR BYTE
newState VAR BYTE
Q_Count VAR WORD
DIR VAR BIT
UP CON 1
DN CON 0
Main_Loop:
newState = (PortB & %00111000)
portb.5 = 1
gosub encoder
portb.5 = 0
if dir = up then
porta.0 = 0
porta.1 = 1
endif
if dir = dn then
porta.0 = 1
porta.1 = 0
endif
goto Main_Loop
encoder:
If newState <> 0 THEN
If newState <> oldState THEN ' Changed from last time?
Select Case oldState
Case 32
If NewState = 128 THEN ' Was 1 now 4 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 1 now 2 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
Case 64
If NewState = 32 THEN ' Was 2 now 1 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 2 now 4 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
Case 128
If NewState = 64 THEN ' Was 4 now 2 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 4 now 1 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
END SELECT
oldState = NewState
ENDIF
ENDIF
Return
..but no change in porta.0 or porta.1 state ...
-
Re: New approach to Rotary Encoder
Update code :
Code:
Main_Loop:
gosub keypadscan
newState = (PortB & %00000111)
gosub encoder
gosub check
goto main_loop
Check :
if dir = up then
porta.0 = 0
porta.1 = 1
endif
if dir = dn then
porta.0 = 1
porta.1 = 0
endif
return
encoder:
If newState <> 0 THEN
If newState <> oldState THEN ' Changed from last time?
Select Case oldState
Case 32
If NewState = 128 THEN ' Was 1 now 4 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 1 now 2 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
Case 64
If NewState = 32 THEN ' Was 2 now 1 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 2 now 4 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
Case 128
If NewState = 64 THEN ' Was 4 now 2 = Up
Q_Count = Q_Count + 1
DIR = UP
ELSE ' Was 4 now 1 = Down
Q_Count = Q_Count - 1
DIR = DN
ENDIF
END SELECT
oldState = NewState
ENDIF
ENDIF
Return
but no matter what M (1,2 or 3) I push, porta.0 goes high and stay so.
-
Re: New approach to Rotary Encoder
Hi,
In the first code you posted you read the status of PortB before driving the the common pin for the encoder so there probably won't be any signals comming in.
In the second, updated example, you never drive the common pin for the encoder at all.
You need to set the "common pin" high (or low depending on hardware) and THEN read the port otherwise you won't get anything back.
You really need to sit back and think the problem thru, not just cut and paste pieces of code together without understanding what they do and how the hardware they're intended to interface to is supposed to work.
Think it thru.... The "encoder" has a "wiper" which "cylces" thru the different contacts. Depending on which contact the wipers is positioned at you'll get a signal out on a certain pin. In order to get that signal out the "wiper" must be "powered" in one way or another. If the inputs from the "contacts" are pulled up then wiper must be grounded so that it pulls the contact (and signal LOW). Likewise if the inputs from the contacts are pulled down then the "wiper" must be high in order to pull the inputs high.
If the inputs are pulled up with resistors then you'll get a "walking zero" across the three pins, if the inputs are pulled down you'll get a "walking one" across the inputs. You must adapt the code to match.
My suggestion, for now, is that you ditch the matrix routine untill you get the encoder working - and understand how it works.
/Henrik.
-
1 Attachment(s)
Re: New approach to Rotary Encoder
Thanks for support !
"In the second, updated example, you never drive the common pin for the encoder at all."
But ..."keypadscan" don't do this ? Proteus show how "0" walk through portb 3,4,5.
-
Re: New approach to Rotary Encoder
Hi,
Like I said earlier, I don't have any experience with that piece fo code but if I'd venture I guess (and I'm pretty certain I'm right) it scans the pins once each time you GOSUB the routine. This means it does NOT scan the pins during the time you GOSUB the encoder routine.
Does Proteus show that walking zero across the pins at the same time as you do newState = PortB & %00000111 - I'd say no.
If your inputs are pulled up with resistors then the common/wiper of the encoder must be LOW at the time you read the status of the port. You must understand and remember that the PIC executes the code sequentially, one instruction after another.
-
1 Attachment(s)
Re: New approach to Rotary Encoder
Step-by-step I think I begin to understand ...
The correct hardware it's this.
The software can be this :
Code:
@ DEVICE pic16F628A, XT_OSC, WDT_OFF, PWRT_ON, BOD_OFF, MCLR_ON, LVP_OFF
Define OSC 4 ' 4MHz
CMCON = 7 ' Disable on-chip comparator, PORTA in digital mode
include "alldigital.pbp"
include "C:\PBP\enc_KEY.BAS"
TRISB = 000000
PORTB = 000000
oldState VAR BYTE
newState VAR BYTE
DIR VAR BIT
UP CON 1
DN CON 0
Main_Loop:
portb.5 = 1
gosub keypadscan
gosub check
goto main_loop
Check :
if dir = up then
portb.0 = 1
pause 1000
portb.0 = 0
endif
if dir = dn then
portb.1 = 1
pause 1000
portb.1 = 0
endif
return
encoder:
portb.5 = 0
newState = (porta & 000111)
If newState <> oldState THEN ' Changed from last time?
Select Case oldState
Case 2
If NewState = 4 THEN ' Was 1 now 4 = Up
DIR = up
ELSE ' Was 1 now 2 = Down
DIR = dn
ENDIF
Case 4
If NewState = 1 THEN ' Was 2 now 1 = Up
DIR = up
ELSE ' Was 2 now 4 = Down
DIR = dn
ENDIF
Case 1
If NewState = 2 THEN ' Was 4 now 2 = Up
DIR = up
ELSE ' Was 4 now 1 = Down
DIR = dn
ENDIF
END SELECT
oldState = NewState
endif
portb.5 = 1
Return
The question is : where to put "gosub encoder" ? Inside the "enc_key.bas" (it's keypad.bas addapted to 2 row/3 cols) ???
-
Re: New approach to Rotary Encoder
Hi,
Now we're getting somewhere - that looks like it might work.
The keypad routine has nothing to do with reading the encoder. Put the GOSUB Encoder in the mainloop, before GOSUB check obviously....
And again, if it doesn't work then remove the keypad routine untill you get the encoder routine working - THEN try to make the two coexist. There's no guarantee that the encoder code works, I just posted it as one possible idea of how to read that kind of "encoder".
-
1 Attachment(s)
Re: New approach to Rotary Encoder
No matter what I do, portb.1 goes high and low :( .... portb.0 don't change :( ....
Code:
TRISB = 000000
PORTB = 000000
oldState VAR BYTE
newState VAR BYTE
DIR VAR BIT
UP CON 1
DN CON 0
oldstate = (porta & 000111)
Main_Loop:
gosub Encoder
gosub check
goto main_loop
Check :
if dir = up then
portb.0 = 1
pause 1000
portb.0 = 0
endif
if dir = dn then
portb.1 = 1
pause 1000
portb.1 = 0
endif
return
encoder:
portb.5 = 1
pause 100
newState = (porta & 000111)
portb.5 = 0
If newState <> oldState THEN ' Changed from last time?
Select Case oldState
Case 1
If NewState = 4 THEN dir=up
If NewState = 2 THEN dir=dn
Case 2
If NewState = 4 THEN dir=up
If NewState = 1 THEN dir=dn
Case 4
If NewState = 1 THEN dir=up
If NewState = 2 THEN dir=dn
END SELECT
oldstate=newstate
endif
Return
-
Re: New approach to Rotary Encoder
Hi,
Since you have the inputs pulled high and the wiper "grounding" each input as it cycles thru them you can't use 1, 2 and 4 as the states since that "looks for" a '1' on the individual pins. You need to use 3, 5 and 6 instead.
-
Re: New approach to Rotary Encoder
Twillight zone ....
Code:
Select Case oldState
Case 3
If NewState = 6 THEN dir=up
If NewState = 5 THEN dir=dn
Case 5
If NewState = 3 THEN dir=up
If NewState = 6 THEN dir=dn
Case 6
If NewState = 5 THEN dir=up
If NewState = 3 THEN dir=dn
END SELECT
No matter what I do, portb.1 goes high and low :( .... portb.0 don't change :( ....
-
1 Attachment(s)
Re: New approach to Rotary Encoder
Don't know what to tell you but the code works just fine here.
Code:
HSEROUT ["Program start",13]
Main:
PortB.5 = 0
newState = PortA & %00000111
PortB.5 = 1
If newState <> 7 THEN
If newState <> oldState THEN
Select Case oldState
Case 3
If NewState = 6 THEN dir=up
If NewState = 5 THEN dir=dn
Case 5
If NewState = 3 THEN dir=up
If NewState = 6 THEN dir=dn
Case 6
If NewState = 5 THEN dir=up
If NewState = 3 THEN dir=dn
END SELECT
HSEROUT["oldState: ", DEC oldState, " newState: ", DEC newState, " DIR: ", DEC DIR, 13]
oldState = newState
Pause 1000
ENDIF
ENDIF
Goto Main
This was executed on an AMICUS18 board with a PIC18F25K20. A wire from RB5 to the pulled up inputs was used to simulate the "encoder", the results are here:
Attachment 6404
As you can see, it works.
Have you verified that PortB.5 does go LOW?
Have you verified that you DO get a LOW on RA0,1 and 2 as you rotate the encoder?
Have you checked the datasheet to see if any other peripherals are multiplexed onto the pins you're trying to use? ADC? Comparator?
-
Re: New approach to Rotary Encoder
Been said before and I will say it again.
NEVER TRUST A SIM!
-
Re: New approach to Rotary Encoder
... ok, so work, despite the "non-working" of simulator !
Next step is to try to make the two coexist (keypad.bas & encoder.bas) .
First I will build the schematic and making some tests. Thanks again for the huge support !
-
Re: New approach to Rotary Encoder
It's this a viable options of reading encoder AND the others buttons ?
Code:
Main:
;==============
;reading buttons on line 0 (pseudo-encoder)
PortB.5 = 0
newState = PortA & %00000111
PortB.5 = 1
If newState <> 7 THEN
If newState <> oldState THEN
Select Case oldState
Case 3
If NewState = 6 THEN
dir=up
portb.0 = 1
endif
If NewState = 5 THEN
dir=dn
portb.1 = 1
endif
Case 5
If NewState = 3 THEN
dir=up
portb.0 = 1
endif
If NewState = 6 THEN
dir=dn
portb.1 = 1
endif
Case 6
If NewState = 5 THEN
dir=up
portb.0 = 1
endif
If NewState = 3 THEN
dir=dn
portb.1 = 1
endif
END SELECT
oldState = newState
Pause 100
ENDIF
ENDIF
;==============
;reading buttons on line 1
Porta.4 = 0
status_2 = PortA & %00000111
Porta.4 = 1
select case status_2
case 3
gosub trackDn
case 5
gosub mute
case 6
gosub trackUp
end select
;==============
;reading buttons on line 2
Porta.3 = 0
status_3 = PortA & %00000111
Porta.3 = 1
select case status_3
case 3
gosub volDn
case 5
gosub volUp
case 6
gosub Sursa
end select
Goto Main
-
1 Attachment(s)
Re: New approach to Rotary Encoder
So far, so god ... Now another problem : how can I separates signals?
If rotary switch is Up, can't read if TK- or V- are pressed ..
If rotary switch is in middle position, can't read if MUTE or V+ are pressed ...
If rotary switch is down, can't read if TK+ or S are pressed...
LE - I think this work :
Code:
;reading buttons on line 1
Porta.4 = 0
trisb.5 = 1
pause 50
status_2 = PortA & %00000111
Porta.4 = 1
trisb.5 = 0
-
Re: New approach to Rotary Encoder
New code works pretty well ... But, how can I avoid false roller codes ? If I turn up, not always the the code "see" up ; if I turn down, not always the code "see" down ...Sometimes, the commands (Up/Down) are inversed !
I try to add some "pause" between different commands, but the problem remains.
-
Re: New approach to Rotary Encoder
No, don't try to slow it down...speed it up. If you have any pauses in there try removing those. If your program is going to do 'other' things as well (which I'm sure it is) then you may need to sample the encoder several times thru out the main loop.
The reason is because if you are at one state and then turn forward two states but you do it fast enough so that the code doesn't detect the "middle" state, then it looks like you turned one state backwards instead of two forward.
So, you want to sample the encoder as fast as you can possibly turn it - and then some.
/Henrik.
-
Re: New approach to Rotary Encoder
I try both variants, presented in code, but without major improvements.
Code:
;==============
;reading buttons on row 0 (pseudo-encoder)
PortA.1 = 0
; pause 10
@ nop
newState = PortA & %00011100 ; this is for my hw : 11100 = 28
PortA.1 = 1
If newState <> 28 THEN
If newState <> oldState THEN
Select Case oldState
Case 12
If NewState = 24 THEN
dir=up
endif
If NewState = 20 THEN
dir=dn
endif
Case 20
If NewState = 12 THEN
dir=up
endif
If NewState = 24 THEN
dir=dn
endif
Case 24
If NewState = 20 THEN
dir=up
endif
If NewState = 12 THEN
dir=dn
endif
END SELECT
oldState = newState
GOSUB UpOrDn
pause 100
endif
ENDIF
-
Re: New approach to Rotary Encoder
Which two variants? I only see one in your previous message.
In that one you have a PAUSE 10 at the beginning, which is commented out, and also a @NOP. Then you have a PAUSE 100 near the end which is NOT commented out.
/Henrik.
-
Re: New approach to Rotary Encoder
Sorry...
"@ nop" ... not good
and then
"pause 10" ....idem.
-
Re: New approach to Rotary Encoder
If you place two 100nF to ground for debouncing false results will be limited.
Ioannis
-
Re: New approach to Rotary Encoder
I already tried that...without results ! %$@#^*#@^ roller !
-
Re: New approach to Rotary Encoder
not sure to understand your thing, but give yourself a chance, plug the encoder on a set of "interruptable" I/O, the wiper to GND and use interrupt to triger the Encoder reading. end of the story.
-
Re: New approach to Rotary Encoder
Code:
END SELECT
oldState = newState
GOSUB UpOrDn
pause 100 ' <--- Have you removed this?
endif
ENDIF
-
Re: New approach to Rotary Encoder
Mr.Mister_E : Can not put the wiper to GND because of hardware ( http://www.picbasic.co.uk/forum/show...126#post113126 ).
Mr.Henrik : I remove already this line ; is better but not best.
-
Re: New approach to Rotary Encoder
I tried to ad a second check of direction :
Code:
loop:
PortA.1 = 0
newState = PortA & 011100 ; this is for my hw : 11100 = 28
pause 50 ; no matter what I put here : none, @ nop , pause 100 !
newa = PortA & 011100
PortA.1 = 1
If newState <> 28 THEN
If newState <> oldState THEN
Select Case oldState
Case 12
If NewState = 20 THEN
if newa = 24 then dir=up
endif
case 12
If NewState = 24 THEN
if newa = 20 then dir=dn
endif
Case 20
If NewState = 24 THEN
if newa = 12 then dir=up
endif
Case 20
If NewState = 12 THEN
if newa = 24 then dir=dn
endif
Case 24
If NewState = 12 THEN
if newa = 20 then dir=up
endif
Case 24
If NewState = 20 THEN
if newa = 12 then dir=dn
endif
END SELECT
oldState = newstate
GOSUB UpOrDn
endif
ENDIF
But, in this way, any direction I rotate, the command is always "Dir Up" ?! Never goes "down" ...
-
Re: New approach to Rotary Encoder
And what does the UpOrDn routine look like?
-
Re: New approach to Rotary Encoder
This routine should do "Track+" /"Track-" :
Code:
UpOrDn:
if dir=1 then
PortB.4 = 0
pauseus 3850
PortB.4 = 1
pauseus 3850
PortB.4 = 0
pauseus 660
PortB.4 = 1
endif
if dir=0 then
PortB.4 = 0
pauseus 4450
PortB.4 = 1
pauseus 4400
PortB.4 = 0
pauseus 660
PortB.4 = 1
endif
return
-
Re: New approach to Rotary Encoder
And what do we have in there, if not delays... They are quite short (8-10ms in total) but it's still possible that that is what's messing with you.
I don't know what you intended to do with that latest version though, why do you have two cases with the same value, just put the code for both in one.
-
1 Attachment(s)
Re: New approach to Rotary Encoder
This is schematic and code...Maybe I miss something important ...
Code:
@ DEVICE pic16F628A, XT_OSC, WDT_OFF, PWRT_ON, BOD_OFF, MCLR_ON, LVP_OFF, PROTECT_ON
include "alldigital.pbp"
Define OSC 4 ' 4MHz
CMCON = 7 ' Disable on-chip comparator, PORTA in digital mode
TrisA = %00011100 ; coloane la RA2, 3, 4 ; randuri la RA1, 0 ,7
porta = %00011100
TRISB = %00000000
PORTB = %00010000
oldState VAR BYTE
newState VAR BYTE
UP CON 1
DN CON 0
loop:
PortA.1 = 0
newState = PortA & %00011100 ; this is for my hw : 11100 = 28
PortA.1 = 1
If newState <> 28 THEN
If newState <> oldState THEN
Select Case oldState
Case 12
If NewState = 20 THEN dir=up
If NewState = 24 THEn dir=dn
Case 20
If NewState = 24 THEN dir=up
If NewState = 12 THEN dir=dn
Case 24
If NewState = 12 THEN dir=up
If NewState = 20 THEN dir=dn
END SELECT
oldState = newstate
GOSUB UpOrDn
pause 15 ; time for UpOrDn
endif
ENDIF
;============
UpOrDn:
if dir=DN then
PortB.4 = 0
pauseus 3850
PortB.4 = 1
pauseus 3850
PortB.4 = 0
pauseus 660
PortB.4 = 1
endif
if dir=UP then
PortB.4 = 0
pauseus 4450
PortB.4 = 1
pauseus 4400
PortB.4 = 0
pauseus 660
PortB.4 = 1
endif
return
end
-
Re: New approach to Rotary Encoder
1) I don't understand why you keep putting those PAUSE statements in there, now you have a PAUSE 15 in there....
2) There's no GOTO LOOP anywhere so the program will "fall thru" into the UpOrDn routine then hit the RETURN and bad things will happpen. (BTW, Loop is a reserved word in newer versions of PBP, best to get used to not using it.
3) Try resampling the pins and set oldState when you return from the subroutine, ie (changes in red):
Code:
Main:
PortA.1 = 0
newState = PortA & %00011100 ; this is for my hw : 11100 = 28
PortA.1 = 1
If newState <> 28 THEN
If newState <> oldState THEN
Select Case oldState
Case 12
If NewState = 20 THEN dir=up
If NewState = 24 THEn dir=dn
Case 20
If NewState = 24 THEN dir=up
If NewState = 12 THEN dir=dn
Case 24
If NewState = 12 THEN dir=up
If NewState = 20 THEN dir=dn
END SELECT
GOSUB UpOrDn
PAUSE 15 ; time for UpOrDn
' Now resample the encoder and keep the state as oldState
PortA.1 = 0
oldState = PortA & %00011100 ; this is for my hw : 11100 = 28
PortA.1 = 1
ENDIF
ENDIF
GOTO MAIN
;============
UpOrDn:
if dir=DN then
PortB.4 = 0
pauseus 3850
PortB.4 = 1
pauseus 3850
PortB.4 = 0
pauseus 660
PortB.4 = 1
endif
if dir=UP then
PortB.4 = 0
pauseus 4450
PortB.4 = 1
pauseus 4400
PortB.4 = 0
pauseus 660
PortB.4 = 1
endif
RETURN
END
-
Re: New approach to Rotary Encoder
Mr. Henrik I must get my hat in front of you ! (Hope G.translate work well :) !).
NOW, the code work verry good !!! Only sometimes the command are inversed , but in 9 case of 10 it's ok, so I can live with this...
Thanks for lost so much time with me ! I am verry grateful !
-
Re: New approach to Rotary Encoder
Great, finally... Now try removing the PAUSE 15 and see if that improves it further.
-
Re: New approach to Rotary Encoder
Thanks to Mr.Henrik Olsson this code work PERFECT !!! I'm sure I would not have done it without his help !
Code:
Main:
PortA.1 = 0
newState = PortA & 011100
PortA.1 = 1
If newState <> 28 THEN
If newState <> oldState THEN
Select Case oldState
Case 12
If NewState = 20 THEN dir=up
If NewState = 24 THEn dir=dn
Case 20
If NewState = 24 THEN dir=up
If NewState = 12 THEN dir=dn
Case 24
If NewState = 12 THEN dir=up
If NewState = 20 THEN dir=dn
END SELECT
GOSUB UpOrDn
PortA.1 = 0
OldState = PortA & 011100
PortA.1 = 1
endif
ENDIF
Goto Main
-
Re: New approach to Rotary Encoder
Hi to all. I want to use a rotary encoder with a 18f252, and i have a lot of troubles. I want to use interupts, so my only solution PORTB or I can use Portc also?
I made a pcb and I made the connections to PORTC, and I also use a debounce circuit, which I think causes problems. Anyone has a snipset code cause I do not have any expieriance with encoders?
5v
__|__
| |
/ /
\ \
/10k / 10K
\ \
| A | B ENC
- -
| |-------------------------------
\ |
/10K \
\ /10K
/ \
|--------------------- |--------------------
PORTC.2 | PORTC.3 |
---- ----- 100nF
---- -----
| |
--------- -----------
----- -----
- -
-
Re: New approach to Rotary Encoder
Hello,
On the 18F252 there's no interrupt capabillity on PortC.
Your schematic really doesn't show up that good here but it LOOKS like you have a 10k from 5V to the "top" of each of the switches in the encoders, then the other side of each switch thru another 10k to the input with a 100nF cap to GND, is that correct?
If the above is not correct please post a proper schematic for us to see.
If the above IS correct then it's not a very good hardware design IMHO. When the switch in the ecoder is closed you have 2*10k in series to the input, decoupled by a 100nF cap, this may be fine. But when the switch is open there's no path for the capacitor to discharge except thru the fairly high input impedance of the pin. In effect the pin floats which is not a good thing for inputs.
/Henrik.
-
1 Attachment(s)
Re: New approach to Rotary Encoder
I finally got around to trying my rotary encoders out on an 18F24K22 using DT interrupts.
I kept things simple; checking for only 1 movement per click (detent). This encoder also has a momentary ON switch.
Code:
'***************************************************************************
'* Name : 18F24K22 encoder.pbp *
'* Author : Demon *
'* Date : Sep 5 2012 *
'* Version : 1.0 *
'* Hardware : PIC 18F24K22, internal oscillator, 8 MHz *
'* : ICSP *
'* : MeLabs U2 Programmer v4.32 *
'* Software : PIC Basic Pro v2.60C *
'* : MicroCode Studio Plus v2.2.1.1 *
'* : MPASM v5.46 *
'* CONFIG : - if you use these, you must comment the ones in the *
' .INC file in PBP folder *
' - available options at the bottom of P*.INC file in *
' MPLAB TOOLS/MPASM SUITE folder *
'***************************************************************************
asm
__CONFIG _CONFIG1H, _FOSC_INTIO67_1H & _PLLCFG_OFF_1H & _PRICLKEN_ON_1H & _FCMEN_OFF_1H & _IESO_OFF_1H
__CONFIG _CONFIG2L, _PWRTEN_ON_2L & _BOREN_SBORDIS_2L & _BORV_285_2L
__CONFIG _CONFIG2H, _WDTEN_OFF_2H
__CONFIG _CONFIG3H, _PBADEN_ON_3H & _HFOFST_OFF_3H & _MCLRE_EXTMCLR_3H
__CONFIG _CONFIG4L, _STVREN_ON_4L & _LVP_OFF_4L & _XINST_OFF_4L & _DEBUG_OFF_4L
endasm
;--- Oscillator speed ------------------------------------------------------
DEFINE OSC 8
CLEAR
;--- Setup Interrupts ------------------------------------------------------
INCLUDE "DT_INTS-18.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP-18.bas" ; PBP Re-entry for external interrupt
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler INT_INT, _ExternalInterrupt0, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE INT_INT ; enable external (INT) interrupts
;--- Setup Registers -------------------------------------------------------
OSCCON = %01100110 ' OSCILLATOR CONTROL REGISTER
OSCTUNE = %00000000 ' OSCILLATOR TUNING REGISTER
PMD0 = %11111111 ' PERIPHERAL MODULE DISABLE REGISTER 0
PMD1 = %11111111 ' PERIPHERAL MODULE DISABLE REGISTER 1
PMD2 = %00001111 ' PERIPHERAL MODULE DISABLE REGISTER 2
INTCON2=%10000100 ' INTERRUPT CONTROL 2 REGISTER
ANSELA = 0 ' Digital I/O
ANSELB = 0 ' Digital I/O
ANSELC = 0 ' Digital I/O
;--- Setup Port directions -------------------------------------------------
TRISA = %00000000 ' Set port A pins to output
TRISB = %00000001 ' Set port B pin 0 to input, others output
TRISC = %00000110 ' Set port C pins 1,2 to input, others output
;--- Pins ------------------------------------------------------------------
WiperA VAR PortB.0 ' Interrupt 0
WiperB VAR PortC.2
Switch VAR PortC.1
LedPower VAR PortB.5
;--- Variables -------------------------------------------------------------
LEDS VAR BYTE ' 8 Leds connected on Port A
;--- Program Start ---------------------------------------------------------
start:
Pause 200 ' Let PIC stabilize
Ledpower = 0
Leds = %00000001
PortA = leds
;--- The Main Loop ---------------------------------------------------------
mainloop:
if Switch = 1 then
Ledpower = 1 ' Turn ON Led
pause 200 ' Debounce
Ledpower = 0 ' Turn it back OFF
endif
Goto mainloop
end
'---[INT - interrupt handler]---------------------------------------------------
ExternalInterrupt0:
if wiperb = 1 then
if leds.7 = 0 then
LEDS = LEDs << 1 ' Leds blink counter-clockwise
endif
else
if leds.0 = 0 then
leds = leds >> 1 ' Leds blink clockwise
endif
endif
PortA = leds
pause 100
@ INT_RETURN
I used both 0.01uF and 0.1uF caps to improve debounce and wired the C pin straight to Vss (only check wiper A and B). This is the recommended circuit by the manufacturer:
Attachment 6657
Robert