Did you know that there are a bunch of built-in FRC examples right in LabVIEW? There are!
Just click on the Help drop-down menu and choose Find Examples. Shablam!LabVIEW Example Finder! You'll see an FRC Robotics folder and a roboRIO folder inside it. There, you'll find examples for everything from CAN and Pneumatics to Joystick, Sensors, and Vision.
These examples are ready to run! You can also customize them, change them, and use them however you want. You can combine them, copy/paste parts of them into other VIs or into your robot project, or just run them independently. The world is your VI!
Sometimes during the competition, it would be nice if the sensitivity of the joystick could be lowered temporarily to allow you to maneuver more precisely. The code snippet below does exactly that. If you press button #7 on your gamepad (this is the right trigger on my gamepad), it halves the sensitivity of the joystick. That way, you can drop the sensitivity mid-match by simply holding down the right button.
Replace the joystick and motor code in Telop.vi with the snippet below.
The code is quite simple: the Joystick Get Values function outputs both an array of joystick data and an array of boolean button data. The index array function is used to get the boolean value of the specified button, in this case, button #7. That value is fed into a case structure. If the button is pressed, the case structure gives a value of 2. If it is not pressed, it gives a value of 1. The value of the joystick position is then divided by the output. This way, when button #7 is pressed, every joystick value is divided by two, dropping the sensitivity. If button #7 is not pressed, the joystick sensitivity is unchanged and the robot moves at full speed.
This example illustrates how to control a servo on your robot using an input - in this case, a potentiometer. The potentiometer can be replaced with a joystick input, LabVIEW Front Panel input, or anything else that can be made to output a value between 0 and 1.
This VI Snippet uses a running average to output the mean of the last 5 potentiometer inputs to the servo. This helps to keep the servo's movement smooth. Each new potentiometer value is stored in an array in the order it is read. Once the array is full, the values are written over the existing values starting from the beginning. The size of the array can be changed to include different quantities of values in the average.
One of the first challenges every programmer faces when beginning with a new programming environment is learning how to troubleshoot their code. There are several simple techniques that can help save you a great deal of time when trying to find the source of a problem with your code.
Probes Probes tell you the current state of the data on the wire they are attached to in your program. In the screenshot below you’ll notice small numbered icons placed on the wires between subVIs in my code. To create these probes, right click on a wire and select Probe. Once the probe is placed, the Probe Watch Window automatically shows up. As your code is executing the Probe Watch Window will continuously update with new data values each time new data is passed on that wire. If I suspected an issue may be occurring in my Teleop.vi and had placed the probes as seen below I would be able to tell if I had a hardware connection or refnum naming issue by looking at probes 1 and 4 so see if they populate with values. Probes 2, 3 and 5 would tell me if I was receiving correct data and sending correct values to my motors.
Keep Code Organized Disorganized code can be very difficult to debug or ask for help with. The code snippet below has identical functionality to the code above, but it is much more difficult to read. Some of these functions have wires going backwards, and for others such as the index array function, it is near impossible to tell what is an input and what is an output. You may know what your code is doing today, but in two months it may be very difficult to remember exactly what it's purpose is. It is easy to resolve issues like this through organization, block diagram comments, and by using the automatic Diagram cleanup tool in LabVIEW. In the screenshot from item 3 below, the last item that looks like a broom (highlighted in red in the image) is the Block Diagram Cleanup tool. Click it and LabVIEW will attempt to organize your entire block diagram in a logical format, that reads left to right. The code below will very closely resemble the code above after running this tool. You can also run the cleanup tool on sections of your code by highlighting a section and typing <CTRL>+U. For more information see this link: http://www.ni.com/tutorial/7386/en
Highlight Execution Click the light-bulb icon in the toolbar of the block diagram (highlighted in red below) to turn on highlight execution mode. While highlight execution mode is enabled, you will see dots on your block diagram flow along the path the code is currently executing. If you are unsure what exactly your code is doing, or where to begin troubleshooting, this tool can help you find where your code is getting stuck, having errors, or returning bad data.
This snippet shows how to read variables from your roboRIO and display them on your custom Dashboard. It reads the current X, Y, and Z values of the built-in accelerometer and writes them to the SmartDashboard. The SmartDashboard entries are then read in the PC Dashboard and displayed on a Waveform Chart.
For more information, check out the tutorial from 2014;
This example shows how tank drive works using a gamepad as a controller. Tank drive allows the driver to control the left and right motors independently of each other. Since each side needs to be controlled separately, one must use two inputs/joysticks to control it. A gamepad is a good choice as it has two joysticks on a single device.
Some gamepads have the ability to disable analog mode, which sets the secondary joystick to read as a button rather than a pair of axes. Be sure that analog mode is enabled when using tank drive.
The code below works by opening a reference to each motor and to the gamepad. In this code the motors are controlled by CAN controllers, but it can be easily modified for another controller type. Because the gamepad has both joysticks on it, only one joystick reference is necessary. The axis position of each stick can be fetched using the JoystickGetValues.vi. The Axes output returns the values of the desired axes (in this case Axis 1 and Axis 3). These values can then be applied to the motors after negating one side since the motor(s) should have an opposite orientation.
This Training Module discusses the basic concepts of motor control. These same concepts are applied in the code below.
This snippet shows how to modify the FRC roboRIO Project built with the Arcade driving configuration to the Tank driving configuration. The only modifications necessary are to the Teleop VI to make this change. The existing Arcade Drive VI can be directly replaced with the Tank Drive VI found in the same pallet location. Then, the joystick must be configured to control each wheel individually. In the case of the below snippet, a joystick with two thumb-sticks was used where the first thumb-stick maps to row 0 of Joystick 0 and the second thumb-stick maps to row 5 of Joystick 0. Below, the array is indexed by row to get individual data per thumb-stick which is passed into each motor input on the Tank Drive VI.
This example explains how to use an encoder to determine the direction and rate of a motor controlled by your roboRIO. Encoder functions can be found in the Encoder subpalette, within the Sensors subpalette of the WPI Robotics Library palette on the block diagram.
These functions work specifically for a quadrature encoder, which contains two rotating disks A and B. Digital pulse outputs from A and B translate into speed, depending on the frequency of pulses, and direction, depending on the which disk’s pulse is detected first.
Connect your quadrature encoder to the DIO pins on the roboRIO such that encoder outputs A and B represent two separate DIO lines. Refer to the diagram shown on the front panel of the MotorwithEncoder.vi example for further direction. (Help > Find Examples > FRC Robotics > roboRIO > Robot and Motor)
How to include in 2015 Robot Project:
The WPI_EncoderOpen.vi automatically creates an encoder reference from two DIO inputs. (LabVIEW will generate two WPI_DigitalInputOpen.vi’s and convert these to source inputs for this VI). This reference can be passed to WPI_EncoderConfigureTimer.vi, which allows for further configuration of the encoder with inputs that specify the number of pulses to average for rpm calculations, as well as the minimum pulse rate before the encoder is considered stopped.
Robot Main VI
The WPI_EncoderGet.vi is used to return information from the encoder about count, direction, and period of pulses, or if the encoder is stopped. Additionally, the WPI_EncoderReset.vi can be used to reset the encoder to 0 between code executions.
The WPI_EncoderClose.vi is used to close the reference to the encoder.
The Producer/Consumer design pattern is a great way to keep two processes in sync when they might run at different rates. This is especially important when there is data transferred between the loops. When programming your robot you can use the Producer/Consumer design to save data about motor speed, various voltages, accelerometer data, and a lot more! This can come in handy as you're testing and fine-tuning your robot.
In this example the Producer loop acquires data from the LabVIEW Front Panel (the "Input Value" and "Scaling Factor" are Front Panel Controls) and adds it to a queue of data to be processed. The Event Structure is where the data is actually added to the queue. This part of the code runs when the number in "Input Value" changes (for more on Event Structures, see this blog post). The Consumer loop then removes each element from the queue, displays it on the Front Panel ("Result Value"), and adds the data to a text file. Because writing data to a text file is a time consuming activity, the Consumer loop takes longer to run than the Producer loop.
This White Paper talks about the Producer/Consumer pattern in more detail and has some additional example code snippets!