LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Critique my loop to send a text file, line by line or en masse?

I need to read a text file containing a command script and send it, line by line, to the input function of a DLL, then read back the response from the output function of the same DLL. I wanted the option to send it one line at a time, for debugging purposes, or all at once, for speed (it might be 6,000+ lines). After reading many examples and not really understanding state machines very well, I arrived at the following solution:

  1. Initialize the Send, Pause, and Line Counter values.
  2. Read the text file into an array of strings.
  3. On Send, send string N to the DLL and read the response into an initialized array.
  4. Increment the line counter.
  5. If Pause is True, set Send to False.
  6. Otherwise, keep sending.

It works, but it seems inelegant, especially the initialization and incrementing. Should I have used some sort of auto-indexing? Or is it really not that bad?

 

PatternFileSnippet.png

Thanks!

0 Kudos
Message 1 of 16
(3,978 Views)

I just realized that my snippet is pretty useless without the DLL, so I removed the DLL calls and just passed the string from the file into the input buffer indicator and then straight through to the output buffer indicator. Then I added a short wait so that you can actually see it running:

 

SendFileSnippet.png

0 Kudos
Message 2 of 16
(3,950 Views)

My first advice is to learn how to use Shift Registers.  They will eliminate some of your local variables (line the Line Counter).

 

I would also only use 1 control for controlling the write/pause.  My advice is to get rid of the Send and just use the Pause.  If Pause is TRUE, do not write and increment.



There are only two ways to tell somebody thanks: Kudos and Marked Solutions
Unofficial Forum Rules and Guidelines
"Not that we are sufficient in ourselves to claim anything as coming from us, but our sufficiency is from God" - 2 Corinthians 3:5
Message 3 of 16
(3,925 Views)

Critiquing in general, I'd say that you need to learn dataflow basics.  From a cursory look at your block diagram, I'd say all of your sequence structures could be eliminated with a proper understanding of dataflow.  (And if proper use of local variables was observed.)

 

This will free up LabVIEW to execute nodes in the order it sees fit to execute them.  This is roughly analogous to letting the operating system decide which thread to run next instead of dictating the order yourself.

Bill
CLD
(Mid-Level minion.)
My support system ensures that I don't look totally incompetent.
Proud to say that I've progressed beyond knowing just enough to be dangerous. I now know enough to know that I have no clue about anything at all.
Humble author of the CLAD Nugget.
Message 4 of 16
(3,908 Views)

¡Hola! and thank you both for your suggestions.

 

Yes, the shift register in place of Line Counter local really cleans things up. For some odd reason I was confusing a shift register with an auto-indexing something-or-other, and I didn't realize I could control the incrementing with the Case. It looks slightly cleaner now:

 

SendFileSnippet2.png

(the False cases are both empty, except for a straight-through wiring of the shift register)

 

I could try to get rid of the remaining local variables and perhaps one of the buttons by using a latch (which would also get rid of the outer sequence), but I did want to retain the existing behavior, which enables:

  • Sending one line at a time, and/or
  • Sending the file all at once, either from the beginning or from a pause, and/or
  • Pausing in the middle of a mass-send.

If I get rid of Send and just pause or not-pause, I won't have fine control over sending one line at a time. But I'm all ears if you have a suggestion in this regard!

 

Could I use a classic For loop with an event-driven pause? That would eliminate the Line Counter and just auto-index through the string array, wouldn't it? I actually started out with a For loop, but couldn't figure out how to pause/resume it, which is why I switched to a While/Case structure. 

0 Kudos
Message 5 of 16
(3,892 Views)

Whoops! Minor error on that snippet. The While control should be Stop, not Run. I must have inadvertently clicked it while I was trying to align everything nicely. Corrected version, here:

 

SendFileSnippet2.png

 

 

0 Kudos
Message 6 of 16
(3,882 Views)

Here are some suggestions:

  • You don't need the Shift Register/Counter line at all -- use the "i" Index variable of the While Loop (which starts at 0 and increments by 1 each time through the loop).
  • If you rename/rethink the "Pause" button and make it a "Single/All" button (True if you want to send All the values, False if you want a Single value), then both controls will initialize (by default) to False, so you don't need to initialize them using Local Variables (unless you run the program, then re-run it without re-setting the Booleans).
  • I'd rename the Send button to "Run" (meaning "When I push this, Run the code").  Note that if you are doing one-at-a-time, you'll need some logic to latch (via a Shift Register) a Boolean so you only do the loop once until you either turn Run off or change Single to All.
  • With the above changes, you can delete all of the Sequence Frames, and let Data Flow do the sequencing for you.
  • The Stop button should end up being wired to the Stop (not the Continue) indicator.
  • Code like this seems (to me) to beg for a Queued State Machine, with the Queue being driven by an Event Loop that handles the three buttons (oh, yes, I forgot -- I named the "stop" button "Abort", as you use it to end the program, "aborting" it, before it finishes).  This would allow you to eliminate the "busy-wait" 1 ms delay in your loop.

Bob Schor

Message 7 of 16
(3,879 Views)

But doesn't the While loop run continuously, regardless of the buttons' states? That would cause my index/line counter to increment even when I'm not sending. Or is there a way to control that, as well?

0 Kudos
Message 8 of 16
(3,875 Views)

@Bob_Schor wrote:

Here are some suggestions:

  • ...
  • Code like this seems (to me) to beg for a Queued State Machine, with the Queue being driven by an Event Loop that handles the three buttons (oh, yes, I forgot -- I named the "stop" button "Abort", as you use it to end the program, "aborting" it, before it finishes).  This would allow you to eliminate the "busy-wait" 1 ms delay in your loop.

Bob Schor


Queued Message Handler.

 

The QMH does what it is asked, the QSM does whatever the stack has decided and may not be possible to define at development time.Smiley Wink

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 9 of 16
(3,860 Views)

Listen to Ben (rather than to me).

 

BS

Message 10 of 16
(3,848 Views)