Joystick motion to CAN connected jaguar

I’m having an issue with black jags connected to the crio.

I’m using C++.

I have a logitech game pad connected to the driver station. In this particular instance, I’m using the Twist axis. When reading the axis, I can see the output swing between -1.0 <= output <= 1.0.

I’m operating the jag in speed mode. I’m monitoring the percent of throttle with the CrossTheRoadElectronics web page. Yes, I’m using the 2CAN.

I’m using the output of the Twist axis as the argument to the Set command.
myJag.Set (logitech.GetTwist () );

I find that I’m getting 99.99% throttle with only 25% axis movement.

-0.25 &lt; axis_output &lt; 0.25 yields -99.99% &lt; speed &lt; 99.99%

Using myJag.Get () confirms the 0.25 value.

I reduced the axis_output by a factor of four to compensate

myJag.Set (logitech.GetTwist () * 0.25 );

but I’d really like to know why this is the case. Can anybody help?

The problem is that the value from your joystick twist axis reaches its maximum and minimum with only 25% of the full physical turn?
Sounds like an issue with your joystick.

If I misunderstood you and you’re wondering why the motor isn’t moving when you send it a value of 1, that’s because 1 RPM is very slow. I have trouble getting my Jaguars to control anything less than 400 RPM on a 20,000 RPM motor (with the encoder directly on the motor shaft).

I believe the joystick is okay. Full range of joystick motion results in a joystick output swing between one and minus one.

Maybe I don’t understand what value Set() is expecting? I was under the impression Set() was expecting a value between one and minus one.

myJag.Set (some value between one and minus one);

I’m using a 360 count encoder mounted on a toughbox. I think the ratio for a toughbox is 12.75:1. A CIM motor is driving the toughbox. The CIM is being powered by a jag. The encoder is being fed into that jag.

How can I confirm that I am in speed mode rather than voltage mode?

I’m using

myJag ( 4, CANJaguar::kSpeed );

I have four jags connected to the 2CAN. Their IDs are 2, 3, 4 and 5.

Below are some messages seen during crio boot-up.

  • Loading StartupDlls: FRC_UserProgram
    task 0xe37400 (FRC_2CAN Rx) deleted: errno=0 (0) status=0 (0)
    task 0x1b13388 (FRC_2CAN Tx) deleted: errno=0 (0) status=0 (0)
    WPILib was compiled from SVN revision 2129:2133

>>>>ERROR: status == -52007 (0xFFFF34D9) in getTransaction() in C:/windriver/workspace/SimpleTemplate/CANJaguar.cpp at line 357

fwVersion[2]: 0

>>>>ERROR: status == -63194 (0xFFFF0926) in InitJaguar() in C:/windriver/workspace/SimpleTemplate/CANJaguar.cpp at line 35

>>>>ERROR: status == -52007 (0xFFFF34D9) in getTransaction() in C:/windriver/workspace/SimpleTemplate/CANJaguar.cpp at line 357

fwVersion[3]: 0

>>>>ERROR: status == -63194 (0xFFFF0926) in InitJaguar() in C:/windriver/workspace/SimpleTemplate/CANJaguar.cpp at line 35

Welcome to LabVIEW Real-Time 8.6.1f2

>>>>ERROR: status == -52007 (0xFFFF34D9) in getTransaction() in C:/windriver/workspace/SimpleTemplate/CANJaguar.cpp at line 357

fwVersion[4]: 0

>>>>ERROR: status == -63194 (0xFFFF0926) in InitJaguar() in C:/windriver/workspace/SimpleTemplate/CANJaguar.cpp at line 35

>>>>ERROR: status == -52007 (0xFFFF34D9) in getTransaction() in C:/windriver/workspace/SimpleTemplate/CANJaguar.cpp at line 357

fwVersion[5]: 0

>>>>ERROR: status == -63194 (0xFFFF0926) in InitJaguar() in C:/windriver/workspace/SimpleTemplate/CANJaguar.cpp at line 35

Line 35 from CANJaguar.cpp is:
wpi_assertCleanStatus (kRIOStatusVersionMisMatch);

Line 357 from CANJaguar.cpp is:
wpi_assertCleanStatus (status);

I pretty sure I’m not supposed to be getting these messages.

Any suggestions?

I forgot you were using 2CAN, and so the BDC-COMM isn’t as practical.
I think I also misunderstood the problem here. The issue you’re having is that the Jaguar is going full speed when you’re only sending it a value of 0.25? Check your encoder lines configuration to make sure you haven’t said something like 10,000 counts per revolution. Also, double-check that it is RPM, not revolutions per second.

Yes, it does sound like your joystick is fine.

Have you gotten voltage mode working over CAN?
If not, let’s work on that first. (It requires less configuration, and is -1 to 1 as you expected)

If you have voltage mode working:
In speed mode, the Jaguar expects an RPM value. On a toughbox with a CIM, that would be 4500 RPM / 12.75, about 350 RPM. Don’t forget to set the PID and number of lines on the encoder. These settings are volatile; they disappear when the Jaguar loses power, and need to be loaded again.
Have you updated the firmware on your Jaguars?
Have you sent “speed mode enable”?

You asked about how to tell if you are in speed mode? There is a CAN “get control mode” command, but it wasn’t implemented last time I checked. Maybe it will be in the next firmware update.

I’m not sure what those errors are, but looking at the functions they’re from, I’d say either your Jaguars don’t have a firmware update, they don’t have power, or the CAN bus isn’t connected correctly.

What does the 2CAN show?
The Black Jaguars should have firmware version 91.

All jags have version 91 firmware. The 2CAN webpage shows the firmware version.

All jags can be controlled in voltage mode.

If by “speed mode enable” you mean

myJag.EnableControl ()

then yes, I’m doing that.

It’s odd. I can read PID values but can’t read firmware version or position. The more I think about it, the jag acts like it’s in voltage mode. This is despite the fact that I declared the jag to be speed controlled.

myJag ( 4, CANJaguar::kSpeed );

I just had a thought. I’m declaring my jaguar object (I think I’m using the correct term) rather than declaring a jaguar object pointer.

Can I use:

CANJaguar my_jag;

or do I have to

CanJaguar *my_jag;
my_jag = new CANJaguar …

I’ll have to try that later.

I don’t use NEW for the voltage mode jags and they work but hey, who knows?

Radical Pi is probably the best to answer questions about C++ with CAN.

However, I can offer more general troubleshooting.
Do you get the same errors in voltage mode, or only in speed mode?
Are the encoders connected correctly?
Have you configured the number of encoder lines?

What happens when you get the speed status? Does it return the correct speed, or does it return zero?

First of all, Marshal is right, you shouldn’t be calling Set with a direct input from the throttle axis. When is speed mode, Set expects a rpm value.

I declare all my jags as pointers, but that’s personal preference and as long as the code builds properly and the voltage-based jags are working it shouldn’t be a problem.

I’ve seen those same errors on my bot during boot. For some reason the jag doesn’t notify the cRIO of its firmware version properly. It seems to have no affect on my bot (using voltage mode), but I do see in the source one command crucial to speed mode that occurs after the point where the code would exit. Try calling SetSpeedReference(CANJaguar::kSpeedRef_Encoder) on the jag.

From what I can see of your problem, the jaguar is reading a speed of 0 from whatever its speed source is. In the default firmware, if no speed reference is set (which may be happening with those errors), checking the speed will always return 0, which can cause those symptoms.

If the speedReference thing doesn’t work, double check that your encoder is working properly. I don’t remember the exact wiring required for this, but the cypress board can read encoders if required (it has something to do with pin 5)

Thank you Radical, I forgot about the Speed Reference command (which tells the Jaguar to use the encoder).

As for wiring:
the order of pins on the Jaguar is this: + A B I -
The + and - are for encoder power; the A and B are actually the channels. Leave “I” unconnected. It is the index, and (according to the datasheet) will reset your position count. It may also affect your speed.

Here’s the latest update.

I took Radical Pi’s advice (thank you) and called,

I can now read non-zero values when calling GetSpeed.

I can now use values for Set () greater than one (hurray!).

I STILL can’t read the firmware version. I’m okay with that.

I am only able to read zero when calling GetPosition. Maybe you have to be in position mode?

With PID values = 10,0,0 and encoder counts of 360, I got a lot of cogging (chattering?) at speeds less than 10 rpm.

