PMDC SERVO MOTOR WITH quadrature encoder DRIVE ?


Closed Thread
Results 1 to 38 of 38

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Hi,
    This is cut and pasted from a larger program I have and this digested version is not tested so take it for what it is please. It's written for the 18F2431 so double check the pin assignments for the QEI module.

    Code:
    DEFINE HSER_RCSTA 90h                       'USART receive status init.
    DEFINE HSER_TXSTA 24h                       'USART transmit status init.
    DEFINE HSER_BAUD 57600                      'Baudrate is 57600.
    
    ANSEL0 = 0                                  'All inputs as digital
    
    PortA = 0
    PortB = 0
    PortC = 0
    
    TRISA = %11000                           'QEI pins as inputs.
    TRISB = %00000000
    TRISC = %10000000                       'USART RX pin as input.
    
    QEICON = %00010100                      'Setup QEI, 4X mode, reset on index. 
    
    PosLow VAR BYTE                          'Storage for the low byte of encoder count
    PosHigh VAR BYTE                         'Storage for the high byte of encoder count
    PosTemp VAR BYTE                        'Temporary storage for low byte of encder count
    Position VAR WORD                        'Actual encoder position, 16bit word.
    
    CLEAR
    
    Main:
      Gosub GetPosition
      HSEROUT ["QEI Count: " , #Position, 10]
      Pause 100
    Goto Main
    
    GetPosition:
    'Since the position counter isn't double buffered we can get to situations
    'where the lowbyte overflows between readings of the high and the low byte. This
    'is prevented by reading the low byte two times and compare the two readings.
    'If they are the same then we're fine, if not re-read the registers.
      
        PosHigh = POSCNTH                       'Get high byte of counter
        PosLow = POSCNTL                        'Get low byte of counter
        PosTemp = POSCNTL                       'Get low byte again
        
        If PosLow - PosTemp = 0 then Goto Done      'Compare, if equal we're done.
        
        PosHigh = POSCNTH                           'If not, get values again.
        PosLow = POSCNTL
    
    Done:
        Position = POSHIGH * 256 + PosLow           'Put high and lowbyte together.
    RETURN
    END
    Again, no guarantees but I hope it serves as a starting point for you.

    /Henrik.

  2. #2
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Hi Henrik,

    I started playing with the 4431 DIP version and wonder if you have ran into this with the one you are using. Maybe it is a 4331 problem, maybe whole series.

    When using a 4Mhz resonator and have the config set for HSPLL and DEFINE OSC 16 all works well.

    If I replace the 4Mhz with a 10 Mhz and try DEFINE OSC 40 everything goes erratic.
    The PIC runs but even a simple "blinky" will blink randomly.

    Here is the very simple code and configs I was playing with to set the OSC.
    Code:
        @ __CONFIG    _CONFIG1H, _OSC_HSPLL_1H
        @ __CONFIG    _CONFIG2H, _WDTEN_ON_2H & _WDPS_512_2H
        @ __CONFIG    _CONFIG2L, _BOREN_OFF_2L & _PWRTEN_ON_2L    
        @ __CONFIG    _CONFIG3H, _MCLRE_OFF_3H
        @ __CONFIG    _CONFIG4L, _LVP_OFF_4L  
        
         DEFINE OSC 16
         
        START:HIGH PORTD.1:PAUSE 500
        LOW PORTD.1:PAUSE 500:GOTO START
    Dave
    Always wear safety glasses while programming.

  3. #3
    Join Date
    May 2007
    Location
    Republic Serbia
    Posts
    105


    Did you find this post helpful? Yes | No

    Talking

    My first step to make led blink and probe with these code:
    Code:
    define osc 20
    
        ADCON1 = 7
        led1 var porta.0
        led2 var porta.1
        high led1
        low led2
        pause 1000
        loop:
        toggle led1
        pause 500
        toggle led2
        pause 500
        goto loop
    And led wor blink...
    Now we will learn other fuses and options on 18F4431..
    But I still mean we must be WIZARD to get all we need..
    There is 400 pages of datasheet.
    All what I want to make is UHU type of PMDC control to interface it to MACH3 software for CNC.
    Idea come from original UHU controller from Uli Hubert from Germany.
    He use ATTINY2313 and make full stf WOW.
    Can you image these :
    He put in that little chip quadrature encoder full measure of his speed , direction and velocity reading ,
    capture coming pulse from PC wich is from 1-5 uS, PID control , RS232 terminal , 20KHz PWM , current measure , and motor control ...ETC.
    Then with 18F4431 must be much easy to do that.
    His UHU controller is maybe the best in world and I was test it like finished module on my friend CNC wich work 2 years without error 10h/day .

    Regards Robert
    Attached Images Attached Images
    Last edited by phoenix_1; - 31st August 2009 at 23:03.

  4. #4
    Join Date
    May 2007
    Location
    Republic Serbia
    Posts
    105


    Did you find this post helpful? Yes | No

    Default

    Hi mackrackit and Henrik,
    My PIC is 18F4431
    I have success with 20MHz XTAL and define osc 20 , fuse HS.
    I found motor with encoder with INDEX pin and little modific Hanrik code.
    Result is 16 bit counter but I must find calculation becouse my encoder is 500 pulse per full rev of motor shaft.
    Henrik you was give me good way for start with 18F4431..thanks man again.
    Last edited by phoenix_1; - 1st September 2009 at 08:55.

  5. #5
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by phoenix_1 View Post
    Hi mackrackit,
    My PIC is 18F4431
    I have success with 20MHz XTAL and define osc 20 , fuse HS.
    Mine works fine with 20Mhz HS also. It is when I try to run at 40Mhz HSPLL the problem starts. Maybe I have some bad 10s that are running a bit fast???
    I have some new 10Mhz on order, find out then.
    Dave
    Always wear safety glasses while programming.

  6. #6
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Hi,
    Again, you don't have to use the index channel, it'll work fine without it. If you set up the QEI module to reset on index (as in my example) and the encoder doesn't have an index channel the counter will simply roll over from $FFFF to $0000 or from $0000 to $FFFF depending on direction. Carefully read the section of the datasheet, play with it a bit and read the datasheet again, you'll figure it out ;-)

    /Henrik.

  7. #7
    Join Date
    May 2007
    Location
    Republic Serbia
    Posts
    105


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson View Post
    Hi,
    Again, you don't have to use the index channel, it'll work fine without it. If you set up the QEI module to reset on index (as in my example) and the encoder doesn't have an index channel the counter will simply roll over from $FFFF to $0000 or from $0000 to $FFFF depending on direction. Carefully read the section of the datasheet, play with it a bit and read the datasheet again, you'll figure it out ;-)

    /Henrik.
    Yes I was read that part a couple of time and again and again...
    How I see that full 18F4431 is extra MCU and most of you must do is to set
    tons of nibbles on config registers but!
    If you do that right you will have pleasure to use many finished hardware periferials without to much programing...inside 18F4431 is so many good things...

    Regards Robert

  8. #8
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson View Post
    Hi,
    Again, you don't have to use the index channel, it'll work fine without it. If you set up the QEI module to reset on index (as in my example) and the encoder doesn't have an index channel the counter will simply roll over from $FFFF to $0000 or from $0000 to $FFFF depending on direction. Carefully read the section of the datasheet, play with it a bit and read the datasheet again, you'll figure it out ;-)

    /Henrik.
    Hi Henrik,
    I do not have an encoder to play with but I might some day
    Reading through all of this I am not seeing how the count will go up or down depending on the direction.

    Would you mind enlightening me?
    Dave
    Always wear safety glasses while programming.

  9. #9
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Hi,
    The encoder outputs channels which has a 90° phase shift between them.

    The QEI-module can be set to 2X or 4X mode (X4 is the most common) but the easiest to understand is the 1X mode....

    Simply, if the B channel is high on the rising edge of the A channel then you count up, if the B channel is low on the rising edge of the A channel then you count down. In 2X mode you "trig" on the rising edge of both channels (giving you a resolution of 2X the line count of the encoder) and it 4X mode you trig on the rising AND falling edge of BOTH channels (giving you a resolution of 4X the line count of the encoder).

    If you look up incremental or quadrature encoder on Wikipedia you'll find more details.

    /Henrik.

  10. #10
    Join Date
    May 2007
    Location
    Republic Serbia
    Posts
    105


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by mackrackit View Post
    Hi Henrik,

    I started playing with the 4431 DIP version and wonder if you have ran into this with the one you are using. Maybe it is a 4331 problem, maybe whole series.

    When using a 4Mhz resonator and have the config set for HSPLL and DEFINE OSC 16 all works well.

    If I replace the 4Mhz with a 10 Mhz and try DEFINE OSC 40 everything goes erratic.
    The PIC runs but even a simple "blinky" will blink randomly.

    Here is the very simple code and configs I was playing with to set the OSC.
    Code:
        @ __CONFIG    _CONFIG1H, _OSC_HSPLL_1H
        @ __CONFIG    _CONFIG2H, _WDTEN_ON_2H & _WDPS_512_2H
        @ __CONFIG    _CONFIG2L, _BOREN_OFF_2L & _PWRTEN_ON_2L    
        @ __CONFIG    _CONFIG3H, _MCLRE_OFF_3H
        @ __CONFIG    _CONFIG4L, _LVP_OFF_4L  
        
         DEFINE OSC 16
         
        START:HIGH PORTD.1:PAUSE 500
        LOW PORTD.1:PAUSE 500:GOTO START
    Maybe you need to set manuel 4 nibbles of config manuel :

    Code:
    bit 7 IESO: Internal External Switchover bit
    1 = Internal External Switchover mode enabled
    0 = Internal External Switchover mode disabled
    bit 6 FCMEN: Fail-Safe Clock Monitor Enable bit
    1 = Fail-Safe Clock Monitor enabled
    0 = Fail-Safe Clock Monitor disabled
    bit 5-4 Unimplemented: Read as ‘0’
    bit 3-0 FOSC<3:0>: Oscillator Selection bits
    11xx = External RC oscillator, CLKO function on RA6
    1001 = Internal oscillator block, CLKO function on RA6 and port function on RA7
    1000 = Internal oscillator block, port function on RA6 and port function on RA7
    0111 = External RC oscillator, port function on RA6
    0110 = HS oscillator, PLL enabled (clock frequency = 4 x FOSC1)
    0101 = EC oscillator, port function on RA6
    0100 = EC oscillator, CLKO function on RA6
    0010 = HS oscillator
    0001 = XT oscillator
    0000 = LP oscillator
    and probe ?
    Last edited by phoenix_1; - 1st September 2009 at 20:34.

  11. #11
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default Duh!!!!

    Quote Originally Posted by mackrackit View Post
    I started playing with the 4431 DIP version and wonder if you have ran into this with the one you are using. Maybe it is a 4331 problem, maybe whole series.

    When using a 4Mhz resonator and have the config set for HSPLL and DEFINE OSC 16 all works well.

    If I replace the 4Mhz with a 10 Mhz and try DEFINE OSC 40 everything goes erratic.
    The PIC runs but even a simple "blinky" will blink randomly.
    In my haste I made the stupid mistake of NOT having capacitors near the PIC across VDD/VSS. A friend pointed this out.

    The PIC runs fine at 40Mhz.
    Dave
    Always wear safety glasses while programming.

  12. #12
    Join Date
    May 2007
    Location
    Republic Serbia
    Posts
    105


    Did you find this post helpful? Yes | No

    Wink

    Quote Originally Posted by mackrackit View Post
    In my haste I made the stupid mistake of NOT having capacitors near the PIC across VDD/VSS. A friend pointed this out.

    The PIC runs fine at 40Mhz.
    You is the member of simple peoples TEAM... :-) like me.
    Regards Robert

  13. #13
    Join Date
    Nov 2003
    Location
    Wellton, U.S.A.
    Posts
    5,924


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by trucubsti View Post
    Out of the many posts, this one attract my attention. I believe it is possible for anyone to participate.
    Excellent ! I like it very much.
    We gotta have some fun while we bang our heads against the wall
    Dave
    Always wear safety glasses while programming.

  14. #14
    Join Date
    May 2007
    Location
    Republic Serbia
    Posts
    105


    Did you find this post helpful? Yes | No

    Wink

    Quote Originally Posted by trucubsti View Post
    Out of the many posts, this one attract my attention. I believe it is possible for anyone to participate.
    Excellent ! I like it very much.
    Yes I spend these days about 6-7 hour experimenting with PID rutine...
    It is the most hard part to make PID to work.....
    Soon I will post result of my expiriance...
    For now regards and if any example from anyone pls post
    Robert
    P.S why simple when we can hard ..

  15. #15
    Join Date
    May 2007
    Location
    Republic Serbia
    Posts
    105


    Did you find this post helpful? Yes | No

    Thumbs up Final test and end of these thread from me

    Maybe someone will be optimise code maybe not.
    Here is my last test and all my problems wos on my wrong seting of 18F4431
    and wrong calc for position counter.
    These code only mowe motor CW but I was tested also CCW and is ok.
    My best regards to all
    /Robert

    Code:
    @ __CONFIG    _CONFIG1H, _OSC_HSPLL_1H
    @ __CONFIG    _CONFIG2H, _WDTEN_ON_2H & _WDPS_512_2H
    @ __CONFIG    _CONFIG2L, _BOREN_OFF_2L & _PWRTEN_ON_2L    
    @ __CONFIG    _CONFIG3H, _MCLRE_ON_3H
    @ __CONFIG    _CONFIG4L, _LVP_OFF_4L 
         clear
         define OSC 40                 ;define osc speed 10MHz x 4 PLL = 40 MHz
         ADCON0= %00000000                                
         ANSEL0= %00000000
         ANSEL1= %00000000
         TRISA = %00011110
         TRISB = %00000000
         TRISC = %00000000
         TRISD = %00000000
         TRISE = %00000000
         LATA = %00000000 
         LATB = %00000000 
         LATC = %00000000 
         LATD = %00000000 
         LATE = %00000000 
         duty var word                  'duty variable for PWM CCP1 
         PosLow VAR BYTE                ; Temp variable for Position calc.           
         PosHigh VAR BYTE               ; Temp variable for Position calc.            
         PosTemp VAR BYTE               ; Temp variable for Position calc.
         position var word              ; Position counter final variable from QEI module
         direction var bit              ; Direction bit for motor CW or CCW
         setpoint var word              ; Setpoint of position variable
         preset_TMR1 var word           ; Timer1 prescaler variable
         include "PID.pbp"              ; Include Henrik PID rutine
         INCLUDE "DT_INTS-18.bas"       ; Base Interrupt System
         INCLUDE "ReEnterPBP-18.bas"    ; Include if using PBP interrupts
    ;----[High Priority Interrupts]-----------------------------------------------
    ASM
    INT_LIST  macro    ; IntSource,        Label,  Type, ResetFlag? 
            INT_Handler   TMR1_INT,  _pidloop,   PBP,  yes
        endm
        INT_CREATE                                    
    ENDASM
         CCP1CON = %00001111
         T2CON = %00000100
         T1CON = %10000101 
         QEICON = %10001000 
         DFLTCON = %00111010
         POSCNTH=0                                    ; set initial counter for encoder, H bit
         POSCNTL=0                                    ; set initial counter for encoder, L bit
         setpoint = 0                                 ; set initial for Setpoint
         duty = 512                                   ; set initial for PWM 512 = motor no move  
         direction = pid_Out.15
         pid_Kp =$0140                    
         pid_Ki =$0020                           
         pid_Kd =$0003                        
         pid_Ti = 8                           
         pid_I_Clamp = 1                        
         pid_Out_Clamp = 511
         preset_TMR1 = 65043  
         TMR1L = preset_TMR1.byte0
         TMR1H = preset_TMR1.byte1 
    @    INT_ENABLE  TMR1_INT     ; Enable Timer 1 Interrupts     
         
         Main:                                        ;  main loop
         IF PORTA.1 = 0 then setpoint = setpoint + 1  ; Increment setpoint from taster on RA1
         select case setpoint                         ; Circular  count for Setpoint condition
         case is >= 65534                             ; Circular  count for Setpoint condition
         setpoint = 0                                 ; reset setpoint
         POSCNTH=0 ; set counter for encoder, H bit   ; reset QEI counter high byte
         POSCNTL=0 ; set counter for encoder, L bit   ; reset QEI counter low byte
         end select                                   ; End of Circular  count for Setpoint condition
         pid_Error = setpoint - position              ; Calculate PID error for PID rutine
         gosub pid                                    ; go to PID rutine
         select case direction                        ; condition determine PWM for locked antiphase  
         case 0                                       ; condition determine PWM for locked antiphase
         Duty = abs(512-pid_out)                      ; condition determine PWM for locked antiphase
         case 1                                       ; condition determine PWM for locked antiphase
         Duty = 512 + pid_Out                         ; condition determine PWM for locked antiphase
         end select                                   ; End condition determine PWM for locked antiphase
    @    INT_DISABLE  TMR1_INT                        ; Prevent disable Timer1 interupt 
         CCPR1L = duty>>2                             ; MSB of duty cycle value
         CCP1CON=%00001111 | (duty<<5)                ; set PWM mode and store the 
    @    INT_ENABLE  TMR1_INT                         ; Enable Timer1 interupt
         goto Main                                    ; do main loop
        
    pidloop:                                          ; Interrupt for fast reading QEI and calc position
         PosHigh = POSCNTH                            ; reading QEI and calc position
         PosLow = POSCNTL                             ; reading QEI and calc position
         PosTemp = POSCNTL                            ; reading QEI and calc position
         If PosLow - PosTemp = 0 then Goto Done       ; reading QEI and calc position
         PosHigh = POSCNTH                            ; reading QEI and calc position
         PosLow = POSCNTL                             ; Done reading QEI and calc position
    Done:                                             ; Final QEI calc position
         Position = 256 * POSHIGH + PosLow            ; Final QEI calc position
         TMR1L = preset_TMR1.byte0                    ; reset Timer1 to preset
         TMR1H = preset_TMR1.byte1                    ; reset Timer1 to preset
    @ INT_RETURN                                      ; return from Timer1 interrupt
          end

  16. #16
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    So, are you saying that it works now? No more "ticks" or "jumps", always smooth? What was the actual problem?

  17. #17
    Join Date
    May 2007
    Location
    Republic Serbia
    Posts
    105


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson View Post
    Hi,
    This is cut and pasted from a larger program I have and this digested version is not tested so take it for what it is please. It's written for the 18F2431 so double check the pin assignments for the QEI module.

    Code:
    DEFINE HSER_RCSTA 90h                       'USART receive status init.
    DEFINE HSER_TXSTA 24h                       'USART transmit status init.
    DEFINE HSER_BAUD 57600                      'Baudrate is 57600.
    
    ANSEL0 = 0                                  'All inputs as digital
    
    PortA = 0
    PortB = 0
    PortC = 0
    
    TRISA = %11000                           'QEI pins as inputs.
    TRISB = %00000000
    TRISC = %10000000                       'USART RX pin as input.
    
    QEICON = %00010100                      'Setup QEI, 4X mode, reset on index. 
    
    PosLow VAR BYTE                          'Storage for the low byte of encoder count
    PosHigh VAR BYTE                         'Storage for the high byte of encoder count
    PosTemp VAR BYTE                        'Temporary storage for low byte of encder count
    Position VAR WORD                        'Actual encoder position, 16bit word.
    
    CLEAR
    
    Main:
      Gosub GetPosition
      HSEROUT ["QEI Count: " , #Position, 10]
      Pause 100
    Goto Main
    
    GetPosition:
    'Since the position counter isn't double buffered we can get to situations
    'where the lowbyte overflows between readings of the high and the low byte. This
    'is prevented by reading the low byte two times and compare the two readings.
    'If they are the same then we're fine, if not re-read the registers.
      
        PosHigh = POSCNTH                       'Get high byte of counter
        PosLow = POSCNTL                        'Get low byte of counter
        PosTemp = POSCNTL                       'Get low byte again
        
        If PosLow - PosTemp = 0 then Goto Done      'Compare, if equal we're done.
        
        PosHigh = POSCNTH                           'If not, get values again.
        PosLow = POSCNTL
    
    Done:
        Position = POSHIGH * 256 + PosLow           'Put high and lowbyte together.
    RETURN
    END
    Again, no guarantees but I hope it serves as a starting point for you.

    /Henrik.
    What if my ENCODER have only A and B output's and dont have INDEX pin ?
    Can I use it ???

  18. #18
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Dave,
    I've never used the PLL on this series of PIC's I've run it on 4Mhz and 20Mhz "straight" though without problems, x-tals though, not resonators. Please keep as posted if/when you find the culprit.

    Robert,
    Yes the UHU-servo chip is impressive - I have a couple of them on 160V/25A drives (the HP-UHU) and they perform very well indeed. I've been meaning to play with replacing the UHU chip with a 18F2431 to gain some performance, mostly in the encoder count frequency. I've found the max encoder count frequency on the UHU-chip to be ~130kHz. Haven't got around to that yet though....

    You can use the encoder without index, the difference would be that the count doesn't automatically reset each each rev of the motor - something you probably don't want it to do anyway. Read up on the operation of the QEI module and QEICON register - you can set it up to operate in a few different ways.

    /Henrik.

  19. #19
    Join Date
    May 2007
    Location
    Republic Serbia
    Posts
    105


    Did you find this post helpful? Yes | No

    Default

    Hi Henrik,
    Yes I will measure a couple of encoder today to find if there INDEX pin.
    Maybe with some logic chip from CD40XX serie I can provide INDEX pulses if there isn't INDEX pin ?

    Regards and thanks for replay to all.
    Robert
    Last edited by phoenix_1; - 1st September 2009 at 07:41.

Similar Threads

  1. Quadrature encoder and ASM Interrupts. questions..
    By godfodder in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 17th March 2013, 14:45
  2. Best quadrature encoder for buck?
    By jrprogrammer in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 23rd June 2009, 13:58
  3. More Servo Woes
    By chrisshortys in forum mel PIC BASIC Pro
    Replies: 10
    Last Post: - 13th May 2009, 08:40
  4. saving RCREG to word
    By Macgman2000 in forum mel PIC BASIC Pro
    Replies: 7
    Last Post: - 15th September 2008, 13:51
  5. encoder wowes
    By wallaby in forum mel PIC BASIC Pro
    Replies: 16
    Last Post: - 6th December 2005, 21:56

Members who have read this thread : 0

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