Read 16-Bit Modbus Input Register to two 8-Bit tags

Is there a way to read only the first 8 bits (or last 8 bits) from a 16 bit modbus input register exposed by a field device and read that into its own tag such that tag1 is the first 8 bits of the modbus register and tag2 is the last 8 bits of the modbus register?

I took a stab in the dark and tried setting the ‘OPC item path’ as follows but these resulted in ‘Error_Configuration’ quality:
[{DeviceName}]IR11.0-7
[{DeviceName}]IR11.0:8

This request relates to reading in the status words for a Micro850 Analog Input module where 8 bits of each 16-bit word relate to the status of an input channel. Yes, I realize I could pull each bit into its own tag but that is tedious and overkill for my current objectives.

https://literature.rockwellautomation.com/idc/groups/literature/documents/um/2080-um003_-en-p.pdf
image

I had written a UDT for DINT to BIT. Feel free to modify to your needs.

DINT2BIT_UDT.xml (8.9 KB)

1 Like

I ran into another similar issue when trying to read the device clock for a Schneider Masterpact breaker (Micrologic 6.0 P controller). It uses 3 16 bit registers to hold the date/Time where each byte of the three registers holds a different datetime component (Year, Month, Day, Hour, Minute, Second)

From documentation [Link]:

3-register date/time format:
register 1: month (byte 1) = 1–12; day (byte 2) = 1–31;
register 2: year (byte 1) = 0–199 (add to 1900 to determine the actual year); hour (byte 2) = 0–23;
register 3: minutes (byte 1) = 0–59; seconds (byte 2) = 0–59
Note: Bits 14 and 15 of the month/day register must be masked.

I ended up reading the three registers as integers (DT_REG1, DT_REG2, DT_REG3) then using the following convoluted expression in an datetime expression tag. It works, I just have the feeling that there must be a better way.

I commented out most of the bits that I knew were not relevant (e.g. 12 being the max for the month, etc.) .

// 23-register date/time format:
// register 1: month (byte 1) = 1–12; day (byte 2) = 1–31; 
// register 2: year (byte 1) = 0–199 (add to 1900 to determine the actual year); hour (byte 2) = 0–23; 
// register 3: minutes (byte 1) = 0–59; seconds (byte 2) = 0–59
// Note: Bits 14 and 15 of the month/day register must be masked.

setTime(
	getDate(
		binenc( // Device DateTime Register 2 Byte 1, Year (add to 1900)
			 {[.]DT_REG2[8]}
			,{[.]DT_REG2[9]}
			,{[.]DT_REG2[10]}
			,{[.]DT_REG2[11]}
			,{[.]DT_REG2[12]}
			,{[.]DT_REG2[13]}
			,{[.]DT_REG2[14]}
			,{[.]DT_REG2[15]}
		)+1900,
		binenc( // Device DateTime Register 1 Byte 1, Month (max 12)
			 {[.]DT_REG1[8]}
			,{[.]DT_REG1[9]}
			,{[.]DT_REG1[10]}
			,{[.]DT_REG1[11]}
		//	,{[.]DT_REG1[12]}
		//	,{[.]DT_REG1[13]}
		//	,{[.]DT_REG1[14]} 
		//	,{[.]DT_REG1[15]} 
		)-1, // Adjust to January as Month 0 for getDate()
		binenc( // Device DateTime Register 1 Byte 2, Day (max 31)
			 {[.]DT_REG1[0]}
			,{[.]DT_REG1[1]}
			,{[.]DT_REG1[2]}
			,{[.]DT_REG1[3]}
			,{[.]DT_REG1[4]}
		//	,{[.]DT_REG1[5]}
		//	,{[.]DT_REG1[6]}
		//	,{[.]DT_REG1[7]}
		)
	),
	binenc( // Device DateTime Register 2 Byte 2, Hour (max 24)
		 {[.]DT_REG2[0]}
		,{[.]DT_REG2[1]}
		,{[.]DT_REG2[2]}
		,{[.]DT_REG2[3]}
		,{[.]DT_REG2[4]}
	//	,{[.]DT_REG2[5]}
	//	,{[.]DT_REG2[6]}
	//	,{[.]DT_REG2[7]}
	),
	binenc( // Device DateTime Register 3 Byte 1, Minute (max 59)
		 {[.]DT_REG3[8]}
		,{[.]DT_REG3[9]}
		,{[.]DT_REG3[10]}
		,{[.]DT_REG3[11]}
		,{[.]DT_REG3[12]}
		,{[.]DT_REG3[13]}
	//	,{[.]DT_REG3[14]}
	//	,{[.]DT_REG3[15]}
	),
	binenc( // Device DateTime Register 3 Byte 2, Second (max 59)
		 {[.]DT_REG3[0]}
		,{[.]DT_REG3[1]}
		,{[.]DT_REG3[2]}
		,{[.]DT_REG3[3]}
		,{[.]DT_REG3[4]}
		,{[.]DT_REG3[5]}
	//	,{[.]DT_REG3[6]}
	//	,{[.]DT_REG3[7]}
	)
)

I did enjoy that the array notation for accessing the bits of an integer worked, even when the source register was not actually a BooleanArray. Much nicer than using getBit().

Not by addressing, you'd need an expression tag for each byte.

I think the most straightforward approach would be to pull each of the 6 bytes into their own expression tags, then make another expression tag for the date. Maybe stick it all inside a UDT you never have to look at again if you have more of these devices.

But your one big expression is fine too as long as you'll be able to figure it out a year from now :slight_smile: