Now you can download a copy of these docs so you can use them offline! Download now
CANJaguar.cpp
00001 /*----------------------------------------------------------------------------*/ 00002 /* Copyright (c) FIRST 2009. All Rights Reserved. */ 00003 /* Open Source Software - may be modified and shared by FRC teams. The code */ 00004 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */ 00005 /*----------------------------------------------------------------------------*/ 00006 00007 #include "CANJaguar.h" 00008 #define tNIRIO_i32 int 00009 #include "ChipObject/NiFpga.h" 00010 #include "CAN/JaguarCANDriver.h" 00011 #include "CAN/can_proto.h" 00012 #include "WPIErrors.h" 00013 #include <stdio.h> 00014 00015 #define swap16(x) ( (((x)>>8) &0x00FF) \ 00016 | (((x)<<8) &0xFF00) ) 00017 #define swap32(x) ( (((x)>>24)&0x000000FF) \ 00018 | (((x)>>8) &0x0000FF00) \ 00019 | (((x)<<8) &0x00FF0000) \ 00020 | (((x)<<24)&0xFF000000) ) 00021 00022 #define kFullMessageIDMask (CAN_MSGID_API_M | CAN_MSGID_MFR_M | CAN_MSGID_DTYPE_M) 00023 00024 const INT32 CANJaguar::kControllerRate; 00025 const double CANJaguar::kApproxBusVoltage; 00026 00030 void CANJaguar::InitCANJaguar() 00031 { 00032 m_transactionSemaphore = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE); 00033 if (m_deviceNumber < 1 || m_deviceNumber > 63) 00034 { 00035 char buf[256]; 00036 snprintf(buf, 256, "device number \"%d\" must be between 1 and 63", m_deviceNumber); 00037 wpi_setWPIErrorWithContext(ParameterOutOfRange, buf); 00038 return; 00039 } 00040 UINT32 fwVer = GetFirmwareVersion(); 00041 if (StatusIsFatal()) 00042 return; 00043 // 3330 was the first shipping RDK firmware version for the Jaguar 00044 if (fwVer >= 3330 || fwVer < 92) 00045 { 00046 char buf[256]; 00047 if (fwVer < 3330) 00048 { 00049 snprintf(buf, 256, "Jag #%d firmware (%d) is too old (must be at least version 92 of the FIRST approved firmware)", m_deviceNumber, fwVer); 00050 } 00051 else 00052 { 00053 snprintf(buf, 256, "Jag #%d firmware (%d) is not FIRST approved (must be at least version 92 of the FIRST approved firmware)", m_deviceNumber, fwVer); 00054 } 00055 wpi_setWPIErrorWithContext(JaguarVersionError, buf); 00056 return; 00057 } 00058 switch (m_controlMode) 00059 { 00060 case kPercentVbus: 00061 case kVoltage: 00062 // No additional configuration required... start enabled. 00063 EnableControl(); 00064 break; 00065 default: 00066 break; 00067 } 00068 m_safetyHelper = new MotorSafetyHelper(this); 00069 } 00070 00076 CANJaguar::CANJaguar(UINT8 deviceNumber, ControlMode controlMode) 00077 : m_deviceNumber (deviceNumber) 00078 , m_controlMode (controlMode) 00079 , m_transactionSemaphore (NULL) 00080 , m_maxOutputVoltage (kApproxBusVoltage) 00081 , m_safetyHelper (NULL) 00082 { 00083 InitCANJaguar(); 00084 } 00085 00086 CANJaguar::~CANJaguar() 00087 { 00088 delete m_safetyHelper; 00089 m_safetyHelper = NULL; 00090 semDelete(m_transactionSemaphore); 00091 m_transactionSemaphore = NULL; 00092 } 00093 00107 void CANJaguar::Set(float outputValue, UINT8 syncGroup) 00108 { 00109 UINT32 messageID; 00110 UINT8 dataBuffer[8]; 00111 UINT8 dataSize; 00112 00113 if (m_safetyHelper && !m_safetyHelper->IsAlive()) 00114 { 00115 EnableControl(); 00116 } 00117 00118 switch(m_controlMode) 00119 { 00120 case kPercentVbus: 00121 { 00122 messageID = LM_API_VOLT_T_SET; 00123 if (outputValue > 1.0) outputValue = 1.0; 00124 if (outputValue < -1.0) outputValue = -1.0; 00125 dataSize = packPercentage(dataBuffer, outputValue); 00126 } 00127 break; 00128 case kSpeed: 00129 { 00130 messageID = LM_API_SPD_T_SET; 00131 dataSize = packFXP16_16(dataBuffer, outputValue); 00132 } 00133 break; 00134 case kPosition: 00135 { 00136 messageID = LM_API_POS_T_SET; 00137 dataSize = packFXP16_16(dataBuffer, outputValue); 00138 } 00139 break; 00140 case kCurrent: 00141 { 00142 messageID = LM_API_ICTRL_T_SET; 00143 dataSize = packFXP8_8(dataBuffer, outputValue); 00144 } 00145 break; 00146 case kVoltage: 00147 { 00148 messageID = LM_API_VCOMP_T_SET; 00149 dataSize = packFXP8_8(dataBuffer, outputValue); 00150 } 00151 break; 00152 default: 00153 return; 00154 } 00155 if (syncGroup != 0) 00156 { 00157 dataBuffer[dataSize] = syncGroup; 00158 dataSize++; 00159 } 00160 setTransaction(messageID, dataBuffer, dataSize); 00161 if (m_safetyHelper) m_safetyHelper->Feed(); 00162 } 00163 00176 float CANJaguar::Get() 00177 { 00178 UINT8 dataBuffer[8]; 00179 UINT8 dataSize; 00180 00181 switch(m_controlMode) 00182 { 00183 case kPercentVbus: 00184 getTransaction(LM_API_VOLT_SET, dataBuffer, &dataSize); 00185 if (dataSize == sizeof(INT16)) 00186 { 00187 return unpackPercentage(dataBuffer); 00188 } 00189 break; 00190 case kSpeed: 00191 getTransaction(LM_API_SPD_SET, dataBuffer, &dataSize); 00192 if (dataSize == sizeof(INT32)) 00193 { 00194 return unpackFXP16_16(dataBuffer); 00195 } 00196 break; 00197 case kPosition: 00198 getTransaction(LM_API_POS_SET, dataBuffer, &dataSize); 00199 if (dataSize == sizeof(INT32)) 00200 { 00201 return unpackFXP16_16(dataBuffer); 00202 } 00203 break; 00204 case kCurrent: 00205 getTransaction(LM_API_ICTRL_SET, dataBuffer, &dataSize); 00206 if (dataSize == sizeof(INT16)) 00207 { 00208 return unpackFXP8_8(dataBuffer); 00209 } 00210 break; 00211 case kVoltage: 00212 getTransaction(LM_API_VCOMP_SET, dataBuffer, &dataSize); 00213 if (dataSize == sizeof(INT16)) 00214 { 00215 return unpackFXP8_8(dataBuffer); 00216 } 00217 break; 00218 } 00219 return 0.0; 00220 } 00221 00227 void CANJaguar::Disable() 00228 { 00229 DisableControl(); 00230 } 00231 00239 void CANJaguar::PIDWrite(float output) 00240 { 00241 if (m_controlMode == kPercentVbus) 00242 { 00243 Set(output); 00244 } 00245 else 00246 { 00247 wpi_setWPIErrorWithContext(IncompatibleMode, "PID only supported in PercentVbus mode"); 00248 } 00249 } 00250 00251 UINT8 CANJaguar::packPercentage(UINT8 *buffer, double value) 00252 { 00253 INT16 intValue = (INT16)(value * 32767.0); 00254 *((INT16*)buffer) = swap16(intValue); 00255 return sizeof(INT16); 00256 } 00257 00258 UINT8 CANJaguar::packFXP8_8(UINT8 *buffer, double value) 00259 { 00260 INT16 intValue = (INT16)(value * 256.0); 00261 *((INT16*)buffer) = swap16(intValue); 00262 return sizeof(INT16); 00263 } 00264 00265 UINT8 CANJaguar::packFXP16_16(UINT8 *buffer, double value) 00266 { 00267 INT32 intValue = (INT32)(value * 65536.0); 00268 *((INT32*)buffer) = swap32(intValue); 00269 return sizeof(INT32); 00270 } 00271 00272 UINT8 CANJaguar::packINT16(UINT8 *buffer, INT16 value) 00273 { 00274 *((INT16*)buffer) = swap16(value); 00275 return sizeof(INT16); 00276 } 00277 00278 UINT8 CANJaguar::packINT32(UINT8 *buffer, INT32 value) 00279 { 00280 *((INT32*)buffer) = swap32(value); 00281 return sizeof(INT32); 00282 } 00283 00284 double CANJaguar::unpackPercentage(UINT8 *buffer) 00285 { 00286 INT16 value = *((INT16*)buffer); 00287 value = swap16(value); 00288 return value / 32767.0; 00289 } 00290 00291 double CANJaguar::unpackFXP8_8(UINT8 *buffer) 00292 { 00293 INT16 value = *((INT16*)buffer); 00294 value = swap16(value); 00295 return value / 256.0; 00296 } 00297 00298 double CANJaguar::unpackFXP16_16(UINT8 *buffer) 00299 { 00300 INT32 value = *((INT32*)buffer); 00301 value = swap32(value); 00302 return value / 65536.0; 00303 } 00304 00305 INT16 CANJaguar::unpackINT16(UINT8 *buffer) 00306 { 00307 INT16 value = *((INT16*)buffer); 00308 return swap16(value); 00309 } 00310 00311 INT32 CANJaguar::unpackINT32(UINT8 *buffer) 00312 { 00313 INT32 value = *((INT32*)buffer); 00314 return swap32(value); 00315 } 00316 00328 INT32 CANJaguar::sendMessage(UINT32 messageID, const UINT8 *data, UINT8 dataSize) 00329 { 00330 static const UINT32 kTrustedMessages[] = { 00331 LM_API_VOLT_T_EN, LM_API_VOLT_T_SET, LM_API_SPD_T_EN, LM_API_SPD_T_SET, 00332 LM_API_VCOMP_T_EN, LM_API_VCOMP_T_SET, LM_API_POS_T_EN, LM_API_POS_T_SET, 00333 LM_API_ICTRL_T_EN, LM_API_ICTRL_T_SET}; 00334 INT32 status=0; 00335 00336 for (UINT8 i=0; i<(sizeof(kTrustedMessages)/sizeof(kTrustedMessages[0])); i++) 00337 { 00338 if ((kFullMessageIDMask & messageID) == kTrustedMessages[i]) 00339 { 00340 UINT8 dataBuffer[8]; 00341 dataBuffer[0] = 0; 00342 dataBuffer[1] = 0; 00343 // Make sure the data will still fit after adjusting for the token. 00344 if (dataSize > 6) 00345 { 00346 // TODO: I would rather this not have to set the global error 00347 wpi_setGlobalWPIErrorWithContext(ParameterOutOfRange, "dataSize > 6"); 00348 return 0; 00349 } 00350 for (UINT8 j=0; j < dataSize; j++) 00351 { 00352 dataBuffer[j + 2] = data[j]; 00353 } 00354 FRC_NetworkCommunication_JaguarCANDriver_sendMessage(messageID, dataBuffer, dataSize + 2, &status); 00355 return status; 00356 } 00357 } 00358 FRC_NetworkCommunication_JaguarCANDriver_sendMessage(messageID, data, dataSize, &status); 00359 return status; 00360 } 00361 00371 INT32 CANJaguar::receiveMessage(UINT32 *messageID, UINT8 *data, UINT8 *dataSize, float timeout) 00372 { 00373 INT32 status = 0; 00374 FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(messageID, data, dataSize, 00375 (UINT32)(timeout * 1000), &status); 00376 return status; 00377 } 00378 00389 void CANJaguar::setTransaction(UINT32 messageID, const UINT8 *data, UINT8 dataSize) 00390 { 00391 UINT32 ackMessageID = LM_API_ACK | m_deviceNumber; 00392 INT32 localStatus = 0; 00393 00394 // If there was an error on this object and it wasn't a timeout, refuse to talk to the device 00395 // Call ClearError() on the object to try again 00396 if (StatusIsFatal() && GetError().GetCode() != -44087) 00397 return; 00398 00399 // Make sure we don't have more than one transaction with the same Jaguar outstanding. 00400 semTake(m_transactionSemaphore, WAIT_FOREVER); 00401 00402 // Throw away any stale acks. 00403 receiveMessage(&ackMessageID, NULL, 0, 0.0f); 00404 // Send the message with the data. 00405 localStatus = sendMessage(messageID | m_deviceNumber, data, dataSize); 00406 wpi_setErrorWithContext(localStatus, "sendMessage"); 00407 // Wait for an ack. 00408 localStatus = receiveMessage(&ackMessageID, NULL, 0); 00409 wpi_setErrorWithContext(localStatus, "receiveMessage"); 00410 00411 // Transaction complete. 00412 semGive(m_transactionSemaphore); 00413 } 00414 00424 void CANJaguar::getTransaction(UINT32 messageID, UINT8 *data, UINT8 *dataSize) 00425 { 00426 UINT32 targetedMessageID = messageID | m_deviceNumber; 00427 INT32 localStatus = 0; 00428 00429 // If there was an error on this object and it wasn't a timeout, refuse to talk to the device 00430 // Call ClearError() on the object to try again 00431 if (StatusIsFatal() && GetError().GetCode() != -44087) 00432 { 00433 if (dataSize != NULL) 00434 *dataSize = 0; 00435 return; 00436 } 00437 00438 // Make sure we don't have more than one transaction with the same Jaguar outstanding. 00439 semTake(m_transactionSemaphore, WAIT_FOREVER); 00440 00441 // Throw away any stale responses. 00442 receiveMessage(&targetedMessageID, NULL, 0, 0.0f); 00443 // Send the message requesting data. 00444 localStatus = sendMessage(targetedMessageID, NULL, 0); 00445 wpi_setErrorWithContext(localStatus, "sendMessage"); 00446 // Caller may have set bit31 for remote frame transmission so clear invalid bits[31-29] 00447 targetedMessageID &= 0x1FFFFFFF; 00448 // Wait for the data. 00449 localStatus = receiveMessage(&targetedMessageID, data, dataSize); 00450 wpi_setErrorWithContext(localStatus, "receiveMessage"); 00451 00452 // Transaction complete. 00453 semGive(m_transactionSemaphore); 00454 } 00455 00463 void CANJaguar::SetSpeedReference(SpeedReference reference) 00464 { 00465 UINT8 dataBuffer[8]; 00466 00467 dataBuffer[0] = reference; 00468 setTransaction(LM_API_SPD_REF, dataBuffer, sizeof(UINT8)); 00469 } 00470 00476 CANJaguar::SpeedReference CANJaguar::GetSpeedReference() 00477 { 00478 UINT8 dataBuffer[8]; 00479 UINT8 dataSize; 00480 00481 getTransaction(LM_API_SPD_REF, dataBuffer, &dataSize); 00482 if (dataSize == sizeof(UINT8)) 00483 { 00484 return (SpeedReference)*dataBuffer; 00485 } 00486 return kSpeedRef_None; 00487 } 00488 00497 void CANJaguar::SetPositionReference(PositionReference reference) 00498 { 00499 UINT8 dataBuffer[8]; 00500 00501 dataBuffer[0] = reference; 00502 setTransaction(LM_API_POS_REF, dataBuffer, sizeof(UINT8)); 00503 } 00504 00510 CANJaguar::PositionReference CANJaguar::GetPositionReference() 00511 { 00512 UINT8 dataBuffer[8]; 00513 UINT8 dataSize; 00514 00515 getTransaction(LM_API_POS_REF, dataBuffer, &dataSize); 00516 if (dataSize == sizeof(UINT8)) 00517 { 00518 return (PositionReference)*dataBuffer; 00519 } 00520 return kPosRef_None; 00521 } 00522 00530 void CANJaguar::SetPID(double p, double i, double d) 00531 { 00532 UINT8 dataBuffer[8]; 00533 UINT8 dataSize; 00534 00535 switch(m_controlMode) 00536 { 00537 case kPercentVbus: 00538 case kVoltage: 00539 wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode"); 00540 break; 00541 case kSpeed: 00542 dataSize = packFXP16_16(dataBuffer, p); 00543 setTransaction(LM_API_SPD_PC, dataBuffer, dataSize); 00544 dataSize = packFXP16_16(dataBuffer, i); 00545 setTransaction(LM_API_SPD_IC, dataBuffer, dataSize); 00546 dataSize = packFXP16_16(dataBuffer, d); 00547 setTransaction(LM_API_SPD_DC, dataBuffer, dataSize); 00548 break; 00549 case kPosition: 00550 dataSize = packFXP16_16(dataBuffer, p); 00551 setTransaction(LM_API_POS_PC, dataBuffer, dataSize); 00552 dataSize = packFXP16_16(dataBuffer, i); 00553 setTransaction(LM_API_POS_IC, dataBuffer, dataSize); 00554 dataSize = packFXP16_16(dataBuffer, d); 00555 setTransaction(LM_API_POS_DC, dataBuffer, dataSize); 00556 break; 00557 case kCurrent: 00558 dataSize = packFXP16_16(dataBuffer, p); 00559 setTransaction(LM_API_ICTRL_PC, dataBuffer, dataSize); 00560 dataSize = packFXP16_16(dataBuffer, i); 00561 setTransaction(LM_API_ICTRL_IC, dataBuffer, dataSize); 00562 dataSize = packFXP16_16(dataBuffer, d); 00563 setTransaction(LM_API_ICTRL_DC, dataBuffer, dataSize); 00564 break; 00565 } 00566 } 00567 00573 double CANJaguar::GetP() 00574 { 00575 UINT8 dataBuffer[8]; 00576 UINT8 dataSize; 00577 00578 switch(m_controlMode) 00579 { 00580 case kPercentVbus: 00581 case kVoltage: 00582 wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode"); 00583 break; 00584 case kSpeed: 00585 getTransaction(LM_API_SPD_PC, dataBuffer, &dataSize); 00586 if (dataSize == sizeof(INT32)) 00587 { 00588 return unpackFXP16_16(dataBuffer); 00589 } 00590 break; 00591 case kPosition: 00592 getTransaction(LM_API_POS_PC, dataBuffer, &dataSize); 00593 if (dataSize == sizeof(INT32)) 00594 { 00595 return unpackFXP16_16(dataBuffer); 00596 } 00597 break; 00598 case kCurrent: 00599 getTransaction(LM_API_ICTRL_PC, dataBuffer, &dataSize); 00600 if (dataSize == sizeof(INT32)) 00601 { 00602 return unpackFXP16_16(dataBuffer); 00603 } 00604 break; 00605 } 00606 return 0.0; 00607 } 00608 00614 double CANJaguar::GetI() 00615 { 00616 UINT8 dataBuffer[8]; 00617 UINT8 dataSize; 00618 00619 switch(m_controlMode) 00620 { 00621 case kPercentVbus: 00622 case kVoltage: 00623 wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode"); 00624 break; 00625 case kSpeed: 00626 getTransaction(LM_API_SPD_IC, dataBuffer, &dataSize); 00627 if (dataSize == sizeof(INT32)) 00628 { 00629 return unpackFXP16_16(dataBuffer); 00630 } 00631 break; 00632 case kPosition: 00633 getTransaction(LM_API_POS_IC, dataBuffer, &dataSize); 00634 if (dataSize == sizeof(INT32)) 00635 { 00636 return unpackFXP16_16(dataBuffer); 00637 } 00638 break; 00639 case kCurrent: 00640 getTransaction(LM_API_ICTRL_IC, dataBuffer, &dataSize); 00641 if (dataSize == sizeof(INT32)) 00642 { 00643 return unpackFXP16_16(dataBuffer); 00644 } 00645 break; 00646 } 00647 return 0.0; 00648 } 00649 00655 double CANJaguar::GetD() 00656 { 00657 UINT8 dataBuffer[8]; 00658 UINT8 dataSize; 00659 00660 switch(m_controlMode) 00661 { 00662 case kPercentVbus: 00663 case kVoltage: 00664 wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode"); 00665 break; 00666 case kSpeed: 00667 getTransaction(LM_API_SPD_DC, dataBuffer, &dataSize); 00668 if (dataSize == sizeof(INT32)) 00669 { 00670 return unpackFXP16_16(dataBuffer); 00671 } 00672 break; 00673 case kPosition: 00674 getTransaction(LM_API_POS_DC, dataBuffer, &dataSize); 00675 if (dataSize == sizeof(INT32)) 00676 { 00677 return unpackFXP16_16(dataBuffer); 00678 } 00679 break; 00680 case kCurrent: 00681 getTransaction(LM_API_ICTRL_DC, dataBuffer, &dataSize); 00682 if (dataSize == sizeof(INT32)) 00683 { 00684 return unpackFXP16_16(dataBuffer); 00685 } 00686 break; 00687 } 00688 return 0.0; 00689 } 00690 00701 void CANJaguar::EnableControl(double encoderInitialPosition) 00702 { 00703 UINT8 dataBuffer[8]; 00704 UINT8 dataSize = 0; 00705 00706 switch(m_controlMode) 00707 { 00708 case kPercentVbus: 00709 setTransaction(LM_API_VOLT_T_EN, dataBuffer, dataSize); 00710 break; 00711 case kSpeed: 00712 setTransaction(LM_API_SPD_T_EN, dataBuffer, dataSize); 00713 break; 00714 case kPosition: 00715 dataSize = packFXP16_16(dataBuffer, encoderInitialPosition); 00716 setTransaction(LM_API_POS_T_EN, dataBuffer, dataSize); 00717 break; 00718 case kCurrent: 00719 setTransaction(LM_API_ICTRL_T_EN, dataBuffer, dataSize); 00720 break; 00721 case kVoltage: 00722 setTransaction(LM_API_VCOMP_T_EN, dataBuffer, dataSize); 00723 break; 00724 } 00725 } 00726 00732 void CANJaguar::DisableControl() 00733 { 00734 UINT8 dataBuffer[8]; 00735 UINT8 dataSize = 0; 00736 00737 switch(m_controlMode) 00738 { 00739 case kPercentVbus: 00740 setTransaction(LM_API_VOLT_DIS, dataBuffer, dataSize); 00741 break; 00742 case kSpeed: 00743 setTransaction(LM_API_SPD_DIS, dataBuffer, dataSize); 00744 break; 00745 case kPosition: 00746 setTransaction(LM_API_POS_DIS, dataBuffer, dataSize); 00747 break; 00748 case kCurrent: 00749 setTransaction(LM_API_ICTRL_DIS, dataBuffer, dataSize); 00750 break; 00751 case kVoltage: 00752 setTransaction(LM_API_VCOMP_DIS, dataBuffer, dataSize); 00753 break; 00754 } 00755 } 00756 00765 void CANJaguar::ChangeControlMode(ControlMode controlMode) 00766 { 00767 // Disable the previous mode 00768 DisableControl(); 00769 00770 // Update the local mode 00771 m_controlMode = controlMode; 00772 } 00773 00781 CANJaguar::ControlMode CANJaguar::GetControlMode() 00782 { 00783 UINT8 dataBuffer[8]; 00784 UINT8 dataSize; 00785 00786 getTransaction(LM_API_STATUS_CMODE, dataBuffer, &dataSize); 00787 if (dataSize == sizeof(INT8)) 00788 { 00789 return (ControlMode)dataBuffer[0]; 00790 } 00791 return kPercentVbus; 00792 } 00793 00799 float CANJaguar::GetBusVoltage() 00800 { 00801 UINT8 dataBuffer[8]; 00802 UINT8 dataSize; 00803 00804 getTransaction(LM_API_STATUS_VOLTBUS, dataBuffer, &dataSize); 00805 if (dataSize == sizeof(INT16)) 00806 { 00807 return unpackFXP8_8(dataBuffer); 00808 } 00809 return 0.0; 00810 } 00811 00817 float CANJaguar::GetOutputVoltage() 00818 { 00819 UINT8 dataBuffer[8]; 00820 UINT8 dataSize; 00821 00822 // Read the volt out which is in Volts units. 00823 getTransaction(LM_API_STATUS_VOUT, dataBuffer, &dataSize); 00824 if (dataSize == sizeof(INT16)) 00825 { 00826 return unpackFXP8_8(dataBuffer); 00827 } 00828 return 0.0; 00829 } 00830 00836 float CANJaguar::GetOutputCurrent() 00837 { 00838 UINT8 dataBuffer[8]; 00839 UINT8 dataSize; 00840 00841 getTransaction(LM_API_STATUS_CURRENT, dataBuffer, &dataSize); 00842 if (dataSize == sizeof(INT16)) 00843 { 00844 return unpackFXP8_8(dataBuffer); 00845 } 00846 return 0.0; 00847 } 00848 00854 float CANJaguar::GetTemperature() 00855 { 00856 UINT8 dataBuffer[8]; 00857 UINT8 dataSize; 00858 00859 getTransaction(LM_API_STATUS_TEMP, dataBuffer, &dataSize); 00860 if (dataSize == sizeof(INT16)) 00861 { 00862 return unpackFXP8_8(dataBuffer); 00863 } 00864 return 0.0; 00865 } 00866 00872 double CANJaguar::GetPosition() 00873 { 00874 UINT8 dataBuffer[8]; 00875 UINT8 dataSize; 00876 00877 getTransaction(LM_API_STATUS_POS, dataBuffer, &dataSize); 00878 if (dataSize == sizeof(INT32)) 00879 { 00880 return unpackFXP16_16(dataBuffer); 00881 } 00882 return 0.0; 00883 } 00884 00890 double CANJaguar::GetSpeed() 00891 { 00892 UINT8 dataBuffer[8]; 00893 UINT8 dataSize; 00894 00895 getTransaction(LM_API_STATUS_SPD, dataBuffer, &dataSize); 00896 if (dataSize == sizeof(INT32)) 00897 { 00898 return unpackFXP16_16(dataBuffer); 00899 } 00900 return 0.0; 00901 } 00902 00908 bool CANJaguar::GetForwardLimitOK() 00909 { 00910 UINT8 dataBuffer[8]; 00911 UINT8 dataSize; 00912 00913 getTransaction(LM_API_STATUS_LIMIT, dataBuffer, &dataSize); 00914 if (dataSize == sizeof(UINT8)) 00915 { 00916 return (*dataBuffer & kForwardLimit) != 0; 00917 } 00918 return 0; 00919 } 00920 00926 bool CANJaguar::GetReverseLimitOK() 00927 { 00928 UINT8 dataBuffer[8]; 00929 UINT8 dataSize; 00930 00931 getTransaction(LM_API_STATUS_LIMIT, dataBuffer, &dataSize); 00932 if (dataSize == sizeof(UINT8)) 00933 { 00934 return (*dataBuffer & kReverseLimit) != 0; 00935 } 00936 return 0; 00937 } 00938 00944 UINT16 CANJaguar::GetFaults() 00945 { 00946 UINT8 dataBuffer[8]; 00947 UINT8 dataSize; 00948 00949 getTransaction(LM_API_STATUS_FAULT, dataBuffer, &dataSize); 00950 if (dataSize == sizeof(UINT16)) 00951 { 00952 return unpackINT16(dataBuffer); 00953 } 00954 return 0; 00955 } 00956 00965 bool CANJaguar::GetPowerCycled() 00966 { 00967 UINT8 dataBuffer[8]; 00968 UINT8 dataSize; 00969 00970 getTransaction(LM_API_STATUS_POWER, dataBuffer, &dataSize); 00971 if (dataSize == sizeof(UINT8)) 00972 { 00973 bool powerCycled = (*dataBuffer != 0); 00974 00975 // Clear the power cycled bit now that we've accessed it 00976 if (powerCycled) 00977 { 00978 dataBuffer[0] = 1; 00979 setTransaction(LM_API_STATUS_POWER, dataBuffer, sizeof(UINT8)); 00980 } 00981 00982 return powerCycled; 00983 } 00984 return 0; 00985 } 00986 00995 void CANJaguar::SetVoltageRampRate(double rampRate) 00996 { 00997 UINT8 dataBuffer[8]; 00998 UINT8 dataSize; 00999 01000 switch(m_controlMode) 01001 { 01002 case kPercentVbus: 01003 dataSize = packPercentage(dataBuffer, rampRate / (m_maxOutputVoltage * kControllerRate)); 01004 setTransaction(LM_API_VOLT_SET_RAMP, dataBuffer, dataSize); 01005 break; 01006 case kVoltage: 01007 dataSize = packFXP8_8(dataBuffer, rampRate / kControllerRate); 01008 setTransaction(LM_API_VCOMP_IN_RAMP, dataBuffer, dataSize); 01009 break; 01010 default: 01011 return; 01012 } 01013 } 01014 01020 UINT32 CANJaguar::GetFirmwareVersion() 01021 { 01022 UINT8 dataBuffer[8]; 01023 UINT8 dataSize; 01024 01025 // Set the MSB to tell the 2CAN that this is a remote message. 01026 getTransaction(0x80000000 | CAN_MSGID_API_FIRMVER, dataBuffer, &dataSize); 01027 if (dataSize == sizeof(UINT32)) 01028 { 01029 return unpackINT32(dataBuffer); 01030 } 01031 return 0; 01032 } 01033 01039 UINT8 CANJaguar::GetHardwareVersion() 01040 { 01041 UINT8 dataBuffer[8]; 01042 UINT8 dataSize; 01043 01044 getTransaction(LM_API_HWVER, dataBuffer, &dataSize); 01045 if (dataSize == sizeof(UINT8)+sizeof(UINT8)) 01046 { 01047 if (*dataBuffer == m_deviceNumber) 01048 { 01049 return *(dataBuffer+1); 01050 } 01051 } 01052 // Assume Gray Jag if there is no response 01053 return LM_HWVER_JAG_1_0; 01054 } 01055 01063 void CANJaguar::ConfigNeutralMode(NeutralMode mode) 01064 { 01065 UINT8 dataBuffer[8]; 01066 01067 dataBuffer[0] = mode; 01068 setTransaction(LM_API_CFG_BRAKE_COAST, dataBuffer, sizeof(UINT8)); 01069 } 01070 01076 void CANJaguar::ConfigEncoderCodesPerRev(UINT16 codesPerRev) 01077 { 01078 UINT8 dataBuffer[8]; 01079 UINT8 dataSize; 01080 01081 dataSize = packINT16(dataBuffer, codesPerRev); 01082 setTransaction(LM_API_CFG_ENC_LINES, dataBuffer, dataSize); 01083 } 01084 01093 void CANJaguar::ConfigPotentiometerTurns(UINT16 turns) 01094 { 01095 UINT8 dataBuffer[8]; 01096 UINT8 dataSize; 01097 01098 dataSize = packINT16(dataBuffer, turns); 01099 setTransaction(LM_API_CFG_POT_TURNS, dataBuffer, dataSize); 01100 } 01101 01112 void CANJaguar::ConfigSoftPositionLimits(double forwardLimitPosition, double reverseLimitPosition) 01113 { 01114 UINT8 dataBuffer[8]; 01115 UINT8 dataSize; 01116 01117 dataSize = packFXP16_16(dataBuffer, forwardLimitPosition); 01118 dataBuffer[dataSize++] = forwardLimitPosition > reverseLimitPosition; 01119 setTransaction(LM_API_CFG_LIMIT_FWD, dataBuffer, dataSize); 01120 01121 dataSize = packFXP16_16(dataBuffer, reverseLimitPosition); 01122 dataBuffer[dataSize++] = forwardLimitPosition <= reverseLimitPosition; 01123 setTransaction(LM_API_CFG_LIMIT_REV, dataBuffer, dataSize); 01124 01125 dataBuffer[0] = kLimitMode_SoftPositionLimits; 01126 setTransaction(LM_API_CFG_LIMIT_MODE, dataBuffer, sizeof(UINT8)); 01127 } 01128 01134 void CANJaguar::DisableSoftPositionLimits() 01135 { 01136 UINT8 dataBuffer[8]; 01137 01138 dataBuffer[0] = kLimitMode_SwitchInputsOnly; 01139 setTransaction(LM_API_CFG_LIMIT_MODE, dataBuffer, sizeof(UINT8)); 01140 } 01141 01150 void CANJaguar::ConfigMaxOutputVoltage(double voltage) 01151 { 01152 UINT8 dataBuffer[8]; 01153 UINT8 dataSize; 01154 01155 m_maxOutputVoltage = voltage; 01156 dataSize = packFXP8_8(dataBuffer, voltage); 01157 setTransaction(LM_API_CFG_MAX_VOUT, dataBuffer, dataSize); 01158 } 01159 01168 void CANJaguar::ConfigFaultTime(float faultTime) 01169 { 01170 UINT8 dataBuffer[8]; 01171 UINT8 dataSize; 01172 01173 // Message takes ms 01174 dataSize = packINT16(dataBuffer, (INT16)(faultTime * 1000.0)); 01175 setTransaction(LM_API_CFG_FAULT_TIME, dataBuffer, dataSize); 01176 } 01177 01183 void CANJaguar::UpdateSyncGroup(UINT8 syncGroup) 01184 { 01185 sendMessage(CAN_MSGID_API_SYNC, &syncGroup, sizeof(syncGroup)); 01186 } 01187 01188 01189 void CANJaguar::SetExpiration(float timeout) 01190 { 01191 if (m_safetyHelper) m_safetyHelper->SetExpiration(timeout); 01192 } 01193 01194 float CANJaguar::GetExpiration() 01195 { 01196 if (!m_safetyHelper) return 0.0; 01197 return m_safetyHelper->GetExpiration(); 01198 } 01199 01200 bool CANJaguar::IsAlive() 01201 { 01202 if (!m_safetyHelper) return false; 01203 return m_safetyHelper->IsAlive(); 01204 } 01205 01206 bool CANJaguar::IsSafetyEnabled() 01207 { 01208 if (!m_safetyHelper) return false; 01209 return m_safetyHelper->IsSafetyEnabled(); 01210 } 01211 01212 void CANJaguar::SetSafetyEnabled(bool enabled) 01213 { 01214 if (m_safetyHelper) m_safetyHelper->SetSafetyEnabled(enabled); 01215 } 01216 01217 void CANJaguar::GetDescription(char *desc) 01218 { 01219 sprintf(desc, "CANJaguar ID %d", m_deviceNumber); 01220 } 01221 01228 void CANJaguar::StopMotor() 01229 { 01230 DisableControl(); 01231 } 01232
Generated on Thu Jan 12 2012 22:35:18 for WPILibC++ by
1.7.1