Instant Int and encoder (Elect. Gearing)
Hi all,
I have been working on this for too long and I'm starting to chase my tail.
I'm to the point that I can remember the post numbers, but I'm still overlooking something.
The purpose is this:
1) Read Encoder #1 to measure direction and distance of a linear movement.
2) If travel is +, do nothing
3) if travel is -, feed pulses to a servo driver to move a motor (feed material at same rate as linear retract).
4) there a couple of lines I left in for adding manual over-ride.
5) testing on a 877 with a X-1 board but the target can be anything.
Thanks for taking a look.
Bo
' 1)Quadrature encoder reading direction and speed of mechanical slide.
' 2) Motor (servo) driven in ONE direction of slide movement,
' not driven for other direction. Pulse & Direction drive.
' 3) Overide switches to drive servo either direction manually.
'
A_INPUT VAR PORTB.4 'encoder A input
B_INPUT VAR PORTB.5 'encoder B input
F_Sw var PORTB.6 'Foward switch input
R_sw var PORTB.7 'Reverse Sw input
P_out var PORTA.0 'Pulse out to motor
D_out var PORTA.1 'level out for direction
'only for manual Sw
' drive. Implement Ltr.
LED1 var PORTA.5 'heartbeat for INT
RdEnc1 VAR BIT
RdEnc2 VAR BIT
COUNTER VAR WORD
TRISA = %00000000
TRISB = %11111111
TRISD = %00000000
OPTION_REG.7 = 0 'enable POTRB pull-ups
INCLUDE "DT_INTS-14.bas" 'Base Inturrupt program
include "ReEnterPBP.pbp" 'allow PBP int
ASM
INT_LIST macro ;IntSource, Label, Type, ResetFlag?
INT_Handler RBC_INT, _MotorDrive, PBP, yes
INT_Handler INT_INT, _ToggleLED1, PBP, yes
endm
INT_ENABLE RBC_INT ;enable RB change int
INT_ENABLE INT_INT ; enable external (INT) interrupts
ENDASM
Start
RdEnc2 = A_INPUT & ~ RdEnc1 'EVERY POSITIVE GOWING EDGE OF A_INPUT
RdEnc1 = A_INPUT 'GIVES A PULSE OF ONE PROGRAM CYCLE
IF RdEnc2 = 1 AND B_INPUT = 1 Then 'Encoder TURNS CW: UP
COUNTER = 1
EndIF
IF RdEnc2 = 1 AND B_INPUT = 0 Then 'Encoder TURNS CCW: DN
COUNTER = 0
EndIF
counter = portb & %00000011 'for troubleshooting: strip i/p.
PORTD = counter 'for troubleshooting: to see i/p.
goto start
'+++++++++++++++++
'Motor Drive Pulse Out inturrupt handler
'++++++++++++++++++
MotorDrive:
if counter = 1 then
pulsout P_out,100
endif
@ INT_RETURN
'---[INT - interrupt handler]---------------------------------------------------
ToggleLED1:
TOGGLE LED1
@ INT_RETURN
end
Progress, but not right yet...
Hi All,
Been banging my head for a while now and I am getting closer. Thank you for the time you have taken to add life to this forum.
The Travel encoder section works pretty well, but the Manual encoder is erratic and sometimes take over the travel section and not let it work. A bump on Manual, and the Travel works again.
As a reminder. The Travel generates Pulse and Direction in one direction only. The Manual is for bi-directional fine adjustment after the Travel section's movement is complete (automatic). Target: 12F675 @ 4mHz INT_OSC
Anybody see what I'm missing?
Thanks
Bo
Code:
A_trav VAR GPIO.0 'Travel encoder A input
B_trav VAR GPIO.1 'Travel encoder B input
A_man var GPIO.2 'Manual Encoder A input
B_man var GPIO.3 'Manual Encoder B input
P_out var GPIO.4 'Pulse output to motor
D_out var GPIO.5 'level output for direction
Dir VAR bit 'Direction
Scratch var byte 'dummy byte
Old_Bits VAR BYTE
New_Bits VAR BYTE
TravEncOld var byte 'TRAVel Measurement ENCoder
TravEncNew Var byte '
ManEncOld var byte 'MANual input ENCoder
ManEncNew var byte '
P_out = 1 'servo I/P = LO pulse, start HI
INTCON = %10001000 'GLOBAL ON, GPIO Int ON
CMCON = 7 'Comparator off, Digital I/O
OPTION_REG = %00000000 'GPIO Pull-up Enabled
TRISIO = %001111
WPU = %000111 'pull-ups 0-2 (3 added on board)
IOC = %001111 'Int On Change GPIO 1-3
ANSEL = 0
INCLUDE "DT_INTS-14-0.bas" '..-14-0 = ALL Banks REM'd
ASM
INT_LIST macro ; IntSource, label, Type, ResetFlag?
INT_Handler RBC_INT, _EncChg, ASM, yes
endm
INT_CREATE ; Creates the interrupt processor
INT_ENABLE RBC_INT ;RB Port Change Interrupt
ENDASM
Old_Bits = GPIO & (%001111) 'Get initial inputs
Main:
GOTO Main
'---[RBC - interrupt handler]---------------------------------------------------
EncChg:
New_Bits = GPIO & (%001111) 'Get inputs
TravEncNew = New_Bits & (%000011) 'strip New Travel encoder
TravEncOld = Old_Bits & (%000011) 'Strip Old Travel Encoder
if TravEncNew = TravEncOld then ManEnc ' If no chg -> Manual Encoder
Dir = TravEncNew.1 ^ TravEncOld.0 'Check direction
D_out = Dir 'Direction LEVEL out
if Dir = 1 then 'Only travel 1 direction
pulsout P_out,20 'drive servo controller
Endif 'Controller is STEP/DIRECTION I/P
goto DoneRotEnc 'skip Manual Encoder
ManEnc:
ManEncNew = New_Bits & (%001100) 'strip Manual Encoder
ManEncOld = Old_Bits & (%001100)
Dir = ManEncNew.3 ^ ManEncOld.2 'Direction of Manual input
D_out = Dir
pulsout P_out,20 'Pulse for either direction
DoneRotEnc:
Old_Bits = New_Bits 'reset reference
Scratch = GPIO 'read GPIO to clear mis-match
@ INT_RETURN
Gotta learn the hard way....
Well, this one has been quite a ride.... I've spent weeks trying to figure this out. I was in the middle of trying to craft a more detailed question that might generate some interest. One encoder was working wonderfully the way I expected, and the other, with almost the exact same code was causing all kinds of problems. I was in the process of using my Logic pod (which I love BTW: www.Saleae.com) to see if I could describe the problem better. I had a heartbeat pulse in the main and noticed that it would cut out for almost 3 mS when RB.4 changed. After looking at the datasheet for the ump-teenth time, I realized that I hadn't disabled the Low Voltage Programming option. That was it. Bet I won't take this long to look at that again!
Thanks for all of you who looked at it, and especially those that took the time to give some feedback.
Bo