Motor Control
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 the PLC commands the drive
In modern plants, variable frequency drives (VFDs, also called inverters or AC drives) are the standard way to control motor speed. You can set a fixed speed on the drive's keypad, but in real production the PLC has to command the speed setpoint, monitor the drive's status and handle its faults, all according to what the process is doing.
This article works through the patterns you need for that in IEC 61131-3 Structured Text: the analog and digital interface, ramp profiles, torque monitoring, fault recovery and multi-motor coordination, and finally fieldbus control.
The digital and analog interface
Most VFDs accept two kinds of signal from the PLC: digital commands and status bits, and an analog speed reference and feedback.
| 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 |
A 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;
Where 0–27648 comes from
Siemens S7 PLCs use 0–27648 as the standard analog range for 0–100% (4–20 mA or 0–10 V). Many Allen-Bradley modules use 0–16383, but the raw range depends on the module and how it is configured, so always check the 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 and deceleration ramps
VFDs have their own ramp parameters. Process applications often need the PLC to control the ramp instead, so that motion stays coordinated, for example when several conveyors change speed together. A software ramp generator in the PLC puts the rates under your program's 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;
An S-curve ramp for smooth starts
A linear ramp jerks the mechanics at the start and end of every speed change. An S-curve ramp smooths the acceleration by raising and lowering the rate of change gradually:
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 the actual motor current. Monitor it in the PLC for overloads the drive's built-in protection might not catch, such as 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 catches faults such as a jammed conveyor or a failing bearing, which draw abnormally high current for a while before the VFD's own thermal model trips.
Fault handling and automatic recovery
A simple "reset and restart" can damage equipment, so a production line needs more careful fault recovery than that. 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;
The drive gets a limited number of automatic resets, three by default, and then locks out until a technician deals with it. After a period of healthy running the cooldown clears the retry count, so occasional nuisance faults far apart in time do not add up to a lockout.
Synchronising the speed of several motors
In printing, coating and winding, several motors have to run at related speeds. The PLC calculates each section's speed from the line speed and a draw ratio:
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;
Draw ratio, diameter and feedback
A draw ratio above 1.0 increases the tension between sections and pulls the material taut. A ratio below 1.0 creates slack, which is what you want in festoon and accumulator zones. When you convert line speed to motor RPM, always include the roll diameter and the gear ratio. And close the loop on the VFD's actual speed feedback rather than trusting the setpoint alone.
Fieldbus control (PROFINET / EtherNet/IP)
Modern installations use a fieldbus instead of analog wiring. The PLC writes a control word and a speed setpoint into the drive's process data:
// Typical PROFINET VFD control word bits (PROFIdrive standard)
// Bit 0: ON/OFF1 (ramp stop if 0; OFF2 is the coast stop)
// 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 and Danfoss, standardizes these bit assignments, so the same control-word logic largely carries over between drive brands on PROFINET.
The patterns in brief
| 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 |
dt), the thresholds and the retry counts for your own application. The structure of each block stays the same.