Motion is very common in so many different applications like Automated Test, Robotics and Control. With the release of the new NI 9501 (A stepper motor controller with integrated drive circuitry) it should be even easier to develop motion applications with NI CompactRIO. An example for driving a single stepper motor using this module can be found in the example folder. To find this example go to Help > Find Examples, and search '9501'. The example is called Offline Traj - Pos Cntrl (open loop) - NI 9501.lvproj.
This project demonstrates how to set up a motion application with this module.
Running on the FPGA is code to generate the steps to actually move the motor, called Offline Traj - Pos Cntrl (open loop) - NI 9501 (FPGA).vi. This VI abstracts the low level signal generation, allowing the RT controller to deal with higher level tasks such as generation nice, smooth motion profiles.
Running on the RT controller is Offline Traj - Pos Cntrl (open loop) - NI 9501 (RT).vi. This VI generates smooth movement profiles, and sends them as an array to the FPGA VI, using a FIFO (called Setpoint). The RT VI also co-ordinates the FPGA VI to ensure configuration parameters are set.
This example is great for getting started, but usually a motion application will require the co-ordination of multiple motors. It can be tough to understand this example, and to know how to adapt it into a program that can simultaneously co-ordinate multiple motors.
The goal of my example is to
This example is a heavily modified version of the project found in the example folder. A lot of annotations have been included to aid understanding. This specific example moves only three motors, but is written to make it relatively easy to add code for controlling additional motors.
How it works
Much like the example project, this project starts with an RT VI.
The RT VI does the following things.
1) Configures the modules, and gets them ready for a movement.
2) Allows you to enter the desired positions for three different motors.
3) Once the command is sent to move the motors, the VI generates a 3D profile to get all three motors to move to the desired position, at a desired velocity and acceleration. It ensures the profile generated will make the motors finish at the same time.
4) Once all the 3D profile has been generated, it encodes this data so that each set of data is specific to it's corresponding motor. It does this using a previous example I wrote, found here. (I strongly recommend you take a look at this example, it will help you understand how data is sent between the RT VI and the FPGA VI here).
5) After encoding, it can send all the different values into a single FIFO. (The encoding ensures data for different motors won't confused with each other, despite being sent using a single communication channel. It then sends a go signal by encoding a unique 'channel'.
6) The RT VI Monitors the movement of the motor by reading the indicators on the FPGA VI. Once a movement is completed, the RT VI allows you to enter a new position to move to.
7) Once the Stop Program button is pressed, the RT VI will disabled the module drives.
The RT Vi is in a 'Producer-Consumer' structure. You can find out more about this online. Put simply, the top loop controls when the bottom loop will run via a queue. In the configuration here, the bottom loop will only run when the 'Motors GO!' control becomes TRUE.
A lot more information can be found in the comments in the code. You may wonder why it is necessary to encode the multiple motor data before sending into the FIFOs, the diagrams below explain this.
Now onto the FPGA VI.
1) The FPGA starts by polling the 'RT to FPGA' FIFO, to read any setpoint data that has been placed into this FIFO. Once available, the FIFO reads this data (and therefore removes it from the FIFO).
2) The FPGA decodes the data from the FIFO using the encoding/decoding VIs described previously. In this way, the raw data from the FIFO is decoded into individual setpoint values, and the specific motor that setpoint applies to. Using this information, the FPGA VI places the values in one of three target-scoped FIFOs.
A target-scoped FIFO is a FIFO that can only be written to/read from on the FPGA. Essentially, it's a block of memory that (in this VI) is used to store the array of setpoints.
3) Even when all the data has been decoded and written to the target-scoped motor FIFOs, the motors will not move. The FPGA waits for a 'GO!' signal; a unique value put into the FIFO by the RT VI. This 'GO!' value is sent after all the data has been sent, so that the motors won't start until all data is actually received by the FPGA VI. Once the signal is recieved, the FPGA VI reads from the target-scoped motor FIFOs, and starts to generate the steps needed to actually move the motors.
This is a broad overview, the low level details are fully explained in the comments on the block diagram.
I am hoping that this example will be a life-saver to anyone who wants to achieve co-ordinated motor control with the 9501, but is a bit stuck on how to do it. I have tested this code multiple times to ensure it does actually work. Once you understand what's going one, adding additional motors should just be a case of code replication.