LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Improving serial communication efficiency

Hi guys,

 

A while back I asked a few questions on how to communicate properly with some syringe pumps we have connected, and I got a lot of help and have been talking with them just fine. However, as I try to scale up the complexity of the program, it seems to be slowing down, and I'm attributing this to the fact that I am writing this program in an inefficient manner. As a sidenote, I am communicating with the pumps via a USB to Serial port adapter (that appears as COM1) and not purely through a serial port.

 

I have attached a version of the VI as well as an example of the sub-VI's that I have called. In short, the motors are first initialized, and then a loop is performed until a stop button is pressed. Inside the loop, four commands (two to each pump) are sent each loop; one pair queries the motors for position, one pair queries if the motors are busy. There are also five sets of case structures. One corresponds to a manual write, where I would enter a command and press a button to write it. The other four case strucutres consist of two pairs of commands, a move and a stop command. All buttons on the front panel are set to "latch when released"; this was my first question that I asked here actually.

 

The program runs OK since there are no errors. But as I build this program up to include more and more commands on the "VISA/error row" the program seems to slow down and the loops take longer and longer to perform. For example, the program as shown below takes 1.119 seconds to loop. I feel like before, while I was adding functions one by one, it would loop faster. Note that the only delays I have in the system are before I write in the sub-VI's; here, the program should wait until the next 10ms multiple. The pump manufacturer states that commands should be sent with a 1ms delay between commands. I imagine the 9ms difference that I see here isn't impacting the slowness of the program as much my bad programming skills!

 

Any feedback on how I could increase the speed of the program would be great. I've tried to read up on some serial port communications, but I admit that some of it is way over my head. If I had to venture a guess, however, I would imagine that what is slowing it down is that I keep having to call VISA write/read/clear for each command. What I would guess is that there is a way to kind of "keep the communication line open" and then just send in X, read Y, then wait until you send another X, instead of going around and around in a loop...

 

Thanks in advance,

B

 

 

Edit: I should also note that the \r in the subVI has "'\' codes display" checked, and that the VISA read is automatically terminated by a line feed so it doesn't read all 20 bytes (and therefore might hang, since only 6 bytes are sent back for a "busy" command for example).

Download All
0 Kudos
Message 1 of 7
(3,407 Views)

It is hard to determine how fast your program should run from an image.

 

It looks like you have 11 subVIs. If each has a 10 ms Wait Until Next ms Multiple, then you have at least 110 ms.  It appears you are using the defalut baud setting of 9600.  That means about 1 ms per byte sent or received.  How many bytes are sent and received?

 

You should not need to clear each time.  If the pumps have sent another character before the clear happens, you will lose data.

 

Rather than just continuing to string things together, I prefer a state machine architecture and a single point of communication with the external device.  Have a parallel loop which does serial read and write. It passes messages to and from the other loop via queues.  All the interpretation and display of data as well as commands to the pumps are handled in the state machine loop.

 

Lynn

0 Kudos
Message 2 of 7
(3,394 Views)

The 10 ms delay in the sub-vi should be between the write and the read to give the unit time to respond.

 

 

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 3 of 7
(3,380 Views)

Hi Lynn,

I'll check out a state machine. Being new to programming I didn't really know what that was, but now that I've read about it, it seems to be what I wrote down at the very beginning on my notebook page!

B

0 Kudos
Message 4 of 7
(3,353 Views)

@Yamaeda wrote:

The 10 ms delay in the sub-vi should be between the write and the read to give the unit time to respond.


No, that's what the VISA timeout is for.

0 Kudos
Message 5 of 7
(3,348 Views)

Hi again,

 

I've been working on trying to make a state machine and I think I have come up with a ghetto verison of one... using the queue functions seem to greatly improve the speed of the program and communications with the pumps, which is great. I have included the main program VI file (no subVI's) here if people want to take a look at it in more detail. The subVIs are very simple; they basically consist of an input (what command do you want to send to the motor), a VISA write, a VISA read, and an output (such as a boolean for "is the pump busy" or a number for what the pump position is at). However, I am having a lot of problems when it comes to creating new loops with new queue functions.

 

It seems that if I move the location of the "preview queue" function anywhere from its current location (which was chosen totally arbitrarily when I wrote the program), the program will hang and not shut down when the stop button is pressed. [Depending on the location I put the preview queue function in, I either get a 1122 error OR the program just hangs.] My gut feeling is that this has to do with timing. I read earlier in another queue thread or website that the author preferred to use wait until the next ms multiple instead of the wait (ms) function. My program does seem to work fine with the wait until the next ms multiple (which is how it is uploaded here), except that I can't make a separate loop for the preview function, or even move it to another loop. For example, I thought a good place for it would be in the false case of the stop loop; "keep telling me what is at the front of the line except when the stop button is pressed because that should end the program". 

 

Ideally I want to have something that adds some commands to the queue, and the top loop (the one that the motor reads commands from) is just constantly pulling the first command off the line and sending that one, as long as the pump isn't busy. I was going to try to do this once I got comfortable with these queues, but the more I use them the more confused I am as to why they work when they work, and why they don't work when they don't work.

 

Anyone have some advice/criticism? Thanks in advance,

B

0 Kudos
Message 6 of 7
(3,322 Views)

B,

 

I suspect that your problem is related to timeouts.  The Dequeue and Preview Queue Element functions have timeout inputs which you have left unwired.  The default is -1 or wait indefinitely for the queue to have an element.  Any time the queue is empty (when Add to Q is False) these loops will be blocked.  The 1122 error occurs when the stop button has been pressed and the queue has been released in the bottom loop. The Stop locals are probably read within nanoseconds of the beginning of each iteration of the upper loops.  If they are False at those times, the loops will run one more iteration even if the Stop button is pressed a millisecond later.

 

The idea of a state machine is to have a system with multiple states.  Your three lower loops can all be one loop.  Create an enumerated control (commonly called enum) listing all the states and connect it to the case selector terminal (?).  You could have states for Flush, Add to Q, Stop, Check Status of Queue, Check Pump Status, and others.  The state is passed from one iteration to the next via a shift register. Look at the exmpales which come with LV.

 

Lynn

0 Kudos
Message 7 of 7
(3,293 Views)