Shop OBEX P1 Docs P2 Docs Learn Events
encoder reading problem — Parallax Forums

encoder reading problem

robotnerd007robotnerd007 Posts: 4
edited 2008-04-11 10:00 in General Discussion
I am working on a project that uses a US digital 400ppr to measure distance and then at two preset values it puts a pin to high in order signaling a basic stamp which takes care of everything else. I am not very experienced programming at all but feel comfortable enough with the basic stamp and have the code i need for that is working. However my code for counting the encoder pulses and signaling the basic stamp does not work. For counting encoder pulses i took the code from an encoder thread listed under "the best SX threads" I kind of understand how it works but could not write it myself. I have channel A of the encoder connected to RA0 and channel B is connected to RA1. I was wondering if someone could take a quick look at this and point out my stupid mistake. A big thank you to anyone who takes the time to help a beginner.
P.S. Is there any reason not to run the sx at 50mhz? Would i have to change anything except the initializing code at the beginning? (i do know how to do that)


' BLINK1.SXB
DEVICE SX28, OSC4MHZ, TURBO, STACKX, OPTIONX
FREQ 4_000_000


EncPort VAR RA ' encoder port
TRIS_Enc VAR TRIS_A
MaxVal CON 255
EndVal Con 400
SlowVal Con 300
'encCheck VAR Byte
EncodersOld VAR byte
EncodersNew VAR byte
Encoder_A_Count VAR word
tmpB1 VAR byte
tmpB2 VAR Byte
tmpB3 VAR Byte

' =========================================================================
INTERRUPT
' =========================================================================
' Runs every 64 uS @ 4 MHz (no prescaler)
ISR_Start:
EncodersNew = EncPort
TmpB1 = EncodersOld XOR EncodersNew ' compare old with new
' to work out which channels have changed
TmpB2 = TmpB1 << 1 ' make single bit that shows change on A or B phase
TmpB1 = TmpB1 OR TmpB2
EncodersOld = EncodersOld << 1 ' make direction bits by comparing old A with new B
EncodersOld = EncodersOld XOR EncodersNew ' xor old A with new B
IF TmpB1.3 = 1 THEN
IF EncodersOld.3 = 1 THEN
INC Encoder_A_Count
ELSE
DEC Encoder_A_Count
ENDIF
ENDIF
EncodersOld=EncodersNew
'ISR_Exit:
RETURNINT
' =========================================================================
PROGRAM Start
' =========================================================================

Start:


EncodersNew = EncPort
EncodersOld = EncodersNew
Encoder_A_Count = 0

OPTION = $88 ' interrupt, no prescaler
bgn:
Do
If Encoder_A_Count >= EndVal then goto stop 'tells BS2 when to slow down and when to stop a robot
IF Encoder_A_Count >= SlowVal then goto slowdown
loop

stop:
high RC.7

slowdown:
high RC.6
goto bgn

