Ten G120 drives on a machine should mean one function block and ten instance data blocks, not ten copies of similar logic. Define a UDT holding the four telegram words, write FB_G120 in SCL with inputs for Enable, Start, Reset and Speed_RPM and outputs for Running, Fault, AtSpeed and Actual_RPM, and pass the telegram structure as an InOut parameter. All the details that go wrong — the 16#047E to 16#047F sequence, clamping the setpoint before it wraps negative, edge-triggering the fault acknowledge — live inside the block once, tested once, and no caller can get them wrong.
- Copied logic diverges. A scaling fix applied to conveyor 3 and not to conveyors 1, 2 and 4 surfaces months later.
- Clamp the setpoint every scan. An unclamped overflow past 32767 wraps negative and runs the motor backwards at full speed.
- Pass the telegram as InOut, not as separate In and Out parameters — one structure, one address assignment, no drift.
- Output Running from ZSW1, never from the block's own Start input.
Why One Block Instead of Ten Copies
The tempting approach on a machine with several drives is to write the logic once in ladder, then copy it and change the addresses. It works on day one and degrades from then on.
What actually happens is this. Six months in, someone discovers the speed setpoint can overflow at high RPM requests and fixes it on the drive where it was noticed. The other nine copies keep the bug. A year later a different engineer changes the fault acknowledge handling on two drives during a shutdown. Now there are three variants of what should be one behaviour, and no one knows which is correct.
An instance-based function block removes the possibility. The logic exists once. Fixing it fixes every drive. Adding an eleventh drive is a tag assignment, not a programming task. This is exactly what function blocks and instance data blocks were designed for, and drive control is close to the ideal use case because every drive genuinely does behave identically.
The UDT That Makes It Possible
Start with a PLC data type describing the telegram, not with the block.
| Member | Type | Maps to |
|---|---|---|
| ControlWord | Word | PZD1 out — STW1 |
| Setpoint | Int | PZD2 out — NSOLL_A |
| StatusWord | Word | PZD1 in — ZSW1 |
| ActualValue | Int | PZD2 in — NIST_A |
Declare one tag of this type per drive and assign it to the address range TIA Portal allocated for that drive's telegram. Name them for the machine, not the network: Drv_Conveyor1, Drv_Conveyor2, Drv_Mixer.
The payoff is that absolute addresses now appear in exactly one place in the whole project — the tag table. Nothing in the program logic references QW258 or IW262, so re-addressing a drive breaks nothing.
Write drive blocks that survive handover
Learn UDT-based, instance-driven drive programming in SCL on real S7 and SINAMICS hardware. Pune classroom or online.
Designing the Block Interface
Design the interface before writing any logic. If the interface is right, the logic follows; if it is wrong, no amount of good code inside will save it.
| Section | Name | Type | Purpose |
|---|---|---|---|
| Input | Enable | Bool | Machine permissive — holds the drive in the ready state |
| Input | Start | Bool | Run command from the sequence |
| Input | Reset | Bool | Operator reset; the block converts it to an edge internally |
| Input | Speed_RPM | Real | Requested speed in engineering units |
| Input | RefSpeed_RPM | Real | The drive's p2000 value, for scaling |
| Input | CommsOK | Bool | Device status from the PROFINET diagnostics |
| Output | Running | Bool | From ZSW1 bit 2, not from Start |
| Output | Ready | Bool | From ZSW1 bit 1 |
| Output | Fault | Bool | From ZSW1 bit 3 |
| Output | AtSpeed | Bool | From ZSW1 bit 8 — permissive for downstream equipment |
| Output | Actual_RPM | Real | Scaled feedback for HMI and archiving |
| InOut | Telegram | UDT | The drive's process data structure |
| Static | Reset_Prev | Bool | Previous state, for edge detection |
Two design choices matter here. RefSpeed_RPM as an input rather than a constant means the same block serves drives with different reference speeds, which is the normal situation on a real machine. And Telegram as InOut keeps the read and write halves together, so there is no way to wire the status word from one drive and the control word from another.
Inside the Block: Scaling with Clamping
NSOLL_A is normalised: 16384 means 100 % of the drive's p2000. The conversion is arithmetic, but it must be guarded.
Ref := (#Speed_RPM / #RefSpeed_RPM) * 16384.0;
IF #Ref > 16384.0 THEN #Ref := 16384.0; END_IF;
IF #Ref < -16384.0 THEN #Ref := -16384.0; END_IF;
#Telegram.Setpoint := REAL_TO_INT(#Ref);
Without those two clamps a request beyond the reference speed can produce a value above 32767, which wraps to a large negative number. Most drives read that as full speed in reverse. On a conveyor that is a broken machine; on a hoist it is considerably worse. Clamp every scan, unconditionally.
Guard the division too. If RefSpeed_RPM arrives as zero — a caller that forgot to set it — the calculation produces a division fault. A single check that returns a zero setpoint and sets an output flag is cheaper than debugging a CPU stop.
Scale the feedback the same way in reverse so Actual_RPM is in engineering units:
#Actual_RPM := (INT_TO_REAL(#Telegram.ActualValue) / 16384.0) * #RefSpeed_RPM;
Archiving raw normalised counts and converting later is a reliable source of reporting errors, so convert here, once, and let everything downstream see RPM.
Inside the Block: Control Word and Edges
Assemble the control word from the enable bits plus the run bit, and pulse the acknowledge bit only on a rising edge of Reset:
| Condition | ControlWord |
|---|---|
| Enable false | 16#0000 |
| Enable true, Start false | 16#047E |
| Enable true, Start true | 16#047F |
| Rising edge on Reset | Current value with bit 7 set, for that scan only |
Edge detection in SCL is two lines and must not be skipped:
#Ack := #Reset AND NOT #Reset_Prev;
#Reset_Prev := #Reset;
Then set bit 7 only while #Ack is true. Because Reset_Prev is a static variable inside the instance data block, each drive keeps its own edge state automatically — which is precisely why this belongs in a function block rather than a function.
Decode the status word into the outputs at the end of the block. Use bit 2 for Running, bit 1 for Ready, bit 3 for Fault, bit 8 for AtSpeed. Never assign Running from the Start input, however tempting the shortcut looks.
Instance per Drive, and Comms Monitoring
Call the block once per drive, each with its own instance data block and its own telegram tag. Ten calls in the drives OB, ten instance DBs, one FB.
Feed CommsOK from the PROFINET device status. On an S7-1500 this is available through the system diagnostics and diagnostic instructions; on an S7-1200 you can monitor the device state through the diagnostic status of the IO device. Inside the block, use it to force the outputs to a safe state — Running false, Fault true — so a lost drive cannot leave a stale "running" indication on the HMI.
What the block must not do is decide what happens to the motor during a comms loss. That behaviour is configured in the drive itself, because during the loss the PLC cannot reach it. The block's job is to tell the rest of the machine that the drive is gone.
Step-by-Step Lab: Build and Instantiate FB_G120
Hands-on- TIA Portal V17 or later with an S7-1200 or S7-1500 project. PLCSIM is enough for the logic; two real G120 drives make step 6 meaningful.
- At least one drive already configured with Standard Telegram 1 and its addresses noted.
- Estimated time: 50 minutes.
Create the UDT and two drive tags
Add a PLC data type Drive_Telegram with the four members, then declare two tags of that type and assign them to two drives' address ranges.
Build the interface before any logic
Create FB_G120 in SCL and enter every input, output, InOut and static from the interface table. Compile with an empty body.
Write the scaling and test the clamp deliberately
Add the setpoint calculation with both clamps and the divide-by-zero guard, then call the block with Speed_RPM set far above RefSpeed_RPM.
Add the control word and edge detection
Implement the three control word states and the rising-edge acknowledge, then toggle Enable, Start and Reset from a watch table while watching ControlWord in hex.
Decode the status word and run a real drive
Map ZSW1 bits to Running, Ready, Fault and AtSpeed, then start an actual drive through the block.
Instantiate twice and prove independence
Call FB_G120 a second time with its own instance DB and second telegram tag. Run both, then hold Reset on one only.
The block is production-ready when an out-of-range speed clamps instead of reversing, a held reset does not repeatedly acknowledge, Running follows ZSW1, and losing one drive leaves the other untouched. Those four behaviours are what separate a block that works on the bench from one that survives a plant.
Frequently asked questions
Why use one function block instead of copying the logic per drive?
Copied logic diverges. A fix applied to one copy and not the others produces failures that appear months later and are hard to trace. One function block with an instance data block per drive means the logic exists once, a fix applies everywhere, and adding another drive is a tag assignment rather than a programming task.
Should the telegram be an In parameter, an Out parameter, or InOut?
InOut, as a single UDT. It keeps the control and status halves of one drive together, so there is no way to accidentally wire the status word from one drive with the control word from another, and it gives the block direct access to both directions.
What happens if I do not clamp the speed setpoint?
A request beyond the reference speed can calculate to more than 32767, which wraps to a large negative number. Most drives read that as full speed in reverse. Clamp to plus and minus 16384 every scan, without exception.
Why does edge detection need to be inside the block?
Because the previous-state variable must be per drive. Declaring it as a static in the function block means each instance data block keeps its own copy automatically. A function without instance memory cannot do this correctly for multiple drives.
Should the block decide what happens during a communication loss?
No. The drive applies its own configured telegram-failure response, because the PLC cannot reach it during the loss. The block's job is to report the loss through a CommsOK-driven output so the rest of the machine stops depending on that drive.
Can the same block handle drives with different reference speeds?
Yes, if RefSpeed_RPM is an input rather than a constant. Each instance is then given its own drive's p2000 value, which is the normal situation on a machine mixing motor sizes.
