Hello boys,
I'm new on the forum and beginner in programming. I try to create a simple digital readout for X-axis on to my small lathe.
For simplicity I want to use rotary encoder and rack and pinion drive to measure distance.
I read and try all suitable codes I have found on the forum but a little success. I try combine this pieces of codes, but no success.
Please can someone to help me how to implement this code to functional end. MCU is 16F628A thank You for help.
This is my code:
Code:
INCLUDE "DT_INTS-14.bas" ; Base Interrupt System
INCLUDE "ReEnterPBP.bas" ; Include if using PBP interrupts
' PIC 16F628A
' PicBasic program to demonstrate operation of an LCD in 4-bit mode
' and reading an optical encoder in quadrature
'
' LCD should be connected as follows:
' LCD PIC
' DB4 PortA.0
' DB5 PortA.1
' DB6 PortA.2
' DB7 PortA.3
' RS PortA.4 (add 4.7K pullup resistor to 5 volts)
' E PortB.0
' RW Ground
' Vdd 5 volts
' Vss Ground
' Vo 20K potentiometer (or ground)
' DB0-3 No connect
; encoder ch A PortB.6
; encoder ch B PortB.7
#config
__config _HS_OSC & _WDT_ON & _PWRTE_ON & _MCLRE_OFF & _LVP_OFF & _CPD_OFF
#endconfig
DEFINE OSC 20
TRISA = %00000000 ' Make all PortA pins output
TRISB = %11100000
Define LCD_DREG PORTA
Define LCD_DBIT 0
Define LCD_RSREG PORTA
define LCD_RSBIT 4
define LCD_EREG PORTB
define LCD_EBIT 0
define LCD_BITS 4
define LCD_LINES 2
define LCD_COMMANDUS 2000
define LCD_DATAUS 50
Flag var bit
wsave VAR BYTE $70 SYSTEM ; alternate save location for W
enc_new VAR BYTE
enc_old VAR BYTE
enc_counter VAR WORD
; Set variable value @ startup
Flag = 0
enc_new = 0
enc_old= 0
enc_counter = 0
Lcdout $fe, 1 ' Clear LCD screen
Lcdout "Encoder test" ' Display message
Pause 500
@ INT_ENABLE RBC_INT ; enable external (INT) interrupts
goto main_loop
asm
INT_LIST macro ; IntSource, Label, Type, Resetflag?
INT_Handler RBC_INT, _enc, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
;================================================
endasm
enc:
asm
;Read latest input from PORTB & put the value in _enc_new.
movf PORTB,W
movwf _enc_new
;Strip off all but the 2 MSBs in _enc_new.
movlw B'11000000' ;Create bit mask (bits 7 & 6).
andwf _enc_new,F ;Zero bits 5 thru 0.
;Determine the direction of the Rotary encoder.
rlf _enc_old,F ;left shift it into _enc_old to align bit 6 of
;_enc_old with bit 7 of _enc_new.
movf _enc_new,W ;Move the contents of _enc_new to W in order to XOR.
xorwf _enc_old,F ;XOR previous inputs (in _enc_old) with latest
;inputs (in W) to determine CW or CCW.
btfsc _enc_old,7 ;Test bit 7 of result (in _enc_old). Skip next line
;if it is 0 (direction is CCW).
goto Up ;Bit is 1 (direction is CW). Go around Down
;and increment counter.
Down
;Decrements _enc_counter because the rotary encoder moved CCW.
;Decrements _enc_counter (16 bit value), sets Z on exit.
decf _enc_counter,F ; Decrement low byte
incfsz _enc_counter,W ; Check for underflow
incf _enc_counter+1,F ; Update
decf _enc_counter+1,F ; Fixup
movf _enc_counter,W
iorwf _enc_counter+1,W ; Set Z bit
;Add here code for the CCW LED if needed.
goto Continue ;Branch around UP.
Up
;Increments _enc_counter because the rotary encoder moved CW.
;Increments _enc_counter (16 bit value), sets Z on exit.
incfsz _enc_counter,W ; Add one to low byte
decf _enc_counter+1,F ; No carry (negates next step)
incf _enc_counter+1,F ; Add one to high byte
movwf _enc_counter ; Store updated low byte back.
iorwf _enc_counter+1,W ; Set Z flag
;Add here code for the CW LED if needed.
Continue
;Assign the latest encoder inputs (in _enc_new) to _enc_old.
movf _enc_new,W
movwf _enc_old
;============ END OF THE ROTARY ENCODER CODE =====
endasm
@ INT_RETURN
Main_Loop:
if Flag = 1 then
Lcdout $fe, 1
Lcdout Dec enc_counter ; display counter value on LCD
Flag = 0
endif
goto Main_Loop
end
Bookmarks