I artificially inflated the encoder counts and got MUCH smoother motion at all speeds.

For the new encoder counts, I used (360 * 12.75 = 4590). I also tried
(360 / 12.75 = 28.2 ==> 28 ) but the cogging was WAY worse than before.

The maximum speed I could achieve that was reported with GetSpeed was about 32. I’m going to have to use something (a strobe light, maybe?) to determine the actual rpm value.

I’m kind of surprised that SetSpeed Reference had to be called. I was looking through the embedded comments in CANJaguar.cpp. The comments stated that the only option for a feedback device in speed mode was … wait for it

… an encoder!

Thanks to everybody that contributed.


The “get position” reporting zero is one of the bugs in the current Jaguar firmware.
“get position” reports zero until the position reference has been set and Position Mode has been enabled. After that, you can read position in any mode.
Likewise, “get speed” reports zero until the speed reference has been set and Speed Mode has been enabled.

Additionally, “get speed” always reports positive, regardless of the direction the encoder is turning. However, speed mode works just fine in a negative direction.

Yeah, that’s an effect of the firmware returning 0. When that happens, the init function exits after the firmware check, which occurs before the call to SetSpeedReference occurs.

Something doesn’t make sense.

If the firmware is the issue, how is the 2CAN web interface able to show the correct version for firmware? The jaguar firmware is the same whether the robot program or the 2CAN web interface is asking. It seems likely that the gremlin lives in a level above the jaguar firmware level.

Looking closer at your boot errors, they seem to be occurring at a slightly different point than mine. You have an error being returned in recieveMessage (from CANJaguar.cpp), while my errors are being thrown from a some .vi, which I believe is in FRC_NetworkCommunication. Perhaps a difference between 2CAN and Serial.

As a check, if you call GetFirmwareVersion() in your code, does it return 91?

P.S. My claiming it is a firmware issue was slightly inaccurate. The problem that we are seeing is a lack of any reply to a firmware version request.

Wait, your firmware version request isn’t returning anything valid?
But it does in LabVIEW…
It’s just the Device Query that doesn’t return anything.
(In LabVIEW, the Jaguar Open VI returns an error if the Jaguar firmware isn’t in the correct range)

GetFirmwareVersion() returns zero.

I’m connecting the crio to the 2CAN through ethernet port 1 (the same port used for the wireless).

Maybe that’s the problem?

I transferred the 2CAN connection over to ethernet port 2 (192.168.x.x). Yes, I changed the 2CAN IP address. The results are the same. GetFirmwareVersion still returns 0. I still get the CANJaguar errors during crio boot-up.

Here’s a little more about the 2CAN web page interface. Sometimes it shows the firmware rev, sometimes not.

Radical Pi, I may have to pull a paper bag over my head in shame for my comments about the firmware.

Well if it returns zero during the actual running of the code and the 2CAN can retrieve a version and it doesn’t work over Serial but everything works in LabVIEW, then there must be a problem in the CANJaguar.cpp file.

2 parts to this one:

Marshal: In LabVIEW’s Get Firmware Version, is 0x80000000 OR’d into the ID?

sam: Go into the function GetFirmwareVersion in CANJaguar.cpp (line 866 for me) and replace this line with a different version:

	// Set the MSB to tell the 2CAN that this is a remote message.
	getTransaction(0x80000000 | CAN_MSGID_API_FIRMVER, dataBuffer, &dataSize);

	// REMOVED: Set the MSB to tell the 2CAN that this is a remote message.
	getTransaction(CAN_MSGID_API_FIRMVER, dataBuffer, &dataSize);

That ORing only occurs in the GetFirmwareVersion function and seems to be the only thing that sets it apart from any other message. Also looking back through the revision logs on svn that code was introduced around the same time I started seeing the problem.

EDIT: It appears that Java had the same problem at one point and the firmware check was bypassed as a workaround

No, the OR is not there in the LabVIEW version.
There is just the decimal value 512 ORed with the device number.
In hexadecimal, that should be 0x0b00

What’s weird about ORing 0x80000000 is that it makes TRUE the highest bit of the Arbitration ID. The highest 3 bits of the arbitration ID should be reserved.

By all means, take it out, and comment what and why you did.