Comments

  • BeanBean Posts: 8,129
    edited 2008-03-24 13:15
    "Not working" doesn't really tell us anything.
    What exactly does it do ?
    What model of encoder are you using ?
    Do you have any required pull-up resistors ?
    How exactly do you have things connected ?
    Does it act differently if you move the encoder slowly ?

    You need to help us help you.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    www.iElectronicDesigns.com

    ·
  • robotnerd007robotnerd007 Posts: 4
    edited 2008-03-24 14:49
    Sorry for not being more specific. I do not have any pull up resistors connected to the encoder outputs. As I understand it the encoder operates TTl level so its high is 5v and that should trigger the SX (i dont have any resistors connected should i to protect the sx?). I am using the 400pulses per revolution http://www.usdigital.com/products/s5/ The current draw is pretty low so i connected ground on the encoder to ground and 5v on the board. have channel A of the encoder connected to RA0 and channel B is connected to RA1 on the breadboard on the SX tech board. The code does not work no matter what speed i move the encoder. I am borrowing a dual trace oscilloscope latter this week to check and make sure the encoder is functioning properly (it should though its brand new). I was there was an obvious error in the code that could be easily corrected but i guess not. Like i said before the only thing i need the SX for is counting encoder pulses for a basic stamp which takes care of everything else. If there is anything else you need to know about my setup let me know.
  • BeanBean Posts: 8,129
    edited 2008-03-24 16:29
    Running the code through the SX-Sim simulator it appears the code is meant for the encoder to be connected to RA.2 an RA.3.
    Also note that you will get 4 counts per cycle. So you will get 1600 counts per revolution.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    www.iElectronicDesigns.com

    ·
  • RobotWorkshopRobotWorkshop Posts: 2,307
    edited 2008-03-24 17:14
    Are you sure about the inputs? The code looks a lot like the example in the SX/B help file which would have the encoder connected to RA.0 and RA.1

    It appears to missing a few things however. It should have:

    EncodersNew = EncPort & %00000011 ' Mask off extra bits

    And the calculations look a bit off.

    To me it appears that your code is kind of mixed in that it expects some of th bits to be on 0 and 1 while others as bits 2 and 3.

    If you are connecting the encoders to ports RA.2 and RA.3 I would used the code in the example program but start out with something like:

    EncodersNew = EncPort & &00001100 ' Mask off extra bits
    EncodersNew = EncodersNew >> 2 ' Shift over to perform all calculations

    Hope this helps,

    Robert
  • BeanBean Posts: 8,129
    edited 2008-03-24 18:42
    All I can say is that when I run the posted code in the SX-Sim the variable changes only when I toggle RA.3 and RA.2 pin.

    Bean.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    www.iElectronicDesigns.com

    ·
  • RobotWorkshopRobotWorkshop Posts: 2,307
    edited 2008-03-24 19:01
    Your right about the since it is checking bit 3 for a change. It shouldn't be checking that bit. It should be checking 1 as in the example encoder application. The problem is that the program as written isn't consistent about bit locations. I guess another way to to it (if the encoders are wired to RA.0 and RA.1 would be to do something like this at the beginning:

    EncodersNew = EncodersNew << 2 ' Shift over to perform all calculations
    EncodersNew = EncPort & &00001100 ' Mask off extra bits

    There are a lot of ways to do it but it just needs to be consistent throughout the code.
  • robotnerd007robotnerd007 Posts: 4
    edited 2008-04-02 05:53
    Thank you all for all the help. After correcting the code so it read bits that the encoder was actually connected to things still did not work for me. I finally thought to try a different sx and my problems went away. Sometimes its the simple problems that i have the most trouble finding.
  • robotnerd007robotnerd007 Posts: 4
    edited 2008-04-11 10:00
    I am storing the encoder value in a word variable; however, i need more space than a word variable can provide. I really need to count up to around 90,000 pulses. I was wondering how to do this is. I would not mind sacrificing some resolution to get a greater range of distance that i could count. I dont really know how to modify the code i have to only detect 2 of the edge changes instead of the 4 that it does now. Is there another easier way to do this that i dont know about or am overlooking? Here is a copy of the code that i am using now.

    DEVICE SX28, OSCHS3, TURBO, STACKX, OPTIONX
    FREQ 50_000_000
    ID "ENCODER"
    '
    ' IO Pins
    '
    EncPort VAR RA ' encoder port
    TRIS_Enc VAR TRIS_A
    '
    ' Constants
    '
    MaxVal CON 100
    EndVal con 17000
    SlowVal con EndVal-2000

    '
    ' Variables
    '
    encCheck VAR byte
    encOld VAR byte ' previous encoder bits
    encNew VAR byte ' new encoder bits
    encValue VAR word ' encoder value
    tmpB3 VAR Byte
    '
    INTERRUPT
    '
    ' Runs every 64 uS @ 4 MHz (no prescaler)
    ISR_Start:
    encNew = EncPort & %00000011 ' get econder bits
    tmpB3 = encOld XOR encNew ' test for change
    IF tmpB3 > 0 THEN ' change?
    encOld = encOld << 1 ' adjust old bits
    encOld = encOld XOR encNew ' test direction
    IF encOld.1 = 1 THEN
    IF encValue < EndVal THEN ' if max, no change
    INC encValue ' increase value
    ENDIF
    ELSE
    IF encValue > 0 THEN ' if 0, no change
    DEC encValue ' decrease value
    ENDIF
    ENDIF
    encOld = encNew ' save last input
    ENDIF
    ISR_Exit:
    RETURNINT
    ' =========================================================================
    PROGRAM Start
    ' =========================================================================
    '
    ' Subroutine Declarations
    '

    '
    ' Program Code
    '
    Start:
    encNew = EncPort & %00000011 ' read encoder pos
    encOld = encNew ' copy
    encValue = 0 ' clear value
    OPTION = $88 ' interrupt, no prescaler
    ' =========================================================================

    low rc.7

    main: ' clear value
    Do
    If encValue = EndVal then goto stop 'tells BS2 when to slow down and when to stop a robot
    IF encValue = SlowVal then goto slowdown
    loop


    slowdown:
    high RC.7
    goto main

    stop:
    low RC.7
    end
Sign In or Register to comment.