T7 streaming by modbus tcp (low level) | LabJack
 

T7 streaming by modbus tcp (low level)

12 posts / 0 new
Last post
ShiraD
ShiraD's picture
T7 streaming by modbus tcp (low level)

Hi,

I have urgent question. I'll happy recieve quick answer.

I'm using T7 to get stream data  from one channel - AIN0, over ethernet, in low level streaming (modbus - tcp). (In my embedded project i can't use LJM library) .

I took example test from link :

https://labjack.com/support/software/examples/modbus/c

and i changed these parameters only: scanRate to 8000,  bufferSizeBytes to 32768, and numScans to 0 (run cotinuously). That's all.

When i tested it, i recieve data correctly from labjack T7 until something happened. After a few minutes of runnig, suddenly i got :

Unexpected read response size: Response = 420, Expected = 1040
PACKET (420): 10 DE 00 01 04 0A 00 4C 10 00 00 02 00 00 00 00 9F C3 9F 28 A0 F2 A1 7B A1 A0 A1 8E A0 DD A3 65 A3 1C A3 A9 A2 FD A1 62 A1 B3 A0 8E 9F F0 A0 57 9F CF 9F A1 9E BB 9F A8 9F A4 9F 6D 9E E5 A1 27 A1 2A A1 81 A1 3F 9F CB 9F E2 9F DB 9F 02 9E A8 9E FF 9F 08 9F 43 9F 6C 9F 78 9F C4 9E 86 A1 1A A0 B4 A1 15 A1 E2 A0 16 A0 6D A0 3B 9F E8 A0 AB A0 FC A0 9D A0 25 A0 96 A0 53 A0 BE A1 2B A3 33 A3 7D A3 9B A3 98 A2 0A A2 19 A1 80 A1 C1 A1 7E A1 C2 A1 08 A0 2C 9F E7 9F 9F A0 3D A0 23 A1 DD A2 46 A2 29 A0 9A A0 97 A0 4D A0 DB A0 44 A0 53 9F B5 A0 46 9F B1 9F ED A0 08 9F 4D 9F D5 A1 A1 A1 66 A2 0C A1 77 9F 6D 9F 33 9F 5C 9F 8F A0 4B 9F C0 9F DA 9F 7E 9F A0 A0 83 A0 67 A0 83 A2 43 A2 30 A2 64 A1 43 A0 41 9F A1 A0 9C 9F B7 9F D5 9F C2 9F 6A 9F EA A0 81 A0 18 A0 C1 A0 7C A2 68 A3 0E A2 76 A2 00 A1 39 A0 83 A0 55 A0 40 9F FD A0 27 9F 68 9F 65 A0 5D 9F C7 A0 E5 A0 35 A2 05 A1 82 A2 89 A1 8D A1 6A A0 6E 9F D1 A0 5A A0 63 A0 28 A1 28 A0 4F A0 05 A0 0E A0 39 9F 74 A1 59 A1 73 A2 10 A2 3A A0 1B 9F EF 9F 56 A0 17 A0 13 9F BD 9F 21 9F 8A 9F A0 9F 69 A0 8D A0 91 A2 36 A2 39 A1 66 A0 DD 9F 9B 9E F6 9E F0 9D B9 9F 68 9F 79 9F 7D 9F DA 9F C3 9F 94 9F BF 9F 91 A2 45 A1 AB A1 A4 A1 CB 9F F6 9F 29 9F FB A0 19 A0 2B 9F A7 A0 0E 9F B1 9E F5 9F C3 9F EE A0 DD A1 71 A1 E5 A2 14


