PLC Motor Control with VFDs: Speed, Torque & Diagnostics in Structured Text

Master VFD control from your PLC — speed references, accel/decel ramps, torque limits, fault recovery, and real production sequencing patterns in Structured Text.

Why PLC-Based VFD Control Matters

In modern plants, Variable Frequency Drives (VFDs) — also called inverters or AC drives — are the standard method for controlling motor speed. While you can set a fixed speed on the drive's keypad, real production requires the PLC to command speed setpoints, monitor status, and handle faults dynamically based on process conditions.

This article covers the practical patterns every controls engineer needs: analog and digital VFD interfaces, ramp profiling, torque management, fault recovery, and multi-motor coordination — all in IEC 61131-3 Structured Text.

VFD Communication: Digital + Analog Interface

Most VFDs accept two types of PLC signals:

| Signal | Type | Purpose | | Control Word | Digital (BOOL) | Run/Stop, Forward/Reverse, Fault Reset | | Speed Reference | Analog (INT/REAL) | 0–100% speed or 0–27648 raw counts | | Status Word | Digital (BOOL) | Running, Faulted, At Speed, Ready | | Actual Speed | Analog (INT/REAL) | Feedback from the drive |

Basic Control Interface

PROGRAM VFD_BasicControl
VAR
    // Commands to VFD
    CMD_Run         : BOOL := FALSE;
    CMD_Reverse     : BOOL := FALSE;
    CMD_FaultReset  : BOOL := FALSE;
    CMD_SpeedRef    : REAL := 0.0;    // 0.0 to 100.0 %

// Status from VFD STS_Ready : BOOL; STS_Running : BOOL; STS_Faulted : BOOL; STS_AtSpeed : BOOL; STS_ActualSpeed : REAL; // Feedback %

// Analog output scaling (0–27648 typical for Siemens) AO_SpeedRaw : INT; END_VAR

// Scale percentage to raw analog output AO_SpeedRaw := REAL_TO_INT(CMD_SpeedRef * 276.48);

// Clamp to valid range IF AO_SpeedRaw < 0 THEN AO_SpeedRaw := 0; END_IF; IF AO_SpeedRaw > 27648 THEN AO_SpeedRaw := 27648; END_IF;

// Auto fault reset: pulse reset for one scan when requested IF STS_Faulted AND CMD_FaultReset THEN CMD_FaultReset := TRUE; ELSE CMD_FaultReset := FALSE; END_IF;

Understanding the 0–27648 Scale

Siemens S7 PLCs use 0–27648 as the standard analog range for 0–100% (or 4–20 mA / 0–10 V). Allen-Bradley uses 0–16383. Always check your I/O module documentation:

| Platform | Analog Range | 50% Value | | Siemens S7 | 0–27648 | 13824 | | Allen-Bradley | 0–16383 | 8192 | | CODESYS (generic) | 0–32767 | 16384 |

Acceleration & Deceleration Ramp Profiles

While VFDs have built-in ramp parameters, process applications often need the PLC to control the ramp for coordinated motion (e.g., synchronized conveyor speed changes). A software ramp generator gives you full control:

FUNCTION_BLOCK FB_SpeedRamp
VAR_INPUT
    TargetSpeed  : REAL;     // Desired speed %
    AccelRate    : REAL;     // % per second acceleration
    DecelRate    : REAL;     // % per second deceleration
    Enable       : BOOL;
END_VAR
VAR_OUTPUT
    CurrentSpeed : REAL;     // Ramped output
    AtTarget     : BOOL;
END_VAR
VAR
    dt           : REAL := 0.01;  // 10ms scan time
END_VAR

IF NOT Enable THEN CurrentSpeed := 0.0; AtTarget := FALSE; RETURN; END_IF;

IF CurrentSpeed < TargetSpeed THEN // Accelerating CurrentSpeed := CurrentSpeed + (AccelRate * dt); IF CurrentSpeed > TargetSpeed THEN CurrentSpeed := TargetSpeed; END_IF; ELSIF CurrentSpeed > TargetSpeed THEN // Decelerating CurrentSpeed := CurrentSpeed - (DecelRate * dt); IF CurrentSpeed < TargetSpeed THEN CurrentSpeed := TargetSpeed; END_IF; END_IF;

AtTarget := ABS(CurrentSpeed - TargetSpeed) < 0.1;

S-Curve Ramp for Smooth Starts

Linear ramps cause mechanical jerk at the start and end of speed changes. An S-curve ramp smooths the acceleration by gradually increasing and decreasing the rate of change:

FUNCTION_BLOCK FB_SCurveRamp
VAR_INPUT
    TargetSpeed : REAL;
    MaxAccel    : REAL;     // Maximum acceleration rate (units/s)
    JerkRate    : REAL;     // Rate of acceleration change (units/s²) — must be > 0
    Enable      : BOOL;
END_VAR
VAR_OUTPUT
    CurrentSpeed : REAL;
    CurrentAccel : REAL;
END_VAR
VAR
    dt           : REAL := 0.01;
    SpeedError   : REAL;
    BrakingDist  : REAL;
END_VAR

