View Single Post
  Spotlight this post!  
Unread 27-12-2013, 16:26
nuttle nuttle is offline
Registered User
AKA: Allen Nuttle
FRC #4080
Team Role: Mentor
 
Join Date: Mar 2010
Rookie Year: 2009
Location: United States
Posts: 104
nuttle has much to be proud ofnuttle has much to be proud ofnuttle has much to be proud ofnuttle has much to be proud ofnuttle has much to be proud ofnuttle has much to be proud ofnuttle has much to be proud ofnuttle has much to be proud of
Re: Jaguar Speed & Position Control with Encoders

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
ControllerPositionMode(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.
//
[...]

Last edited by nuttle : 27-12-2013 at 23:45.