54 #include <arch/board/board.h> 63 #define TIMEOUT_US 10500 66 #define TIMEOUT_RETRIES 1 70 #define STOP_RETRIES 10 73 #define ENCODER_MESSAGE_SIZE 10 76 #define ENCODER_SPEED_MESSAGE_SIZE 7 83 _uart_timeout{.tv_sec = 0, .tv_usec =
TIMEOUT_US},
99 _uart = open(deviceName, O_RDWR | O_NOCTTY);
101 if (
_uart < 0) {
err(1,
"could not open %s", deviceName); }
104 struct termios uart_config {};
105 ret = tcgetattr(
_uart, &uart_config);
107 if (ret < 0) {
err(1,
"failed to get attr"); }
109 uart_config.c_oflag &= ~ONLCR;
110 ret = cfsetispeed(&uart_config,
_parameters.serial_baud_rate);
112 if (ret < 0) {
err(1,
"failed to set input speed"); }
114 ret = cfsetospeed(&uart_config,
_parameters.serial_baud_rate);
116 if (ret < 0) {
err(1,
"failed to set output speed"); }
118 ret = tcsetattr(
_uart, TCSANOW, &uart_config);
120 if (ret < 0) {
err(1,
"failed to set attr"); }
142 PX4_ERR(
"Unable to connect to Roboclaw. Shutting down Roboclaw driver.");
154 uint64_t encoderTaskLastRun = 0;
157 uint64_t actuatorsLastWritten = 0;
167 fds[0].events = POLLIN;
169 fds[1].events = POLLIN;
171 fds[2].events = POLLIN;
174 _wheelEncoderMsg[0].pulses_per_rev =
_parameters.counts_per_rev;
175 _wheelEncoderMsg[1].pulses_per_rev =
_parameters.counts_per_rev;
179 int pret = poll(fds,
sizeof(fds) /
sizeof(pollfd), waitTime / 1000);
183 if (fds[0].revents & POLLIN) {
189 if (pret > 0 && (fds[1].revents & POLLIN || fds[2].revents & POLLIN || actuators_timeout)) {
193 int drive_ret = 0, turn_ret = 0;
203 PX4_ERR(
"Error trying to stop: Drive: %d, Turn: %d", drive_ret, turn_ret);
212 if (drive_ret <= 0 || turn_ret <= 0) {
213 PX4_ERR(
"Error controlling RoboClaw. Drive err: %d. Turn err: %d", drive_ret, turn_ret);
225 for (
int i = 0; i < 2; i++) {
226 _wheelEncoderMsg[i].timestamp = encoderTaskLastRun;
242 PX4_ERR(
"Error reading encoders");
247 waitTime = waitTime < 0 ? 0 : waitTime;
265 bool success =
false;
277 PX4_ERR(
"Error reading encoders");
283 uint8_t *count_bytes;
284 uint8_t *speed_bytes;
286 for (
int motor = 0; motor <= 1; motor++) {
289 count_bytes = &rbuff_pos[motor * 4];
290 speed_bytes = &rbuff_speed[motor * 4];
294 for (
int byte = 0; byte < 4; byte++) {
295 count = (count << 8) + count_bytes[byte];
296 speed = (speed << 8) + speed_bytes[byte];
310 uint32_t rev_diff = _lastEncoderCount[motor] - count;
312 int32_t diff = fwd_diff <= rev_diff ? fwd_diff : -int32_t(rev_diff);
314 _lastEncoderCount[motor] = count;
324 snprintf(
string, n,
"pos1,spd1,pos2,spd2: %10.2f %10.2f %10.2f %10.2f\n",
340 warnx(
"Unknown motor value passed to RoboClaw::getMotorPosition");
354 warnx(
"Unknown motor value passed to RoboClaw::getMotorPosition");
431 auto byte = (uint8_t)(data * INT8_MAX);
441 }
else if (data < -1.0
f) {
445 auto buff = (uint16_t)(data * INT16_MAX);
447 return _transaction(command, (uint8_t *) &buff, 2, &recv_buff, 1);
453 return _transaction(command,
nullptr, 0, &recv_buff, 1);
460 for (
size_t byte = 0; byte < n; byte++) {
461 crc = crc ^ (((uint16_t) buf[byte]) << 8);
463 for (uint8_t bit = 0; bit < 8; bit++) {
465 crc = (crc << 1) ^ 0x1021;
477 uint8_t *rbuff,
size_t rbytes,
bool send_checksum,
bool recv_checksum)
483 tcflush(
_uart, TCIOFLUSH);
484 uint8_t buf[wbytes + 4];
489 memcpy(&buf[2], wbuff, wbytes);
492 wbytes = wbytes + (send_checksum ? 4 : 2);
495 uint16_t sum =
_calcCRC(buf, wbytes - 2);
496 buf[wbytes - 2] = (sum >> 8) & 0xFF;
497 buf[wbytes - 1] = sum & 0xFFu;
502 if (count < (
int) wbytes) {
503 PX4_ERR(
"Only wrote %d out of %d bytes", count, (
int) wbytes);
512 uint8_t *rbuff_curr = rbuff;
513 size_t bytes_read = 0;
517 while (bytes_read < rbytes) {
528 err_code =
read(
_uart, rbuff_curr, rbytes - bytes_read);
534 bytes_read += err_code;
535 rbuff_curr += err_code;
542 if (bytes_read < 2) {
548 uint16_t checksum_calc =
_calcCRC(buf, 2);
549 checksum_calc =
_calcCRC(rbuff, bytes_read - 2, checksum_calc);
550 uint16_t checksum_recv = (rbuff[bytes_read - 2] << 8) + rbuff[bytes_read - 1];
552 if (checksum_calc == checksum_recv) {
560 if (bytes_read == 1 && rbuff[0] == 0xFF) {
actuator_armed_s _actuatorArmed
void _parameters_update()
int _sendNothing(e_command)
int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)
struct timeval _uart_timeout
float getMotorPosition(e_motor motor)
int readEncoder()
read data from serial
__EXPORT int param_get(param_t param, void *val)
Copy the value of a parameter.
struct RoboClaw::@20 _parameters
static bool taskShouldExit
parameter_update_s _paramUpdate
int orb_set_interval(int handle, unsigned interval)
actuator_controls_s _actuatorControls
RoboClaw(const char *deviceName, const char *baudRateParam)
constructor
int setMotorSpeed(e_motor motor, float value)
set the speed of a motor, rev/sec
High-resolution timer with callouts and timekeeping.
int _actuatorsSub
actuator controls subscription
int turn(float value)
Turn.
static void read(bootloader_app_shared_t *pshared)
int orb_subscribe(const struct orb_metadata *meta)
#define ENCODER_SPEED_MESSAGE_SIZE
wheel_encoders_s _wheelEncoderMsg[2]
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
float getMotorSpeed(e_motor motor)
orb_advert_t _wheelEncodersAdv[2]
void init()
Activates/configures the hardware registers.
int resetEncoders()
reset the encoders
void printStatus(char *string, size_t n)
print status
int orb_unsubscribe(int handle)
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Simple error/warning functions, heavily inspired by the BSD functions of the same names...
#define ENCODER_MESSAGE_SIZE
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
static void write(bootloader_app_shared_t *pshared)
int setMotorDutyCycle(e_motor motor, float value)
set the duty cycle of a motor
int _sendUnsigned7Bit(e_command command, float data)
int _sendSigned16Bit(e_command command, float data)
uint32_t _lastEncoderCount[2]
int _transaction(e_command cmd, uint8_t *wbuff, size_t wbytes, uint8_t *rbuff, size_t rbytes, bool send_checksum=true, bool recv_checksum=false)
Perform a round-trip write and read.
static uint16_t _calcCRC(const uint8_t *buf, size_t n, uint16_t init=0)
int64_t _encoderCounts[2]
int drive(float value)
Drive both motors.
virtual ~RoboClaw()
deconstructor
orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority)
struct RoboClaw::@21 _param_handles
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).