parseReadMultRegsRes error: Packet size (420) is    not    too    small Modbus length (1034 + 6).
PACKET (420): 10 DE 00 01 04 0A 00 4C 10 00 00 02 00 00 00 00 9F C3 9F 28 A0 F2 A1 7B A1 A0 A1 8E A0 DD A3 65 A3 1C A3 A9 A2 FD A1 62 A1 B3 A0 8E 9F F0 A0 57 9F CF 9F A1 9E BB 9F A8 9F A4 9F 6D 9E E5 A1 27 A1 2A A1 81 A1 3F 9F CB 9F E2 9F DB 9F 02 9E A8 9E FF 9F 08 9F 43 9F 6C 9F 78 9F C4 9E 86 A1 1A A0 B4 A1 15 A1 E2 A0 16 A0 6D A0 3B 9F E8 A0 AB A0 FC A0 9D A0 25 A0 96 A0 53 A0 BE A1 2B A3 33 A3 7D A3 9B A3 98 A2 0A A2 19 A1 80 A1 C1 A1 7E A1 C2 A1 08 A0 2C 9F E7 9F 9F A0 3D A0 23 A1 DD A2 46 A2 29 A0 9A A0 97 A0 4D A0 DB A0 44 A0 53 9F B5 A0 46 9F B1 9F ED A0 08 9F 4D 9F D5 A1 A1 A1 66 A2 0C A1 77 9F 6D 9F 33 9F 5C 9F 8F A0 4B 9F C0 9F DA 9F 7E 9F A0 A0 83 A0 67 A0 83 A2 43 A2 30 A2 64 A1 43 A0 41 9F A1 A0 9C 9F B7 9F D5 9F C2 9F 6A 9F EA A0 81 A0 18 A0 C1 A0 7C A2 68 A3 0E A2 76 A2 00 A1 39 A0 83 A0 55 A0 40 9F FD A0 27 9F 68 9F 65 A0 5D 9F C7 A0 E5 A0 35 A2 05 A1 82 A2 89 A1 8D A1 6A A0 6E 9F D1 A0 5A A0 63 A0 28 A1 28 A0 4F A0 05 A0 0E A0 39 9F 74 A1 59 A1 73 A2 10 A2 3A A0 1B 9F EF 9F 56 A0 17 A0 13 9F BD 9F 21 9F 8A 9F A0 9F 69 A0 8D A0 91 A2 36 A2 39 A1 66 A0 DD 9F 9B 9E F6 9E F0 9D B9 9F 68 9F 79 9F 7D 9F DA 9F C3 9F 94 9F BF 9F 91 A2 45 A1 AB A1 A4 A1 CB 9F F6 9F 29 9F FB A0 19 A0 2B 9F A7 A0 0E 9F B1 9E F5 9F C3 9F EE A0 DD A1 71 A1 E5 A2 14

And the test stopped. Why this happened?

Full thanks in advance.

Shira

LabJack Support
labjack support's picture
1. Since the Modbus header

1. Since the Modbus header claims the packet length is 0x04 0A (1034), it seems like you need to read from the socket again, for the length of 1040 - 420 = 620. Have you tried that yet?

2. What platform are you seeing this error on? Can you replicate it on a non-embedded platform?

ShiraD
ShiraD's picture
What do you mean? How do that

What do you mean? How do that? Can you detail more info for your first suggestion please?

Now i am testing this on linux- ubuntu 16.04 platform(non embedded platform), but i will enter this code to my embedded system later.  

This test that i gave its link above, work well if  i left those parameters without touch them: scanRate 1000,  bufferSizeBytes 0(default), and numScans 5120.(As is) But even if i change only numScans parameter to 0, or to milion, then same error occur.

Maybe i have to define another settings if i want to run this continuously?

Thanks a lot.

LabJack Support
labjack support's picture
I haven't been able to

I haven't been able to reproduce this yet, but here's some suggestsions.

1. For my first suggestion, you can try reading from the socket again in a loop until you've read as many bytes as you expected. For example, you could change the part of spontaneousStreamRead that does readTCP:


    size = readTCP(sock, res, resSize);
    if(size <= 0)
    {
        ret = -1;
        goto end;
    }

...to contain a read loop like this:


    int readBytes = 0;
    while(resSize - readBytes > 0)
    {
        size = readTCP(sock, res + readBytes, resSize - readBytes);
        if(size <= 0)
        {
            ret = -1;
            goto end;
        }
        readBytes += size;
    }

You could change readTCP to do the loop instead.

TCP is a stream-based protocol instead of a message-based protocol, so even if the T7 sends a 1040 "packet", it can still arrive at the host in pieces. This could be due to the way a network switch deals with TCP, for example.

2. You can try reading only 420 bytes every time instead of the full 1040 bytes. To do so change:

samplesPerPacket = STREAM_MAX_SAMPLES_PER_PACKET_TCP;

...to:

samplesPerPacket = 202;

and see if that works for the 420 packet size.

3. Please ensure your T7 is using the most recent firmware. You can use Kipling to do so.

ShiraD
ShiraD's picture
Hi,

Hi,

First of all, many thanks. Your answer was very helpful for me.

I used your first suggestion (changing readTCP call to be in loop). It's improved significant. Now the test can be running during half hour. very nice.

But yet, sometimes the test stopping in 'readTCP' call,  when 'recv' function  return with ret = -1. Here this occur :