// Physical parameters must be configured before enabling. JerkRate = 0 // has no engineering meaning (no S-curve shape) and would fault the // braking-distance divide on the very first scan. IF NOT Enable OR JerkRate <= 0.0 THEN CurrentSpeed := 0.0; CurrentAccel := 0.0; RETURN; END_IF;

SpeedError := TargetSpeed - CurrentSpeed;

// Calculate braking distance to decide when to decelerate BrakingDist := (CurrentAccel CurrentAccel) / (2.0 JerkRate);

IF ABS(SpeedError) < 0.1 AND ABS(CurrentAccel) < 0.01 THEN // At target — hold steady CurrentAccel := 0.0; ELSIF SpeedError > BrakingDist THEN // Accelerating phase: increase accel up to MaxAccel CurrentAccel := CurrentAccel + (JerkRate * dt); IF CurrentAccel > MaxAccel THEN CurrentAccel := MaxAccel; END_IF; ELSE // Decelerating phase: decrease accel CurrentAccel := CurrentAccel - (JerkRate * dt); IF CurrentAccel < -MaxAccel THEN CurrentAccel := -MaxAccel; END_IF; END_IF;

CurrentSpeed := CurrentSpeed + (CurrentAccel * dt);

// Hard clamp IF CurrentSpeed < 0.0 THEN CurrentSpeed := 0.0; CurrentAccel := 0.0; END_IF; IF CurrentSpeed > 100.0 THEN CurrentSpeed := 100.0; CurrentAccel := 0.0; END_IF;

Torque Limiting and Overload Protection

VFDs report actual motor current. The PLC should monitor this for overload conditions that the drive's built-in protection might not catch (e.g., gradual mechanical binding):

FUNCTION_BLOCK FB_TorqueMonitor
VAR_INPUT
    ActualCurrent   : REAL;     // Amps from VFD feedback
    RatedCurrent    : REAL;     // Motor nameplate FLA — must be > 0
    OverloadPct     : REAL;     // Trip threshold, e.g. 110.0
    WarningPct      : REAL;     // Warning threshold, e.g. 90.0
    OverloadTime    : TIME;     // Sustained overload time before trip
END_VAR
VAR_OUTPUT
    LoadPercent     : REAL;
    Warning         : BOOL;
    Trip            : BOOL;
END_VAR
VAR
    tmrOverload     : TON;
END_VAR

// Refuse to run with an uncommissioned motor: RatedCurrent comes from // the nameplate (FLA) and must be configured before this FB executes. IF RatedCurrent <= 0.0 THEN LoadPercent := 0.0; Warning := FALSE; Trip := FALSE; RETURN; END_IF;

LoadPercent := (ActualCurrent / RatedCurrent) * 100.0; Warning := LoadPercent >= WarningPct;

// Sustained overload detection tmrOverload(IN := LoadPercent >= OverloadPct, PT := OverloadTime); Trip := tmrOverload.Q;

This pattern catches scenarios like a jammed conveyor, a failing bearing, or a pump running dry — all producing abnormal current draw before the VFD's own thermal model trips.

Fault Handling and Auto-Recovery

Production lines need intelligent fault recovery. A simple "reset and restart" can damage equipment. Use a retry counter with escalation:

FUNCTION_BLOCK FB_VFD_FaultHandler
VAR_INPUT
    VFD_Faulted     : BOOL;
    VFD_Running     : BOOL;
    AutoResetEnable : BOOL;
    MaxRetries      : INT := 3;
    RetryDelay      : TIME := T#5S;
    CooldownTime    : TIME := T#60S;
END_VAR
VAR_OUTPUT
    ResetCommand    : BOOL;
    RunPermit       : BOOL;
    Lockout         : BOOL;
    RetryCount      : INT;
END_VAR
VAR
    State           : INT := 0;
    tmrDelay        : TON;
    tmrCooldown     : TON;
END_VAR

ResetCommand := FALSE;

CASE State OF 0: // NORMAL RUNNING RunPermit := TRUE; Lockout := FALSE; IF VFD_Faulted THEN RunPermit := FALSE; State := 1; END_IF;

1: // FAULT DETECTED — wait before retry tmrDelay(IN := TRUE, PT := RetryDelay); IF tmrDelay.Q THEN tmrDelay(IN := FALSE); IF AutoResetEnable AND (RetryCount < MaxRetries) THEN ResetCommand := TRUE; RetryCount := RetryCount + 1; State := 2; ELSE State := 3; // Lockout END_IF; END_IF;

2: // RESET SENT — wait for drive to recover tmrDelay(IN := TRUE, PT := T#3S); IF VFD_Running THEN // Recovered — start cooldown to clear retry count tmrDelay(IN := FALSE); RunPermit := TRUE; State := 4; ELSIF tmrDelay.Q THEN // Reset didn't work tmrDelay(IN := FALSE); State := 1; END_IF;

3: // LOCKOUT — manual intervention required Lockout := TRUE; RunPermit := FALSE;

