Modbus UA

Is it possible to have future versions of the Modbus UA server have the ability to write to a bit of a word?

The reason I asked about the bit of the word is that I have a few hundred signals to convert and it can’t be done easily in ladder. So the question is can the Modbus driver be modified or will the future Automation direct driver have the ability to write a bit of a word or should I plan on running part UA and part Kepware?

There are no plans to support writing to bits in either the drivers or the server.

Writing to an individual bit turns into a tricky race condition when done at the driver or server level.

The best solution is to handle writing to bits in the client. Read the latest value, apply a bit mask to it, then write that new value down. You can do this very easily using scripting.

Ok, so what would the script look like?

Here are some functions you can include in the Global Script Modules section under Project -> Script Modules. I called the module bit:[code]def getBit(value, position):
return (value >> position) & 1

def setBit(value, position, newValue):
newValue = (newValue & 1) << position
mask = 1 << position
return (value & ~mask) | newValue

def writeBit(tagPath, position, value):
import system, app
currentValue = system.tag.getTagValue(tagPath)
system.tag.writeToTag(tagPath, app.bit.setBit(currentValue, position, value))[/code]To use this script just do the following:app.bit.writeBit("Path/To/Tag", 0, 1)The first argument is the tag you want to flip the bit on, the second is the bit position and the third is the value of the bit. Hope this helps.

Henry,
How did this solution work out for you? I have a similiar request and don’t necessarily agree with this approach on a system with 100’s of boolean tags referenced in register memory space.

When you have lots of tags referenced to bits in holding registers, this doesn’t seem like it would be easy to keep track of what bit to write in what register. How to keep things straight at the individual tag level when you have 16 different boolean tags in a register. I agree that structured PLC code could have helped some here but the issue still holds.

The script is only needed to write a bit of a word. The Modbus UA driver can read a bit of a word with no problems, you just tell it which bit. The script had a small modification to allow me to control two bits in the same word.

[code]def getBit(value, position):
return (value >> position) & 1

def setBit(value, position, newValue):
newValue = (newValue & 1) << position
mask = 1 << position
return (value & ~mask) | newValue

def writeBit(tagPath, position, value):
import system, app
s = system.tag.getTagValue("%s.OPCServer" % tagPath)
ip = system.tag.getTagValue("%s.OPCItemPath" % tagPath)
currentValue = system.opc.readValue(s,ip)
system.tag.writeToTag(tagPath, app.bit.setBit(currentValue.value, position, value))[/code]

This is the HOA expression (The tag type is in an INT4)

app.bit.writeBit("DIST/HELIX1A_PS/HELIX1A_PS_CMD_BITS_V13150", 2, 1) (bit 2 on) app.bit.writeBit("DIST/HELIX1A_PS/HELIX1A_PS_CMD_BITS_V13150", 3, 0) (bit 3 off)

Followup - we do have plans now to add true bit-level addressing to the modbus driver.

Any updates on when will this bit level writing to words be added to the driver?

That should be rolled in sometime in the 7.2 timeframe.

Hi,

Device I’m polling does not support the Modbus Mask Write Register function (0x16), therefore even if Ignition does, I had to implement the suggested script.

It works well. Unfortunately I’ve noticed that calling the “app.bit.writeBit” 2 or more times in a single event (e.g. button pressed, windowclosed, etc), I get only the bit of the last call written. Bits of previous calls keep their value.

Any idea about this problem?
Could it be because the 2nd (and further) call reads the tag value not yet updated by the tag write of the first call? Any workaround?
Thanks!

You need to call the system.opc.readValue and system.opc.writeValue in the functions. The system.tag functions are not synchronous and you are not guaranteed to have the value in the tag when you call the function. The OPC functions read and write the value when you call it.

I am having the same situation.
Did you find any solution or workaround ?

Appreciate if you can give me a suggestion.

Thanks!

Can this modified script write to more than 2 bits within the register in the same event script?

This and original script only difference seems to be system.opc.readValue vs system.tag,writeToTag.
How does this affect the ability to write 2 bits within the register at the same time?

Appreciate if you could help.