We use cookies to personalise content and ads, to provide social media features and to analyse our traffic. We also share information about your use of our site with our social media, advertising and analytics partners who may combine it with other information that you've provided to them or that they've collected from your use of their services.

Addressing variables in PLC's memory

I must confess that the location of variables in the memory and their addresses had been until recently a complete black magic.  I was raised on simple programming languages like Basic or JavaScript and if I needed to declare a variable I wrote "var Variable".  I never had to know where the program stores the new value.  Such an information is normally redundant.

In case of a PLC the addressing became important.  If one knows the variable's address, one can read it via a webserver using the READPI command.  If I declare "myVariable AT MB0 : BYTE" and use the command "READPI ADR=MB0&FORMAT=%d" (by, for example, creating a SSI file placed in the PLC memory and entering into the browser address bar: "http://PLCaddress/READPI?ADR=MB0&FORMAT=%d) I will get the current value of myVariable.  

What are the differences between different type of variables?  What is the difference between MX0.2 od MB2 i MW2? You can find my explanation below.

My WAGO 750-841 has 8kB of addressable memory, which can be used to store and exchange values.  That memory is, naturally, built of individual bits (accepting value 0 or 1).  Those bits, when connected into groups of 8 turn into bytes (accepting values from 0 to 255), which connected into pairs store WORD values (accepting values from 0 to 65 536), which in turn, when connected into pairs store DWORD values.  One can imagine that the memory is like a tape, which can be cut into individual bits or larger bytes etc.

Once a variable is defined in CoDeSys and it receives a fixed address, the compiler is told where it should reach to read/write a value to that variable.  If a BOOL variable receives a MX0.0 address, it is placed in the 1st bit of our addressable memory.  If a BYTE variable is defined under MB0, it will be placed in the 1st byte.

Here is the first thing, which surprised me: by addressing different variables, one can assign them to overlapping parts of memory.  A change of a BOOL variable stored at MX0.0 will change the value of a BYTE variable stored at MB0.

To show how it all functions I prepared a simple program using many different variables:

V_BOOL 		AT %MX0.0 : BOOL;

In the programming part just one line is sufficient:


Once we compile such a program in the simulation mode, this is what we will see:


Once we run the program (F5), the values will change:


What happened? Where do those numbers come from?

On program start the variable V_STRING receives the value 'abcd'.  The 'a' is stored in the 1st byte of the memory, 'b' in the 2nd etc.  Letter 'a' in ASCI code is equal to 97, so V_BYTE addressed to the 1st memory byte (so also to the first character of the V_STRING) is equal to 97.  97 in binary form is equal to 0110001, so the value of V_BOOL, addressed to the first bit of the memory is equal to 1 = TRUE.

The letter 'b' in the ASCI code is 98, so the 2nd byte of the memory stores the value 98.  Consequently the V_WORD is equal to 97+256*98 = 25 185. The value of the V_DWORD comes from 97+256*98+2562*99+2563*100 (where 99 is the letter 'c' and 100 is 'd').

Here is a link to a simple program with the above-presented example.  You can enter any value you want via a visualization and see how it affects the value of the remaining variables.


Now a few words about the addressing convention.  Here is an example taken from the PLC manual: 

Bit   %MX11.0 ... 15  %MX12.0 ... 15 
Byte   %MB22  %MB23  %MB24 %MB25 
Word    %MW11   %MW12

Which means:

  • BOOL variables should be addressed with the number of the Word and the bit number after a dot.  
  • BYTE variables are addressed by assigning consecutive bytes: %MB22, %MB23 etc.
  • WORD variables receive the consecutive number of 'words' : %MW11, %MW12…

Furthermore, the address itself is built of 4 parts, which we can call „ABCD”:

Position Allowed values Description
A % Address Mark





Single Bit

D Address Address number 

That's all! That is how the inputs and outputs are addressed.  I used it previously by reading for example a status of an output: by READPI?ADR=IX8.2. Now I know that I red a 3rd bit from the 8th word from the memory part dedicated to outputs.

The main lessons from it all are:

  1. BOOL variables can be addressed as MX…, and not as MB, but changing them will require specialized libraries (the compiler reserves the whole byte for each bool variable)
  2. Reading variables 'of a higher scale' one can at once read values of many variables 'of lower scale'.  Instead of making 16 queries for variables stored at MX0.0 - MX0.15, one can read the WORD value stored at MW0 and process its individual bits.  Instead of checking output statuses individually by reading IX3.1, IX3.3 etc., one can read the WORD stored at IW3, change it to binary form and read individual outputs.
  3. Understanding the above opens the doors to MODBUS communication.  It is all quite exciting!