PCA9629 a stepper motor controller class library

Dependents:   PCA9629_Hello

Class library for PCA9629.

A sample program available on http://mbed.org/users/nxp_ip/code/PCA9629_Hello/

PCA9629.h

Committer:
nxp_ip
Date:
2012-07-23
Revision:
7:199f109eb0c6
Parent:
6:138665018069

File content as of revision 7:199f109eb0c6:

/** PCA9629 library
 *
 *  @author  Akifumi (Tedd) OKANO, NXP Semiconductors
 *  @version 1.1
 *  @date    23-Jul-2012
 *
 *  revision history
 *      version 1.0 (24-Apr-2011) : Initial version
 *      version 1.1 (23-Jul-2012) : API modification
 *                                  Correction for comments
 *
 *  Released under the MIT License: http://mbed.org/license/mit
 *
 *  An operation sample of PCU9629 stepper motor controller.
 *  The mbed accesses the PCU9629 registers through I2C.
 *
 *  About PCA9629:
 *    http://www.nxp.com/products/interface_and_connectivity/i2c/i2c_bus_controller_and_bridge_ics/PCA9629PW.html
 */

#ifndef        MBED_PCA9629
#define        MBED_PCA9629

#define     INTELIGENT_WRITE

#define     DEFAULT_STEPS_PER_ROTATION  48
#define     DEFAULT_PCA9629_ADDR        0x42

/** PCA9629 class
 *
 *  This is a driver code for the PCA9629 stepper motor controller.
 *  This class provides interface for PCA9629 operation and accessing its registers.
 *  Detail information is available on next URL.
 *    http://www.nxp.com/products/interface_and_connectivity/i2c/i2c_bus_controller_and_bridge_ics/PCA9629PW.html
 *
 *  Example:
 *  @code
 * #include "mbed.h"
 * #include "PCA9629.h"
 * 
 * PCA9629 motor( p28, p27, 48 );  //  SDA, SCL, Steps/rotation, I2C_address (option)
 * 
 * int main() {
 *     
 *     //  Speed setting 200pps for clockwise (CW) rotation
 *     motor.pps( PCA9629::CW, 200 );
 *     
 *     //  Set 2 rotations and 24 steps for CW
 *     motor.rotations_and_steps( PCA9629::CW, 2, 24 );
 * 
 *     //  Speed setting 100pps for counterclockwise (CCW) rotation
 *     motor.pps( PCA9629::CCW, 100 );
 *     
 *     //  Set 1 rotation and 24 steps for CCW
 *     motor.rotations_and_steps( PCA9629::CCW, 1, 24 );
 * 
 *     while ( 1 ) {
 *         motor.start( PCA9629::CW ); //  Motor start for CW
 *         wait( 1.0 );
 * 
 *         motor.start( PCA9629::CCW ); //  Motor start for CCW
 *         wait( 1.0 );
 *     }
 * }
 *  @endcode
 */