int    readTCP(TCP_SOCKET sock, unsigned char *packet,    int    size)
{
    int ret = 0;
    ret = recv(sock, (char *)packet, size, 0);
    if(ret != size)

....

I printed variables when this occur and the value return from function:

    while(resSize - readBytes > 0)
    {
        size = readTCP(sock, res + readBytes, resSize - readBytes);
        if(size <= 0)
        {
            ret = -1;
            printf("\nFailed in 286 line size: %d resSize: %d readBytes: %d\n",size,resSize,readBytes);
            goto end;
        }
        readBytes += size;
    }

 

And this is the result:

Failed in 286 line size:-1 resSize: 1040 readBytes: 0

That's mean, that already first time it doesnt read succesfully!

What do you think on this behavior?

My firmware version is 1.0242

Thanks again..

LabJack Support
labjack support's picture
What does errno indicate? 

What does errno indicate? (Run man recv to see more details.)

ShiraD
ShiraD's picture
I printed the error

I printed the error description:

    while(resSize - readBytes > 0)
    {
        size = readTCP(sock, res + readBytes, resSize - readBytes);
        if(size <= 0)
        {
            ret = -1;

n 286 line size: %d resSize: %d readBytes: %d\n",size,resSize,readBytes);
            printf("Error description: %s\n",strerror(errno));
            goto end;
        }
        readBytes += size;
    }

The results:

Resource temporarly unavailable

It took me bit time to reproduce this.

Its seem that labjack T7 device sometimes not avialable. What can be the reason?

What can i do in this case?

LabJack Support
labjack support's picture
From https://www.systutorials

From https://www.systutorials.com/docs/linux/man/2-recv/ , EAGAIN indicates:

a receive timeout had been set and the timeout expired before data was received.

So you can either retry or set the timeout value to be larger.

Edit: fixed link.

ShiraD
ShiraD's picture
Hi,

Hi,

Thanks about your help.

Now i have  another question:

I read data using stream(low level), scan read = 8000, scan per packet = 512, one channel[AIN0] continusuly. I increased buffer size to maximum.

I get data correctly, but sometimes i get dummy samples because 'stream auto recovery active' happened.

Its not good for me, i canot let for me to lose this data... i try to prevent as soon as possible this case.

I found this section in your documentation:

If the device buffer overflows, the device will continue streaming but will discard data until the buffer is emptied, after which data will be stored in the buffer again. The device keeps track of how many scans are discarded and reports that value. Based on the number of scans discarded, the LJM library adds the proper number of dummy samples (with the value -9999.0) such that the correct timing is maintained. This will only work if the first channel in the scan is an analog channel.

Ok, but there is a way to prevent this?  

 

LabJack Support
labjack support's picture
To prevent stream buffer

To prevent stream buffer overflows which causes auto-recovery and the dummy samples, the application needs to read data from the T7 at a fast enough rate to keep up with the scan rate. The stream read loop in your case needs to keep up with the 8000 Hz scan rate. If your stream read loop has code with enough overhead to prevent it from keeping up with the stream read loop, remove code (such as sleep) causing the delay, or consider using a thread dedicated to streaming only and another thread for stream data processing (logging to file, charting, etc.).

In the Modbus Feedback stream response, bytes 10-11 are the Backlog bytes indicating how many bytes are in the device stream buffer. If this is constantly increasing, that will indicate the stream data is not being read fast enough and a buffer overflow will eventually occur.

ShiraD
ShiraD's picture
Thank on your reply.

Thank on your reply.

Now i running test continuesly, with same settings: scan read = 8000,  scan per packet = 512, one channel-AIN0. maximum buffer size .

Eech time that i reading the first from 8000, i print time-stamp to log file.

After some time(30 sec- 5min), i look in log file, and i expect to see timestamp in frequency one in second. But instead of, i see that sometime the timestamp too late(2 sec instead of 1sec) for example: 04:45:05.879,  04:45:06.879, 04:45:08.80004:45:08.90004:45:09.892 

and the next timestamps catching the rhythm.

Why this happend? how to fix it? i must have get data exactly once in second.

LabJack Support
labjack support's picture
A couple of questions:

A couple of questions:

  1. If you time your stream read call or recv, does it sometimes take longer than one second? Where does the delay come from? You can add timing calls to specific spots in your loop. E.g. read the clock once per loop and calculate how long the whole loop took; then add other clock reads to see how long specific function calls took.
  2. How is your program sleeping? Is it interval-based (does it account for how long reading from stream took) or delay-based (does it always sleep a set length of time)? See my note on interval timing below.
  3. What is happening to the device scan backlog?
  4. Can you read smaller amounts of data more often? Since 8000 samples per second / 512 samples per packet = 15.625 packets per second, you should be able to read 512 samples 15.625 times per second (as opposed to 8000 samples once per second)

Interval timing note:

An interval timing system tries to execute a task once per a given time period, regardless of how long the task takes to complete. As described on the LJM_StartInterval page:

In many applications an interval timer is preferable to using a normal delay (sleep), as it is difficult to get an exact interval using a delay.  For example, say a loop makes an I/O call that takes 5 to 15 milliseconds (ms) each time, and this is followed by a 90 ms delay.  The loop will take 95 to 105 ms per iteration, and the average time per iteration over time could be anywhere in that range.  Using interval timers avoids this problem because the loop will always take the specified number of milliseconds (or else LJM_WaitForNextInterval will notify you of skipped intervals).

Assuming you have an interval timer, the task may take longer than the interval length. For your case, that means that perhaps the stream read call may be taking 2 seconds. One reason reading from stream could take a larger-than-normal amount of time is because of real-world network latency.