Jaguar Speed & Position Control with Encoders

Last year we tried to use the Jaguar Motor Controller’s position and speed control functions in our Ultimate Accent bot. We got the BDC-COMM utility to work but couldn’t work out the “C” programming.

We’ve had good success on the FTC team using the Matrix motor controller and would like to achieve a similar performance with Jaguars.

I’d appreciate any feedback or point me to a thread where this is discussed.

I’m going to operate with the assumption that by “C programming,” you mean the C++ programming on the cRIO.

While we use Java, that should be similar to the API we use, which can be found here for all of the classes used in WPILibJ, or here for the CANJag class.

Does anyone know of similar documentation for C++?

I’m not a C++ programmer and will relay any info about this to my son who knows that stuff. I’m mechanical and would understand mechanism and controls hardware. I’ve worked with industrial PLCs using ladder logic and have some understanding of controls systems. The big questions for me are:

  • Do the Jaguar on-board speed and position controls work? If so, looking for examples of successful controls strategy?
  • Is my assumption correct that using the Jaguar’s micro-controller PID loops faster and more efficient than running feedback/feed-forward loops from the CReo?
  • Is the CAN Bus route worth the effort?
  • What questions have I forgotten to ask? :slight_smile:

The PID functionality of the Jaguars does work, but adding CAN can be expensive depending on which adapter you use.

The PID on the cRIO is just as fast and as powerful as the one on the jaguar, but works with all types of speed controllers and sensors. If you’re looking for basic getting started examples, there are plenty for PID on the cRIO.

  • Yes. However, it is the opinion of some (myself included) has been that the physical connections and mechanical implementation in the Jaguar motor controller are unreliable.
  • Yes.
  • In my experience, I’d say that doing PID on the cRIO is much less of a headache and much easier to implement than CANBus. I personally find the CAN interface on the Jaguar to be much more trouble than it’s worth. That being said, there are several teams who have used the CANBus route successfully and prefer it (according to my friends on 195, it can have cleaner wiring if you do it right, and it is more computationally efficeint than doing it on the cRIO). Whether or not it is a success on your team is a function of your determination, human resources, experience, and time.
  • It’s worth noting that there is not an insignificant chance that the interface for CAN in 2015 will be much different than it was in 2013 (with new roboRIO, and with a new CAN-based Talon). I’d read the following documents/forum discussion. Hopefully they’ll answer more questions than they raise, but as always, feel free to ask any new questions you might have. That’s what ChiefDelphi is all about. :slight_smile:


Thanks so much for the help!

I was very excited about the performance of the Jaguar/CIM running on the bench through BCD-COMM. If this can be done through the cRIO, I’m willing to forge ahead. I’ve read through VEX and TI manuals, read the NI forums but no joy finding a servo/motor/Jaguar set-up problem to solve the problem. I guess I’ll need to delve into programming language to get the complete picture :O.

No problem. Always glad to help.

Best of luck. You’re far braver than I am…

What do you mean by a set-up problem? Are you referring to the PID coefficients, or a simple set-up diagram of sorts?

Yes, I would recommend that. What language do you use?

Why do you say this? I wasn’t aware that anyone was running PID at 1000 hz on the cRIO. Doing PID on the cRIO is more flexible, however, since you can implement your own.

The serial CAN interface is somewhat inefficient, and you may find that if you send to many updates, it may use more cRIO throughput then running a 50 or 100hz PID on the cRIO would. One option would be to invest in the 2CAN. Another option would be to limit the amount of CAN traffic. Setting a setpoint every few seconds isn’t a problem. Changing setpoints at 50hz to multiple jaguars and requesting lots of status can be a problem.

This thread shows the required calls for setting up a CAN Jaguar in position mode. You also need to using the imaging tool to set the appropriate CAN Jaguar plugin (Serial or 2CAN).

We successfully utilized Jags last year with CAN bus and a position sensor. We were going to also use the speed sensor but had wired a hall-effect sensor for speed vice an encoder. The Jag could not utilize the hall-effect sensor.

