Can someone explain exactly how the Move Distance vi works? From my investigation it looks like this VI functions by constructing a message with the target encoder count, power, etc and simply sends that to the Motor Controller and waits for it to return or returns immediately. If this is the case then I presume it offloads all of the work to the Motor Controller.
Another thought/question is if I will have an issue using the move distance vi the way i would like. Below is what my current code does:
The reason I am asking is that we have had a TON of issues with encoder counts and the NXT. Last year I tried all sorts of things (including the move distance vi) and nothing worked. I ended up giving up on distance and just used time to move our bot. This year we decided to try to do this "right" and use encoders but we still had a ton of issues consistently getting encoder readings. So we spent a TON of time building logic to sample the encoders and choose a good value and eventually we got it to work very well.
However, this was all outside of the FCS. Last night I added the code into our actual autonomous and nothing works correctly now. I know the reason is that Autonomous has two loops that run to communicate and disable the robot. These are slowing our encoder sammple rate down to the point where it is no longer accurate. I tried a few different things to correct this and I might be able to get something to work. Right now I am considering trying to make the Move Distance work for us. However, if it works in a similar way to my own logic there will be no chance of success.
Sorry if this seems statter brained. I was up very late last night working on this.
Solved! Go to Solution.
The link you provided is helfpul, but it does not answer the question directly. Thus I will try to summarize below, for people who read this down the road. You can also verify I am correct.
The "out of the box" Move VI simply communicates to the Motor controller the encoder count that it is targeting and the motor controller handles the rest. There is no "out of the box" VI or examples to allows for more complex logic when trying to move using encoders.
Based on this, it seems like using encoders for "advanced" distance work is simply not a good strategy. I have yet to see an example that consistently works in an FTC autonomous program and I have personally spent 100's of hours trying to come up with one and it simply doesn't work. In most cases it is the same or less reliable than just using time.
Sorry it has taken so long to get back to you here. It sounds like from your testing you are pretty confident that the parallelism in the autonomous template is causing error in the encoder readings.
I would try replacing the Wait for Time VI's in the "Wait for Disable" loop with a VI which has only a Wait (ms) function inside (found in the Programming>>Time palette). That bugger has a TETRIX Watchdog feed, which takes a long time to execute and is probably responsible for your problems. It's also definitely unecessary since the FCS communication loop is already feeding the watchdog timer!
If that doesn't dramatically improve your results, you could do the same thing to the Wait for Time VI in the FCS loop, and either ensure you're communicating with the motors at least every three seconds, or create another parallel loop to feed the watchdog timers only once every second or so.
This seems to me to be a glaring flaw in the template.
Thanks for the response.
I don't think the parallelism is causing the encoders to read wrong. The issue seems to be that the paralellism cuases the program to not read enough encoder counts to get a good value. Not sure if that makes sense.
I will definently try replacing the wait times. You mentioned "feeding the watchdog". Can you explain or point me to some documentation that explains what this means better? From what you are saying it seems like this is a key difference between the NXT wait and the standard LabView wait. I hadn't thought there was really a difference.
From what I can tell the VI that had the most impact on my code was the FCS communication code. If I left all of the loops the same, but removed the FCS VI's it worked much better. After looking into those peices of code, I came to think that perhaps the issue was more related to the "motor mutex" check in the Disable Robot VI. Though I am not sure and I gave up before I tested that idea too much. Do you think this could be an issue?
Thanks again for all of your help,
I really think the problem is the wait for time VIs. The TETRIX motor controllers have a watchdog timer, which is a hardware timer that automatically generates a system reset if the main program neglects to periodically service it. Sending any message to the motor controller will "feed the watchdog", which resets the timer. To ensure the watchdog timers get fed during long operations, we put a feed the watchdog VI in the wait for time VI.
Running two parallel loops at 20 ms and 50 ms both with a watchdog feed is a complete waste of resources
VI that the autonomous template uses:
VI that I recommend the autonomous template use:
This really explains a number of issues I have seen in the past. I never understood why there were two different "wait" VI's. I ALWAYS used the NXT wait which then means if I had multiple parallel loops I would end up with the same issue where the watchdog is being "over fed".
Now a more general question on the watchdog. From what I understand now the purpose of the watchdog is to ensure hardware devices are turned off if communications are lost or a failure occurs. Based on this, feeding the watchdog is only required when you are running a long process and want to make sure that all hardware continues with the previous command. While you MUST feed the watchdog, you want to feed the watchdog as little as possible to reduce resource usage (which is probably what is happening to me).
Do I understand the watchdog?
Thanks again this is really "demystifying" how this all works.
You're correct about the purpose of the watchdog. According to the document linked above, the motor controller only needs to be fed every 2.5 seconds.
No problem, and I'm refactoring the code right now to fix this problem for future releases.