Mitsubishi GXWorks2 FBD Vs LAD

parky

Member
Join Date
Oct 2004
Location
Midlands
Posts
5,758
Not very often I ask for help, but this one has got me stumped.
There are two ways to indirectly address memory areas in Mitsubishi PLC's.
Using the index registers Z0-Z15, these act as pointers to an offset in the Z register so for example if 10 is put in the Z0 register then you do a move
[MOV 1234 D0Z0] it will move the value 1234 into D0+10 (D10), however, the other way is to use the ADRSET function, this moves the actual address of the variable into a double word [ADRSET D0 D100]and then Add 10 to D100 (pointer to D10) then call function [MOV @D00 D30] will move the value in D10 into D30.
This works in ladder but does not work in FBD even though we are using the equivalent functions as it comes up with a compile error(s). I have tried to find why the @ symbol is not a valid character in FBD but to no avail, I wonder if anyone out there has the answer. There are differences in ladder to FBD for example in FBD to do a move or maths function then they are MOV 1234 to Dxx or EMOVE 1.23 Dxx where in ladder they are MOV K1234 to Dxx or EMOVE E1.23 Dxx so in FBD use direct numbers but in ladder use K for int, E for floats etc.

See pics.

Direct offset address.png Direct Offset FBD.png
 
Hi Parky
While not answering your question you could consider preloading a D register outside of the FBD.. this may or may not be a workaround
 
How does the MOV, in either ladder or FBD, know the size of the data at the pointer i.e at @D100? Presumably by the destination, but maybe that doesn't work in FBD.



Is it possible the FBD move uses a different character for pointer dereferencing, e.g. * instead of @?


Or is there a different move command, or maybe an AB-like COP/CPW/CPS/copy that moves bits not values, that understands the @ syntax?
 
No this will not work, although the ADRSET gets the 32 bit address of say Variable D0 and stores it in D100, the problem is if for example I want to offset the address pointer by a number that works but the only way to address D0 + the offset is by using the @ symbol, this works if I create a ladder block within GXWorks but not if I use FBD, for some reason it does not like the @ symbol.
This seems odd as it works in the equivalent in ladder. I think it is a bug in GXWorks that they have not found or it maybe that a different symbol is used. for example in Ladder to move a fixed value into a register the format is K1234 so this will move 1234 into the register, however, in FBD you do not need the "K" there are formats for different types i.e. K = integer or Double integer H for hex value & E for floating point, however, you do not use these in FBD it knows from the function what the format is for example instead of K1234 it's just 1234, for Floats it's E12.34 and just 12.34. I can get round it by using the Z registers but this will not allow me to pass the actual address to a function.
 
DR: that was my rekoning but I have not found it yet if it exists. Using the Z pointer registers is ok but you need to know whether it is say a "D" type or "W" type, the idea of the direct address is you can pass the parameter to a function by using a variable. a little difficult to explain but here goes,
Using indirect you put a value in the Z register say 10 then you reference the register by move D0Z0 this moves the value in D10 (D0 with offset of 10 so D10), this is fine but you cannot have a pointer transferred to a function so for example, the idea is as an input parameter say D0, inside the function I want to find the direct address in memory of D0 and then add an offset to reference the D register of 0 + offset, by passing D0 to the function it takes the actual value of the register not it's physical address, the only way to pass it is to do the ADRSET outside the function then the parameter passed to the function is the direct address in memory, unfortunately again the @ symbol does not work which you need inside the function.
The only work around is to assume within the function that the pointer is going to be a "D" register and use the Z pointer as an offset, so rather than have a parameter passed as "D0" it would need to be a fixed value or a value in a register, then move that into the Z register and use D0Z0 as the pointer.
The actual idea was that any register i.e. "D" or "W" could be passed by reference. it looks like I will need to create separate functions for different areas of registers.
I Think I will create the function in ladder, the idea was to have it all in FBD.
 
Last edited:
Can you pass the indirect offset into the function as a D value, copy that offset to Z0 inside the fucntion, then use D0Z0?


Wait, I think you already said that does not work.


It seems odd the the ADRSET instruction is available in FBD to set an address, but there is no way to use that address.
 
