Can PBP read optical encoder damn fast? :)


Closed Thread
Page 1 of 2 12 LastLast
Results 1 to 40 of 47
  1. #1
    Join Date
    Feb 2013
    Posts
    1,104

    Default Can PBP read optical encoder damn fast? :)

    Hello.

    Say we have optical encoder from inkjet printer. It has 60 pulses per 1cm of movement. So say it is moving with 20cm per second speed, this is 60x20=1200 readings per second. So can be software written in PBP, which will reliably count number of pulses and direction too? Output will be fed into AD9833, chip won't be doing anything else in realtime. So is this task doable with PBP, and which MCU I should consider?

  2. #2
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,980


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Well a very fast chip at 64MHz may help.

    But using another approach I guess it is possible with slower PIC also. You may use the CCP module to capture the rising and falling edge of the pulses in regard with the Timer so the PIC will capture the timer readings. Either just waiting or doing other stuff while the ISR will just transfer the timer value to your variable.

    With 1200 readings you will have to count double that. Rising and falling edge so is 2400 reading and I guess double that also, for the quadrature readings. Finally your pulse to pulse time may be about 200usec. Not too demanding but fast.

    Ioannis

  3. #3
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,569


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Yeah, 1200 counts per second really isn't THAT much. How to go about it depends - as always - on what else the PIC is supposed to do while keeping count (ie should it output to the AD9833 and if so, how, while counting pulses or how it's supposed to work) and on what peripherals and interrups sources are available.

    If counting is one state and outputting is another then a tight loop polling the inputs will most likely do just fine for 1200 transistions per second.

    It's important to determine if the 60 counts are with 4x decoding or not and if that is needed or not. Not doing 4x decoding is a lot easier than doing it.

    The 18F2431 family contains a QEI module that will happily keep track of an encoder producing counts up in the MHz

  4. #4
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Well the task is as follows. On power up, ribbon is stopped, AD9833 is set to output certain frequency. Depending on ribbon movement direction afterwards, frequency is increased or decreased. Movement can be fast or slow or even non-linear speed.

  5. #5
    Join Date
    Jan 2006
    Location
    Istanbul
    Posts
    1,185


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    You may have a timer in counter mode in background; so you can do things in foreground while it counts in background.
    "If the Earth were a single state, Istanbul would be its capital." Napoleon Bonaparte

  6. #6
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    I tried to start it at all, even at slow speeds, and looked forum for rotary encoder debug code. Most examples have things like this in it:
    OLDR = PORTB & $30 and similar, current hardware config limiting code.
    Is there a way to have "universal" rotary encoder code, which will work, if say one pin is going to PORTD.4 and another to PORTA.2 ? I'm not sure how all this XORing and ANDs can be performed across the various ports.

  7. #7
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,569


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Do you have hardware already on which this has to run? If that's the case then please tell us what that is which PIC and which pins are available.

    Having the encoder pins spread across two different port register will slow it down and is not ideal, two adjacent pins on the same port is prefferable. If those pins have IOC capabilities that's one way to skin it.

    You say the encoder have 60 pulses, is that 60 pulses per channel (240 edges per cm) or 15 pulses per channel (60 edges)? If it's the former and you're fine with 60 Counts per cm that makes it easier since it's just a mater of sampling channel B on the Rising edge of channel A. No qudrature decoding needed.

    I take it you've already figured out how to talk to the AD9833 or is that going to be the follow up question?

  8. #8
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    I have not went with AD9833 yet, because if I can't run encoder, then there is no need for DDS. And by the way, some DDS code I see around the forum, so I think I can re-use it. For the encoder, this is simple encoder from inkjet printer, HEDS-9730. The ribbon has plain strips, 60 per centimeter (I've counted it under microscope). Before going with this encoder, I want to have some code running with simple, rotary, 3 pin, incremental encoder. My prototyping system has PIC16F886 on it now, and while now I can connect both pins to same port - say PORTA.1 and PORTA.2, if doing own code, I'd like to have a code, which will not be limited by same port.

  9. #9
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,980


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    If on different port, then you will spend time on transferring the data to a temp variable and do the XOR/AND on that temp byte.

    Ioannis

  10. #10
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    While I know how XOR AND and other logical operations work, I can't get idea, how they are used over time based domain, as in case of encoder. I mean, where is that component, which defines the frequency of readout and pulse width and so on.

  11. #11
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    I came up with this code idea (have not tested it yet)

    Code:
    STATE: 'WAIT FOR ENCODER TO BE MOVED (STATE CHANGE)
    X=PORTB.1
    Y=PORTB.2
    PAUSE 10
    X1=PORTB.1
    Y1=PORTB.2
    IF X<>X1 OR Y<>Y1 THEN GOTO NEXTSTEP 
    GOTO STATE
    
    NEXTSTEP:
    
    SOMELOOP: 'COUNTER LOOP FOR PULSE LENGTH COUNTING
    IF PORTB.1=1 THEN XIN=XIN+1 'X INCREMENT
    IF PORTB.2=1 THEN YIN=YIN+1 'Y INCREMENT
    IF PORTB.1=0 OR PORTB.2=0 THEN GOTO ANALYZE 'EXIT AND COMPARE LENGTHS
    GOTO SOMELOOP
    
    ANALYZE: 'DETERMINE DIRECTION AND INCREMENT CORRESPONDING VARIABLE
    IF XIN>YIN THEN 
    CCW=CCW+1
    ELSE
    CW=CW+1
    ENDIF
    XIN=0 'RESET VARIABLES
    YIN=0 
    GOTO STATE

  12. #12
    Join Date
    Jan 2010
    Posts
    20


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Check out https://www.microchip.com/wwwproducts/en/PIC18F4431 this series has a hardware quadrature encoder feedback module that runs on it's own in the back ground.

  13. #13


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    For optical encoder I use this:
    Code:
    ; PIC18F4520 
    
    DEFINE OSC 4
    
    INCLUDE "DT_INTS-14.bas"        ; Base Interrupt System
    INCLUDE "ReEnterPBP.bas"        ; Include if using PBP interrupts
    
    TRISA    = %00000000 ' Make all PortA pins output
    TRISB    = %11001000
    
    Define LCD_DREG PORTA
    Define LCD_DBIT 0
    Define LCD_RSREG PORTA
    define LCD_RSBIT 4
    define LCD_EREG PORTA 
    define LCD_EBIT 6
    define LCD_BITS 4
    define LCD_LINES 2
    define LCD_COMMANDUS 2000
    define LCD_DATAUS 50
    
    ; encoder ch A PortB.6
    ; encoder ch B PortB.7
    
    wsave       VAR BYTE $70     SYSTEM  ; alternate save location for W 
    enc_new     VAR BYTE bank0
    enc_old     VAR BYTE bank0
    enc_counter VAR word bank0
    Flag        var BYTE bank0
    
    asm
    INT_LIST  macro    ; IntSource,        Label,  Type, Resetflag?
            INT_Handler    RBC_INT, _enc,  ASM,  yes
        endm
        INT_CREATE     ; Creates the interrupt processor
    endasm
    
    ; Set variable value @ startup       
    enc_new = 0
    enc_old= 0
    enc_counter = 0
    Flag = 0
    @ INT_ENABLE RBC_INT  ; enable external (INT) interrupts 
    
    Main_Loop:                                         
    Lcdout $fe, 1
    lcdout  Dec enc_counter  
    goto Main_Loop
    
    enc:
    asm    
        ;Read latest input from PORTB & put the value in _enc_new.
             MOVE?CB 1,_Flag
             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.  
             rlcf     _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
             INT_RETURN
        ;============ END OF THE ROTARY ENCODER CODE =====
        endasm

  14. #14
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Yes I checked that PIC datasheet already, but I don't see any ways to implement it in PBP, we don't have statement for encoder reading, like we have for LCDOUT or OWIN.

  15. #15
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    I've modified my code and it works ok, but sometimes I get false readings too - say for 20 pulses of CW, I will have 2-3 pulses of CCW and vise versa

    Code:
    STATE: 'WAIT FOR ENCODER TO BE MOVED (STATE CHANGE)
    'Lcdout $Fe, $1, "WAIT..." , DEC ENX, " ", DEC ENY
    X=ENX
    Y=ENY
    PAUSE 1
    X1=ENX
    Y1=ENY
    IF X<>X1 OR Y<>Y1 THEN GOTO SOMELOOP
    GOTO STATE
    
    
    SOMELOOP: 'COUNTER LOOP FOR PULSE LENGTH COUNTING
    IF ENX=1 THEN X1IN=X1IN+1 'X INCREMENT
    IF ENY=1 THEN Y1IN=Y1IN+1 'Y INCREMENT
    IF ENX=0 and ENY=0 THEN GOTO ANALYZE 'EXIT AND COMPARE LENGTHS
    PAUSE 1
    GOTO SOMELOOP
    
    
    ANALYZE: 'DETERMINE DIRECTION AND INCREMENT CORRESPONDING VARIABLE
    IF X1IN>Y1IN THEN 
    CCW=CCW+1
    ELSE
    CW=CW+1
    ENDIF
    LCDOUT $FE, $1, "RAW", DEC Y1IN, "  ", DEC X1IN, "  "
    LCDOUT $FE, $C0, "VAL ", DEC CCW, "  ", DEC CW, "  "
    PAUSE 1
    X1IN=0 'RESET VARIABLES
    Y1IN=0 
    GOTO STATE

  16. #16
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    This is simple 3 pin incremental encoder, middle pin is tied to VCC, A and B are tied to PORTB.3 PORTB.4, which are also pull down with 10K resistors. If I rotate shaft slowly, then no false readings. What can be reason, some wiring issue or code inefficiency?

  17. #17
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,980


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Quote Originally Posted by CuriousOne View Post
    Yes I checked that PIC datasheet already, but I don't see any ways to implement it in PBP, we don't have statement for encoder reading, like we have for LCDOUT or OWIN.
    What stops you from writing directly to the registers?

    Ioannis

  18. #18
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,980


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Quote Originally Posted by CuriousOne View Post
    This is simple 3 pin incremental encoder, middle pin is tied to VCC, A and B are tied to PORTB.3 PORTB.4, which are also pull down with 10K resistors. If I rotate shaft slowly, then no false readings. What can be reason, some wiring issue or code inefficiency?
    Well, your LCD may be slowing down the response. And since you use PAUSE and LCDOUT it is expected that program is not the most efficient. The encoder is best done in ISR and even better using hardware module when available.

    Ioannis

  19. #19
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    I don't see how to avoid use of pause statement. We have time changing, things are happening within time, so how not to consider time? In final device, there will be no LCDOUT, if that is the problem.

  20. #20
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,980


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    ISR then.

    Ioannis

  21. #21
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,569


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    If the encoder strip has 60 lines per cm then you can get a resolution of 240 counts per cm by counting all four edges of the quadrature cycle.

    If you're OK with 60 it makes it a lot easier (compared to 4x decoding) since, again, all you need to do is poll channel B on the rising edge of channel A and you have your count direction. Using a coupe of external NAND gates (or perhaps the CLC module if your PIC has one) you can decode that into two discrete signals, up & down. Feed those into two counters on they'll count for you while you PAUSE.

    If counting with software, polling the inputs, then using PAUSE, LCDOUT or any other command that takes longer to execute than the shortest time between two pulses WILL ruin the day - in which case resorting to interrupts or hardware counter is the only way. This is why I asked if the the counting should go on WHILE outputting to the DDS.

    /Henrik.

  22. #22
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    As said above, there will be no LCDOUT or any other statements in the loop, except DDS updating. Regarding the precision, have not decided it yet, because have not build and have not heard maybe 10 readings per CM also will be ok....

  23. #23
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    I've found this: https://hackaday.io/project/122039-i2c-encoder-v2 - Ready firmware for the above mentioned PIC with I2C output. So what if I use this chip with that firmware to get data from encoder, and then use my PIC to send required data to DDS?

  24. #24
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,980


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    If I get it right, you will use a PIC to read a quadrature encoder, then communicate with I2C to another PIC and the second PIC will send the data to your DDS?

    Does this sound logical and efficient?

    You have a PIC then just do it! Use some lines in ISR and get the job done.

    After all, it is a good programming exercise! And the bonus is that you will be thrilled when finished! Don't be afraid of the ISR. A bit of work but you can do it!

    Ioannis

    P.S. what is your current PIC?
    Last edited by Ioannis; - 2nd June 2020 at 22:09.

  25. #25
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    I'm result-oriented person
    And knowing my programming skill, literally saying, I'd prefer to buy wheel, instead of inventing it
    I have many different PICs, but no software knowledge that deep to handle all this stuff

  26. #26
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,569


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Have you read the specs for that HackADay thing?
    •It's support the standard rotary encoder and the RGB encoder
    •It's possible to set all the 7bit of the I2C address trough a SMD jumper
    •Dimension of 25x25mm or 0.98x0.98in
    •With the castellated holes is possible to connected several boards on the 4 sides
    •Possibility to solder the pull-up resistor on the I2C bus
    •3 General Purpose pins. (GP pins)
    •256byte of internal EEPROM divided in the 2 bank of 128 byte
    •Advanced configuration respect the first version
    •The maximum frequency of the A/B signal is 150Hz.
    Anything that sticks out?

  27. #27
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,980


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    I am a terrible programmer but have done some ISR routines that also do things fast.

    If I can do it, everyone can do it! Try it and see how it goes. After all we are still here...

    I'd select a PIC of relatively recent 18F series so the famous DT INTS-18 will support it, follow the instructions for the DT INTS and do some test. See here: http://dt.picbasic.co.uk/INT16/DTINTS-18

    Nothing to be afraid of.

    Ioannis

  28. #28
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Yes I see 150Hz limitation. But as said above, I'd like to test idea first, if it is working at all.

  29. #29
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,569


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    I couldn't help myself, had to see what I could do with just some simple, basic (no pun intended) coding. No interrupts, no hardware assist, no inline assembly language, just 33 line loop of straight PBP.

    On an 18F4520 running at 20MHz it's seems solid as a rock at 20kHz. Above 20kHz it misses the odd count when subjected to long bursts. This is with a function generetor generating bursts of "perfect" signals with 50% dutycyle so in real life it might be a little less.
    Connecting an optical encoder works fine but a mechanical one does not due to contact bounce. Using a 16bit WORD for the position counter and simple 1x decoding, pissing away 3/4 of the resoultion but that was what was asked for.

    It bit-bangs SPI data to an AD9833 but there's no math to calculate actual frequency.

    The LCD code is there for my debug purposes but I left it there just in case.

    Code:
    DEFINE LOADER_USED 1
    DEFINE OSC 20
    
    DEFINE LCD_DREG PORTD       'LCD data port 
    DEFINE LCD_DBIT 0           'LCD data starting bit 0 or 4 
    DEFINE LCD_RSREG PORTA      'LCD register select port 
    DEFINE LCD_RSBIT 3          'LCD register select bit 
    DEFINE LCD_EREG PORTA       'LCD enable port 
    DEFINE LCD_EBIT 1           'LCD enable bit 
    DEFINE LCD_RWREG PORTA      'LCD read/write port 
    DEFINE LCD_RWBIT 2          'LCD read/write bit 
    DEFINE LCD_BITS 8           'LCD bus size 4 or 8 
    DEFINE LCD_LINES 2          'Number lines on LCD 
    DEFINE LCD_COMMANDUS 3000   'Command delay time in us 
    DEFINE LCD_DATAUS 40        'Data delay time in us
    
    
    FSYNC       VAR LATB.3
    SCLK        VAR LATB.4
    SDATA       VAR LATB.5
    Ch_A        VAR PortB.6
    Ch_B        VAR PortB.7
    
    Position    VAR WORD            ' Encoder position
    Frequency   VAR WORD            ' 
    AD9833      VAR WORD[5]         ' Array for data to be sent to the AD9833
    BitsToSend  VAR BYTE            ' Number of bits -1 to send to the AD9833 (max 127)
    Ch_A_Old    VAR BIT             ' Memory bit for edge-detection
    
    
    '-------------------------------------------------------------
    '------------------------- Init ------------------------------
    '-------------------------------------------------------------
    CMCON = 7
    ADCON1 = %00001111              ' No analog inputs.
    TRISB  = %11000001
    
    Frequency = 0
    Position = 0
    BitsToSend = 255
    
    
    PAUSE 1000
    LCDOUT $FE, 1, "AD9833..."
    
    
    ' Initialize the AD9833 as per example in AN-1070.
    ' Just to verify that we're good to go.
    ' This should make it output 400Hz with a 25MHz base clock
    AD9833[4] = $2100
    AD9833[3] = $50C7
    AD9833[2] = $4000
    AD9833[1] = $C000
    AD9833[0] = $2000
    
    FSYNC = 0
    
    For BitsToSend = 79 to 0 Step -1
        SDATA = AD9833.0[BitsToSend]
        SCLK = 0
        PAUSEUS 20
        SCLK = 1
        PAUSEUS 20
    NEXT
    
    FSYNC = 1
    
    
    Main:
    '-------------------------------------------------------------
    '--------------Poll encoder and keep count -------------------
    '-------------------------------------------------------------
        IF Ch_A = 1 THEN        
            IF Ch_A_Old = 0 THEN
                IF Ch_B = 1 THEN
                    Position = Position + 1
                ELSE
                    Position = Position - 1
                ENDIF
                Ch_A_Old = 1
            ENDIF
        ELSE
            Ch_A_Old = 0
        ENDIF
    '-------------------------------------------------------------
    
    
    '-------------------------------------------------------------
    '------------- If needed, prepare to update DDS --------------
    '-------------------------------------------------------------
        IF Position <> Frequency THEN           ' Has the count changed since last update of the DDS?
            IF BitsToSend.7 THEN                ' Are we free to update?
                Frequency = Position
                
                ' See datasheet for AD9833, this is just for basic testing.
                AD9833[2] = %0010000000000000
                AD9833[1] = %0100000000000111
                AD9833[0] = Frequency
                
                AD9833.0[15] = 0
                AD9833.0[14] = 1
           
                BitsToSend = 47                 ' 3*16 = 48 but we're using this variable to index the bits so minus 1
    
            ENDIF
        ENDIF
    '-------------------------------------------------------------    
    
    
    '-------------------------------------------------------------
    '---If DDS is to be updated, do it one bit per loop iteration----
    '-------------------------------------------------------------
        IF NOT BitsToSend.7 THEN              ' Still bits left to send ?
            FSYNC = 0                         ' Chip select
            SDATA = AD9833.0[BitsToSend]      ' Setup data
            SCLK = 0                          ' Clock low
            BitsToSend = BitsToSend - 1       ' Index next bit
            SCLK = 1                          ' Clock high
        ELSE
            SCLK = 1
            FSYNC = 1                          ' Chip select
        ENDIF
        
            
    ' This is for debugging purposes.
    ' If button is pressed and LCD updated while the encoder is moved
    ' counts will obviously be missed.            
    IF PortB.0 = 0 THEN
        LCDOUT $FE, 1, DEC Position, "  ", DEC Frequency, "   ", DEC BitsToSend
    ENDIF
    
    Goto Main

  30. #30
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,980


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Excellent job Henrik.

    At the expense of a little slower response, a couple of 100nF will help a lot debouncing mechanical encoders. I used that as I did not want to make a software debouncing at that time.

    Ioannis

  31. #31
    Join Date
    Feb 2013
    Posts
    1,104


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    IF A=1 or B=1 AND A<>B

    Is this proper replacement for XOR statement?

  32. #32
    Join Date
    May 2013
    Location
    australia
    Posts
    2,512


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    You could always write a little program to test your supposition and find out , you never know you may learn something


    Code:
    TOUCH                var byte
    A   VAR TOUCH.0
    B          VAR TOUCH.1
    RES        var byte    
        
        
    touch = 4
    Debug 9,"XOR TRUTH TABLE"
    Debug ,13 ,10,"A",9,"B",9,"A^B",9,"CUT",13 ,10
    while touch
        touch=touch-1 
        touch=~touch 
    ;CODE UNDER TEST
       IF A = 1 or  B = 1  AND A <> B THEN 
           RES=1
       ELSE
          RES=0
       ENDIF
       DEBUG #A,9,#B,9," ",#A^B ,9," ",#RES ,13 ,10
       touch=~touch     
    WEND
    Last edited by richard; - 6th June 2020 at 08:46. Reason: white space
    Warning I'm not a teacher

  33. #33
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,980


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    And although the little debug program of Richard's might not give you a clue, the keyword is "priority".

    Machines do not follow your thoughts. Need more detailed explanations, so parenthesis will help. See page 87 of the manual to understand why your expression is way out of what you intended to.

    Ioannis

  34. #34
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,569


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    If not pissing away 3/4 of the encoder resolution is something worth doing here's a replacement routine that does 4x decoding. It might not be the most optimized or elegant way but is works. Surprisingly (to me) it seems to work fine up to around 8kHz which means it does 32000 counts per second when being fed "perfect" quadrature signals my function gen.

    Code:
    ' Added variables:
    Encoder VAR BYTE
    Old_Enc VAR BYTE
    Test VAR BYTE
    Dir VAR WORD          ' Must be same size as Position variable
    
    
    '-------------------------------------------------------------
    '--------------Poll encoder and keep count -------------------
    '-------------Alternative routine with 4x decoding------------
    '-------------------------------------------------------------
    
        Encoder.0 = Ch_A
        Encoder.1 = Ch_B
    
        Test = Encoder ^ Old_Enc
    
        Dir = 0
    
        If Test = 1 THEN
            If Old_Enc = 0 THEN Dir = 1
            IF Old_Enc = 1 THEN DIR = -1
            IF Old_Enc = 2 THEN Dir = -1
            If Old_Enc = 3 Then Dir = 1
        ENDIF
    
        IF Test = 2 THEN
            IF Old_Enc = 0 THEN DIR = -1
            IF Old_Enc = 1 THEN Dir = 1
            IF Old_Enc = 2 THEN Dir = 1
            IF Old_Enc = 3 THEN Dir = -1
        ENDIF
    
        Position = Position + Dir
        
        Old_Enc = Encoder

  35. #35
    Join Date
    Nov 2003
    Location
    Greece
    Posts
    3,980


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    To me looks elegant enough! Wow, 32000 counts/s? I suppose on a fast 18F device, right?

    Ioannis

  36. #36
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,569


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Same setup as before, 18F4520 @20MHz so not really that fast.
    I don't know why it seems faster than the 1x version from earlier, perhaps I made a mistake when measuring either one of them.

  37. #37
    Join Date
    May 2013
    Location
    australia
    Posts
    2,512


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    Henrik assuming i have implemented your ideascorrectly it works not at all well for a ky040 re in real life, i get about 400 counts per indent and rarely does it get direction correct.
    my old code previously posted works near perfectly in the same rig either as isr or polled even a couple of .1uf across the pins does not help.


    Code:
    #CONFIG
                 __config        _CONFIG1,    _FOSC_INTOSC & _CP_OFF & _WDTE_ON  &  _PWRTE_ON  &  _MCLRE_ON  & _CLKOUTEN_OFF
                  __config      _CONFIG2, _PLLEN_ON & _LVP_OFF
    #ENDCONFIG
    
    
    DEFINE OSC 32
        OSCCON=$70
        ANSELA=0
        OPTION_REG.6=0
        ENCODER    VAR BYTE   ;THE STATE OF THE ENCODER
        DIR   VAR BYTE    ;POSN
        Old_Enc  VAR BYTE    ;LAST MOVE 
        TEST   VAR BYTE 
        Position   VAR WORD 
        TRISA = %11111110
        lata.0=1 ;DEBUG
        Ch_A    VAR PORTA.4
        Ch_B    VAR PORTA.5
        
        
        DEFINE DEBUG_REG PORTA
        DEFINE DEBUG_BIT 0        
        DEFINE DEBUG_BAUD 38400
        DEFINE DEBUG_MODE 0     
        pause 2000
        Debug "Start",13 ,10
        Position =0 
        Old_Enc=0
        
    mainloop:
    '     Encoder.0= Ch_A    ;WON'T WORK AT ALL MOST TIMES
    '     Encoder.1= Ch_B 
        Encoder = (PORTA&48)>>4
        Test = Encoder ^ Old_Enc
        Dir = 0
        If Test = 1 THEN
            If Old_Enc = 0 THEN Dir = 1
            IF Old_Enc = 1 THEN DIR = -1
            IF Old_Enc = 2 THEN Dir = -1
            If Old_Enc = 3 Then Dir = 1
        ENDIF
        IF Test = 2 THEN
            IF Old_Enc = 0 THEN DIR = -1
            IF Old_Enc = 1 THEN Dir = 1
            IF Old_Enc = 2 THEN Dir = 1
            IF Old_Enc = 3 THEN Dir = -1
        ENDIF
        Old_Enc = Encoder
        Position = Position + Dir
        IF DIR THEN 
            debug 13,10, "C",SDEC Position
        ENDIF
    goto mainloop


    my take [no pic18 worky or shitty old chips with no wreg access]

    Code:
    '****************************************************************'*  Name    : RE16.BAS                                          *
    '*  Author  : RICHARD                                           *
    '*  Notice  :                                                   *
    '*          : All Rights Reserved                               *
    '*  Date    : 5/06/2020                                         *
    '*  Version : 1.0                                               *
    '*  Notes   :    ONLY PIC16'S AND 12'S WITH WREG                *
    '*          :   IN THIS INCARNTATION NO SHITTY OLD CHIPS        *
    '****************************************************************
    
    
    #CONFIG
                 __config        _CONFIG1,    _FOSC_INTOSC & _CP_OFF & _WDTE_ON  &  _PWRTE_ON  &  _MCLRE_ON  & _CLKOUTEN_OFF
                  __config      _CONFIG2, _PLLEN_ON & _LVP_OFF
    #ENDCONFIG
    
    
    DEFINE OSC 32
        OSCCON=$70
        ANSELA=0
        OPTION_REG.6=0
        ev    VAR BYTE bank0   ;THE STATE OF THE ENCODER
        cnt   VAR WORD bank0   ;POSN
        TMP   VAR BYTE bank0   ;LAST MOVE IS 1, 0, -1
        TRISA = %11111110
        lata.0=1 ;DEBUG
        
        DEFINE DEBUG_REG PORTA
        DEFINE DEBUG_BIT 0        
        DEFINE DEBUG_BAUD 38400
        DEFINE DEBUG_MODE 0     
        pause 2000
        Debug "Start",13 ,10
        CNT=0 
    
    
    mainloop:
    ASM
        bcf STATUS,C      
        RLF _ev ,f        ;shift last reading into position
        bcf STATUS,C
        RLF _ev ,f
        MOVF PORTA,W     ;read enc pins 4,5
        ANDLW 48         ;mask off others
        SWAPF   WREG ,w  ;shift NEW reading into position
        IORWF _ev,F     ;combine this read with last read
        MOVF _ev,W     ;save ev
        ANDLW 15
        L?CALL enc_lut       ; decide to inc , dec or ignore 
        MOVWF _TMP         ;save decision
        BTFSC  _TMP,7
        GOTO myDEC16
        BTFSC  _TMP,0
        GOTO myINC16
    enc_exit                    ;  exit
        GOTO OUT
    myINC16
        INCF _cnt ,f
        BTFSC STATUS,Z
        INCF  _cnt +1 ,f 
        GOTO enc_exit
    myDEC16
        MOVF  _cnt ,w
        BTFSC STATUS,Z
        DECF   _cnt +1, f   
        DECF   _cnt , f       
        GOTO enc_exit
    OUT    
        ENDASM
        IF TMP THEN 
            debug 13,10,SDEC CNT
        ENDIF
    goto mainloop
    
    
    enc:
    ASM
    enc_lut                     ; the decision matrix
        addwf   PCL, F          
        retlw   0
        retlw   255
        retlw   1
        retlw   0
        retlw   1
        retlw   0
        retlw   0
        retlw   255
        retlw   255
        retlw   0
        retlw   0
        retlw   1
        retlw   0
        retlw   1
        retlw   255
        retlw   0  
    ENDASM
    Warning I'm not a teacher

  38. #38
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,569


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    I have it running on the bench, works perfectly fine with an optical encoder (Scancon 2RMHF-500, 500 lines / 2000 edges per rev) - IRL :-)
    Like I said previously I do not expect it to work reliably with a mechanical encoder unless it is properly debounced in hardware. Why your ASM version works with the same encoder I do not know :-(

    You have a DEBUG statement within the loop - that will obviously mess up the timing but I know you know that.

  39. #39
    Join Date
    May 2013
    Location
    australia
    Posts
    2,512


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    silly me i had the dir var as byte, it now works with this added change

    ' Encoder.0 = Ch_A
    ' Encoder.1 = Ch_B
    encoder =(porta&48)>>4

    reading the pins individually wont work for me @32mhz
    Warning I'm not a teacher

  40. #40
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,569


    Did you find this post helpful? Yes | No

    Default Re: Can PBP read optical encoder damn fast? :)

    I made that exact mistake initially, hence the comment where the DIR variable is declared - yet I missed it when looking at you code...

    I wonder why reading the pins individually doesn't work in your case. I only did it that way because CuriousOne wanted to be able to have the signals placed arbitrarily. I suspect though that reading them individually might be faster than masking and shifting.

    I've been playing around with the math to go from encoder counts to actual frequency and I'm down to 110 cycles for calculating and stuffing the bits into the array. Had to resort to a tiny bit of ASM, getting the high word of a 16*16bit multiplication back from PBP without resorting to actually using LONGs.

Similar Threads

  1. HEDS5540 optical encoder
    By louislouis in forum mel PIC BASIC Pro
    Replies: 23
    Last Post: - 12th October 2016, 00:23
  2. how to read ky40 mechanical encoder ?
    By iw2fvo in forum mel PIC BASIC Pro
    Replies: 20
    Last Post: - 25th October 2015, 17:22
  3. Probe to read quadrature encoder with DT_INT need help
    By phoenix_1 in forum mel PIC BASIC Pro
    Replies: 11
    Last Post: - 31st August 2009, 21:43
  4. USB Optical mouse as motor encoder
    By RodSTAR in forum mel PIC BASIC Pro
    Replies: 6
    Last Post: - 24th August 2008, 16:09
  5. Damn these low power PIC and other Microcontrollers
    By keithdoxey in forum Off Topic
    Replies: 8
    Last Post: - 12th November 2006, 22:52

Members who have read this thread : 2

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts