MakingThings
  • Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List
  • Globals

motor.c

Go to the documentation of this file.
00001 /*********************************************************************************
00002 
00003  Copyright 2006-2008 MakingThings
00004 
00005  Licensed under the Apache License, 
00006  Version 2.0 (the "License"); you may not use this file except in compliance 
00007  with the License. You may obtain a copy of the License at
00008 
00009  http://www.apache.org/licenses/LICENSE-2.0 
00010  
00011  Unless required by applicable law or agreed to in writing, software distributed
00012  under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
00013  CONDITIONS OF ANY KIND, either express or implied. See the License for
00014  the specific language governing permissions and limitations under the License.
00015 
00016 *********************************************************************************/
00017 
00018 // MakingThings - Make Controller Board - 2006
00019 
00020 /** \file motor.c 
00021   DC_Motor.
00022   Functions for controlling DC Motors with the MAKE Application Board.
00023 */
00024 
00025 #include "motor.h"
00026 #include "pwmout.h"
00027 #include "config.h"
00028 
00029 #define MOTOR_COUNT 4
00030 
00031 static int Motor_Start( int motor );
00032 static int Motor_Stop( int motor );
00033 
00034 struct Motor_
00035 {
00036   int users;
00037   int direction;
00038   int speed;
00039 } Motor[ MOTOR_COUNT ];
00040 
00041 static int Motor_SetFinal( int index, struct Motor_ * mp );
00042 
00043 /** \defgroup Motor Motor
00044 The Motor subsystem provides forward/reverse and speed control for up to 4 DC motors across the 8 high current outputs.
00045 Each motor controller is composed of 2 adjacent Digital Outs on the Make Application Board:
00046 - motor 0 - Digital Outs 0 and 1.
00047 - motor 1 - Digital Outs 2 and 3.
00048 - motor 2 - Digital Outs 4 and 5.
00049 - motor 3 - Digital Outs 6 and 7.
00050 
00051 Other output devices cannot be used simultaneously - for example, the DigitalOuts cannot be called without
00052 first setting overlapping the DC motor I/O lines to inactive.
00053 
00054 See the digital out section of the 
00055 <a href="http://www.makingthings.com/documentation/tutorial/application-board-overview/digital-outputs">
00056 Application Board overview</a> for more details.
00057 \ingroup Libraries
00058 @{
00059 */
00060 
00061 /**
00062   Sets whether the specified motor is active.
00063   @param index An integer specifying which Motor (0-3).
00064   @param state An integer specifying the availability of the motor's I/O lines - 1 (active) or 0 (inactive).
00065   @return Zero on success.
00066   
00067   \b Example
00068   \code
00069   // Enable motor 0
00070   Motor_SetActive(0, 1);
00071   \endcode
00072 */
00073 int Motor_SetActive( int index, int state )
00074 {
00075   if ( index < 0 || index >= MOTOR_COUNT )
00076     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00077 
00078   if ( state )
00079     return Motor_Start( index );
00080   else
00081     return Motor_Stop( index );
00082 }
00083 
00084 /**
00085   Returns the active state of the DC Motor I/O lines.
00086   @param index An integer specifying which DC Motor (0-3).
00087   @return The availability of the motor's I/O lines - 1 (active) or 0 (inactive).
00088   
00089   \b Example
00090   \code
00091   if( Motor_GetActive(0) )
00092   {
00093     // Motor 0 is active
00094   }
00095   else
00096   {
00097     // Motor 0 is inactive
00098   }
00099   \endcode
00100 */
00101 int Motor_GetActive( int index )
00102 {
00103   if ( index < 0 || index >= MOTOR_COUNT )
00104     return false;
00105   return Motor[ index ].users > 0;
00106 }
00107 
00108 /** 
00109   Set the speed of a DC motor.
00110   @param index An integer specifying which DC Motor (0-3).
00111   @param duty An integer (0 - 1023) specifying the speed.
00112   @returns Zero on success.
00113   
00114   \b Example
00115   \code
00116   // Set the speed of motor 3 to %75
00117   Motor_SetSpeed(3, 768);
00118   \endcode
00119 */
00120 int Motor_SetSpeed( int index, int duty )
00121 {
00122   if ( index < 0 || index >= MOTOR_COUNT )
00123     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00124 
00125   struct Motor_* mp = &Motor[ index ];
00126 
00127   if ( mp->users == 0 )
00128   {
00129     int status = Motor_Start( index );
00130     if ( status != CONTROLLER_OK )
00131       return status;
00132   }
00133   
00134   mp->speed = duty;
00135   
00136   return Motor_SetFinal( index, mp );
00137 }
00138 
00139 /** 
00140   Set the direction of a DC motor.
00141   @param index An integer specifying which DC Motor (0-3).
00142   @param forward A character specifying direction - 1/non-zero (forward) or 0 (reverse).
00143   @return Zero on success.
00144   
00145   \b Example
00146   \code
00147   // Set the direction of motor 2 to reverse.
00148   Motor_SetDirection(2, 0);
00149   \endcode
00150 */
00151 int Motor_SetDirection( int index, char forward )
00152 {
00153   if ( index < 0 || index >= MOTOR_COUNT )
00154     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00155 
00156   struct Motor_* mp = &Motor[ index ];
00157 
00158   if ( mp->users == 0 )
00159   {
00160     int status = Motor_Start( index );
00161     if ( status != CONTROLLER_OK )
00162       return status;
00163   }
00164 
00165   mp->direction = forward;
00166 
00167   return Motor_SetFinal( index, mp );
00168 }
00169 
00170 /** 
00171   Read the speed of a DC motor.
00172   @param index An integer specifying which DC Motor (0-3).
00173   @return the speed (0 - 1023)
00174   
00175   \b Example
00176   \code
00177   // check the current speed of motor 1
00178   int motor1_speed = Motor_GetSpeed(1);
00179   \endcode
00180 */
00181 int Motor_GetSpeed( int index )
00182 {
00183   if ( index < 0 || index >= MOTOR_COUNT )
00184     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00185 
00186   struct Motor_* mp = &Motor[ index ];
00187 
00188   if ( mp->users == 0 )
00189   {
00190     int status = Motor_Start( index );
00191     if ( status != CONTROLLER_OK )
00192       return 0;
00193   }
00194   
00195   return mp->speed;
00196 }
00197 
00198 /** 
00199   Read the direction of a DC motor.
00200   @param index An integer specifying which DC Motor (0-3).
00201   @return Direction - non-zero (forward) or 0 (reverse).
00202   
00203   \b Example
00204   \code
00205   if( Motor_GetDirection(0) )
00206   {
00207     // Motor 0 is going forward
00208   }
00209   else
00210   {
00211     // Motor 0 is going in reverse
00212   }
00213   \endcode
00214 */
00215 int Motor_GetDirection( int index )
00216 {
00217   if ( index < 0 || index >= MOTOR_COUNT )
00218     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00219 
00220   struct Motor_* mp = &Motor[ index ];
00221 
00222   if ( mp->users == 0 )
00223   {
00224     int status = Motor_Start( index );
00225     if ( status != CONTROLLER_OK )
00226       return 0;
00227   }
00228 
00229   return mp->direction;
00230 }
00231 
00232 /** @}
00233 */
00234 
00235 int Motor_Start( int index )
00236 {
00237   if ( index < 0 || index >= MOTOR_COUNT )
00238     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00239 
00240   struct Motor_* mp = &Motor[ index ];
00241   if ( mp->users++ == 0 )
00242   {
00243     mp->direction = 1;
00244     mp->speed = 0; 
00245 
00246     int status = PwmOut_SetActive( index, true );
00247     if ( status != CONTROLLER_OK )
00248     {
00249       mp->users--;
00250       return status;
00251     }
00252   }
00253 
00254   return Motor_SetFinal( index, mp );
00255 }
00256 
00257 int Motor_Stop( int index )
00258 {
00259   if ( index < 0 || index >= MOTOR_COUNT )
00260     return CONTROLLER_ERROR_ILLEGAL_INDEX;
00261 
00262   struct Motor_* mp = &Motor[ index ];
00263   if ( --mp->users == 0 )
00264   {  
00265     return PwmOut_SetActive( index, false );
00266   }
00267 
00268   return CONTROLLER_OK;
00269 }
00270 
00271 
00272 static int Motor_SetFinal( int index, struct Motor_ * mp )
00273 {
00274   int speed = mp->speed;
00275   // Work out the speed
00276   if ( !mp->direction )
00277     speed *= -1;
00278 
00279   // possibly add a dead zone inbetween?
00280   int status;
00281   if ( speed >= 0 )
00282     status = PwmOut_SetAll( index, speed, 0, 1 );
00283   else
00284     status = PwmOut_SetAll( index, -speed, 1, 0 );
00285   return status;
00286 }
00287 
00288 #ifdef OSC
00289 
00290 /** \defgroup MotorOSC Motor - OSC
00291   Control DC motors with the Application Board via OSC.
00292   \ingroup OSC
00293   
00294   \section devices Devices
00295   There are 4 DC Motor controllers available on the Application Board, numbered 0 - 3.
00296   
00297   Each motor controller is composed of 2 adjacent Digital Outs on the Make Application Board:
00298   - motor 0 - Digital Outs 0 and 1.
00299   - motor 1 - Digital Outs 2 and 3.
00300   - motor 2 - Digital Outs 4 and 5.
00301   - motor 3 - Digital Outs 6 and 7.
00302   
00303   \section properties Properties
00304   Each motor controller has three properties:
00305   - speed
00306   - direction
00307   - active
00308 
00309   \par Speed
00310   The \b speed property corresponds to the speed at which a motor is being driven.
00311   This value can be both read and written.  The range of values expected by the board
00312   is from 0 - 1023.  A speed of 0 means the motor is stopped, and 1023 means it is
00313   being driven at full speed.
00314   \par
00315   To set the second motor (connected to Digital Outs 2 and 3) at half speed, send the message
00316   \verbatim /motor/1/speed 512 \endverbatim
00317   Leave the argument value off to read the speed of the motor:
00318   \verbatim /motor/1/speed \endverbatim
00319   
00320   \par Direction
00321   The \b direction property corresponds to the forward/reverse direction of the motor.
00322   This value can be both read and written, and the range of values expected is simply 
00323   0 or 1.  1 means forward and 0 means reverse.
00324   \par
00325   For example, to set the first motor to move in reverse, send the message
00326   \verbatim /motor/0/direction 0 \endverbatim
00327   Simply change the argument of 0 to a 1 in order to set the motor's direction to forward.
00328   
00329   \par Active
00330   The \b active property corresponds to the active state of the motor.
00331   If the motor is set to be active, no other tasks will be able to
00332   use its 2 digital out lines.  If you're not seeing appropriate
00333   responses to your messages to the motor, check the whether it's 
00334   locked by sending a message like
00335   \verbatim /motor/0/active \endverbatim
00336   \par
00337   If you're no longer using the motor, you can free the 2 Digital Outs by 
00338   sending the message
00339   \verbatim /motor/0/active 0 \endverbatim
00340 */
00341 
00342 #include "osc.h"
00343 #include "string.h"
00344 #include "stdio.h"
00345 
00346 // Need a list of property names
00347 // MUST end in zero
00348 static char* MotorOsc_Name = "motor";
00349 static char* MotorOsc_PropertyNames[] = { "active", "speed", "direction", 0 }; // must have a trailing 0
00350 
00351 int MotorOsc_PropertySet( int index, int property, int value );
00352 int MotorOsc_PropertyGet( int index, int property );
00353 
00354 // Returns the name of the subsystem
00355 const char* MotorOsc_GetName( )
00356 {
00357   return MotorOsc_Name;
00358 }
00359 
00360 // Now getting a message.  This is actually a part message, with the first
00361 // part (the subsystem) already parsed off.
00362 int MotorOsc_ReceiveMessage( int channel, char* message, int length )
00363 {
00364   int status = Osc_IndexIntReceiverHelper( channel, message, length, 
00365                                      MOTOR_COUNT, MotorOsc_Name,
00366                                      MotorOsc_PropertySet, MotorOsc_PropertyGet, 
00367                                      MotorOsc_PropertyNames );
00368                                      
00369   if ( status != CONTROLLER_OK )
00370     return Osc_SendError( channel, MotorOsc_Name, status );
00371   return CONTROLLER_OK;
00372 }
00373 
00374 // Set the index LED, property with the value
00375 int MotorOsc_PropertySet( int index, int property, int value )
00376 {
00377   switch ( property )
00378   {
00379     case 0: 
00380       Motor_SetActive( index, value );
00381       break;      
00382     case 1:
00383       Motor_SetSpeed( index, value );
00384       break;
00385     case 2:
00386       Motor_SetDirection( index, value );
00387       break;
00388   }
00389   return CONTROLLER_OK;
00390 }
00391 
00392 // Get the index LED, property
00393 int MotorOsc_PropertyGet( int index, int property )
00394 {
00395   int value = 0;
00396   switch ( property )
00397   {
00398     case 0:
00399       value = Motor_GetActive( index );
00400       break;
00401     case 1:
00402       value = Motor_GetSpeed( index );
00403       break;
00404     case 2:
00405       value = Motor_GetDirection( index );
00406       break;
00407   }
00408   
00409   return value;
00410 }
00411 
00412 #endif

The Make Controller Kit is an open source project maintained by MakingThings.
MakingThings code is released under the Apache 2.0 license.
Bug tracker, development wiki and status can be found at http://dev.makingthings.com.
This document was last updated on 18 May 2009.