Last edited:
No, the problem is that the Z registers are indirect so you reference them as for example:
If Z contains 1 then D0Z0 points to D1
If Z contains 30 Then D0Z0 points to D30
However, if Z contains 30 And you reference D5Z0 then it points to D5 + 30 = D35 so it is an indirect whereas the @ pointer is reference to the actual memory direct.
An example is D0 actual address is 27489102.
I have it working in ladder but I have to do the ADRSET (find the address of the word) outside of the function, this is unfortunate this is because if you pass say D0 to a function it takes the value and stores it into a temp so doing the ADRSET on a temp gets the address of the temp, Again I have got round this by making my function a macrocode so instead of creating a separate block outside of the program scan that is called & the result returned it actually creates the code within the main code, one downside of this is that normally creating a function and use it many times is it only creates one instance, using macrocode it creates the code for every instance. EDIT: Yes that's right for some reason they do not show the FBD, however the functions for ADRSET are in FBD & they work, however, if you try to use the move function it does not recognise the @ symbol it seems strange that it allows you to create the pointer to an address but not use it in FBD?
 
Last edited:
Okay, it's scratching your left ear with your right foot, but you are on that side of the Atlantic ...

Outside function
Code:
[ADRSET  D0  D100]   # put address of D0 into D100
[D+ D100  20  D100]  # increment address in D100, so @D100 = D20
[MOV   1234  D20]    # put 1234 into D20 i.e. into @D100
Inside function
Code:
[ADRSET  D0  D200]   # put address of D0 into D200  
[D- D100 D200 D200]  # Get offset of @D100 from D0
[MOV  D200 Z0]       # Put offset into Z0
[MOV D0Z0 ...]       # Move data from @D100


Your workaround is better ;).
 
The problem with that is you cannot use @ symbol in FBD so it has to be in ladder, second problem is that you also need to pass D0 to the function in macrocode it works because it creates the code for each instance which I have already done and it becomes simpler than what your doing, however, If I create the function so that it is a true subroutine i.e. it jumps to the sub & returns it and use it as one instance passing D0 to the function actually copies the data not the address for example the compiled code is:
LD SM400
Mov D0 D13309 // here it moves the data in D0 to D13309 (used as a temp)
JC P00234 // Jump to the subroutine
Mov D13309 // returns here
FEND // end of main code
P00234: // Subroutine
LD D13309 // here it is loading the wrong register it contains the data of D0 so if you point to the address it points to D13309 not D0
RET // return back to main program
See pics, although they are different code I cannot create the same code because it would fault the plc due to it not pointing to the correct register


