Mindstorms 3rd Party ROBOTC Drivers RobotC
[Home] [Download] [Submit a bug/suggestion] [ROBOTC Forums] [Blog] [Support this project]

FLAC-driver.h

Go to the documentation of this file.
00001 /*!@addtogroup other
00002  * @{
00003  * @defgroup firgelli Firgelli Linear Actuator
00004  * Firgelli Linear Actuator driver
00005  * @{
00006  */
00007 /*
00008  * $Id: FLAC-driver.h 29 2010-06-25 12:55:41Z xander $
00009  */
00010 
00011 #ifndef __FLAC_H__
00012 #define __FLAC_H__
00013 /** \file FLAC-driver.h
00014  * \brief Firgelli Linear Actuator driver
00015  *
00016  * FLAC-driver.h provides an API for the Firgelli Linear Actuator.
00017  *
00018  * Changelog:
00019  * - 0.1: Initial release
00020  *
00021  * TODO:
00022  * - Add ramping support (being worked on, has a few bugs)
00023  *
00024  * Credits:
00025  * - Big thanks to Firgelli for providing me with the hardware necessary to write and test this.
00026  *
00027  * License: You may use this code as you wish, provided you give credit where its due.
00028  *
00029  * THIS CODE WILL ONLY WORK WITH ROBOTC VERSION 2.00 AND HIGHER.
00030  * \author Xander Soldaat (mightor@gmail.com), version 0.1
00031  * \date 16 february 2010
00032  * \version 0.1
00033  * \example FLAC-test1.c
00034  */
00035 
00036 #pragma systemFile
00037 
00038 #define STALL_TIME_SLOW   1200             /*!< Counter to check if motor is stalled when motor speeds are < 50 */
00039 #define STALL_TIME_FAST   800              /*!< Counter to check if motor is stalled when motor speeds are >= 50 */
00040 
00041 long _encoderTarget[3] = {0, 0, 0};       /*!< Motor encoder targets - INTERNAL */
00042 long _motorHighPower[3] = {0, 0, 0};      /*!< High Power - top speed of the motor - INTERNAL */
00043 bool _stalled[3] = {false, false, false}; /*!< Are we stalling? - INTERNAL */
00044 
00045 
00046 // tasks
00047 task _FLACcontrolTaskA();
00048 task _FLACcontrolTaskB();
00049 task _FLACcontrolTaskC();
00050 
00051 // Functions
00052 void _FLACcontrolTasks(tMotor _motor, int _highPower, long _encTarget);
00053 
00054 bool isDone(tMotor _motor);
00055 void FLACextendLA(tMotor _motor, int _highPower);
00056 void FLACextendLA(tMotor _motor, int _highPower, int distance);
00057 void FLACtretractLA(tMotor _motor, int _highPower);
00058 void FLACtretractLA(tMotor _motor, int _highPower, int distance);
00059 void FLACmoveLA(tMotor _motor, int highpower, int pos);
00060 
00061 
00062 // Task to control motor A
00063 task _FLACcontrolTaskA() {
00064   long _currentEncVal;                // _currentEncVal encoder value
00065   bool _reverse = false;
00066   bool _done = false;
00067   long _lastEncoderCount = 0;
00068   long _stallCounter = 0;
00069 
00070   // This has to be done to prevent the PID regulator from
00071   // messing with the motor speeds
00072   nMotorPIDSpeedCtrl[motorA] = mtrNoReg;
00073 
00074   // we're not stalled just yet, so reset the variable.
00075   _stalled[motorA] = false;
00076 
00077   _currentEncVal = nMotorEncoder[motorA];
00078   _stallCounter = 0;
00079 
00080   // Flip it and reverse it
00081   if (_encoderTarget[motorA] < _currentEncVal)
00082     _reverse = true;
00083 
00084   while (!_done) {
00085     _currentEncVal = nMotorEncoder[motorA];
00086 
00087     // Are we there yet?
00088     if (_reverse && (_currentEncVal <= _encoderTarget[motorA]))
00089       _done = true;
00090     else if (!_reverse && (_currentEncVal >= _encoderTarget[motorA]))
00091       _done = true;
00092 
00093     // Stall detection magic bits happening here.
00094     if (!_done && (abs(_lastEncoderCount - _currentEncVal) > 0)) {
00095       _stallCounter = 0;
00096     } else if (!_done && (_stallCounter > STALL_TIME_SLOW) && _motorHighPower[motorA] < 50) {
00097       _stalled[motorA] = true;
00098       _done = true;
00099     } else if (!_done && (_stallCounter > STALL_TIME_SLOW) && _motorHighPower[motorA] >= 50) {
00100       _stalled[motorA] = true;
00101       _done = true;
00102     } else {
00103       _stallCounter++;
00104     }
00105 
00106     // Only change the motor speed if we're not done yet
00107     if (!_done)
00108       motor[motorA] = (_reverse) ? -_motorHighPower[motorA] : _motorHighPower[motorA];
00109 
00110     // update the _lastEncoderCount for the stall detection
00111     _lastEncoderCount = _currentEncVal;
00112     EndTimeSlice();
00113   }
00114   motor[motorA] = 0; //turn motor off
00115 }
00116 
00117 
00118 // Task to control motor B
00119 task _FLACcontrolTaskB() {
00120   long _currentEncVal;                // _currentEncVal encoder value
00121   bool _reverse = false;
00122   bool _done = false;
00123   long _lastEncoderCount = 0;
00124   long _stallCounter = 0;
00125 
00126   // This has to be done to prevent the PID regulator from
00127   // messing with the motor speeds
00128   nMotorPIDSpeedCtrl[motorB] = mtrNoReg;
00129 
00130   // we're not stalled just yet, so reset the variable.
00131   _stalled[motorA] = false;
00132 
00133   _currentEncVal = nMotorEncoder[motorB];
00134   _stallCounter = 0;
00135 
00136   // Flip it and reverse it
00137   if (_encoderTarget[motorB] < _currentEncVal)
00138     _reverse = true;
00139 
00140   while (!_done) {
00141     _currentEncVal = nMotorEncoder[motorB];
00142 
00143     // Are we there yet?
00144     if (_reverse && (_currentEncVal <= _encoderTarget[motorB]))
00145       _done = true;
00146     else if (!_reverse && (_currentEncVal >= _encoderTarget[motorB]))
00147       _done = true;
00148 
00149     // Stall detection magic bits happening here.
00150     if (!_done && (abs(_lastEncoderCount - _currentEncVal) > 0)) {
00151       _stallCounter = 0;
00152     } else if (!_done && (_stallCounter > STALL_TIME_SLOW) && _motorHighPower[motorB] < 50) {
00153       _stalled[motorA] = true;
00154       _done = true;
00155     } else if (!_done && (_stallCounter > STALL_TIME_SLOW) && _motorHighPower[motorB] >= 50) {
00156       _stalled[motorA] = true;
00157       _done = true;
00158     } else {
00159       _stallCounter++;
00160     }
00161 
00162     // Only change the motor speed if we're not done yet
00163     if (!_done)
00164       motor[motorB] = (_reverse) ? -_motorHighPower[motorB] : _motorHighPower[motorB];
00165 
00166     // update the _lastEncoderCount for the stall detection
00167     _lastEncoderCount = _currentEncVal;
00168     EndTimeSlice();
00169   }
00170   motor[motorB] = 0; //turn motor off
00171 }
00172 
00173 
00174 // Task to control motor C
00175 task _FLACcontrolTaskC() {
00176   long _currentEncVal;                // _currentEncVal encoder value
00177   bool _reverse = false;
00178   bool _done = false;
00179   long _lastEncoderCount = 0;
00180   long _stallCounter = 0;
00181 
00182   // This has to be done to prevent the PID regulator from
00183   // messing with the motor speeds
00184   nMotorPIDSpeedCtrl[motorC] = mtrNoReg;
00185 
00186   // we're not stalled just yet, so reset the variable.
00187   _stalled[motorC] = false;
00188 
00189   _currentEncVal = nMotorEncoder[motorC];
00190   _stallCounter = 0;
00191 
00192   // Flip it and reverse it
00193   if (_encoderTarget[motorC] < _currentEncVal)
00194     _reverse = true;
00195 
00196   while (!_done) {
00197     _currentEncVal = nMotorEncoder[motorC];
00198 
00199     // Are we there yet?
00200     if (_reverse && (_currentEncVal <= _encoderTarget[motorC]))
00201       _done = true;
00202     else if (!_reverse && (_currentEncVal >= _encoderTarget[motorC]))
00203       _done = true;
00204 
00205     // Stall detection magic bits happening here.
00206     if (!_done && (abs(_lastEncoderCount - _currentEncVal) > 0)) {
00207       _stallCounter = 0;
00208     } else if (!_done && (_stallCounter > STALL_TIME_SLOW) && _motorHighPower[motorC] < 50) {
00209       _stalled[motorC] = true;
00210       _done = true;
00211     } else if (!_done && (_stallCounter > STALL_TIME_SLOW) && _motorHighPower[motorC] >= 50) {
00212       _stalled[motorC] = true;
00213       _done = true;
00214     } else {
00215       _stallCounter++;
00216     }
00217 
00218     // Only change the motor speed if we're not done yet
00219     if (!_done)
00220       motor[motorC] = (_reverse) ? -_motorHighPower[motorC] : _motorHighPower[motorC];
00221 
00222     // update the _lastEncoderCount for the stall detection
00223     _lastEncoderCount = _currentEncVal;
00224     EndTimeSlice();
00225   }
00226   motor[motorC] = 0; //turn motor off
00227 }
00228 
00229 
00230 /**
00231  * Stop and start the motor control tasks and set their parameters.
00232  *
00233  * Note: this is an internal function and should not be called directly.
00234  * @param _motor the motor to be controlled
00235  * @param _highPower the highest speed the motor should turn at
00236  * @param _encTarget the target the motor should move to
00237  */
00238 void _FLACcontrolTasks(tMotor _motor, int _highPower, long _encTarget) {
00239   switch(_motor) {
00240     case motorA:
00241       if (getTaskState(_FLACcontrolTaskA) == taskStateRunning) {
00242         StopTask(_FLACcontrolTaskA);
00243         while(getTaskState(_FLACcontrolTaskA) != taskStateStopped) EndTimeSlice();
00244         wait1Msec(50);
00245         motor[motorA] = 0;
00246       }
00247       _motorHighPower[_motor] = _highPower;
00248       _encoderTarget[_motor] = _encTarget;
00249 
00250       StartTask(_FLACcontrolTaskA);
00251       while(getTaskState(_FLACcontrolTaskA) != taskStateRunning) EndTimeSlice();
00252       break;
00253 
00254     case motorB:
00255       if (getTaskState(_FLACcontrolTaskB) == taskStateRunning) {
00256         StopTask(_FLACcontrolTaskB);
00257         while(getTaskState(_FLACcontrolTaskB) != taskStateStopped) EndTimeSlice();
00258         wait1Msec(50);
00259         motor[motorB] = 0;
00260       }
00261       _motorHighPower[_motor] = _highPower;
00262       _encoderTarget[_motor] = _encTarget;
00263 
00264       StartTask(_FLACcontrolTaskB);
00265       while(getTaskState(_FLACcontrolTaskB) != taskStateRunning) EndTimeSlice();
00266       break;
00267 
00268     case motorC:
00269       if (getTaskState(_FLACcontrolTaskC) == taskStateRunning) {
00270         StopTask(_FLACcontrolTaskC);
00271         while(getTaskState(_FLACcontrolTaskC) != taskStateStopped) EndTimeSlice();
00272         wait1Msec(50);
00273         motor[motorA] = 0;
00274       }
00275       _motorHighPower[_motor] = _highPower;
00276       _encoderTarget[_motor] = _encTarget;
00277 
00278       StartTask(_FLACcontrolTaskC);
00279       while(getTaskState(_FLACcontrolTaskC) != taskStateRunning) EndTimeSlice();
00280       break;
00281   }
00282 }
00283 
00284 
00285 /**
00286  * Check if the motor is done with the current operation
00287  * @param _motor the motor to be checked
00288  * @return true if the motor is done, false if it isn't
00289  */
00290 bool isDone(tMotor _motor) {
00291   switch(_motor) {
00292     case motorA: return (getTaskState(_FLACcontrolTaskA) == taskStateStopped);
00293     case motorB: return (getTaskState(_FLACcontrolTaskB) == taskStateStopped);
00294     case motorC: return (getTaskState(_FLACcontrolTaskC) == taskStateStopped);
00295   }
00296   return false;
00297 }
00298 
00299 
00300 /**
00301  * Check if the motor stalled on the last operation
00302  * @param _motor the motor to be checked
00303  * @return true if the motor stalled, false if it hadn't.
00304  */
00305 bool isStalled(tMotor _motor) {
00306   return _stalled[_motor];
00307 }
00308 
00309 
00310 /**
00311  * Extend the Linear Actuator fully until stalled.
00312  * @param _motor the motor to be controlled
00313  * @param _highPower the highest speed the motor should turn at
00314  */
00315 void FLACextendLA(tMotor _motor, int _highPower) {
00316   _FLACcontrolTasks(_motor, _highPower, -210);
00317   _stalled[_motor] = false;
00318 }
00319 
00320 
00321 /**
00322  * Extend the Linear Actuator.
00323  * @param _motor the motor to be controlled
00324  * @param _highPower the highest speed the motor should turn at
00325  * @param distance the number of encoder ticks (0.5mm) the actuator should move
00326  */
00327 void FLACextendLA(tMotor _motor, int _highPower, int distance) {
00328   _FLACcontrolTasks(_motor, _highPower, nMotorEncoder[_motor] - distance);
00329   _stalled[_motor] = false;
00330 }
00331 
00332 
00333 /**
00334  * Retract the Linear Actuator fully until stalled. It is wise to reset
00335  * the encoder count for that motor afterwards.
00336  * @param _motor the motor to be controlled
00337  * @param _highPower the highest speed the motor should turn at
00338  */
00339 void FLACtretractLA(tMotor _motor, int _highPower) {
00340   _FLACcontrolTasks(_motor, _highPower, 210);
00341  _stalled[_motor] = false;
00342 }
00343 
00344 
00345 /**
00346  * Retract the Linear Actuator.
00347  * @param _motor the motor to be controlled
00348  * @param _highPower the highest speed the motor should turn at
00349  * @param distance the number of encoder ticks (0.5mm) the actuator should move
00350  */
00351 void FLACtretractLA(tMotor _motor, int _highPower, int distance) {
00352   _FLACcontrolTasks(_motor, _highPower, nMotorEncoder[_motor] + distance);
00353   _stalled[_motor] = false;
00354 }
00355 
00356 
00357 /**
00358  * Move the Linear Actuator to an absolute position
00359  * @param _motor the motor to be controlled
00360  * @param highpower the highest speed the motor should turn at
00361  * @param pos the exact encoder count to move to
00362  */
00363 void FLACmoveLA(tMotor _motor, int highpower, int pos) {
00364   _FLACcontrolTasks(_motor, highpower, pos);
00365 }
00366 
00367 #endif // __FLAC_H__
00368 
00369 /*
00370  * $Id: FLAC-driver.h 29 2010-06-25 12:55:41Z xander $
00371  */
00372 /* @} */
00373 /* @} */