[Home]Closed Loop Spindle Speed Control

LinuxCNCKnowledgeBase | RecentChanges | PageIndex | Preferences | LinuxCNC.org

I've managed to get closed loop spindle speed control working. It takes a few seconds for the RPMs to settle down to the commanded RPMs but I'm sure with better PID loop tuning it could settle down faster.


An encoder is attached to the spindle, in my case a 1 pulse per revolution encoder. The position of the encoder is scaled using a HAL scale component from pulses per second to pulses per minute thereby giving RPMs. In my case since I had a single pulse per revolution I scaled by 60 to give spindle RPM. This spindle RPM is connected to the feedback pin of a HAL pid component. The commanded spindle RPM is connected to the command pin of the PID. The PID is tuned to use Pgain=0, Igain=1, Dgain=1. The output of the PID is added to the commanded spindle RPM and then fed into the pwmgen as the value of the pwm.

Update: I've managed to better tune my system by using Pgain=1, Igain=1, Dgain=0.5, maxoutput=1500 . The spindle doesn't overshoot too much and it oscillates down to the commanded RPM within 2 seconds.

Update: I haven't done this yet, but setting FF0=1 will enable you to not have to use the sum2 component since the commanded RPM will be automatically added into the output of the PID, but you will have to adjust the maxoutput to your real maxoutput, not the max amount of error allowed.

Hal file snippet

# --------------------------------------------------
#   Closed Loop Spindle Control
# --------------------------------------------------
    # Initialize the encoder (spindle)
        loadrt encoder num_chan=1
        addf encoder.update-counters base-thread
        addf encoder.capture-position servo-thread
        setp encoder.0.position-scale 1
        setp encoder.0.counter-mode 1

    # Initialize the PID 
        loadrt pid num_chan=1
        addf pid.0.do-pid-calcs servo-thread
        setp pid.0.Pgain 0
        setp pid.0.Igain 1
        setp pid.0.Dgain 1
        setp pid.0.maxoutput 4000

    # Initialize the pwmgen
        loadrt pwmgen output_type=0
        addf pwmgen.update servo-thread
        addf pwmgen.make-pulses base-thread
        setp pwmgen.0.pwm-freq 1000.0
        setp pwmgen.0.scale 4000
        setp pwmgen.0.dither-pwm true

    # Initialize the scale
    # (This is used to scale the encoder pulse to RPM)
    # (In my case, i have 1 ppr so it is scaled by 60)
        loadrt scale count=1
        addf scale.0 servo-thread
        setp scale.0.gain 60

    # Initialize the sum2
        loadrt sum2 count=1
        addf sum2.0 servo-thread

    # Attach the motion.spindle-on to enable the pwmgen and the pid
        net spindle_enable motion.spindle-on => pwmgen.0.enable => pid.0.enable

    # Attach the encoder to the parallel port pin
        net parport_15_in         parport.0.pin-15-in => encoder.0.phase-A => encoder.0.phase-Z

    # Attach the encoder to the motion and the scale
        net spindle_rev_count     encoder.0.position => motion.spindle-revs
        net spindle_index_enable  encoder.0.index-enable <=> motion.spindle-index-enable
        net encoder_raw_velocity  encoder.0.velocity => scale.0.in

    # Attach the pid to the scale, motion, and sum
        net pid_feedback          pid.0.feedback <= motion.spindle-speed-in <= scale.0.out
        net pid_command           pid.0.command  <= motion.spindle-speed-out => sum2.0.in0
        net pid_output            pid.0.output   => sum2.0.in1

    # Attach the pwmgen to the sum and the parallel port
        net pwmgen_value          pwmgen.0.value <= sum2.0.out
        net pwmgen_out            pwmgen.0.pwm   => parport.0.pin-16-out

LinuxCNCKnowledgeBase | RecentChanges | PageIndex | Preferences | LinuxCNC.org
This page is read-only. Follow the BasicSteps to edit pages. | View other revisions
Last edited April 15, 2009 12:15 pm by FlyingElectron (diff)
Published under a Creative Commons License