![]() | ![]() | ![]() |
| |||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
![]() |
| | Tools |
| | #1 |
|
Hi guys, I've decided to use a quadrature rotary encoder for my next project and the encoder itself will be used to control some settings via a 20x4 LCD. The idea is to have the knob 'scroll' through the available settings (3 for now) and the button to select the setting you want. After pressing the button you access the setting and further knob turns will scroll through the available options for that setting (usually ON or OFF). So it's like a two level menu accessible via encoder. To handle the encoder I've written a short function which uses a primitive delay method to debounce the contacts: Code: ; ######################### CHECK ENCODER ########################## Rot_Enc movf PORTC, W ;copy PORTC to W andwf b'00000111',W ;mask bits3-7 so only 0,1,2 are saved (the rotary enc inputs) movwf PORTC_new ;copy to variable subwf PORTC_last, W ;do (PORTC_last - PORTC_new) => W btfsc STATUS, Z ;check zero bit goto Rot_Enc_end ;values the same because result = 0 btfsc deb_flag ;test debounce flag to see if this is first change detected goto Rot_Enc_change ;if PORTC is different than last value and again different after 50ms call Delay50 ;primitive debounce by waiting 50ms bsf deb_flag, 0 ;set debounce flag goto Rot_Enc ;after debouncing check port again Rot_Enc_change ; check if turned right movlw HIGH turn_right ;preload PCLATH with movwf PCLATH ;high byte of turn_right table movf PORTC_last, W ;move PORTC_last to W call turn_right ;get the next correct value from the table subwf PORTC_new, W ;do (PORTC_new - next correct value) => W btfsc STATUS, Z ;check zero bit goto Rot_Enc_right ;values the same because result = 0 ; check if turned left movlw HIGH turn_left ;preload PCLATH with movwf PCLATH ;high byte of turn_left table movf PORTC_last, W ;move PORTC_last to W call turn_left ;get the next correct value from the table subwf PORTC_new, W ;do (PORTC_new - next correct value) => W btfsc STATUS, Z ;check zero bit goto Rot_Enc_left ;values the same because result = 0 ; check if pressed btfss PORTC_new, 2 ;check bit 2 = knob press goto Rot_Enc_press ;values the same because result = 0 goto Rot_Enc_update ;if not it means that there was a skip in steps so just update the value Rot_Enc_right ; knob turned right goto Rot_Enc_update Rot_Enc_left ; knob turned left goto Rot_Enc_update Rot_Enc_press ; knob pressed Rot_Enc_update ; update the last scan value movf PORTC_new, W ;move new value to W movwf PORTC_last ;update last scan value Rot_Enc_end retlw 0x00 Now the encoder will be turned by hand and obviously if you turn it too fast it will skip a step and not do anything. I'm curious if the 50ms delay for debounce is not going to force very slow turns in order to change the settings. Perhaps someone here tried something similar? Regards, dsc. | |
| |
| | #2 |
|
I've used a rotary encoder for the input portion of an LCD menu system before and it worked quite well. The encoder I used had 16 detent positions with all four quadrature states between the detents so I simply detected all of the "change" states but ignored all but the change into the detent state. I used something like 2-msecs between samples... Regards, Mike <added> You can determine "direction" of a quadrature A-B signal state change by exclusive-or'ing the A or B bit from the new sample with the opposite bit from the previous sample. Here's a quick example that uses a single variable (though you would still need to add your "inc" and "dec" code). Code: ;
; sample rotary encoder at 2-msec intervals
;
movf PORTC,W ; sample encoder, W = '------BA'
andlw b'00000011' ; mask off unused bits
xorwf encold,W ; state change?
bz done ; no, branch, else
xorwf encold,W ; restore WREG
rrf encold,F ; shift B old '-------B'
xorwf encold,F ; bit 0 = direction (A new ^ B old)
rrf encold,F ; Carry = direction
movwf encold ; update 'encold' to current sample
;
; Carry = direction. Check for detent position.
;
xorlw b'00000011' ; detent (BA = 11)?
bz done ; no, branch, else
done
Last edited by Mike, K8LH; 2nd November 2009 at 02:55 PM. | |
| |
| | #3 |
|
Hi Mike, ah yes the famous XOR, much easier indeed, thanks for the tip. I've noticed you haven't bothered with debouncing, is that because the transitions are pretty much bounce-less? Regards, Tom EDIT: I've just checked and my rotary encoder goes through the entire A/B cycle per dent. This means the above code should work but it might lose a lot of steps (especially if I want to do time-based) debouncing. I might consider switching to 3 tactile switches instead. Last edited by dsc; 2nd November 2009 at 08:26 PM. | |
| |
| | #4 |
|
Hi Tom, The switches still bounce but the intermediate state changes between detents are ignored in my implementation so it doesn't matter if they're bouncing between left and right. The 2-msec sample interval I used seemed fast enough to keep me from missing a change and long enough to debounce the switches. Regards, Mike | |
| |
| | #5 |
|
Hi Mike, ah yes true you only act on a dent (11 state) and not in between states. Might give this a try, although the encoder I've got has 32 positions instead of 16, so it's actually quite hard to make small changes manually and it might be quite hard to operate. Regards, Tom | |
| |
| | #6 |
|
Tom, Could you pass along distributor and part number for that encoder, please? Mike | |
| |
| | #7 |
|
Hi Mike, unfortunately I don't know the model number (nothing on the case), don't know the manufacturer and don't have a datasheet. It's a big unknown to be honest. Regards, Tom | |
| |
|
| Tags |
| check, encoder, lcd, pic, rotary, sanity |
| Thread Tools | |
| Display Modes | |
| |
Similar | ||||
| Title | Starter | Forum | Replies | Latest |
| Identifying and using a rotary encoder, help! | dec_lan | General Electronics Chat | 3 | 11th August 2009 04:55 AM |
| Rotary Encoder | vk6kci | Electronic Projects Design/Ideas/Reviews | 6 | 21st May 2009 12:57 AM |
| wind speed meter with direction using PIC16f877A, rotary encoder and LCD 16x2 | mokh | Electronic Projects Design/Ideas/Reviews | 14 | 29th October 2008 08:00 AM |
| Sanity check on relay ratings | Torben | General Electronics Chat | 13 | 12th August 2008 07:30 AM |
| Rotary Encoder with Switch | Mike, K8LH | Datasheet/Parts Requests | 3 | 24th March 2005 03:28 PM |