This page will go over the following components for the TI RSLK MAX Enhancement project:
- TI-RSLK MAX base kit: Rover and bumper sensors from the standard kit. (www.ti.com/rslk)
- IR sensors: OPT3101 by Pololu (https://www.pololu.com/product/3680)
- GripperServoCity standard gripper kit A (https://www.servocity.com/standard-gripper-kit-a)
The base kit, when fully assembled, will appear as shown in the above picture and will include the following:
- Robot chassis
- MSP432 microcontroller; this is responsible for implementing any programs you create for this kit
- Two brushed DC motors with accompanying wheels
- Two sets of bump sensors for collision detection
- Roller ball; installed under the chassis, this will balance the robot as it moves
This kit is powered with 6 AA batteries, which are not included with the kit.
The kit is fully functional on its own, so feel free to start programming the motors and bump sensors that are included. You can find guides to get started here: https://university.ti.com/en/faculty/ti-robotics-system-learning-kit/ti-rslk-max-edition-curriculum
Rover
The TI RSLK robot is driven by two brushless, direct current motors, one motor on each side. The robot is balanced by a single omnidirectional ball wheel in its rear. This design allows for differential steering and pin-point turns.
On the rover, each motor is connected to rotary encoders and a DRV8838 H-bridge motor driver. The rotary encoders allow information about the position, speed, and acceleration of the motors to be measured. The H-bridge allows the brushed motors to change direction. The speed of each motor can be controlled by quickly enabling and disabling the motor with a PWM signal. The PWM signal controls the wheel speed by creating an average voltage across the motor.
The rover also incorporates a basic control system using the encoder outputs to adjust the speed of each motor based on a given RPM. Since the left and right motors are often not completely identical, one motor is usually running at a slightly higher speed than the other, which the control system aims to remedy. The control system is implemented in the form of a first-order compensator. You can see the benefits of the compensator in the graph below.
A PWM library is available in the sample code to provide a foundation. This PWM library allows the user to simply input the desired frequency, duty cycle, and output pin. This library was built as a multipurpose library and was both used in the gripper and rover implementations. The main behaviors for rover movement are moving forwards, backwards, and rotating either left or right. Within each behavior, there are separate functions for moving for a specified amount of time and distance, or for a specified number of degrees for rotation functions. The library also gives you the option to implement the control system.
Here are some examples of functions:
// moveForwardForTimeComp
// robot moves forward for a specified amount of time
// inputs: _rpm indicates robot speed
// milliSecs indicates amount of time
// outputs: none
void moveForwardForTimeComp(uint32_t _rpm, uint32_t milliSecs)
{
enableCompensator();
//nominal _rpm unit is deci rpm
move_timer.target_count = milliSecs;
move_timer.count = 0;
move_end_cond = TIME;
right_wheel_data.des_rpm = _rpm;
left_wheel_data.des_rpm = _rpm;
setWheelDirForward(&right_wheel_data);
setWheelDirForward(&left_wheel_data);
rover_state = MOVING_FORWARD;
}
// moveBackwardForTimeComp
// robot moves backward for a specified amount of time
// inputs: _rpm indicates robot speed
// milliSecs indicates amount of time
// outputs: none
void moveBackwardForTimeComp(uint32_t _rpm, uint32_t milliSecs)
{
enableCompensator();
//nominal _rpm unit is deci rpm
move_timer.target_count = milliSecs;
move_timer.count = 0;
move_end_cond = TIME;
right_wheel_data.des_rpm = _rpm;
left_wheel_data.des_rpm = _rpm;
setWheelDirBackward(&right_wheel_data);
setWheelDirBackward(&left_wheel_data);
rover_state = MOVING_BACKWARD;
}
// rotateRightForTimeComp
// robot rotates to the right for a specified amount of time
// inputs: _rpm indicates robot speed
// milliSecs indicates amount of time
// outputs: none
void rotateRightForTimeComp(uint32_t _rpm, uint32_t milliSecs)
{
enableCompensator();
move_timer.target_count = milliSecs;
move_timer.count = 0;
move_end_cond = TIME;
right_wheel_data.des_rpm = _rpm;
left_wheel_data.des_rpm = _rpm;
setWheelDirForward(&left_wheel_data);
setWheelDirBackward(&right_wheel_data);
rover_state = ROTATING_RIGHT;
}
// rotateLeftForTimeComp
// robot rotates to the left for a specified amount of time
// inputs: _rpm indicates robot speed
// milliSecs indicates amount of time
// outputs: none
void rotateLeftForTimeComp(uint32_t _rpm, uint32_t milliSecs)
{
enableCompensator();
move_timer.target_count = milliSecs;
move_timer.count = 0;
move_end_cond = TIME;
right_wheel_data.des_rpm = _rpm;
left_wheel_data.des_rpm = _rpm;
setWheelDirForward(&right_wheel_data);
setWheelDirBackward(&left_wheel_data);
rover_state = ROTATING_LEFT;
}
Bump Sensors
The bump sensors from the RSLK-MAX base kit are used alongside the IR sensor to provide detection of obstacles that are undetectable by the IR sensor due to lower obstacle height or poor lighting conditions.
For testing purposes, the team uses the seven segment display to verify that all six bump sensors work properly by assigning a unique value with each bump sensor.
Here are the functions used for the bump sensors:
// initBumpsensors
// initializes the bump sensors for use
// inputs: none
// outputs: none
void initBumpSensors()
{
GPIO_setAsInputPinWithPullUpResistor(BUMP_PORT, BUMP0);
GPIO_setAsInputPinWithPullUpResistor(BUMP_PORT, BUMP1);
GPIO_setAsInputPinWithPullUpResistor(BUMP_PORT, BUMP2);
GPIO_setAsInputPinWithPullUpResistor(BUMP_PORT, BUMP3);
GPIO_setAsInputPinWithPullUpResistor(BUMP_PORT, BUMP4);
GPIO_setAsInputPinWithPullUpResistor(BUMP_PORT, BUMP5);
}
// getBumpSensorInput
// returns the state of a given bump sensor
// inputs: bumpPin indicates pin number of bump sensor
// outputs: uint8_t indicates state of bump sensor
uint8_t getBumpSensorInput(uint_fast16_t bumpPin)
{
return GPIO_getInputPinValue(BUMP_PORT, bumpPin);
}
// bumpSensorPressed
// returns whether a bump sensor is pressed
// inputs: bumpPin indicates pin number of bump sensor
// outputs: bool indicates state of bump sensor
bool bumpSensorPressed(uint_fast16_t bumpPin)
{
if(GPIO_getInputPinValue(BUMP_PORT, bumpPin))
return false;
return true;
}
The demo video for using bump sensor to create instant turns in from 0:27 to 0:32 of the demo video:
OPT3101 Sensor ArrayThe OPT3101 Sensor Array is responsible for detecting obstacles in front of the rover in RoboNav mode, which is our autonomous driving system. There are three sets of sensors on this component which utilize time-of-flight to determine distances from the sensors to any obstacles. You will need to solder the included header to the robot's PCB in order to mount the IR sensors to the front of the robot as shown above.
The sample code created by the team uses the raw data from the IR sensor for instantaneous response; that is, without using the low pass filter that comes with the example code. The sensor array has an effective field of view of about 180 degrees in front of the robot. You should be careful with it when trying to make modifications on functions which use obstacle detection such as RoboNav.
The demo video for using IR sensor for auto navigation and obstacle avoiding is from 0:12 to 0:18 of the demo video:
Standard Gripper Kit AThe gripper uses a servo motor to open and close the arms with one degree of freedom. The arm is capable of holding a standard aluminum can. This is mounted on the rear of the chassis and will require a 3-D printed mounting bracket for assembly.
Here are some of the functions used for gripper functionality:
//opens the servo as defined by 'openDeg'
void openServo(Servo180 *servoSettings)
{
moveServoToDegree(servoSettings->openDeg, servoSettings);
}
//closes the servo as defined by 'closedDeg'
void closeServo(Servo180 *servoSettings)
{
moveServoToDegree(servoSettings->closedDeg, servoSettings);
}
//toggles between open and closed, as defined by 'closedDeg' and 'openDeg'
//if servo is not currently open or closed, the servo is moved to the open position
void toggleOpenClose(Servo180 *servoSettings)
{
if(servoSettings->degree == servoSettings->closedDeg)
openServo(servoSettings);
else if(servoSettings->degree == servoSettings->openDeg)
closeServo(servoSettings);
else
openServo(servoSettings);
}
Comments