59 #include "rnr/rnrconfig.h" 81 static const char *SubSysName =
"Motors";
82 static const char *ProdName =
"RoboClaw";
89 const char *m_sCtlrKey;
96 const char *m_sMotorKey;
98 } m_motors[LaeNumMotorsPerCtlr];
107 LaeKeyFront, LaeMotorCtlrAddrFront, LaeMotorCtlrIdFront,
true,
false,
108 { {LaeKeyLeftFront, LaeMotorLeft}, {LaeKeyRightFront, LaeMotorRight} }
112 LaeKeyRear, LaeMotorCtlrAddrRear, LaeMotorCtlrIdRear,
true,
false,
113 { {LaeKeyLeftRear, LaeMotorLeft}, {LaeKeyRightRear, LaeMotorRight} }
131 string strDevSymName(LaeDevMotorCtlrs);
133 int nBaudRate = LaeBaudRateMotorCtlrs;
137 printSubHdr(
"Initialize Motor Controller Interfaces");
146 printTestResult(FatalTag,
"Motor controllers power enable.");
152 printTestResult(PassTag,
"Enabled power to motor controllers.");
160 MotorCtlrEnable.
sync();
166 printTestResult(WarnTag,
167 "Motor controllers are already enabled - may be in usse by another " 171 else if( MotorCtlrEnable.
enable() )
173 printTestResult(PassTag,
"Motor controllers enabled.");
178 printTestResult(FatalTag,
"Motor controllers failed to be enabled.");
191 if( MotorCtlrCs.
open(LaeGpioMotorCtlrCs) < 0 )
193 printTestResult(FatalTag,
194 "Failed to open motor controllers chip select on GPIO pin %d: %s(%d).",
195 LaeGpioMotorCtlrCs, strerror(errno), errno);
200 printTestResult(PassTag,
201 "Open motor controllers chip select on GPIO pin %d.",
215 if( MotorCtlrComm.
open(strDevName, nBaudRate) < 0 )
217 printTestResult(FatalTag,
218 "%s: Failed to open motor controllers comm at %d baud: %s(%d)",
219 strDevName.c_str(), nBaudRate, strerror(errno), errno);
224 printTestResult(PassTag,
225 "Open motor controllers serial communication on %s@%d.",
226 strDevName.c_str(), nBaudRate);
240 nCtlr = LaeMotorCtlrIdFront;
242 new RoboClaw(MotorCtlrComm, LaeMotorCtlrAddrFront, LaeKeyFront);
243 MotorCtlr[nCtlr]->
setMotorDir(LaeMotorLeft, LaeMotorDirNormal);
244 MotorCtlr[nCtlr]->
setMotorDir(LaeMotorRight, LaeMotorDirNormal);
245 printTestResult(PassTag,
246 "Created %s motor controller interface, address=0x%02x.",
247 LaeKeyFront, LaeMotorCtlrAddrFront);
255 nCtlr = LaeMotorCtlrIdRear;
257 new RoboClaw(MotorCtlrComm, LaeMotorCtlrAddrRear, LaeKeyRear);
258 MotorCtlr[nCtlr]->
setMotorDir(LaeMotorLeft, LaeMotorDirNormal);
259 MotorCtlr[nCtlr]->
setMotorDir(LaeMotorRight, LaeMotorDirNormal);
260 printTestResult(PassTag,
261 "Created %s motor controller interface, address=0x%02x.",
262 LaeKeyRear, LaeMotorCtlrAddrRear);
272 double fMainBattMinV, fMainBattMaxV;
273 double fLogicMinV, fLogicMaxV;
282 printSubHdr(
"Read Motor Controller Information and State");
284 pCtlr = MotorCtlr[info.
m_idx];
293 printTestResult(sTag,
"Motor Controller %s(0x%02x): Read firmware version.",
305 printTestResult(sTag,
306 "Motor Controller %s(0x%02x): Read main battery voltage cutoffs.",
318 printTestResult(sTag,
319 "Motor Controller %s(0x%02x): Read logic voltage cutoffs.",
330 printTestResult(sTag,
"Motor Controller %s(0x%02x): Read error status.",
341 printTestResult(sTag,
"Motor Controller %s(0x%02x): Read board temperature.",
353 printTestResult(sTag,
354 "Motor Controller %s(0x%02x): Read main battery voltage.",
365 printTestResult(sTag,
366 "Motor Controller %s(0x%02x): Read logic voltage.",
370 printf(
"Motor controller %s Info and State Summary:\n", info.
m_sCtlrKey);
372 printf(
" Address: 0x%02x\n", pCtlr->
getAddress());
373 printf(
" Motor Controller: %s\n", ProdName);
374 printf(
" FW Version: %s\n", strFwVer.c_str());
375 printf(
" Main Battery Cutoffs(V): [%.1lf, %.1lf]\n",
376 fMainBattMinV, fMainBattMaxV);
377 printf(
" Logic Cutoffs(V): [%.1lf, %.1lf]\n", fLogicMinV, fLogicMaxV);
378 printf(
" Status: 0x%04x\n", uErrors);
379 printf(
" Temperature(C): %.1lf\n", fTemp);
380 printf(
" Battery(V): %.1lf\n", fMainBattV);
381 printf(
" Logic(v): %.1lf\n", fLogicV);
394 for(nCtlr = 0; nCtlr < LaeNumMotorCtlrs; ++nCtlr)
396 stats = readCtlrState(MotorsInfo[nCtlr]);
398 printSubTotals(stats);
400 statsSubTotal += stats;
403 return statsSubTotal;
409 const char *sCtlrKey;
410 const char *sMotorKey;
418 double fMaxMaxMotorAmps;
426 printSubHdr(
"Read Motor Information and State");
428 pCtlr = MotorCtlr[info.
m_idx];
435 if( nMotor == Motor1 )
448 printTestResult(sTag,
"Motor %s: Read encoder mode.", sMotorKey);
452 if( mode == ParamEncModeQuad )
454 strEncMode =
"Quadrature";
458 else if( mode & ParamEncModeAbs )
460 strEncMode =
"Absolute";
462 else if( mode & ParamEncModeRCAnalogEn )
464 strEncMode =
"RC Analog";
468 strEncMode =
"Unknown";
470 printTestResult(sTag,
"Motor %s: Encoder mode 0x%02x = %s.",
471 sMotorKey, mode, strEncMode.c_str());
482 Kp = (double)uKp / (
double)ParamVelPidCvt;
483 Ki = (double)uKi / (
double)ParamVelPidCvt;
484 Kd = (double)uKd / (
double)ParamVelPidCvt;
486 printTestResult(sTag,
"Motor %s: Read velocity PID constants.", sMotorKey);
497 printTestResult(sTag,
"Motor %s: Read maximum current limit.", sMotorKey);
501 fMaxMaxMotorAmps = LaeMotorMaxAmps_2_1;
505 fMaxMaxMotorAmps = LaeMotorMaxAmps_2_0;
510 if( fMaxAmps <= fMaxMaxMotorAmps )
515 printTestResult(sTag,
516 "Motor %s: Maximum current limit %.2lf <= system max of %.2lf amps.",
517 sMotorKey, fMaxAmps, fMaxMaxMotorAmps);
527 printTestResult(sTag,
"Motor %s: Read motor encoder position.", sMotorKey);
537 printTestResult(sTag,
"Motor %s: Read motor speed.", sMotorKey);
542 if( nMotor == Motor1 )
555 printTestResult(sTag,
"Motor %s: Read motor current draw.", sMotorKey);
558 printf(
"Motor %s Info and State Summary:\n", sMotorKey);
559 printf(
" Encoder Mode: 0x%02x (%s)\n", mode, strEncMode.c_str());
560 printf(
" Velocity PID:\n");
561 printf(
" Kp: %3lf (raw = 0x%08x)\n", Kp, uKp);
562 printf(
" Ki: %3lf (raw = 0x%08x)\n", Ki, uKi);
563 printf(
" Kd: %3lf (raw = 0x%08x)\n", Kd, uKd);
564 printf(
" Max QPPS: %u\n", qpps);
565 printf(
" Max. Current: %.2lf (amperes)\n", fMaxAmps);
567 printf(
" Encoder: %ld (pulses)\n", encoder);
569 printf(
" Encoder: %lld (pulses)\n", encoder);
571 printf(
" Speed: %d (qpps)\n", speed);
572 printf(
" Draw: %.2lf (amperes)\n", amps);
586 for(i = 0; i < LaeNumMotorCtlrs; ++i)
588 for(j = 0; j < LaeNumMotorCtlrs; ++j)
590 stats = readMotorState(MotorsInfo[i], MotorsInfo[i].m_motors[j].m_idx);
592 printSubTotals(stats);
594 statsSubTotal += stats;
598 return statsSubTotal;
604 static s32_t speedProf[] =
606 1000, 5000, 8000, 5000, 1000, -1000, -5000, -8000, -5000, -1000
609 uint_t red, green, blue;
616 const char *sCtlrKey;
618 const char *sMotorKey;
630 for(i = 0; i < LaeNumMotorCtlrs; ++i)
632 pCtlr = MotorCtlr[MotorsInfo[i].
m_idx];
633 sCtlrKey = MotorsInfo[i].m_sCtlrKey;
643 printTestResult(sTag,
"%s motors stopped.", sCtlrKey);
652 printTestResult(sTag,
"%s motor encoders reset.", sCtlrKey);
658 for(i = 0; i < LaeNumMotorCtlrs; ++i)
660 pCtlr = MotorCtlr[MotorsInfo[i].
m_idx];
661 sCtlrKey = MotorsInfo[i].m_sCtlrKey;
663 for(j = 0; j < LaeNumMotorCtlrs; ++j)
665 nMotor = MotorsInfo[i].m_motors[j].m_idx;
666 sMotorKey = MotorsInfo[i].m_motors[j].m_sMotorKey;
668 for(k = 0; k < arraysize(speedProf); ++k)
671 if( pCtlr->
cmdQDrive(nMotor, speedProf[k]) == OK )
674 printTestResult(PassTag,
"Motor %s: Set target speed=%d.",
675 sMotorKey, speedProf[k]);
677 wt = fabs((
float)speedProf[k] / 8000.0);
678 if( speedProf[k] < 0 )
680 red = (uint_t)(255.0 * wt);
688 blue = (uint_t)(255.0 * wt);
696 printTestResult(FailTag,
"Motor %s: Set target speed=%d.",
697 sMotorKey, speedProf[k]);
703 safeSpeed = speedProf[k] != 0? speedProf[k]: 1;
706 for(t = 0.0; !bAtSpeed && t <= 4.0; t += 0.1)
712 if( fabs(speed - speedProf[k])/ fabs(safeSpeed) <= 0.05 )
720 if( isatty(fileno(stdout)) )
723 printf(
"%s Motor %s: Accelerating: speed=%5d: encoder=%8ld\r",
724 WaitTag, sMotorKey, speed, encoder);
726 printf(
"%s Motor %s: Accelerating: speed=%5d: encoder=%8lld\r",
727 WaitTag, sMotorKey, speed, encoder);
728 #endif // ARCH_x86_64 739 printTestResult(sTag,
740 "Motor %s: Accelerating: speed=%5d: encoder %8ld.",
741 sMotorKey, speed, encoder);
743 printTestResult(sTag,
744 "Motor %s: Accelerating: speed=%5d: encoder %8lld.",
745 sMotorKey, speed, encoder);
746 #endif // ARCH_x86_64 751 if( pCtlr->
cmdStop(nMotor) == OK )
757 printTestResult(sTag,
"Motor %s stopped.", sMotorKey);
768 printSubHdr(
"De-Initialize Motor Controller Interfaces");
777 printTestResult(FailTag,
"Motor controllers power disable.");
781 printTestResult(PassTag,
"Disabled power to motor controllers.");
790 if( MotorCtlrComm.
close() < 0 )
792 printTestResult(FailTag,
"Close motor controllers serial connection.");
796 printTestResult(PassTag,
"Close serial connection with motor controllers.");
803 DiagStats runMotorsDiagnostics(
bool bTestMotion)
808 printHdr(
"Motors Diagnostics");
812 printf(
" (Warning: motors and wheels will rotate)");
820 statsTest = initMotorInterfaces();
822 printSubTotals(statsTest);
824 statsTotal += statsTest;
829 if( !statsTotal.fatal )
831 statsTest = testMotorCtlrsState();
833 printSubTotals(statsTest);
835 statsTotal += statsTest;
841 if( !statsTotal.fatal )
843 statsTest = testMotorsState();
845 printSubTotals(statsTest);
847 statsTotal += statsTest;
855 if( !statsTotal.fatal )
857 statsTest = testMotors();
859 printSubTotals(statsTest);
861 statsTotal += statsTest;
868 statsTest = deinitMotorInterfaces();
870 printSubTotals(statsTest);
872 statsTotal += statsTest;
874 printSubTotals(statsTest);
876 statsTotal += statsTest;
881 printTotals(statsTotal);
uint_t getProdHwVer() const
Get this robot's packed hardware version number.
virtual int cmdEnableMotorCtlrs(bool bEnable)
Enable/disable power in to motor controllers.
RoboClaw 2 motor controller class.
static LaelapsMotorsInfo MotorsInfo[LaeNumMotorCtlrs]
Laelaps motors subsystem information.
virtual int cmdReadEncoderMode(byte_t &mode1, byte_t &mode2)
Read encoder mode.
virtual void setMotorDir(int motor, int motorDir)
set the direction of motor rotation.
virtual int cmdQDrive(int motor, s32_t speed)
Drive a motor at the given speed.
virtual int open(std::string &strDevName, int nBaudRate, RoboClawChipSelect *pChipSelect=NULL)
Open connection to motor controller(s).
virtual int cmdResetQEncoders()
Reset both motors' encoders.
uint_t m_addr
motor controller address.
bool isEnabled()
Test if power to motor controllers is enabled.
Laelaps motor controller power enable class.
struct LaelapsMotorsInfo::@0 m_motors[LaeNumMotorsPerCtlr]
motors info
virtual int cmdReadMotorMaxCurrentLimit(int motor, double &maxAmps)
Read a motor's maximum current limit.
virtual int cmdReadMotorCurrentDraw(double &s1, double &s2)
Read the motors ampere draw.
Laelaps motors subsystem information structure.
RoboClaw motor controller chip select class.
RoboClaw motor controller class interface.
Laelaps WatchDog software class interface.
bool enable()
Enable power to motor controllers.
virtual int cmdResetRgbLed()
Reset the LED RGB color to state defaults.
virtual int cmdSetRgbLed(uint_t red, uint_t green, uint_t blue)
Set the LED RGB color command.
Laelaps Odroid General Purpose I/O class interfaces.
virtual int cmdReadBoardTemperature(double &temp)
Read RoboClaw board's temperature.
virtual int cmdReadMainBattCutoffs(double &min, double &max)
Read the RoboClaw's main battery minimum and maximum voltage cutoff settings.
virtual int cmdQStop()
Stop both motors.
The <b><i>Laelaps</i></b> namespace encapsulates all <b><i>Laelaps</i></b> related constructs...
Simple diagnostics statistics class.
virtual int cmdReadFwVersion(std::string &strFwVer)
Read the RoboClaw's firmware version.
Laelaps common utilities.
const char * m_sMotorKey
motor key
bool isConfigured() const
Is the exported GPIO number configured to match this ojbect?
virtual int cmdReadQEncoder(int motor, s64_t &encoder)
Read motor's encoder.
virtual int cmdReadQSpeed(int motor, s32_t &speed)
Read motor's speed.
Laelaps motors, encoder, and controllers hardware abstraction interfaces.
virtual int cmdReadStatus(uint_t &status)
Read RoboClaw board's status bits.
virtual int cmdStop(int motor)
Stop a motor.
int m_idx
motor controller index
virtual int cmdReadMainBattVoltage(double &volts)
Read the RoboClaw's main battery input voltage.
virtual int close()
Close connection to motor controller.
byte_t getAddress() const
Get the controller address associated with this class instance.
#define LAE_VERSION(major, minor, revision)
Convert version triplet to integer equivalent.
virtual int cmdReadLogicVoltage(double &volts)
Read the RoboClaw's LB-/LB+ terminals input voltage powered by and optional logic dedicated battery...
const char * m_sCtlrKey
motor controller key
static RoboClawComm MotorCtlrComm
motor ctrl serial communication bus
RoboClaw communication class.
virtual int open(int pinGpio)
Open GPIO pin interface.
virtual int cmdReadLogicCutoffs(double &min, double &max)
Read the RoboClaw's optional logic dedicated battery minimum and maximum voltage cutoff settings...
virtual int cmdReadVelocityPidConst(int motor, u32_t &Kp, u32_t &Ki, u32_t &Kd, u32_t &qpps)
Read motor's velocity PID constants.
virtual void sync()
Synchronized this with GPIO hardware state.
std::string getRealDeviceName(const std::string &strDevName)
Get real device name.
static RoboClaw * MotorCtlr[LaeNumMotorCtlrs]
RoboClaw motor controllers.
Top-level package include file.