The problem is using the Z register by putting in the actual address means that Z0 will contain something like 29456301 so D0Z0 would point to D0 + offset of 29456301 way outside of the address range using Z register. so for example D0Z0 (assuming Z0 is 100 would point to D100, but using direct addressing would point to D29456301 there are no registers in this range.

will not work.

FB instance.png Macrocode.png
 
Last edited:
...
The problem is using the Z register by putting in the actual address means that Z0 will contain something like 29456301 so D0Z0 would point to D0 + offset of 29456301 way outside of the address range using Z register. so for example D0Z0 (assuming Z0 is 100 would point to D100, but using direct addressing would point to D29456301 there are no registers in this range.

will not work.




You missed the D- instruction in my suggestion, I am putting 20, not 2G, into Z.



I agree your solution - ladder - is better, but I am not convinced mine - with the D- to calculate the OFFSET from D0 to put into D200, then into Z0, - will not work.


It would work in the C equivalent, but that means bupkis, of course.
 
That's ok for direct calls to the D registers but the idea of a function block is to pass the D words by reference, it cannot be done only by doing the ADRSET and putting it into a register before calling the FB, however, I cannot do the @ direct address in FBD. Even though I can pass the direct address.
There are two ways that will work, call the function as a macro block (this just creates the compiled code within the main program, the problem is that as a macro it will create a block of code in the main code so if there is 10 calls to the FB it creates 10 lots of code, not very efficient and takes memory.
The other way is to create a FB that is a true subroutine but pass the reference as a integer, then use the Z registers in the FB, unfortunately this means If I want to do this in the "W" register range then I have to have two FB's or do a check in the FB and jump to the code depending if it is a "D" or "W" register.
It's not a major problem it's just a bit messy it appears that according to the books that it is not possible to reference any Direct address in FBD but you can find the direct address, also even in ladder, you cannot reference using the @ symbol using labels (Tags) only direct Words it's sort of like in AB 500 you always use the actual address not the symbol (tag), whereas in controllogix it is purely based on symbols (tags/labels if you like).
Mitsubishi has a trade off where they keep the compatibility with the older software in a loose manner. I noticed that those functions are not shown in FBD only ladder, I'm going to try ST but it still remains that to reference the actual address it will still need to pass the direct address to the FB because a true FB it's only the data that is transferred not the address of the register.
AS I tried to point out populating a FB with D0 does not actually use D0 in the FB it passes it's data to another post compiled register, it's this register that is used so when you get the address it gets the address of the register that D0 data has passed so it is not the address of register D0.
An example is If I wanted to pass a "D" register to a function then on the next call wanted to pass a "W" register, the function will not know if it is a D or W, that is the idea of the ADRSET. It seems to me that it is possible to use the @ symbol in FBD as it is probably the same code for the ladder version but like constants in ladder you use K or E , in FBD you do not need these just the value so the compiler knows the difference i believe that they have missed the symbol in compiling FBD so it says it is an invalid character. This is probably because they use tag based rather than actual address base.
Ladder uses address base but shows the label, FBD uses label and once compiled shows both label and address. This has come about to be compatible with IEC etc. Unfortunately, it appears that Mitsubishi have kept the old stile addressing of fixed amount of registers instead of a tag or label, I would have thought they would have junked the old system with GXWorks but it seems they have tried a compatible system with the older hardware. I have yet to try the functions in the newer processors but do not hold any hopes.
Just as a side line, If you use an HMI on a Mitsi system you have to make the registers globals, this means that tags are tied to actual addresses you type in so in the HMI you reference the actual register not the tag or label.
Any labels (tags) not registered in the global labels are allocated at compile time so you do not know what the actual address is. What Mitsubishi do is assign an area of addresses at the top end that they use when you use tags (labels) only so only the PLC knows what they are.
 
Ah, sorry, I did not pick up that d0 on the fbd function is not there same address as the d0 of the caller, so yeah, my d- trick will not work.

Vewy fwust.wating!
 
Unless you have worked with Mitsubishi, or others then it is difficult to understand the transition from fixed addressing base to tag base, however, it seems my theory may be right, if I run GXWorks 3 the latest version but select the still current but soon to be dis-continued processors it loads GXWorks3 in GXWorks compatibility mode (I suspect it just runs GXWorks2) then you cannot use the @ symbol), however, if I select the new FX5 or other new processors runs GXWorks3 and it allows you to use the @ symbol, so it does appear that there are a few bugs (well not thought of compile quirks) in GXWorks2.
As you cannot use GXWorks3 for the new processors I cannot use FBD & the @ symbol but can for the later, this is not the processor type it is definitely the compiler as it works in ladder I'm assuming they have no intention of bringing in an update for Works2. It is not a function that many people would use and there is a get around just not very pretty. I can use the Z registers but it just makes the code a little unreadable before the function I intended to create as it requires some processing before the call to the FB and means having a number of different FB's for different areas of memory or creating an FB with a number of extra pins & internal logic.
 
...I can use the Z registers but it just makes the code a little unreadable before the function I intended to create as it requires some processing before the call to the FB...




Yeah, you definitely don't want to go there, it's better if the functions are self-contained and don't wear their insides on the outside, if you get my meaning. Even if you could pass in the outside ADRSET from D0 and do it by difference that is just going down Silliness Lane.
 

Similar Topics

Hi I am using a FX3u plc and as i want to create function blocks, I have to use labels. I have to use an array in my program, I want to use a...
Replies
13
Views
7,292
Hello! If someone can help me with the following problem. I can't change the phone number. Do I really need the interface (AL-232CAB - Programming...
Replies
0
Views
59
how to communicate FactoryTalk Optix and Mitsubishi Q Series. I want to know the details of that
Replies
0
Views
56
HOW to communicate with OPTIX and Mitsubishi's Q Series PLC?? PLEASE HELP ME
Replies
0
Views
64
I'm at a new job as the sole control engineer and trying to piece together where my predecessor left off. One machine I'm trying to get online...
Replies
2
Views
113
Back
Top Bottom