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/

Revision:
4:9a80b6d63005
Child:
5:aff87a1c8bd6
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/PCA9629.cpp	Fri Feb 03 04:03:34 2012 +0000
@@ -0,0 +1,198 @@
+/** A sample code for PCA9629
+ *
+ *  @author  Tedd OKANO, NXP Semiconductors
+ *  @version 1.0
+ *  @date    03-Feb-2011
+ *
+ *  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. 
+ */
+
+#include    "mbed.h"
+#include    "PCA9629.h"
+
+#define     STEP_RESOLUTION     333333      //  1/(3e-6) = 333333
+
+char *reg_name[] = {
+    "MODE", "SUBADR1", "SUBADR2", "SUBADR3", "ALLCALLADR", "WDTC", "WDMOD", "IP",
+    "INTSTAT", "OP", "IOC", "MSK", "CLRINT", "INTMODE1", "INTMODE2", "INT_ACT_SETUP",
+    "INT_MRT_SETUP", "INT_ES_SETUP", "SETMODE", "PHCNTL", "SROTNL", "SROTNH",
+    "CWPWL", "CWPWH", "CCWPWL", "CCWPWH",
+    "CWSCOUNTL", "CWSCOUNTH", "CCWSCOUNTL", "CCWSCOUNTH",
+    "CWRCOUNTL", "CWRCOUNTH", "CCWRCOUNTL", "CCWRCOUNTH",
+    "EXTRASTEPS0", "EXTRASTEPS1", "RAMPX", "LOOPDLY", "MCNTL"
+};
+
+PCA9629::PCA9629(
+    PinName I2C_sda,
+    PinName I2C_scl,
+    char    I2C_address
+) : i2c( I2C_sda, I2C_scl ), i2c_addr( I2C_address ) {
+
+    i2c.frequency( 400 * 1000 );    
+    init_registers();
+}
+
+void PCA9629::init_registers( void ) {
+    char    init_array[] = { 0x80,                                                //  register access start address (0x00) with incremental access flag (MSB)
+                            0x30, 0xE2, 0xE4, 0xE6, 0xE0, 0x02, 0x10,             //  for registers MODE - WDCNTL (0x00 - 0x06
+                            0x00, 0x00,                                           //  for registers IP and INTSTAT (0x07, 0x08)
+                            0x07, 0x0F, 0x00, 0x0F, 0x0F, 0x00, 0x03, 0x02, 0x01, //  for registers OP - INT_AUTO_CLR (0x09 - 0x11)
+                            0x00, 0x00, 0x30, 0x00, 0x82, 0x66, 0x82, 0x06,       //  for registers SETMODE - CCWPWH (0x12 - 0x19)
+                            0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,       //  for registers CWSCOUNTL - CCWRCOUNTH (0x1A - 0x21)
+                            0x00, 0x00,                                           //  for registers EXTRASTEPS0 and EXTRASTEPS1 (0x22, 0x23)
+                            0x00, 0x00, 0x00                                      //  for registers RMPCNTL - MCNTL (0x24 - 0x26)
+                           };
+
+    set_all_registers( init_array, sizeof( init_array ) );
+}
+
+void PCA9629::set_all_registers( char *a, char size )
+{
+    int     error_code;
+
+    error_code  = i2c.write( i2c_addr, a, size );
+
+    if ( error_code )
+        error( "error @ initializing PCA9629" );
+}
+
+void PCA9629::write( RegisterName register_name, char value ) {
+    int     error_code;
+    char    cmd[ 2 ];
+
+    cmd[ 0 ]    = register_name;
+    cmd[ 1 ]    = value;
+
+    error_code  = i2c.write( i2c_addr, cmd, 2 );
+
+    if ( error_code )
+        error( "PCA9629 writing failed\r\n" );
+}
+
+void PCA9629::write( Register16bits register_name, short value ) {
+    int     error_code;
+    char    cmd[ 3 ];
+
+    cmd[ 0 ]    = register_name;
+    cmd[ 1 ]    = value & 0xFF;
+    cmd[ 2 ]    = value >> 8;
+
+    error_code  = i2c.write( i2c_addr, cmd, 3 );
+
+    if ( error_code )
+        error( "PCA9629 writing failed\r\n" );
+}
+
+char PCA9629::read( RegisterName register_name ) {
+    int     error_code;
+    char    cmd;
+    char    data;
+
+    cmd = register_name;
+
+    error_code  = i2c.write( i2c_addr, &cmd, 1, false );
+
+    if ( error_code )
+        error( "PCA9629 reading (command phase) failed\r\n" );
+
+    error_code  = i2c.read( i2c_addr, &data, 1 );
+
+    if ( error_code )
+        error( "PCA9629 reading (data phase) failed\r\n" );
+
+    return ( data );
+}
+
+short PCA9629::read( Register16bits register_name ) {
+    int     error_code;
+    char    cmd;
+    char    data[ 2 ];
+
+    cmd = register_name;
+
+    error_code  = i2c.write( i2c_addr, &cmd, 1, false );
+
+    if ( error_code )
+        error( "PCA9629 reading (command phase) failed\r\n" );
+
+    error_code  = i2c.read( i2c_addr, data, 2 );
+
+    if ( error_code )
+        error( "PCA9629 reading (data phase) failed\r\n" );
+
+    return ( data[ 1 ] << 8 | data[ 0 ] );
+}
+
+void PCA9629::start( Direction dir ) {
+    write( MCNTL, 0xA8 | dir );
+}
+
+void PCA9629::stop( void ) {
+    write( MCNTL, 0x00 );
+}
+
+short PCA9629::pps( Direction dir, PrescalerRange prescaler, int pps ) {
+    int     step_pulse_width;
+
+    step_pulse_width    = STEP_RESOLUTION / ((1 << prescaler) * pps);
+
+    if ( step_pulse_width & 0xE000 ) {  //error( "pps setting: out of range" );
+        step_pulse_width    = 0x1FFF;
+        printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / ((float)0x1FFF * (float)(1 << prescaler)) );
+    }
+    if ( !step_pulse_width ) {  //error( "pps setting: out of range" );
+        step_pulse_width    = 0x1;
+        printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / (float)(1 << prescaler) );
+    }
+
+    step_pulse_width    |= (prescaler << 13);
+
+    write( (dir == CW) ? CWPW_ : CCWPW_, step_pulse_width );
+
+    return ( step_pulse_width );
+}
+
+void PCA9629::rotations( Direction dir, int rotations ) {
+    write( (dir == CW) ? CWRCOUNT_ : CCWRCOUNT_, rotations );
+}
+
+void PCA9629::steps( Direction dir, int steps ) {
+    write( (dir == CW) ? CWSCOUNT_ : CCWSCOUNT_, steps );
+}
+
+
+void PCA9629::register_dump( void ) {
+    char    data[ 0x27 ];
+    char    cmd = 0x80;
+    int     i;
+    int     j;
+
+    i2c.write( i2c_addr, &cmd, 1 );
+    i2c.read( i2c_addr, data, sizeof( data ) );
+
+    printf( "PCA9629 register dump\r\n" );
+
+    for ( i = 0, j = 0x14; i <= 0x12; i++, j++ )
+        printf( "  %-13s (0x%02X): 0x%02X    %-13s (0x%02X): 0x%02X\r\n", reg_name[ i ], i, data[ i ], reg_name[ j ], j, data[ j ] );
+
+    printf( "  %-13s (0x%02X): 0x%02X\r\n", reg_name[ 0x13 ], 0x13, data[ 0x13 ] );
+}
+
+
+void PCA9629::speed_change( unsigned short pw ) {
+    char    cmd0[]   = { PCA9629::MCNTL, 0x00};                         //  data for stop the motor
+    char    cmd1[]   = { PCA9629::CW__STEP_WIDTH, pw & 0xFF, pw >> 8 }; //  data for rewrite pulse width
+    char    cmd2[]   = { PCA9629::MCNTL, 0xB4};   //  start             //  data for start again
+    wait_us(10);
+
+    i2c.write( i2c_addr, cmd0, sizeof( cmd0 ), true );  //  stop the motor
+    wait_us(50);
+    i2c.write( i2c_addr, cmd1, sizeof( cmd1 ), true );  //  rewrite pulse width
+    i2c.write( i2c_addr, cmd2, sizeof( cmd2 ), false ); //  start again
+}
+
+
+