Decode floats using unpack (for Modbus)

Hi,

I’m trying to pull floats from a ModbusTCP readHoldingRegisters() poll and fairly new to Lua.

This is the poll that is sent to the LS300 (I’ve removed the 6 bytes TCP header): 01,10,00,00,00,0A,28,3F,80,00,00,40,00,00,00,40,40,00,00,40,80,00,00,40,A0,00,00

10 holding registers, 20 bytes.

E.g. the 4 byte sequence 3F,80,00,00 is a 32 bit float representing 1.0. The above poll is for 5 registers with values 1 through to 40,A0,00,00 that represents 5.0.

I can traverse the bytes in the string that contains the above data but I’m struggling to decode these into floats.

e.g.

reg@0
b1:3f b2:80 b3:00 b4:00

I thought something like this would work but as of yet I’ve had no success:

local _,mystring,myfloat = string.unpack(str_value, “>f10”)

I can’t even get anything meaningful from the example in the docs:

local bindata = string.pack("zf", "foo", 4.2)
	local mystring,myfloat = string.unpack(bindata, "zf")
	print("f:"..myfloat.." s:"..mystring)

this prints : “f:foo s:9” when I was expecting 4.2 to be displayed. If I dump bindata to a file I can see the x40866666 bytes present, along with “foo” and some null endings.

Can anybody give me some pointers / simple working examples of pack/unpack.

Thanks,
Steve

Hi Steve,

In deed, it looks like the top level example for pack module is not correct, whereas unpack function usage is good.
The correct coding/decoding example should be:

require"pack"
local bindata = string.pack("zf", "foo", 4.2)
local _, mystring, myfloat = string.unpack(bindata, "zf")

Note the “": the first argument returned by unpack is the next unread position in the string to decode. it used when doing incremental decoding.
The decoded values come afterwards.
(Using "
” char as a variable name is something that is done, time to times, to indicate the variable is not useful in current code section.)

Let me know if this solves your decoding issues.
I’ll notify the doc issue to the appropriate contact.

Regards,

Laurent

Hi Laurent,

That fixed the example code. Many thanks.

Can you suggest what format I should use to decode a IEEE754 encoded 32 bit number, i.e.

3F,80,00,00 decoded to 1.0

I maybe able to decode all 5 floats from 3F,80,00,00,40,00,00,00,40,40,00,00,40,80,00,00,40,A0,00,00 with one unpack command, but the formatting specifier has so far eluded me.

Regards,
Steve

Hi Steve,

I think you can try:

local read_pos, f1, f2, f3, f4, f5 = string.unpack(bindata, ">f5")

Let me know if it works for you.

Regards,

Hi,

Thank you that helped. In addition not realising you could return several values into several variables my words needed to be swapped in my register buffer.

Regards,
Steve