Tool Management – Useful System Variables

$TC_MPP6[magno, locno]

Magazine Place Parameter 6: I like to think of this as the magazine mapping. It gives the internal tool identifier or tool number (a number between 0 and 32000, inclusive) of the tool occupying this location (locno) in this magazine (magno). Zero (0) means no tool in that location. To find out which tool is in the spindle, you would use $TC_MPP6[9998,1] – incredibly handy!


Tool parameter 2: Tool ID (a string) – this is what you use to call a tool, as in T=”CUTTER”, or T90. Note, in the latter case, $TC_TP2[x]=90, but x is not necessarily equal to 90, and is more likely to be some completely different number. It is important to remember that when reading the Siemens documentation, any parameter that uses the tool number to address it will use the internal identifier, not the tool ID.

$TC_DP3[toolNumber, edgeNumber]

Cutting Edge Parameter 3: Length 3 which is generally applied in the Z direction for milling applications (G17) in both 3 and 5 axis milling. In standard 5 axis milling with the system in G17, Length 3 will be applied along the tool vector in TRAORI.

$TC_DP6[toolNumber, edgeNumber]

Cutting Edge Parameter 3: Tool radius (by default – can be changed to diameter via machine data). Very important when using cutter radius compensation (e.g. G41, G42, CUT3DC).

Why Doesn’t My G-Code Program Work? Have you tried STOPRE?

Understanding STOPRE and NEWCONF

There are many reasons why a G-code program can fail. In this post I’ll just be looking at a couple of commands you may not have heard of which can save you from a lot of otherwise inexplicable bugs.


Relatively simple one here: you’ve changed machine data in a program and are confused as to why you’re not seeing any effect. It comes down to those two little letters beside the machine data.

First, “im” is immediately active, just set and forget. Second, “cf” is only active after a NEWCONF or by pressing the “Set MD to Active” softkey (or by pressing reset – if all else fails, press reset). Note: the “Set MD to Active” softkey does nothing while a program is running, you will have to reset the program in order for it to work. The “re” and “po” are channel reset and power on reset respectively and therefore are not particularly useful if you want to set data live within a program.

Take home message: if you set machine data within a program – first make sure it’s going to work but checking how it’s activated; second, use NEWCONF.


STOp PREprocessing. Here is where a lot of software writers get tripped up when writing programs to be executed on an NC. G-Code is sequential (whereas PLC code is cyclic) – that part’s easy enough; in a normal computer program on line is executed after the other – sequential, easy.

The difference between the NC and a computer is that some lines in a program take quite a bit more time to execute than to calculate (for example movement commands), so there’s quite a bit of extra time up the NC processor’s sleeve. In a lot of cases it is important to know what the next 20-50 movement commands are so that the NC can plan axis acceleration, deceleration and block smoothing. Combine these two together and you get the pre-processor – the NC will read in several lines of code ahead so that it can optimise what it has to do now. This is great for standard G-code and CAM output, but when you start writing parametric code which performs calculations on the fly, it can get messy.

What’s the problem? Well, the NC can have a movement command sitting in the pre-processed blocks which contains a calculated value (e.g. an R-Parameter). At some point later in the program this value gets re-calculated. Unfortunately, this has the effect of changing already pre-processed block so that by the time it is actually executed, it does something other than what was planned.

Solution – use STOPRE to perform a preprocessing stop before new values are calculated, this forces the buffer to be completely executed before processing any further lines. Be warned, though, excessive use of STOPRE (particularly in long FOR or WHILE loops) will blow out the execution time of your program.

UDP Communication using 840Dsl

I recently came across an application for 840Dsl which required communication over ethernet from the PLC. Upon adding in the Siemens standard blocks (FB63-FB67) I found some gaping holes in the documentation which I hope to rectify.


Whether you are using TCP or UDP you will need to set up a connection. You do this in Net Pro: Select the CPU of the 840Dsl, right-click and choose New Connection. You will have to choose an ID for the connection and possibly a communication partner (unless you choose UDP broadcast/multicast). This part is key, because all the standard communication FBs will need to know this connection ID.


The documentation is largely sufficient to sort out what you should do here, however, it doesn’t tell you anywhere that the local_device_id in UDT65 should be B#16#4 for the Sinumerik 840Dsl – this is pivotal. Also, you will need to setup the connection ID in both the UDT65 data as well as the ID input for the TCON call.


My biggest problem using TUSEND was that I was consistently getting an error 80C4. A couple of things I found: multicast doesn’t appear to work, even if you have setup your UDP connection as multicast you will need to specify a receiver’s address; despite configuring the connection on the company network I found all my packets were going out over the Profinet bus – I needed to set the receiver’s address within the subnet of the Profinet I/O system and I had to connect my receiver on that bus.


UDP communication with 840Dsl is possible but it doesn’t work the way you’d expect.

Read-In Disable

DOConCD is an incredibly useful resource with myriad pieces of information. What is lacking is some solid guidance on how to use this information. Here are some tips to get around some problems I have faced with DB21 and more specifically, read-in disables.

Always modify DB21 at the end of OB1

Why? Mainly because of the way M-code synchronisation works between the NC and PLC. If you want your user program to have any meaningful effect on your NC program execution, there are certain bits which should be written only at the end of OB1 (once you’ve had a chance to request, say, a read-in disable). Take the following simple program: M50 is used to clamp a fixture and the PLC sets a read-in disable until the fixture is clamped:

N10 G0 X0 Y0 Z100 S10000 M3
N30 Z10
N40 G1 Z-50 F1000
N50 G0 Z100
N60 M30

DB21 modified at the beginning of OB1

  1. NC program executes up to N20 where it calls M50 to clamp  fixture.
  2. NC delays execution until the PLC acknowledges the M50 command.
  3. PLC sets read-in disable based on the status from the previous scan (no clamping request so no read-in disable).
  4. PLC user program detects the M50, requests clamping and requests a read-in disable (this one will only be read in the next scan).
  5. PLC scan completes, M50 acknowledge occurs NC continues with execution of block N30.
  6. After the next PLC scan the read-in disable will be active (assuming clamping feedback hasn’t occurred). This will only affect block N40 onwards.
  7. End result: Read-in disable didn’t work as expected, the program continued when it should have stopped.

DB21 modified at the end of OB1

  1. NC program executes up to N20 where it calls M50 to clamp  fixture.
  2. NC delays execution until the PLC acknowledges the M50 command.
  3. PLC user program detects the M50, requests clamping and requests a read-in disable.
  4. PLC sets read-in disable.
  5. PLC scan completes, M50 acknowledge occurs NC delays execution of block N30 until read-in disable disappears (part clamped).
  6. End result: Read-in disable worked as expected, the program waited for clamping.

What about the rest of DB21?

Sure my main reason for putting all your modifications of DB21 at the end of the cyclic scan is to prevent wayward read-in disables. I also like to compartmentalise my use of interface signals so I will have an FC which just handles channel signals. In this case you would make this the last FC you call in OB1.