4: // COOLDOWN — if no faults for CooldownTime, clear retries RunPermit := TRUE; tmrCooldown(IN := NOT VFD_Faulted, PT := CooldownTime); IF tmrCooldown.Q THEN RetryCount := 0; tmrCooldown(IN := FALSE); State := 0; ELSIF VFD_Faulted THEN tmrCooldown(IN := FALSE); RunPermit := FALSE; State := 1; END_IF; END_CASE;

This is production-proven logic: the drive gets a limited number of auto-resets, then locks out for a technician. The cooldown clears retries after sustained healthy operation, so intermittent nuisance faults don't accumulate unfairly.

Multi-Motor Speed Synchronization

Many processes (printing, coating, winding) require multiple motors to run at related speeds. The PLC calculates draw ratios between sections:

PROGRAM MultiMotorSync
VAR
    LineMasterSpeed : REAL := 60.0;   // Master speed in m/min
    DrawRatio_S2    : REAL := 1.02;   // Section 2: 2% faster (slight tension)
    DrawRatio_S3    : REAL := 1.05;   // Section 3: 5% faster

SpeedRef_S1 : REAL; SpeedRef_S2 : REAL; SpeedRef_S3 : REAL;

// Mechanical parameters — roll diameters come from the mechanical // drawing and MUST be non-zero before the line runs. A "0.0" left in // a recipe is a commissioning bug, not an operating state. RollDia_S1 : REAL := 0.200; // meters RollDia_S2 : REAL := 0.200; RollDia_S3 : REAL := 0.150; // smaller roll = higher RPM needed

GearRatio_S1 : REAL := 5.0; GearRatio_S2 : REAL := 5.0; GearRatio_S3 : REAL := 8.0; END_VAR

// Calculate motor RPM from line speed: // LineSpeed (m/min) / (PI * Diameter) = Roll RPM // Motor RPM = Roll RPM * GearRatio // In production, gate the run permit on RollDia_Sx > 0 alongside the // other interlocks rather than guarding every divide individually.

SpeedRef_S1 := (LineMasterSpeed / (3.14159 RollDia_S1)) GearRatio_S1; SpeedRef_S2 := (LineMasterSpeed DrawRatio_S2 / (3.14159 RollDia_S2)) * GearRatio_S2; SpeedRef_S3 := (LineMasterSpeed DrawRatio_S3 / (3.14159 RollDia_S3)) * GearRatio_S3;

Key Engineering Points

  • Draw ratio > 1.0 increases tension between sections (pulling material taut)
  • Draw ratio < 1.0 creates slack (used in festoon/accumulator zones)
  • Always account for roll diameter and gear ratio when converting line speed to motor RPM
  • Use the VFD's actual speed feedback to close the loop, not just the setpoint
  • Fieldbus VFD Control (PROFINET / EtherNet/IP)

    Modern installations use fieldbus instead of analog wiring. The PLC writes a control word and speed setpoint to the drive's process data:

    // Typical PROFINET VFD control word bits (PROFIdrive standard)
    // Bit 0: ON/OFF1 (coast stop if 0)
    // Bit 1: OFF2 (free stop)
    // Bit 2: OFF3 (quick stop)
    // Bit 3: Enable operation
    // Bit 4: Ramp generator enable
    // Bit 5: Continue ramp
    // Bit 6: Speed setpoint enable
    // Bit 7: Fault acknowledge
    // Bit 10: Control by PLC

    PROGRAM VFD_ProfidriveControl VAR ControlWord : WORD := 16#0; SpeedSetpoint : INT := 0; // 0–16384 = 0–100% StatusWord : WORD; ActualSpeed : INT;

    bRun : BOOL; bFaultReset : BOOL; rSpeedPct : REAL; END_VAR

    // Build control word ControlWord := 16#0;

    IF bRun THEN // Standard run command: bits 0,1,2,3,4,5,6,10 ControlWord := 16#047F; ELSE // Stop command: controlled ramp-down ControlWord := 16#043E; END_IF;

    IF bFaultReset THEN ControlWord := ControlWord OR 16#0080; // Set bit 7 END_IF;

    // Scale speed SpeedSetpoint := REAL_TO_INT(rSpeedPct * 163.84); IF SpeedSetpoint > 16384 THEN SpeedSetpoint := 16384; END_IF; IF SpeedSetpoint < 0 THEN SpeedSetpoint := 0; END_IF;

    The PROFIdrive profile (used by Siemens SINAMICS, SEW, Lenze, Danfoss) standardizes these bit assignments, so the same PLC code works across different VFD brands on PROFINET.

    Summary

    | Topic | Key Takeaway | | Analog Interface | Scale 0–100% to your platform's raw range (27648, 16383, etc.) | | Ramp Control | PLC-side ramps enable coordinated multi-motor acceleration | | S-Curve | Reduces mechanical jerk; critical for precision applications | | Torque Monitoring | Catches mechanical issues before the VFD's thermal model trips | | Fault Recovery | Retry with escalation prevents both stuck lines and equipment damage | | Multi-Motor Sync | Use draw ratios and account for roll diameters and gear ratios | | Fieldbus Control | PROFIdrive control word gives precise, wiring-free VFD command |

    Every pattern shown here is production-tested. Adapt the scan times, thresholds, and retry counts to your specific application — but the architecture is universal.