Correct me if I am wrong. If the cause is really over current (not because of loose wires etc) and the breakers got cut off, your robot will be cut out no matter if you are using Jaguars or Victors (CAN or PWM for Jaguars). The only difference between Jaguars and Victrors (or CAN vs PWM) is that when the breaker resets, Victors (and Jaguars with PWM) will work again versus Jaguar with CAN may not work because its configuration has been cleared by the "brownout". If that is really the cause, software may be able to help to recover by detecting brownout and reconfiguring the Jaguars if necessary. We have written a wrapper class for CANJaguar (included below) that you can try. Caveat: This code is new and hasn't been tested extensively so use at your own risk. Unfortunately (or fortunately), we haven't really hit a brownout condition, so we don't know if the code works as intended. It is possible that we have hit brownouts and the code worked beautifully to recover that we did not even notice. We have added a "printf" in the recovery code path so it is supposed to print a warning to the net console if a brownout has been detected. We haven't noticed that warning but it's possible it's been drowned in the sea of debug printouts. It is also possible that our drive train design doesn't cause brownouts (e.g. weaker drive train). If you find bugs in the code, comments are welcome.
Code:
#if 0
/// Copyright (c) Titan Robotics Club. All rights reserved.
///
/// <module name="CanJag.h" />
///
/// <summary>
/// This module contains the definition and implementation of the
/// CanJag class.
/// </summary>
///
/// <remarks>
/// Environment: Wind River C++ for National Instrument cRIO based Robot.
/// </remarks>
#endif
#ifndef _CANJAG_H
#define _CANJAG_H
/**
* This class defines and implements the CanJag object. The CanJag object
* inherits from the CANJaguar object in the WPI library. It basically wraps
* the CANJaguar class so it can shadow all the volatile Jaguar configuration
* parameters. If the Jaguar ever browns out, we will be able to restore the
* Jaguar configurations.
*/
class CanJag: public CANJaguar
{
private:
UINT16 m_encoderLines;
UINT16 m_potTurns;
float m_faultTime;
NeutralMode m_neutralMode;
double m_fwdLimitPos;
double m_revLimitPos;
double m_voltRampRate;
SpeedReference m_speedRef;
PositionReference m_posRef;
double m_Kp;
double m_Ki;
double m_Kd;
float m_motorValue;
double m_position;
double m_speed;
/**
* This funcion checks if a power cycle has occurred. If so, it will
* reconfigure the Jaguar with the shadowed information.
*
* @return Returns true if the Jaguar has been power cycled since we
* check last.
*/
bool
CheckPowerCycled(
void
)
{
bool fPowerCycled = GetPowerCycled();
if (fPowerCycled)
{
//
// Jaguar has lost power, restore configuration appropriately.
//
printf("Detected brownout on Jag %d.", m_deviceNumber);
CANJaguar::ChangeControlMode(m_controlMode);
if (m_controlMode == kPosition)
{
CANJaguar::SetPID(m_Kp, m_Ki, m_Kd);
CANJaguar::SetPositionReference(m_posRef);
if (m_posRef == kPosRef_QuadEncoder)
{
CANJaguar::ConfigEncoderCodesPerRev(m_encoderLines);
}
else if (m_posRef == kPosRef_Potentiometer)
{
CANJaguar::ConfigPotentiometerTurns(m_potTurns);
}
}
else if (m_controlMode == kSpeed)
{
CANJaguar::SetPID(m_Kp, m_Ki, m_Kd);
CANJaguar::SetSpeedReference(m_speedRef);
if (m_speedRef != kSpeedRef_None)
{
CANJaguar::ConfigEncoderCodesPerRev(m_encoderLines);
}
}
else if (m_controlMode == kCurrent)
{
CANJaguar::SetPID(m_Kp, m_Ki, m_Kd);
}
if (m_maxOutputVoltage > 0.0)
{
CANJaguar::ConfigMaxOutputVoltage(m_maxOutputVoltage);
}
if (m_faultTime > 0.0)
{
CANJaguar::ConfigFaultTime(m_faultTime);
}
if (m_neutralMode != kNeutralMode_Jumper)
{
CANJaguar::ConfigNeutralMode(m_neutralMode);
}
if (m_fwdLimitPos == 0.0 && m_revLimitPos == 0.0)
{
CANJaguar::DisableSoftPositionLimits();
}
else
{
CANJaguar::ConfigSoftPositionLimits(m_fwdLimitPos,
m_revLimitPos);
}
if (m_voltRampRate > 0.0)
{
CANJaguar::SetVoltageRampRate(m_voltRampRate);
}
CANJaguar::EnableControl();
}
return fPowerCycled;
} //CheckPowerCycled
public:
/**
* Constructor: Create an instance of the CanJag object that inherits
* the CANJaguar class.
*
* @param deviceNumber Specifies the CAN ID for the device.
* @param controlMode Specifies the control mode to set the device to.
*/
CanJag(
UINT8 deviceNumber,
ControlMode controlMode = kPercentVbus
): CANJaguar(deviceNumber, controlMode),
m_encoderLines(0),
m_potTurns(0),
m_faultTime(0.0),
m_neutralMode(kNeutralMode_Jumper),
m_fwdLimitPos(0.0),
m_revLimitPos(0.0),
m_voltRampRate(0.0),
m_speedRef(kSpeedRef_None),
m_posRef(kPosRef_None),
m_Kp(0.0),
m_Ki(0.0),
m_Kd(0.0),
m_motorValue(0.0),
m_position(0.0),
m_speed(0.0)
{
if (controlMode == kSpeed)
{
m_speedRef = GetSpeedReference();
m_Kp = GetP();
m_Ki = GetI();
m_Kd = GetD();
}
else if (controlMode == kPosition)
{
m_posRef = GetPositionReference();
m_Kp = GetP();
m_Ki = GetI();
m_Kd = GetD();
}
else if (controlMode == kCurrent)
{
m_Kp = GetP();
m_Ki = GetI();
m_Kd = GetD();
}
m_motorValue = CANJaguar::Get();
m_position = CANJaguar::GetPosition();
m_speed = CANJaguar::GetSpeed();
//
// Clear the power cycled flag.
//
GetPowerCycled();
} //CanJag
/**
* Destructor: Destroy an instance of the CanJag object.
*/
virtual
~CanJag(
void
)
{
} //~CanJag
/**
* This function sets the motor power.
*
* @param value Specifies the motor power.
* @param syncGroup Optionally specifies the syncgroup of the motor.
*/
void
Set(
float value,
UINT8 syncGroup = 0
)
{
CheckPowerCycled();
if (value != m_motorValue)
{
m_motorValue = value;
CANJaguar::Set(value, syncGroup);
}
} //Set
/**
* This function sets the reference source device for speed control mode.
*
* @param reference Specifies the reference device.
*/
void
SetSpeedReference(
SpeedReference reference
)
{
m_speedRef = reference;
CANJaguar::SetSpeedReference(reference);
} //SetSpeedReference
/**
* This function sets the reference source device for position control mode.
*
* @param reference Specifies the reference device.
*/
void
SetPositionReference(
PositionReference reference
)
{
m_posRef = reference;
CANJaguar::SetPositionReference(reference);
} //SetPositionReference
/**
* This function sets the PID constants for the closed loop modes.
*
* @param Kp Specifies the P constant.
* @param Ki SPecifies the I constant.
* @param Kd Specifies the D constant.
*/
void
SetPID(
double Kp,
double Ki,
double Kd
)
{
m_Kp = Kp;
m_Ki = Ki;
m_Kd = Kd;
CANJaguar::SetPID(Kp, Ki, Kd);
} //SetPID
/**
* This function sets the maximum voltage change rate.
*
* @param rampRate Specifies the max voltage ramp rate.
*/
void
SetVoltageRampRate(
double rampRate
)
{
m_voltRampRate = rampRate;
CANJaguar::SetVoltageRampRate(rampRate);
} //SetVoltageRampRate
/**
* This function configures the neutral mode.
*
* @param mode Specifies the neutral mode.
*/
void
ConfigNeutralMode(
NeutralMode mode
)
{
m_neutralMode = mode;
CANJaguar::ConfigNeutralMode(mode);
} //ConfigNeutralMode
/**
* This function configures the number of encoder lines per revolution.
*
* @param encoderLines Specifies the number of encoder lines per rev.
*/
void
ConfigEncoderCodesPerRev(
UINT16 encoderLines
)
{
m_encoderLines = encoderLines;
CANJaguar::ConfigEncoderCodesPerRev(encoderLines);
} //ConfigEncoderCodesPerRev
/**
* This function configures the number of turns of the potentiometer.
*
* @param turns Specifies the number of turns of the potentiometer.
*/
void
ConfigPotentiometerTurns(
UINT16 turns
)
{
m_potTurns = turns;
CANJaguar::ConfigPotentiometerTurns(turns);
} //ConfigPotentiometerTurns
/**
* This function configures the forward and reverse position limits.
*
* @param fwdLimitPos Specifies the forward limit position.
* @param revLimitPos Specifies the reverse limit position.
*/
void
ConfigSoftPositionLimits(
double fwdLimitPos,
double revLimitPos
)
{
m_fwdLimitPos = fwdLimitPos;
m_revLimitPos = revLimitPos;
CANJaguar::ConfigSoftPositionLimits(fwdLimitPos, revLimitPos);
} //ConfigSoftPositionLimits
/**
* This function disables soft position limits.
*/
void
DisableSoftPositionLimits(
void
)
{
m_revLimitPos = 0.0;
CANJaguar::DisableSoftPositionLimits();
} //DisableSoftPositionLimits
/**
* This function configures how long the Jaguar waits in the case of a
* fault before resuming operation.
*
* @param faultTime Specifies the fault time.
*/
void
ConfigFaultTime(
float faultTime
)
{
m_faultTime = faultTime;
CANJaguar::ConfigFaultTime(faultTime);
} //ConfigFaultTime
/**
* This function gets the motor position from the Jaguar controller.
*
* @return Returns the motor position.
*/
double
GetPosition(
void
)
{
m_position = CANJaguar::GetPosition();
return m_position;
} //GetPosition
/**
* This function gets the motor speed from the Jaguar controller.
*
* @return Returns the motor speed.
*/
double
GetSpeed(
void
)
{
m_speed = CANJaguar::GetSpeed();
return m_speed;
} //GetSpeed
}; //class CanJag
#endif //ifndef _CANJAG_H