Returned Data Format Confusion


RJE

Recommended Posts

I have managed to create a serial device for my Ocelot Controller and send it a command in the Monitor Window and get data back. So far so good.

I then created a test sequence for the polling. So far so good, I think.

From my serial port monitor program, I see the Tx command sent requesting a block of data from the Ocelot

2A 00 00 91 AA 00 00 A6

The data block returned is:

2A 00 00 91 AA 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 FF FF

00 00 48 00 FF 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 48 00 68 00 8F 00 26 00 AF 00

C9 00 0F 1A 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

00 00 00 00 00 00 66 63

This data is correct, the data of interest (for this test) starts at 48, 00, 68 ..1A. 48 & 00 represents the 2 byte values for the internal variable #80, LSB first then the MSB. Converting the hex values to decimal matches the values in the Ocelot.

When I view the data in DAQFactory's monitor window I get this:

Tx: *\x00\x00\x91\xAA\x00\x00\xA6

Rx: *\x00\x00\x91\xAA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\x00\x00G\x00\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00G\x00i\x00\x90\x00$\x00\xB5\x00\xC9\x00\x10\x1A\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xB1=

From here I'm a little lost due to the different data results to carry on. The next step would be to parse out the data such as 48 00, swap the bytes around, convert to decimal, put in a channel and do a conversion on the number to get the result, in this case it is temperature value.

My sequence is:

Private string DataIn

if (!Device.Ocelot.Lock())
   throw("Port in use!")
   return
endif

Device.Ocelot.purge()

try
   Device.Ocelot.Write(Chr(42) + chr(0) + chr(0) + chr(145) + chr(170) + chr(0) + chr(0) + chr(166))
   DataIn = Device.Ocelot.Read(0)

   Device.Ocelot.Unlock()
catch()
   Device.Ocelot.Unlock()
   throw()
endcatch

Where am I going wrong with this?

Thanks

Randy

Link to comment
Share on other sites

First, to clarify, the DF monitor shows slightly different data because you don't have "display all chars as ASCII codes" checked. Without it checked, DF assumes you have ASCII data, not binary, and so whenever a byte is between 32 and 127, it displays the character. That's why you get a * instead of \x2A. Next, in your sequence, I don't think you want read(0), but rather read(x) where x is the number of bytes returned in your data block. I believe your data is fixed length fields.

Finally, note that you can do:

chr(0x2a)

instead of

chr(42)

if you don't want to convert all the hex in your device docs to decimal.

Likewise, if you are generating a long binary string, its usually user to use the ChrA() function. For example, to output:

2A 00 00 91 AA 00 00 A6

you'd do:

Device.Ocelet.Write(chra({0x2a,0,0,0x91,0xaa,0,0,0xa6}))

Link to comment
Share on other sites

Another full day but making some head way. I hate to pester for help and I do read the manuals but sometimes they just leave you hanging for more help. Probably like my manuals for the control systems I create at work.

So far I have created a serial device called "ocelot" and wriiten a sequence that sends a command for data and I Rx back 263 bytes (fixed length) of data from "ocelot". From there I can pick the 2 bytes of interest, lets say 021(lsb) & 034(msb), flip them around and have them print to the command/alert window as the real number, 3421.

This is where I'm confused, how do I deal with this block of data and put it into channels for DAQFactory to log and display? Do I have to create another device with channels and then do the Local.Channel.AddValue function?

Right now, in that block of data, there are only 7 pairs of lsb & msb bytes that need to be logged but this could increase if I add more sensors to the Ocleot system.

Thanks again.

Link to comment
Share on other sites

Your not being a pain, and its pretty much impossible to write documentation that covers a program as flexible as DAQFactory in a reasonable amount of pages (its already some 440 pages), so this forum is a great place to post questions and to find answers to things that might not be perfectly clear.

Like most things in DF there are several ways to do this. The easiest is to create channels with device type "Test", I/O type "A to D" and Timing of 0, then use channelname.addvalue() to stick the data into the channel. You can see samples of this in the modbus section of the help. But first you need to get your two values into one. You can't just line them up because they are in hex, not decimal (or at least the full value is in hex). What you want is msb * 256 + lsb, or you can just use the To.uWord() function. So, something like:

datain = device.octalet.read(263)

mychannel.addvalue(to.uword(asca(mid(datain,10,2))))

mysecondchannel.addvalue(to.uword(asca(mid(datain,12,2))))

...etc

remember, datain is a string of hex values. If you print it, it shows as ascii, but really its just a string of bytes. We do mid() to pull out the appropriate two values (I don't know what they are, I just used 10 and 11 for the first, and 12 and 13 for the second). Then we do asca() on this, which breaks the single string of bytes (a string data type in DF) into an array of bytes. The to.uword() takes an array of bytes and assembles them into a single word (16 bit) value. It assumes little endian, which means LSB first. If you are big endian, then you want to.urword(). Finally, we do addvalue() on the result for the desired channel that we created.

Link to comment
Share on other sites

Thanks Member #63.

Know what you mean on the manual end of things.

I was on the right track, and the Modbus examples helped. I'm now polling the Ocelot, getting data back, parsing it, putting it into channels and logging/graphing it. Sweet!

Now, from the manual, I have to do conversions in the script because the conversion funtions don't work when you do addvalue to a channel?

Thanks

Member # 4150

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.