I’m getting really frustrated trying to modify the default code. I have no interest in using a pre made 2 wheel drive code block; I want to control motors individualy. Do I really have to add a motordevref block to the robotdata control for every motor I want to control? I’m thinking there has to be a way to create a bundle without specifying default values, but I cannot figure it out. I have labview with the first update installed, is the current code template necessarily the last one?
It’s funny - my first year with the team (their second year) was the first year we really got into the coding. I kept saying the same thing about the ifi code. “Boy, this is a silly way to do it.” “Boy, that makes no sense!”
By the second year though, we had figured out why they did things the way they did. We were also able to reuse and improve modules we had written the year before.
Now, I find myself and our team members going through the same learning process all over again. I’m reasonably sure that while I’m saying “why the heck do I have to do THAT” right now, in a year or two once I’ve figured it out it will all make far more sense… and I won’t “hate” it quite so much.
I agree with Tom. At first, code doesn’t always make sense, but as you work with it you begin to delve into it more and it becomes more understandable.
Also, if you want a different approach to code, there’s always C++. Once you get past the initial syntax barrier, it’s not as hard as you would think. There’s great tutorials like www.leancpp.com and the default code is fairly easy to understand.
In the Advanced framework, yes you do have to add a motordevref to the RobotData cluster for every motor you want to control. This is by design so you can initialize it in the Begin.vi, use it in the various other VIs, and close it in the Finish.vi. Adding the controls to the cluster isn’t too complicated, though. Especially once they’re already there anyways. If you really can’t be bothered, you can add an array of motordevrefs and initialize that array and keep track of where you’ve put each motor ref, instead of using the nice labels in the cluster. In any case, you shouldn’t need to set up default values for any of the data elements you add to the RobotData cluster. Leave them all at their default values, then initialize them in Begin.vi. Creating devref constants or otherwise avoiding calling ??? Open.vi for things can muck things up by not properly reserving resources.
That said, if you’re having difficulties with the Advanced template, try switching to the Basic template. More or less everything is in the same VI, so there’s no RobotData cluster to configure and carry around.
I agree that the default drive base doesn’t work for any of our robots. Three independantly steered wheels require independant control of speed and direction. The default code is only useful as an example of what we need. Our students just finished recreating the Labview code in the release framework this evening and this is what they came up with.
In the Begin .vi they replaced the robotbase open with a PWM open for each motor (8 in all). They also opened the joysticks, analog inputs, etc. Then they bundled all the DevRefs and passed them through to the mode case statement in RobotMain. It sure makes a big mess in the TypeDefs panel and all the front panels but it looks like the only way.
Then they unbundled the DefRefs in the Teleop .vi and inserted all the steering code before setting the speed of each motor. This is their second attempt to control the entire robot and it is beginning to make sense enough to be able to understand the layout even though teleop is over two screens high.
I hope to post the code soon but they took it with them tonight to clean up. If you are interested I’ll try to clarify some of this when I see the code again.
The short answer is there is no shortcut. I was able to write the equivelant code in the C++ iterative example a lot faster but it isn’t as impressive and the kids really get more excited seeing the Labview code work. I still relate to assembly language better than object oriented languages.
If you open up the pre made 2 wheel drive subVI, it creates two motor dev refs and builds an array from them. You can follow this lead and have a single array entry in the robotdata which holds all of your motor refs. The slight downside to using an array is remembering what slot in the array is for what motor. There are plenty of ways for handling that, or you could build a cluster – similar to a struct or record in other languages – and there you can give the elements of the cluster descriptive names. The default value as the controls are dropped should be fine as their value will really be defined by the Open. All LV controls except refnums support a default value, and it is quite useful, but not always necessary.
Greg McKaskle
Yup, arrays are the way to go. Create an array in begin.vi with all your motordevrefs wired into it, right click on the output terminal, and create a constant. Copy paste the constant into the robotdata global type def. The array can be grown and shrunk in begin.vi by creating more inputs on the build array block, and the constant won’t need to be changed and won’t take up three screens worth of space when you use all 20 pwm ports.
Why isn’t there a way to create clusters like this? I keep wishing for a build cluster block that simply builds a cluster with n number of named elements from n number of inputs, instead of one that replaces elements in a constant.
Good question. I suppose one reason is that when you look at a cluster of identical elements, and an array of the same elements, they are very similar, and can in fact be converted back and forth pretty easily.
I’m not sure if it is done in the dashboard, but it is pretty common to take an array datatype, cast to a cluster of say eight elements, and display in a cluster arranged in an octagon or something. The math on the diagram can now work on the array, often more easily than the cluster, but the user sees the discrete elements arranged in a meaningful way. If you decide to do this, beware that the LV node to convert from array to cluster has no way of knowing how many elements may be in the array or how big to make the cluster, so there is a popup menu item for setting the size of the cluster.
Also, rereading your question, maybe you are looking for the old fashioned bundle node rather then the newer bundle by name. The bundle does work like the build array, you grow it and wire stuff up. It has a middle terminal in case you are simply replacing elements, but doesn’t require it as the bundle by name does. The advantages to the named node are that it is more verbose and somewhat more documented code, and when the cluster changes, it does a better job of using the names to match up the elements. The replace mode of the bundle only works well when adding to the end of your cluster type.
Greg McKaskle
Uh, is it a problem that I’ve been using the basic framework all along? I saw it as an option, but when I started, I used the basic framework and never tried the advanced. Guess I better take a look at it.
It’s funny. I actually find the “advanced” template easier to understand, because all the stuff isn’t crammed on one page. The use of sub-vis heps to compartmentalize my understanding of the process.
However, back to SparrowKC’s original question…
I think everyone is missing the easy way to do this.
How many wheel’s you got? 4 probably… so start out by changing the “Open 2 Wheels” VI to “Open 4 wheels”.
You can do this simply by right clicking on the VI and selecting “Replace”.
Go ahead and specify the other 2 PWM channels and wheel directions.
OK, now your device reference cluster holds references for 4 wheels.
You want to roll your own drive code… no problem. Just don’t use the standard Drive VIs.
You can access the refs in the cluster and do your own motor control… how?
Just look inside the canned drive VI’s (eg: Drive:ArcadeDrive) by double clicking them, and pulling up the Block Diagrams.
There’s lots of flexibility built into them, so you may have to go a couple of levels deep to see the basic wheel control code, but a really good sample is found in RobotDrive:Motors.vi
Basically you use Drive:GetPwmRef, and then pass the ref to Motor:SetSpeed.
Now you have total freedom to roll your own code, with very little hacking of existing globals.
I took a look at the advanced template, your absolutely right. Much better layout.
As to the topic at hand, you just gotta experiment and try stuff. If what PhilBot suggested does not work for you, then you’re gonna have to have a motor ref for every motor in the global vi. I think you can put them in a cluster like the robot data so it’s all in one package, then unbundle by name the different motors when you need them.
Characterizing the two templates, the advanced template was actually developed first. If your team is interested in writing very much code, I think this is a better place to begin.
Based upon feedback from the beta, we then built the basic template with an eye towards eliminating SW concepts and getting results in the shortest amount of time. This resulted in code that is a bit flat and will be harder to maintain throughout a season, but it seems to fit the bill.
There are many possible variations, and I expect that many teams will develop their own framework. I hope they are shared, and I hope to incorporate the good ideas into the templates in coming years.
Greg McKaskle
If your code is expanding past a reasonable screen size, then you probably need to start creating your own sub-vi’s.
Look at your code and see where you have duplicated code that just varies by a specific parameter (eg a pair of motor drives).
Take that code, select the common parts and then use EDIT/Create SubVI.
The code will cet condensed out into a sepparate file and all the wires that passed into the selected area will become connections on the new VI. Double click it and you will see the extracted code. DO a “Save as” and give it a good name. On the Front panel, double click the icon (top right corner) and edit you own graphic.
Now, go back to the main block diagram and replace the other instances of that code with your own VI. Once you build your own VI, you’ll never look back
Yeah, sounds like sub vi’s can be very handy.
check out these video’s for some tutorial on creating custom sub vi’s.
http://www.lvmastery.com/files/FIRSTDec12_Part1/FIRSTDec12_Part1(2).html
(^^this one starts out boring, but has some useful info for part2,
and is still much less boring than the official NI video’s)
http://www.lvmastery.com/files/FirstDec12_Part2/FirstDec12_Part2.html
http://www.lvmastery.com/files/FirstDec12_Part3b/FirstDec12_Part3b.html
To cause less mistakes in the implementation of the array of Motor TypeDefs, you can create a ring terminal TypeDef (Strict), and use it as a constant on the block diagram. It’s effectively the same as unbundling a cluster by name on the block diagram, but it’s much neater on the Front Panel.