class PCA9629 {
public:
    /** name of the PCA9629 registers */
    typedef enum {
        MODE,            /**< Mode rgister */
        SUBADR1,         /**< I2C-bus subaddress 1 */
        SUBADR2,         /**< I2C-bus subaddress 2 */
        SUBADR3,         /**< I2C-bus subaddress 3 */
        ALLCALLADR,      /**< All call I2C-bus address */
        WDTOI,           /**< Watchdog time-out interval register */
        WDTCNTL,         /**< Watchdog control register */
        IP,              /**< Input port register */
        INTSTAT,         /**< Interrupt status register */
        OP,              /**< Output port register */
        IOC,             /**< I/O configuration register */
        MSK,             /**< Mask interrupt register */
        CLRINT,          /**< Clear Interrupts */
        INTMODE,         /**< Interrupt mode register */
        INT_ACT_SETUP,   /**< Interrupt action setup control register */
        INT_MTR_SETUP,   /**< Interrupt motor setup control register */
        INT_ES_SETUP,    /**< Interrupt extra steps setup control register */
        INT_AUTO_CLR,    /**< Interrupt auto clear control register */
        SETMODE,         /**< Output state on STOP */
        PHCNTL,          /**< Phase control register */
        SROTNL,          /**< Steps per rotation low byte */
        SROTNH,          /**< Steps per rotation high byte  */
        CWPWL,           /**< Step pulse width for CW rotation low byte */
        CWPWH,           /**< Step pulse width for CW rotation high byte */
        CCWPWL,          /**< Step pulse width for CCW rotation low byte */
        CCWPWH,          /**< Step pulse width for CCW rotation high byte */
        CWSCOUNTL,       /**< Number of steps CW low byte */
        CWSCOUNTH,       /**< Number of steps CW high byte */
        CCWSCOUNTL,      /**< Number of steps CCW low byte */
        CCWSCOUNTH,      /**< Number of steps CCW high byte */
        CWRCOUNTL,       /**< Number of rotatations CW low byte */
        CWRCOUNTH,       /**< Number of rotatations CW high byte */
        CCWRCOUNTL,      /**< Number of rotatations CCW low byte */
        CCWRCOUNTH,      /**< Number of rotatations CCW high byte */
        EXTRASTEPS0,     /**< Count value for extra steps or rotations for INTP0 */
        EXTRASTEPS1,     /**< Count value for extra steps or rotations for INTP1 */
        RAMPCNTL,        /**< Ramp control register */
        LOOPDLY,         /**< Loopdelay time register */
        MCNTL,           /**< Control start/stop motor */
    } RegisterName;
    
private:
    /* register names for 2 bytes accessing */
    typedef enum {
        SROTN_      = SROTNL     | 0x80,    /**< Steps per rotation */
        CWPW_       = CWPWL      | 0x80,    /**< Step pulse width for CW rotation */
        CCWPW_      = CCWPWL     | 0x80,    /**< Step pulse width for CCW rotation */
        CWSCOUNT_   = CWSCOUNTL  | 0x80,    /**< Number of steps CW */
        CCWSCOUNT_  = CCWSCOUNTL | 0x80,    /**< Number of steps CCW */
        CWRCOUNT_   = CWRCOUNTL  | 0x80,    /**< Number of rotatations CW */
        CCWRCOUNT_  = CCWRCOUNTL | 0x80,    /**< Number of rotatations CCW */
    } _RegisterNameFor16bitAccess;
    
public:
    /** register names for 2 bytes accessing */
    typedef enum {
        STEPS_PER_ROATION   = SROTN_,
        CW__STEP_WIDTH      = CWPW_,
        CCW_STEP_WIDTH      = CCWPW_,
        CW__STEP_COUNT      = CWSCOUNT_,
        CCW_STEP_COUNT      = CCWSCOUNT_,
        CW__ROTATION_COUNT  = CWRCOUNT_,
        CCW_ROTATION_COUNT  = CCWRCOUNT_
    } RegisterNameFor16bitAccess;

    /** keyword to select direction of rotation */
    typedef enum {
        CW      = 0,    /**< Clockwise direction */
        CCW             /**< ConterClockwise direction */
    } Direction;

    /** Create a PCA9629 instance connected to specified I2C pins with specified address
     *
     * @param I2C_sda I2C-bus SDA pin
     * @param I2C_scl I2C-bus SCL pin
     * @param steps_per_rotation motor specific setting. This determines how many steps are needed to execute one full turn of motor shaft (360°).
     * @param I2C_address I2C-bus address (default: 0x42)
     */
    PCA9629(
        PinName I2C_sda,
        PinName I2C_scl,
        short   steps_per_rotation,
        char    I2C_address         = DEFAULT_PCA9629_ADDR
    );

    /** Software reset
     *
     *  Performs software reset through I2C bus
     */
    void software_reset( void );

    /** Initialize all registers
     *
     *  The initializing values are defined in the function
     */
    void init_registers( void );

    /** Initialize all registers
     *
     *  The initializing values are defined in the function
     */
    void set_all_registers( char *a, char size );

    /** Write 1 byte data into a register
     *
     *  Setting 8 bits data into a register
     *
     *  @param register_name the register name: data writing into
     *  @param value 8 bits writing data
     */
    void write( RegisterName register_name, char value );

    /** Write 2 bytes data into a register
     *
     *  Setting 16 bits data into registers
     *
     *  @param register_name the register name: data writing into (it can be "SROTN_", "CWPW_", "CCWPW_", "CWRCOUNT_", "CCWSCOUNT_", "CWRCOUNT_" or "CCWRCOUNT_" )
     *  @param value 16 bits writing data
     */
    void write( RegisterNameFor16bitAccess register_name, short value );

    /** Read 1 byte data from a register
     *
     *  Setting data into a register
     *
     *  @param register_name the register name: data reading from
     *  @return read 8 bits data from the register
     */
    char read( RegisterName register_name );

