/**************************************************************************** * * Copyright (C) 2013 PX4 Development Team. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * 3. Neither the name PX4 nor the names of its contributors may be * used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************/ /** * @file RoboClas.hpp * * RoboClaw Motor Driver * * references: * http://downloads.orionrobotics.com/downloads/datasheets/motor_controller_robo_claw_R0401.pdf * */ #pragma once #include #include #include #include #include /** * This is a driver for the RoboClaw motor controller */ class RoboClaw { public: /** control channels */ enum e_channel { CH_VOLTAGE_LEFT = 0, CH_VOLTAGE_RIGHT }; /** motors */ enum e_motor { MOTOR_1 = 0, MOTOR_2 }; /** * constructor * @param deviceName the name of the * serial port e.g. "/dev/ttyS2" * @param address the adddress of the motor * (selectable on roboclaw) * @param pulsesPerRev # of encoder * pulses per revolution of wheel */ RoboClaw(const char *deviceName, uint16_t address, uint16_t pulsesPerRev); /** * deconstructor */ virtual ~RoboClaw(); /** * @return position of a motor, rev */ float getMotorPosition(e_motor motor); /** * @return speed of a motor, rev/sec */ float getMotorSpeed(e_motor motor); /** * set the speed of a motor, rev/sec */ int setMotorSpeed(e_motor motor, float value); /** * set the duty cycle of a motor, rev/sec */ int setMotorDutyCycle(e_motor motor, float value); /** * reset the encoders * @return status */ int resetEncoders(); /** * main update loop that updates RoboClaw motor * dutycycle based on actuator publication */ int update(); /** * read data from serial */ int readEncoder(e_motor motor); /** * print status */ void printStatus(char *string, size_t n); private: // Quadrature status flags enum e_quadrature_status_flags { STATUS_UNDERFLOW = 1 << 0, /**< encoder went below 0 **/ STATUS_REVERSE = 1 << 1, /**< motor doing in reverse dir **/ STATUS_OVERFLOW = 1 << 2, /**< encoder went above 2^32 **/ }; // commands // We just list the commands we want from the manual here. enum e_command { // simple CMD_DRIVE_FWD_1 = 0, CMD_DRIVE_REV_1 = 1, CMD_DRIVE_FWD_2 = 4, CMD_DRIVE_REV_2 = 5, // encoder commands CMD_READ_ENCODER_1 = 16, CMD_READ_ENCODER_2 = 17, CMD_RESET_ENCODERS = 20, // advanced motor control CMD_READ_SPEED_HIRES_1 = 30, CMD_READ_SPEED_HIRES_2 = 31, CMD_SIGNED_DUTYCYCLE_1 = 32, CMD_SIGNED_DUTYCYCLE_2 = 33, }; static uint8_t checksum_mask; uint16_t _address; uint16_t _pulsesPerRev; int _uart; /** poll structure for control packets */ struct pollfd _controlPoll; /** actuator controls subscription */ uORB::Subscription _actuators; // private data float _motor1Position; float _motor1Speed; int16_t _motor1Overflow; float _motor2Position; float _motor2Speed; int16_t _motor2Overflow; // private methods uint16_t _sumBytes(uint8_t * buf, size_t n); int _sendCommand(e_command cmd, uint8_t * data, size_t n_data, uint16_t & prev_sum); }; // unit testing int roboclawTest(const char *deviceName, uint8_t address, uint16_t pulsesPerRev); // vi:noet:smarttab:autoindent:ts=4:sw=4:tw=78