One way to clean up code is to use SubVIs. You can learn more information about SubVIs here: http://www.ni.com/white-paper/7593/en . Hope this helps!
That is a lot cleaner and easier to read! We can find out what is going on! You DO have multiple race conditions. LabVIEW is not like text based languages. Search on the term Dataflow and you'll get more information but basically any section of code can start running as soon as all of its inputs are available. In your code this section.
needs to run before any of the other loops start. But because there is no data dependancy all of your loops start and may be running and reading from FP terminals or Locals before this case executes and writes the desired initial values. ( The very Definition of a race condition)
Locals are notorious for causing rae conditions because they break dataflow.
Place a boolean constant in each case and wire it to a output tunnel. Wire that output to each of your other loops. This will force LabVIEW to finish the initialization before the rest of the program executes.
It's almost impossible to follow what's going on in your code because the block diagram is so large. Good practice is for the entire VI to fit on one screen, and if that's not possible, to have some logical flow (for example lots of property nodes can result in a very wide block diagram, but it can still be easy to follow if it only scrolls from left to right). Also, as previously mentioned local variables are not a good way to communicate between loops. Queues and notifiers, and action engines, are better. You may be able to combine multiple functions into the same loop - items inside a loop can run in parallel too, they don't need to be in separate loops. Several of the cases where you read or write to property nodes constantly would be better as events, because they do not need to be updated constantly. For example you have a case structure in the top loop where the selector is a local variable of "Offset Control - Top/Bottom Master" and it only writes to a property node. Instead, make a value change event for that control and set the property node there.
OK, so thanks to all the comments.
I've tried to take most of these things on, I knew it was getting too ungainly. I've made a bunch of nice subVis that take care of a lot of the loops that were going on. I've changed a lot more to events, and I think I've managed to get most of the race conditions gone. It looks like one is still hanging around however.
When I open up the MainVI for the first time and run it, it still does not initialize the main plate cluster info array and the start/stop button array. If I stop the VI and restart it, it will be good, but the first run every time causes a problem. I've tried running it in step mode to see what happens, but when I do, it works. I'm wondering if it's some kind of empty array being sent into a for loop, but I do'nt have anything else to go on.
Again, any ideas would be appreciated, I think I'm almost set here, its just one little bug.
Which array is causing you problems? The array in the right panel - the "Plate Info Cluster Array" - or some other item? If it's that array, I would put a breakpoint and a probe just before you write to that indicator inside the timed loop. Maybe the initialization works properly but is being immediately overwritten by an empty array in that loop. I would use a local variable instead of a property node for the initialization, and I would use the same value to initialize the shift register as you use to initialize the local variable to make sure there's no mismatch.
There are still way too many local variables and the block diagram is still huge. You really want to think about how to structure the tasks so that they can be grouped into logical subVIs that do not require front panel objects for communication.
The loop that is doing nothing other than checking the tab page should also be handled as an event.
Buttons such as the "Save" button in the settings tab should be set to the mechanical action of "Latch Until Released" and handled with a "Value Change" event instead of Mouse Up. The way you have it now you can get odd results. For example, try clicking somewhere outside that button, hold down the mouse button, move over that button, and release it. The event will trigger, and that's probably not what you want.
You're definitely making progress, and it's not easy to get the structure of an application right without trying several times.
OK, looks like I found it. I had an empty array going into a for loop and indexing through it, but it obviously didn't index anything.
Thanks to all who helped.