PCA9629 a stepper motor controller class library

Dependents:   PCA9629_Hello

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PCA9629.h Source File

PCA9629.h

00001 /** PCA9629 library
00002  *
00003  *  @author  Akifumi (Tedd) OKANO, NXP Semiconductors
00004  *  @version 1.1
00005  *  @date    23-Jul-2012
00006  *
00007  *  revision history
00008  *      version 1.0 (24-Apr-2011) : Initial version
00009  *      version 1.1 (23-Jul-2012) : API modification
00010  *                                  Correction for comments
00011  *
00012  *  Released under the MIT License: http://mbed.org/license/mit
00013  *
00014  *  An operation sample of PCU9629 stepper motor controller.
00015  *  The mbed accesses the PCU9629 registers through I2C.
00016  *
00017  *  About PCA9629:
00018  *    http://www.nxp.com/products/interface_and_connectivity/i2c/i2c_bus_controller_and_bridge_ics/PCA9629PW.html
00019  */
00020 
00021 #ifndef        MBED_PCA9629
00022 #define        MBED_PCA9629
00023 
00024 #define     INTELIGENT_WRITE
00025 
00026 #define     DEFAULT_STEPS_PER_ROTATION  48
00027 #define     DEFAULT_PCA9629_ADDR        0x42
00028 
00029 /** PCA9629 class
00030  *
00031  *  This is a driver code for the PCA9629 stepper motor controller.
00032  *  This class provides interface for PCA9629 operation and accessing its registers.
00033  *  Detail information is available on next URL.
00034  *    http://www.nxp.com/products/interface_and_connectivity/i2c/i2c_bus_controller_and_bridge_ics/PCA9629PW.html
00035  *
00036  *  Example:
00037  *  @code
00038  * #include "mbed.h"
00039  * #include "PCA9629.h"
00040  * 
00041  * PCA9629 motor( p28, p27, 48 );  //  SDA, SCL, Steps/rotation, I2C_address (option)
00042  * 
00043  * int main() {
00044  *     
00045  *     //  Speed setting 200pps for clockwise (CW) rotation
00046  *     motor.pps( PCA9629::CW, 200 );
00047  *     
00048  *     //  Set 2 rotations and 24 steps for CW
00049  *     motor.rotations_and_steps( PCA9629::CW, 2, 24 );
00050  * 
00051  *     //  Speed setting 100pps for counterclockwise (CCW) rotation
00052  *     motor.pps( PCA9629::CCW, 100 );
00053  *     
00054  *     //  Set 1 rotation and 24 steps for CCW
00055  *     motor.rotations_and_steps( PCA9629::CCW, 1, 24 );
00056  * 
00057  *     while ( 1 ) {
00058  *         motor.start( PCA9629::CW ); //  Motor start for CW
00059  *         wait( 1.0 );
00060  * 
00061  *         motor.start( PCA9629::CCW ); //  Motor start for CCW
00062  *         wait( 1.0 );
00063  *     }
00064  * }
00065  *  @endcode
00066  */
00067 
00068 
00069 class PCA9629 {
00070 public:
00071     /** name of the PCA9629 registers */
00072     typedef enum {
00073         MODE,            /**< Mode rgister */
00074         SUBADR1,         /**< I2C-bus subaddress 1 */
00075         SUBADR2,         /**< I2C-bus subaddress 2 */
00076         SUBADR3,         /**< I2C-bus subaddress 3 */
00077         ALLCALLADR,      /**< All call I2C-bus address */
00078         WDTOI,           /**< Watchdog time-out interval register */
00079         WDTCNTL,         /**< Watchdog control register */
00080         IP,              /**< Input port register */
00081         INTSTAT,         /**< Interrupt status register */
00082         OP,              /**< Output port register */
00083         IOC,             /**< I/O configuration register */
00084         MSK,             /**< Mask interrupt register */
00085         CLRINT,          /**< Clear Interrupts */
00086         INTMODE,         /**< Interrupt mode register */
00087         INT_ACT_SETUP,   /**< Interrupt action setup control register */
00088         INT_MTR_SETUP,   /**< Interrupt motor setup control register */
00089         INT_ES_SETUP,    /**< Interrupt extra steps setup control register */
00090         INT_AUTO_CLR,    /**< Interrupt auto clear control register */
00091         SETMODE,         /**< Output state on STOP */
00092         PHCNTL,          /**< Phase control register */
00093         SROTNL,          /**< Steps per rotation low byte */
00094         SROTNH,          /**< Steps per rotation high byte  */
00095         CWPWL,           /**< Step pulse width for CW rotation low byte */
00096         CWPWH,           /**< Step pulse width for CW rotation high byte */
00097         CCWPWL,          /**< Step pulse width for CCW rotation low byte */
00098         CCWPWH,          /**< Step pulse width for CCW rotation high byte */
00099         CWSCOUNTL,       /**< Number of steps CW low byte */
00100         CWSCOUNTH,       /**< Number of steps CW high byte */
00101         CCWSCOUNTL,      /**< Number of steps CCW low byte */
00102         CCWSCOUNTH,      /**< Number of steps CCW high byte */
00103         CWRCOUNTL,       /**< Number of rotatations CW low byte */
00104         CWRCOUNTH,       /**< Number of rotatations CW high byte */
00105         CCWRCOUNTL,      /**< Number of rotatations CCW low byte */
00106         CCWRCOUNTH,      /**< Number of rotatations CCW high byte */
00107         EXTRASTEPS0,     /**< Count value for extra steps or rotations for INTP0 */
00108         EXTRASTEPS1,     /**< Count value for extra steps or rotations for INTP1 */
00109         RAMPCNTL,        /**< Ramp control register */
00110         LOOPDLY,         /**< Loopdelay time register */
00111         MCNTL,           /**< Control start/stop motor */
00112     } RegisterName;
00113     
00114 private:
00115     /* register names for 2 bytes accessing */
00116     typedef enum {
00117         SROTN_      = SROTNL     | 0x80,    /**< Steps per rotation */
00118         CWPW_       = CWPWL      | 0x80,    /**< Step pulse width for CW rotation */
00119         CCWPW_      = CCWPWL     | 0x80,    /**< Step pulse width for CCW rotation */
00120         CWSCOUNT_   = CWSCOUNTL  | 0x80,    /**< Number of steps CW */
00121         CCWSCOUNT_  = CCWSCOUNTL | 0x80,    /**< Number of steps CCW */
00122         CWRCOUNT_   = CWRCOUNTL  | 0x80,    /**< Number of rotatations CW */
00123         CCWRCOUNT_  = CCWRCOUNTL | 0x80,    /**< Number of rotatations CCW */
00124     } _RegisterNameFor16bitAccess;
00125     
00126 public:
00127     /** register names for 2 bytes accessing */
00128     typedef enum {
00129         STEPS_PER_ROATION   = SROTN_,
00130         CW__STEP_WIDTH      = CWPW_,
00131         CCW_STEP_WIDTH      = CCWPW_,
00132         CW__STEP_COUNT      = CWSCOUNT_,
00133         CCW_STEP_COUNT      = CCWSCOUNT_,
00134         CW__ROTATION_COUNT  = CWRCOUNT_,
00135         CCW_ROTATION_COUNT  = CCWRCOUNT_
00136     } RegisterNameFor16bitAccess;
00137 
00138     /** keyword to select direction of rotation */
00139     typedef enum {
00140         CW      = 0,    /**< Clockwise direction */
00141         CCW             /**< ConterClockwise direction */
00142     } Direction;
00143 
00144     /** Create a PCA9629 instance connected to specified I2C pins with specified address
00145      *
00146      * @param I2C_sda I2C-bus SDA pin
00147      * @param I2C_scl I2C-bus SCL pin
00148      * @param steps_per_rotation motor specific setting. This determines how many steps are needed to execute one full turn of motor shaft (360°).
00149      * @param I2C_address I2C-bus address (default: 0x42)
00150      */
00151     PCA9629(
00152         PinName I2C_sda,
00153         PinName I2C_scl,
00154         short   steps_per_rotation,
00155         char    I2C_address         = DEFAULT_PCA9629_ADDR
00156     );
00157 
00158     /** Software reset
00159      *
00160      *  Performs software reset through I2C bus
00161      */
00162     void software_reset( void );
00163 
00164     /** Initialize all registers
00165      *
00166      *  The initializing values are defined in the function
00167      */
00168     void init_registers( void );
00169 
00170     /** Initialize all registers
00171      *
00172      *  The initializing values are defined in the function
00173      */
00174     void set_all_registers( char *a, char size );
00175 
00176     /** Write 1 byte data into a register
00177      *
00178      *  Setting 8 bits data into a register
00179      *
00180      *  @param register_name the register name: data writing into
00181      *  @param value 8 bits writing data
00182      */
00183     void write( RegisterName register_name, char value );
00184 
00185     /** Write 2 bytes data into a register
00186      *
00187      *  Setting 16 bits data into registers
00188      *
00189      *  @param register_name the register name: data writing into (it can be "SROTN_", "CWPW_", "CCWPW_", "CWRCOUNT_", "CCWSCOUNT_", "CWRCOUNT_" or "CCWRCOUNT_" )
00190      *  @param value 16 bits writing data
00191      */
00192     void write( RegisterNameFor16bitAccess register_name, short value );
00193 
00194     /** Read 1 byte data from a register
00195      *
00196      *  Setting data into a register
00197      *
00198      *  @param register_name the register name: data reading from
00199      *  @return read 8 bits data from the register
00200      */
00201     char read( RegisterName register_name );
00202 
00203     /** Read 2 byte data from registers
00204      *
00205      *  Setting data into a register
00206      *
00207      *  @param register_name the register name: data writing into (it can be "SROTN_", "CWPW_", "CCWPW_", "CWRCOUNT_", "CCWSCOUNT_", "CWRCOUNT_" or "CCWRCOUNT_" )
00208      *  @return read 16 bits data from the registers
00209      */
00210     short read( RegisterNameFor16bitAccess register_name );
00211 
00212     /** Motor start
00213      *
00214      *  Start command
00215      *  This function starts motor operation with hard-stop flag and rotation+step enabled, no repeat will be performed
00216      *  If custom start is required, use "write( PCA9629::MCNTL, 0xXX  )" to control each bits.
00217      *
00218      *  @param dir rotate direction ("CW" or "CCW")
00219      */
00220     void start( Direction dir );
00221 
00222     /** Motor stop
00223      *
00224      *  Stop command
00225      *
00226      */
00227     void stop( void );
00228 
00229     /** Set PPS
00230      *
00231      *  Setting PulsePerSecond
00232      *  This interface can be used to set CWPWx or CCWPWx registers
00233      *
00234      *  @param dir rotate direction ("CW" or "CCW")
00235      *  @param pulse_per_second pps defineds pulse width for the motor. The pulse width will be 1/pps
00236      *  @return 16 bit data that what set to the CWPWx or CCWPWx registers
00237      */
00238     short pps( Direction dir, float pulse_per_second );
00239 
00240     /** Set rotations count
00241      *
00242      *  Setting rotation count
00243      *  This interfaces CWRCOUNTx and CCWRCOUNTx registers
00244      *
00245      *  @param dir rotate direction ("CW" or "CCW")
00246      *  @param rotation_count sets number of rotations with 16 bit value
00247      */
00248     void rotations( Direction dir, int rotation_count );
00249 
00250     /** Set steps count
00251      *
00252      *  Setting step count
00253      *  This interfaces CWSCOUNTx and CCWSCOUNTx registers
00254      *
00255      *  @param dir rotate direction ("CW" or "CCW")
00256      *  @param step_count sets number of steps with 16 bit value
00257      */
00258     void steps( Direction dir, int step_count );
00259 
00260     /** Set rotations and steps counts
00261      *
00262      *  Setting rotation and step count
00263      *  This interfaces CWRCOUNTx, CCWRCOUNTx, CWSCOUNTx and CCWSCOUNTx registers
00264      *
00265      *  @param dir rotate direction ("CW" or "CCW")
00266      *  @param rotation_count sets number of rotations with 16 bit value
00267      *  @param step_count sets number of steps with 16 bit value
00268      */
00269     void rotations_and_steps( Direction dir, int rotation_count, int step_count );
00270 
00271     /** Register dump
00272      *
00273      *  Dumping all register data to serial console
00274      *
00275      */
00276     void register_dump( void );
00277 
00278     /** Register dump
00279      *
00280      *  Dumping all register data to serial console
00281      *
00282      */
00283     void speed_change( unsigned short pw );
00284 
00285 private:
00286     /* plescaler range setting */
00287     typedef enum {
00288         PRESCALER_FROM_40_TO_333333,    /*< Prescaler range from   3us(333333pps) to   24.576ms(40   pps) */
00289         PRESCALER_FROM_20_TO_166667,    /*< Prescaler range from   6us(166667pps) to   49.152ms(20   pps) */
00290         PRESCALER_FROM_10_TO_83333,     /*< Prescaler range from  12us( 83333pps) to   98.304ms(10   pps) */
00291         PRESCALER_FROM_5_TO_41667,      /*< Prescaler range from  24us( 41667pps) to  196.608ms( 5   pps) */
00292         PRESCALER_FROM_2_5_TO_20833,    /*< Prescaler range from  48us( 20833pps) to  393.216ms( 2.5 pps) */
00293         PRESCALER_FROM_1_27_TO_10416,   /*< Prescaler range from  96us( 10416pps) to  786.432ms( 1.27pps) */
00294         PRESCALER_FROM_0_64_TO_5208,    /*< Prescaler range from 192us(  5208pps) to 1572.864ms( 0.64pps) */
00295         PRESCALER_FROM_0_32_TO_2604,    /*< Prescaler range from 384us(  2604pps) to 3145.728ms( 0.32pps) */
00296     } PrescalerRange;
00297 
00298     /* Set PPS
00299      *
00300      *  Setting PulsePerSecond
00301      *  This interface can be used to set CWPWx or CCWPWx registers
00302      *
00303      *  @param dir rotate direction ("CW" or "CCW")
00304      *  @param prescaler prescaler setting (for 3 bits setting range from 0 to 0x7. See datasheet)
00305      *  @param pulse_per_second pps defineds pulse width for the motor. The pulse width will be 1/pps
00306      *  @return 16 bit data that what set to the CWPWx or CCWPWx registers
00307      */
00308     short pps( Direction dir, PrescalerRange prescaler, int pulse_per_second );
00309 
00310     I2C     i2c;
00311     char    i2c_addr;
00312 };
00313 
00314 #endif  //  MBED_PCA9629
00315