how to read ky40 mechanical encoder ?


Closed Thread
Results 1 to 21 of 21

Hybrid View

  1. #1
    Join Date
    Jun 2008
    Location
    Varese , Italy
    Posts
    326


    Did you find this post helpful? Yes | No

    Default Re: how to read ky40 mechanical encoder ?

    I am sorry Richar for having posted the file that is not the final one:
    please change the following:

    A VAR PORTD.0 ' encoder A PHASE
    shAll be:
    A VAR PORTB.0

    This is the interrupt input !

    I would be happy to know ...
    Thanks and regards,
    Ambrogio

  2. #2
    Join Date
    Jun 2008
    Location
    Varese , Italy
    Posts
    326


    Did you find this post helpful? Yes | No

    Default Re: how to read ky40 mechanical encoder ?

    I did capture the output of the terminal printout for a better check.
    There are about 200 changes of the cnt obtained by "manually" turning the encoder knob on my control panel. Probably sometims cw and ccw.
    I noted very few spikes : I am not shure if they are due to the time required for the serial port output or to the encoder software.
    Any improvement to the program is very much appreciated.
    I am really searching for a good solution.
    Thanks
    regards,
    Ambrogio

  3. #3
    Join Date
    May 2013
    Location
    australia
    Posts
    2,643


    Did you find this post helpful? Yes | No

    Default Re: how to read ky40 mechanical encoder ?

    I do it this way

    enc pins must be sequential and on same port
    both enc pins must be able to generate an interrupt (ioc on neg and pos edge is best , ioc, rac,rbc on neg or pos edge will work as will int0 int1)
    enc pins must be pulled up (10k) and have 0.1uF filter caps

    I have an asm version that's 100 bytes smaller and has about 1 tenth of the irq latency and is much faster too


    Code:
    '****************************************************************
    '*  Name    : rotary encoder.BAS                                *
    '*  Author  : richard                                           *
    '*  Notice  : Copyright (c) 2013                                *
    '*          : All Rights Reserved                               *
    '*  Date    : 9/4/2013                                          *
    '*  Version : 1.0    16f1825                                    *
    '*  Notes   :  enca porta.2 encb porta.3                        *
    '*          :   note mclr disabled ,full quad decode            *
    '****************************************************************
      
    #CONFIG
                 __config        _CONFIG1,    _FOSC_INTOSC & _CP_OFF & _WDTE_ON  &  _PWRTE_ON  &  _MCLRE_OFF  & _CLKOUTEN_OFF
                  __config      _CONFIG2, _PLLEN_ON & _LVP_OFF
    #ENDCONFIG
      
     
    include "dt_ints-14.bas"
    include "REENTERPBP.bas"
     
    asm
    INT_LIST macro
          INT_HANDLER IOC_INT, _enc_isr,pbp,NO
          endm
     INT_CREATE
    ENDASM    
     
    DEFINE OSC 32
     
     
     
     
       OSCCON=$70
       ANSELA=0
       
       OPTION_REG.6=0
     
       ev    VAR BYTE bank0
       cnt   VAR WORD bank0
       TMP   VAR BYTE bank0
       enca  VAR porta.2 
       encb  VAR porta.3
       TRISA = 111110
      
       lata.0=1
       IOCAP=12    ;enca porta.2 encb porta.3  pos edge trigger
       IOCAN=12    ;enca porta.2 encb porta.3  neg edge trigger
        
        
       pause 4000 
       
       serout2 PORTA.0,84,[ "ready",13,10]
       IOCAF=0
       
       INTCON=$C8
       
       
       
    mainloop:  
     
     serout2 PORTA.0,84,[13,10, "C",#CNT]
     pause 1000
     
     goto mainloop
        
     
        
     
    enc_isr:
        
    
    ev=ev<<2              ;shift last reading into position
    ev=ev|((porta&12)>>2)  ;read enc pins 2,3  mask off others then  combine this reading with last reading
    LOOKUP (ev&$f),[0,255, 1, 0, 1, 0, 0, 255, 255, 0, 0, 1, 0, 1, 255, 0],tmp ;lookup the decision matrix
    if tmp then         ; decide to inc , dec or ignore 
     if tmp.7 then
       cnt=cnt-1
     else
        cnt=cnt+1
     endif
    endif
    intcon.0=0                   ; clean up and exit
    iocaf=0
    @ INT_RETURN

  4. #4
    Join Date
    Jun 2008
    Location
    Varese , Italy
    Posts
    326


    Did you find this post helpful? Yes | No

    Default Re: how to read ky40 mechanical encoder ?

    Thanks Richard for the code.
    I am just a little bit busy on these days and so I plan to try your code on next days.
    As you have seen I am using pic18f452: Is your code applicable to this micro ?
    If no, what should I modify or adapt ?
    Thanks
    Regards,
    Ambrogio

  5. #5
    Join Date
    May 2013
    Location
    australia
    Posts
    2,643


    Did you find this post helpful? Yes | No

    Default Re: how to read ky40 mechanical encoder ?

    for a pic18f452 you need to use RBC_INT for best results and pins portb.4,5 or portb.6,7 or portb.5,6

    this line needs to match chosen p1ns

    ev=ev|((porta&12)>>2) ;read enc pins 2,3 mask off others then combine this reading with last reading
    for pins portb.4,5 it would be

    ev=ev|((portb&48)>>4)
    Code:
    INT_LIST macro
          INT_HANDLER IOC_INT, _enc_isr,pbp,NO
          endm
     INT_CREATE
    would be
    Code:
    INT_LIST macro
          INT_HANDLER RBC_INT, _enc_isr,pbp,NO
          endm
     INT_CREATE
    IOCAP=12 ;enca porta.2 encb porta.3 pos edge trigger
    IOCAN=12 ;enca porta.2 encb porta.3 neg edge trigger
    IOCAF=0
    INTCON=$C8
    would be
    dummy_var = portb
    INTCON=$C8

    any references to IOCAF need to be deleted , trisb must be appropiate

  6. #6
    Join Date
    Jun 2008
    Location
    Varese , Italy
    Posts
    326


    Did you find this post helpful? Yes | No

    Default Re: how to read ky40 mechanical encoder ?

    Hi Richard,
    I am going to modify my previous program with your indications.
    Probably I did something wrong and it is not working.
    I am attaching the full code : could you please have a look of it ?
    Thanks again for the assistance
    regards,
    Ambro
    Attached Files Attached Files

  7. #7
    Join Date
    May 2013
    Location
    australia
    Posts
    2,643


    Did you find this post helpful? Yes | No

    Default Re: how to read ky40 mechanical encoder ?

    I would do it like this

    Code:
    '****************************************************************
    '*  Name    : pic controlled power supply                       *
    '*  Author  : [select VIEW...EDITOR OPTIONS]                    *
    '*  Notice  : Copyright (c) 2015 [select VIEW...EDITOR OPTIONS] *
    '*          : All Rights Reserved                               *
    '*  Date    : 11/09/2015                                        *
    '*  Version : 1.0                                               *
    '*  Notes   : pic18f452 10mhz x 4 pll = 40 MHZ                  *
    '****************************************************************
    ';Program Configuration Register 1H
    @  __CONFIG    _CONFIG1H, _OSCS_OFF_1H & _HSPLL_OSC_1H      
    ';Program Configuration Register 2L
    @  __CONFIG    _CONFIG2L, _BOR_OFF_2L & _BORV_20_2L & _PWRT_ON_2L
    ';Program Configuration Register 2H
    @  __CONFIG    _CONFIG2H, _WDT_OFF_2H & _WDTPS_128_2H
    ';Program Configuration Register 3H
    @  __CONFIG    _CONFIG3H, _CCP2MX_OFF_3H
    ';Program Configuration Register 4L
    @  __CONFIG    _CONFIG4L, _STVR_OFF_4L & _LVP_OFF_4L & _DEBUG_OFF_4L
    ';Program Configuration Register 5L
    @  __CONFIG    _CONFIG5L, _CP0_OFF_5L & _CP1_OFF_5L & _CP2_OFF_5L & _CP3_OFF_5L 
    ';Program Configuration Register 5H
    @  __CONFIG    _CONFIG5H, _CPB_OFF_5H & _CPD_OFF_5H
    ';Program Configuration Register 6L
    @  __CONFIG    _CONFIG6L, _WRT0_OFF_6L & _WRT1_OFF_6L & _WRT2_OFF_6L & _WRT3_OFF_6L 
    ';Program Configuration Register 6H
    @  __CONFIG    _CONFIG6H, _WRTC_OFF_6H & _WRTB_OFF_6H & _WRTD_OFF_6H
    ';Program Configuration Register 7L
    @  __CONFIG    _CONFIG7L, _EBTR0_OFF_7L & _EBTR1_OFF_7L & _EBTR2_OFF_7L & _EBTR3_OFF_7L
    ';Program Configuration Register 7H
    @  __CONFIG    _CONFIG7H, _EBTRB_OFF_7H
    ' ***************************************************************************
     
    DEFINE OSC 40                 ' XTAL= 10 MHZ   CLOCK= 40 MHZ
    INCLUDE "MODEDEFS.BAS"
    include "dt_ints-14.bas"
    include "REENTERPBP.bas"
     
    
    CNT VAR WORD                   ' COUNTER TO BE DISPLAYED ON TERMINAL
    CNT= 32000
    CNTOLD VAR WORD
    CNTOLD=32000
    counter VAR WORD
    counter= 32000
    ' DEBUG INTERFACE  \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
    '' Set Debug pin port   ________________________________________
    DEFINE DEBUG_REG PORTD
    '' Set Debug pin bit   _________________________________________ PIC_PIN_30
    DEFINE DEBUG_BIT 7
    '' Set Debug baud rate _________________________________________
    DEFINE DEBUG_BAUD 115200
    '' Set Debug mode: 0 = true, 1 = inverted ______________________
    DEFINE DEBUG_MODE 1
    DEBUG 13,10,13,10, " PROGRAM IS STARTING...", 13, 10, 13, 10                         
    ADCON1=7                      ' all digital !
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag?
            INT_Handler    RBC_INT,  _enc_isr,   PBP,  NO
        endm
        INT_CREATE               ; Creates the interrupt processor
    ENDASM
    
      
    '@   INT_ENABLE   RBC_INT     ; enable external (INT) interrupts
       ev    VAR BYTE BANK0
       TMP   VAR BYTE BANK0
       enca  VAR portb.4 
       encb  VAR portb.5
       TRISA = 255
      
       lata.0=1
       tmp = portb  ;; read portb to establish pin change status
       INTCON=$C8  ; enable RBC_INT and clear rbcif
    Main:
      PAUSE 1000
      gosub get_cnt:
      IF counter <> CNTOLD THEN
         DEBUG DEC CNT,13,10
         CNTOLD=counter  ENDIF
      
    GOTO Main
    enc_isr:
        
    ev=ev<<2              ;shift last reading into position
    ev=ev|((portb&48)>>4)  ;read enc pins 4+5  mask off others then  combine this reading with last reading
    LOOKUP (ev&$f),[0,255, 1, 0, 1, 0, 0, 255, 255, 0, 0, 1, 0, 1, 255, 0],tmp ;lookup the decision matrix
    if tmp then         ; decide to inc , dec or ignore 
     if tmp.7 then
       cnt=cnt-1
     else
        cnt=cnt+1
     endif
    endif
    intcon.0=0                   ; clean up and exit
    @ INT_RETURN
    
    
    
    get_cnt:       ;  cnt is not atomic   this is needed to avoid rollover miss reads
    intcon.3=0
    counter=cnt
    intcon.3=1
    return

Similar Threads

  1. Question about mechanical relay
    By Megahertz in forum mel PIC BASIC Pro
    Replies: 8
    Last Post: - 1st October 2012, 10:37
  2. Mechanical question
    By muddy0409 in forum mel PIC BASIC Pro
    Replies: 20
    Last Post: - 11th October 2011, 05:41
  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, 20:43
  4. Mechanical question
    By selbstdual in forum Off Topic
    Replies: 10
    Last Post: - 8th February 2008, 14:34
  5. Replies: 6
    Last Post: - 14th October 2005, 19:41

Members who have read this thread : 1

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