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

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