LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Passing data through a state machine

Solved!
Go to solution

Hello.

I am controlling the velocity of a treadmill based on the peak detection of a force signal. For the Etrip and Perturbation Assessment moves, I 'Init', 'Start' and 'GetData' from the force plates. I then move into velocity control for the treadmill belts. Once the treadmill is at the desired speed, I want to use the force plate data to initiate a change in treadmill velocity. How do I continue to acquire force data once I have moved past the 'GetData' state and use that data in a future state? 

Thank you.

Emily

0 Kudos
Message 1 of 4
(3,691 Views)
Solution
Accepted by topic author Miller37

Hi Emily.  It sounds like what you are trying to do is to repeat portions of the 'GetData' case (the part that actually gets the data...) while you are in either the Etrip or the Perturbation Assessment sequences; is that correct?

 

If that is so, then it looks like you might have to move the 'Select Move' case (I will call that case 'SM') that is within 'GetData' to its own case and then add a 'calling chain' shift register variable that will tell the 'GetData' case to next go to 1) 'SM' if it was called as it is now, 2) 'Etrip' if it was called from the Etrip sequence or 3) 'Perturbation Assessment' if it was called from that sequence.  Then add the 'GetData' case into the Etrip or Pert. Assess. sequences where required.  Probably much more difficult to describe than it is to implement 😉

 

Another option would be to bundle the actual functions required to get data into a subvi that you can then drop where needed in the other sequences.

 

Hope that helps.

 

Matt

Message 2 of 4
(3,633 Views)
Solution
Accepted by topic author Miller37

Emily,

     Congratulations on using a State Machine design.  However, it is extremely difficult to "wrap my mind" around your code, largely because I only have my laptop here with a single screen, and it would take about 8 laptop screens to see your entire Block Diagram and begin to understand what you are trying to do.

 

     A wonderful trick to "hide the messy details" so you can "see the Forest for the Trees" is to use sub-VIs to do "one thing".  For example, you have States where you manipulate Profile Settings.  If you wrapped that code in a suitable sub-VI, you might find that each of your Perturb states can use the same sub-VI, but with different inputs, which would make looking at the various States easier to comprehend ("Oh, here you use X1 and X2 as inputs, and there it is Y1 and Y2 -- that makes sense!") as you don't have to "look at the details".  Plus a sub-VI takes up 32x32 pixels of BD space ...

 

     If you can encapulate Get Data into a sub-VI, you could place it in various States, wherever it is needed.

 

     You have a large amount of almost-the-same-name States, which makes understanding what you are doing difficult (of course, you know and understand it, but unless someone else reads the thorough documentation that you've written to describe this code, they'll have a great deal of trouble maintaining and/or modifying it).  "ETrip3bPart2" does not have much mnemonic meaning for me ...  See if you can "rationalize" this, maybe by having a ETrip State that does various things depending on input settings (which could be held in Shift Registers) so you go "smoothly" from 1 to 2 to 3 (and why 3b?).

 

     You might consider creating an Enum for the States.  When you wire an Enum to a Case Statement, you can "Create Case for Every Value" and all your States will show up.  Plus you don't have to worry about spelling (PertrubDecelerate, for example).  Of course, when you want to add a State, you need to edit your Enum (and things break, but it's easy to find the errors, fix them, and you're Good to Go).

 

     You've forgotten about Data Flow!  You have a bunch of disconnected (free-floating) assignments to the left of the State Machine that I assume you intend as initializations, to be run before the State Machine starts.  Because there is no Data Flow, there's no way to know that they will run first!  One way to serialize the initializations that use Value properties is to extend the Error Line to the input of the While Loop -- Data Flow requires that the Property Nodes "set the Error inputs" to the State Machine before it can run.  However, a more "logical" thing to do is to have a State called "Init Variables" and do it first!  [I've been known to have 2 or 3 Initialization States to prevent my State Machine from bloating past the boundaries of my laptop screen].

 

Bob Schor

Message 3 of 4
(3,630 Views)

All data that might be needed later should be kept in Shift registers, and in those cases/states where it's not changed you simply wire it through.

E.g. the two end loops - Rear Belts, just move the shift register to the While loop and it'll be cleaner code.

/Y

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

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 4 of 4
(3,620 Views)