    /** Read 2 byte data from registers
     *
     *  Setting data into a register
     *
     *  @param register_name the register name: data writing into (it can be "SROTN_", "CWPW_", "CCWPW_", "CWRCOUNT_", "CCWSCOUNT_", "CWRCOUNT_" or "CCWRCOUNT_" )
     *  @return read 16 bits data from the registers
     */
    short read( RegisterNameFor16bitAccess register_name );

    /** Motor start
     *
     *  Start command
     *  This function starts motor operation with hard-stop flag and rotation+step enabled, no repeat will be performed
     *  If custom start is required, use "write( PCA9629::MCNTL, 0xXX  )" to control each bits.
     *
     *  @param dir rotate direction ("CW" or "CCW")
     */
    void start( Direction dir );

    /** Motor stop
     *
     *  Stop command
     *
     */
    void stop( void );

    /** Set PPS
     *
     *  Setting PulsePerSecond
     *  This interface can be used to set CWPWx or CCWPWx registers
     *
     *  @param dir rotate direction ("CW" or "CCW")
     *  @param pulse_per_second pps defineds pulse width for the motor. The pulse width will be 1/pps
     *  @return 16 bit data that what set to the CWPWx or CCWPWx registers
     */
    short pps( Direction dir, float pulse_per_second );

    /** Set rotations count
     *
     *  Setting rotation count
     *  This interfaces CWRCOUNTx and CCWRCOUNTx registers
     *
     *  @param dir rotate direction ("CW" or "CCW")
     *  @param rotation_count sets number of rotations with 16 bit value
     */
    void rotations( Direction dir, int rotation_count );

    /** Set steps count
     *
     *  Setting step count
     *  This interfaces CWSCOUNTx and CCWSCOUNTx registers
     *
     *  @param dir rotate direction ("CW" or "CCW")
     *  @param step_count sets number of steps with 16 bit value
     */
    void steps( Direction dir, int step_count );

    /** Set rotations and steps counts
     *
     *  Setting rotation and step count
     *  This interfaces CWRCOUNTx, CCWRCOUNTx, CWSCOUNTx and CCWSCOUNTx registers
     *
     *  @param dir rotate direction ("CW" or "CCW")
     *  @param rotation_count sets number of rotations with 16 bit value
     *  @param step_count sets number of steps with 16 bit value
     */
    void rotations_and_steps( Direction dir, int rotation_count, int step_count );

    /** Register dump
     *
     *  Dumping all register data to serial console
     *
     */
    void register_dump( void );

    /** Register dump
     *
     *  Dumping all register data to serial console
     *
     */
    void speed_change( unsigned short pw );

private:
    /* plescaler range setting */
    typedef enum {
        PRESCALER_FROM_40_TO_333333,    /*< Prescaler range from   3us(333333pps) to   24.576ms(40   pps) */
        PRESCALER_FROM_20_TO_166667,    /*< Prescaler range from   6us(166667pps) to   49.152ms(20   pps) */
        PRESCALER_FROM_10_TO_83333,     /*< Prescaler range from  12us( 83333pps) to   98.304ms(10   pps) */
        PRESCALER_FROM_5_TO_41667,      /*< Prescaler range from  24us( 41667pps) to  196.608ms( 5   pps) */
        PRESCALER_FROM_2_5_TO_20833,    /*< Prescaler range from  48us( 20833pps) to  393.216ms( 2.5 pps) */
        PRESCALER_FROM_1_27_TO_10416,   /*< Prescaler range from  96us( 10416pps) to  786.432ms( 1.27pps) */
        PRESCALER_FROM_0_64_TO_5208,    /*< Prescaler range from 192us(  5208pps) to 1572.864ms( 0.64pps) */
        PRESCALER_FROM_0_32_TO_2604,    /*< Prescaler range from 384us(  2604pps) to 3145.728ms( 0.32pps) */
    } PrescalerRange;

    /* Set PPS
     *
     *  Setting PulsePerSecond
     *  This interface can be used to set CWPWx or CCWPWx registers
     *
     *  @param dir rotate direction ("CW" or "CCW")
     *  @param prescaler prescaler setting (for 3 bits setting range from 0 to 0x7. See datasheet)
     *  @param pulse_per_second pps defineds pulse width for the motor. The pulse width will be 1/pps
     *  @return 16 bit data that what set to the CWPWx or CCWPWx registers
     */
    short pps( Direction dir, PrescalerRange prescaler, int pulse_per_second );

    I2C     i2c;
    char    i2c_addr;
};

#endif  //  MBED_PCA9629