10-05-2018 06:24 AM - edited 10-05-2018 06:26 AM
Recently I had a long thread about interfacing a external MCU based device that responds to the LV app.
Using a State machine architecture i have got what I wanted. But then I would not say its seamless ... some hiccups which cannot be diagnosed are still there. So just thought will get some more clarity into the way the Serial comm works :
I have the following two cases :
1. When I send a Query Byte like <S> , my external device parses the same and reacts to the "S" and sends in reply a small four byte message.
2. If the query byte is <F> then the device will need to send a large CSV file , with hundreds of records with each record terminated by a line feed.
Which is the best way to handle the bytes in the Input Buffer in teh above scenario ?
- Try to read a large value of bytes more than expected and depend on the New Line feed char to terminate the read ?
- Simply read the Input Buffer based on the BytesAtPort property node ?
- Is the small delay between sending the command and receiving the response required. I thought communication failures were less with that. But that may be just coincidence.
- How do you set the Loop delay ? I have noticed that if i choose the Fixed Byte method, then loop delay is not required as it strictly follows the external device sending rate. But with the BytesAtPort method I have to set the loop delay.
Would like to hear from experts on this .. I have enclosed a typical diagram to explain the process :
Solved! Go to Solution.
10-05-2018 06:53 AM - edited 10-05-2018 07:00 AM
This may be one of the rare instances where using Bytes at Port might make some sense.
My experience is that 99% of the time you shouldn't use it. The complication of having multiple linefeeds in a single response message is what complicates things in your scenario and will require you to do multiple reads.
Let me ask the question, does the CSV file ALWAYS end with a linefeed character? If so, what I'm about to propose should work.
1. Write your command.
2. In a while loop do a VISA read with a very large number of bytes, more bytes than the longest single line of a CSV file you ever expect to read.
3. Append your message to a string you keep in a shift register.
4. Read the number of bytes at port. If equal to zero, then end the while loop. You should also AND this with the error wire from the VISA Read.
I'm assuming here that when you do a VISA read and it stops at a line feed in the CSV file data, that there will already be at least one byte sitting in the buffer from the next line. That is what keeps the While Loop going.
10-05-2018 07:23 AM
Lets make separate SubVIs for each function,
1. Initialize
2. Write VISA command (Before sending command please do Flush IO buffer)
3. Delay (depends on your application)
4. Read VISA inside while loop with 10 ms delay.
Thanks,
Manikandan.
10-05-2018 08:51 AM - edited 10-05-2018 08:52 AM
I would tend to have a layer of subvi's for my instrument driver that help handle the difference between "normal" commands and "special" commands.
I'd have one for commands I write with no reply expected, one for commands I write with a "normal" (short, immediate) reply expected, and then I'd have special subvi's for very special cases like your command that returns a bulk of 100's of records. Each of these would write the designated command, and then have an idea how much / what kind of response its waiting for.
With many (probably most) devices and instruments I've dealt with, it's been pretty important not to queue up a new command until getting the *entire* reply to the previous command. Making this layer of subvi's helps make that happen naturally with dataflow.
-Kevin P
10-05-2018 09:11 AM
Do you have any ability to modify the code on the device at the other end?
If you do have, you could add another command which will tell you the number of records to expect.
The you can just loop N times waiting for LF terminated data until you are done.
10-05-2018 10:14 AM - edited 10-05-2018 10:16 AM
@deceased wrote:
Do you have any ability to modify the code on the device at the other end?
He can, but he doesn't know how.
This post is a continuation on his other post about the Arduino !
10-06-2018 01:47 AM
@RavensFan
Thanks ... yes i also agree that Bytes at Port often leads to issues when a variety of incoming byte stream scenarios are to be handled. I saw your method of using both which is differnt line of thinking. In my case I send a OK from the MCU when the last record is sent and hence I compare the incoimng stream and terminate. Works most of the time !! And few odd times the stream gets stuck
Anyway since yesterday I brought in another refinment to change the while loop timing dynamically- 200mS when receiving four byte response and 5 ms timing when receving a large stream of bytes. Trials are encouraging ... let me see if it helps to resolve the issue completely.
Attaching the ZIP of my whole project. This is beta version and will go thorugh a few iterations before close.
10-06-2018 01:51 AM
@Kevin
With many (probably most) devices and instruments I've dealt with, it's been pretty important not to queue up a new command until getting the *entire* reply to the previous command.
Yes a very important point. Thanks. Unless this kind of a software handshake protocol is implemented, wired things happen. Only for this the RS-232 has robust hardware implemented RTS / CTS pins. But we ( or atleast me ) seldom use these pins to keep the interface simple with a Tx / Rx / Gnd.
10-06-2018 01:57 AM
@deceased
I agree this is another method which is used in serial transfer protocols. But then right now i am sending an end marker like OK, to signal end of data. Works good.
My real issue is not the MCU end but the LV end. MCU when sending a serial byte stream is single focussed and does not do anything else. But on the other hand LV is under the control of a OS and which anyway does zillion things in parallel or on a time slice basis. Why we need Input and Output buffers. So all effort is to handle these buffers properly.
10-06-2018 02:00 AM
@nyc
Since i wrote the MCU code also, I CAN change that but WON'T. Better solutions have been suggested.