Couple of things we learned.

  1. Wire the serial port of the cRio to the first Jag, than CAN to the other Jags
  2. Don’t forget the terminator on the last Jag
  3. ReImage the cRio with CAN support (that one took us a while to learn :slight_smile:
  4. Write simple test programs to exercise the Jag before integrating Jag support into your overall robot code. Its MUCH easier to debug.

Don’t forget, Jags also work well with limit switches (CAN and PWM control).

Good luck with the Jags this year.

Hooking up to the BCD-COMM wasn’t easy for us:

  • I had some quad encoders with index and it took some time to realize that the index was resetting the counter when trying position control
  • Struggled a bit with USB/Serial converter to Jaguar; PC serial software
  • Didn’t have documentation about PID (PI only) constants; had to trial-and-error the integral.
  • “Bricked” a Jaguar by failed firmware update (VEX had good support and fixed it for free)

I know none of these are that big a deal individually, but when you’re dealing with multiple snags it can get daunting. What I meant is: I wanted to make sure there wasn’t some issue like those with the cRIO CAN setup that was preventing proper operation.

I tested this last year. I tried 800 hz to 10 hz, and everything faster than 100 hz behaves the same way as 100 hz because the victor can only be updated every ~20 ms (50 hz).

Also, I don’t think that a drivetrain used in FRC will benefit from being updated 100 times a second vs 1000.

Where did you find the 1000hz number? I’m not saying it’s wrong, but I couldn’t find it online.

The point Joe was making is that the built-in PID in the Jag’s firmware closes the loop at 1000 Hz. You can’t do that with cRIO. You can’t do that with Victor or Talon.

everything faster than 100 hz behaves the same way as 100 hz because the victor can only be updated every ~20 ms (50 hz).

Victors will accept 200 Hz input PWM frequency.

I don’t think that a drivetrain used in FRC will benefit from being updated 100 times a second vs 1000.

Other systems might.

It’s in the jaguar source code (not sure if it’s still available online, used to be available from TI). There is a 1ms timer interrupt. It runs the PID and updates the H-bridge PWM from the same interrupt.

Portions of the relevant source code were posted here by dyanoshak:

Hi Joe,

Thanks for the link and info in previous post. I work with industrial control systems (not programming) and I like distributed control over a network. My bias from work makes me lean toward using the Jaguar’s controller for the feedback control and send setting over the BUS.

I really appreciate the real-world experience with the FRC electronics.

I spent a fair amount of time using CAN and the Jags and this architecture has a lot of potential – in my opinion, the problems were all in the implementation and the current Jags seem to have addressed the most severe problems. I also designed and built my own smart motor controllers that used different silicon and was very happy with how these turned out. I’m really looking forward to seeing a second-generation motor controller with these capabilities generally available – and therefore legal for competition use.

I’d second the points about watching the serial bandwidth if you go this way and about using the 2CAN to open up this potential bottleneck. There at least used to be a source (eStop robotics, IIRC) for pre-made serial-to-CAN converters and terminators, as well as cables. Some teams have trouble with these, particularly the terminators. You’ll need a serial converter for using BDC-COMM with a PC anyway. And BTW, making sure things work under BDC-COMM is a good first step and troubleshooting tool.

I’ve also seen people tripped up because the encoder connector on the Jag has a different pinout than the standard one used by US Digital, so pre-made cables at least need to be modified. Also, the space around the pins is very tight and so you have to have the right connector for this.

I sent this for a fix to the problem where the index signal messes up position control, AFAIK, it never made it into official firmware, but I haven’t tried to use this in the past couple of seasons (this refers to a source file for the Jag firmware):

Note that this is in the ControllerPositionMode() function in controller.c.

Briefly, the problem was that when using PID position-based control with an indexed encoder, things don’t go well when the index is hit and the position count wraps.

static void
long lTemp;
// Get the motor position.
// Compute the error between the target position and the motor position.
lTemp = g_lPositionTarget - lTemp;

The preceding line is deriving the position error, but neglects that there are really two errors and this code need to evaluate both of these and pick the smaller of the two. The second error crosses through zero and when this is the smaller of the two, the existing code does not do the right thing.

This shows up especially when using an indexed encoder where the count gets set to zero when the index is encountered. Note that if using a pot, you really don’t want to move through zero, so the logic change only applies when dealing with an encoder!

One possible fix is to leave the preceding line as-is, but add this code:

// When using an encoder, handle the case where the most direct way to reach the
// desired position crosses through zero. If the encoder lines global has not been set,
// this will be zero, meaning the count wraps at QEI_MAXPOS_M. If the position
// error is more than halfway through a full revolution, going through zero is the shorter
// distance. If the error is exactly half-way around, it would make sense to keep going
// in the current direction, but PID behavior should adequately cover this case.
// This code should really be gone over to be sure there are no issues mixing signed and
// unsigned 32-bit integers. Also, it might make sense to use QEI_MAXPOS_M in the
// case where the encoder lines global has not been set (but this is more a usage problem).

if (HWREGBITW(&g_ulFlags, FLAG_POS_SRC_ENCODER) == 1 && g_ulEncoderLines != 0)
if (lTemp > g_ulEncoderLines / 2)
lTemp = lTemp - g_ulEncoderLines;
else if (lTemp < -(g_ulEncoderLines / 2))
lTemp = lTemp + g_ulEncoderLines;
// Run the PID controller, with the output being the output voltage that
// should be driven to the motor.

Another thing that can trip people up is if the controller resets for any reason (power brown-out, bug?, bandwidth saturates on serial link and something bad happens?). Or maybe the cRIO resets but the Jaguar does not, or maybe something bad happens around losing the safety heartbeat, …

Anyway, there is a possibility that the configuration parameters will all be lost and things will revert to the defaults. You want to have some sort of error handler in the cRIO code and probably also to periodically read at least something from the Jag to be sure things seem good.

There are some old threads on this topic and also that go into more detail on some of the issues in my prior post.

Hi Joe,

I’ve read about the 2CAN but the price scared me away. I’ll put that on my list to investigate.


Hi Ether,

First- I’ve read many of your posts and want to compliment you on your contributions to the teams. Your to-the-point, thorough, and expert responses are a pleasure to read. Thank you!

I’ve begun following your links and have a lot of studying to do…