Below is more information on what I did. My write-up is not intended to be a detailed user’s or teaching guide, so your mileage will vary.
If you run into bugs, please let me know, and I will fix them.
Legacy Motor Control Interface:
The original motor control functions (e.g. moveForward(), moveRight(), gripperOpen() etc.) still work, but I’ll be using my new motor control functions from hereon. First, the new functions provide additional features. Second, the old move*() functions use floating point numbers which are expensive in terms of computation time and code size. The new motor control code (except for the legacy functions) does not use floating point anywhere (although some other non-motor functions in the library still use floating point).
Primary Motor Control Interface:
driveForward(), driveBackward()
driveForward() and driveBackward() replace moveForward() and moveBackward(), respectively. Sparki will drive straight forward or backward. Note that the drive*() functions take distances in millimeters whereas the move*() functions took their distances in centimeters (1cm=10mm). Also, unlike the move*() functions, the drive*() functions let you play with motor speed (see speedPercent parameter).
Function interface definition:
[code] void driveForward (
int16_t distanceToDriveMm = 0,
boolean waitUntilDone = true,
uint8_t speedPercent = -1
);
void driveBackward (
int16_t distanceToDriveMm = 0,
boolean waitUntilDone = true,
uint8_t speedPercent = -1
);[/code]
As with the legacy functions, a distance of zero actually means drive forever, although this behavior can be changed by setting
so that driving a distance (or spinning an angle) of zero means do nothing.
Note that the waitUntilDone parameter defaults to true unless the distance is zero. If the distance is zero or waitUntilDone is set to false, then the drive*() function will be non-blocking. The motors will start and code after the drive*() function will continue execution right away.
The default of -1 for speedPercent means that the speed will be taken from the sparki.wheelSpeedPercentDefault variable. This variable is initially set to 80 but can be changed as in
Examples:
[code] sparki.driveForward ( 50 );
sparki.driveForward ( 50, true );
// drives forward 50mm (or 5cm) at default speed; following
// code is only executed once the 50mm drive is done
sparki.driveForward ( 80, false );
// drives forward 80mm at default speed; following code is
// executed immediately, even if motors are still running
sparki.driveForward ( 80, true, 100 );
// drives forward 100mm at 100% speed; following code is
// executed only after the drive is done
sparki.driveForward ();
sparki.driveForward ( 0 );
// drives forward at default speed and keeps going until
// stopped with stopWheels() (see below); does nothing if
// sparki.distanceOfZeroMeansInfinity = false[/code]
spinLeft(), spinRight()
spinLeft() and spinRight() cause Sparki to spin in place and replace moveLeft() and moveRight(), respectively. The spin amount is specified in degrees (as it was with the move*() functions, although now it’s only an integer). The waitUntilDone and speedPercent parameters work like they do with the drive*() functions.
void spinLeft (
int16_t distanceToSpinDeg = 0,
boolean waitUntilDone = true,
uint8_t speedPercent = SPARKI_MOTOR_DEFAULT_SPEED_PERCENT
);
void spinRight (
int16_t distanceToSpinDeg = 0,
boolean waitUntilDone = true,
uint8_t speedPercent = SPARKI_MOTOR_DEFAULT_SPEED_PERCENT
);
turnLeft(), turnRight()
With turnLeft() and turnRight(), Sparki will drive a turn with a particular angle and radius.
void turnLeft (
int16_t angleToTurnDeg = 90,
int16_t radiusOfTurnMm = SPARKI_TURN_RADIUS_DEFAULT_MM,
boolean waitUntilDone = true,
int8_t speedPercent = -1
);
void turnRight (
int16_t angleToTurnDeg = 90,
int16_t radiusOfTurnMm = SPARKI_TURN_RADIUS_DEFAULT_MM,
boolean waitUntilDone = true,
int8_t speedPercent = -1
);
The default turn angle is 90 degrees. The turn radius is relative to Sparki’s pen hole, and the default radius is currently set to 75mm.
Examples:
[code] sparki.turnRight ( 360 );
// drives a circle clockwise, and with a pen will
// draw a 75mm radius (150mm diameter) circle
sparki.turnLeft ( 180, 100 );
// makes a counter-clockwise U-turn with a 100mm
// (10cm) turn radius[/code]
wheelsAreRuning(), stopWheels()
The wheelsAreRunning() function may be used to test whether the wheels are still turning from a prior, non-blocking drive*(), spin*() or turn*() (i.e. a drive, spin or turn with waitUntilDone set to false).
Example:
openGripper(), closeGripper(), setGripperSpacing()
openGripper() may be used to open the gripper fully or open it by a specific number of millimeters. At most, the gripper will run long enough to open it from a fully closed position. closeGripper() works like openGripper() but in the closing direction.
Once the gripper has been fully opened or closed, setGripperSpacing() may be used to set spacing between the grippers to a specific number of millimeters. If the gripper is somehow prevented from closing or opening to the commanded position (e.g. if the gripper is set to close to 20mm but it’s grabbing a 30mm object), the subsequent calls to setGripperSpacing() will not yield accurate results until the gripper is once again fully opened or closed.
Without arguments, the openGripper() function will run the gripper long enough to open it fully if it was previously fully closed.
Examples:
[code] sparki.openGripper ();
// opens the gripper fully and calibrates its position
sparki.closeGripper ( 10 );
// closes the gripper by 10mm (i.e. space between
// grippers will become 10mm less than it is)
sparki.setGripperSpacing ( 25 );
// moves the gripper, so that the separation will be
// 25mm (assuming the gripper position calibration
// is valid)[/code]
setWheelDiameter(), setWheelSeparation ()
Driving distance and spin angles are calibrated for a wheel diameter (outer diameter of the black o-rings around the wheels) of 51.0mm and a wheel-to-wheel distance (o-ring to o-ring) of 85.5mm. If your Sparki is a little different, then drive distances and spin angles will not be quite right. You can tune the behavior by using the setWheelDiameter() and setWheelSeparation() functions.
void setWheelDiameter (
uint16_t wheelDiameterUm
);
void setWheelSeparation (
uint16_t wheelSeparationUm
);
Call either or both of these functions before performing any driving or spinning actions. For either function, the argument is in tenths of millimeters (100=10.0mm).
Example:
setWheelSeparation ( 860 );
// sets wheel separation to 860 mm/10 or 86.0mm.