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/

Committer:
nxp_ip
Date:
Wed Jul 18 07:42:48 2012 +0000
Revision:
6:138665018069
Parent:
5:aff87a1c8bd6
Child:
7:199f109eb0c6
auto prescaler setting

Who changed what in which revision?

UserRevisionLine numberNew contents of line
nxp_ip 4:9a80b6d63005 1 /** A sample code for PCA9629
nxp_ip 4:9a80b6d63005 2 *
nxp_ip 5:aff87a1c8bd6 3 * @author Akifumi (Tedd) OKANO, NXP Semiconductors
nxp_ip 4:9a80b6d63005 4 * @version 1.0
nxp_ip 5:aff87a1c8bd6 5 * @date 24-Apr-2011
nxp_ip 4:9a80b6d63005 6 *
nxp_ip 4:9a80b6d63005 7 * Released under the MIT License: http://mbed.org/license/mit
nxp_ip 4:9a80b6d63005 8 *
nxp_ip 6:138665018069 9 * An operation sample of PCU9629 stepper motor controller.
nxp_ip 6:138665018069 10 * The mbed accesses the PCU9629 registers through I2C.
nxp_ip 4:9a80b6d63005 11 */
nxp_ip 4:9a80b6d63005 12
nxp_ip 4:9a80b6d63005 13 #include "mbed.h"
nxp_ip 4:9a80b6d63005 14 #include "PCA9629.h"
nxp_ip 4:9a80b6d63005 15
nxp_ip 4:9a80b6d63005 16 #define STEP_RESOLUTION 333333 // 1/(3e-6) = 333333
nxp_ip 4:9a80b6d63005 17
nxp_ip 4:9a80b6d63005 18 char *reg_name[] = {
nxp_ip 4:9a80b6d63005 19 "MODE", "SUBADR1", "SUBADR2", "SUBADR3", "ALLCALLADR", "WDTC", "WDMOD", "IP",
nxp_ip 4:9a80b6d63005 20 "INTSTAT", "OP", "IOC", "MSK", "CLRINT", "INTMODE1", "INTMODE2", "INT_ACT_SETUP",
nxp_ip 4:9a80b6d63005 21 "INT_MRT_SETUP", "INT_ES_SETUP", "SETMODE", "PHCNTL", "SROTNL", "SROTNH",
nxp_ip 4:9a80b6d63005 22 "CWPWL", "CWPWH", "CCWPWL", "CCWPWH",
nxp_ip 4:9a80b6d63005 23 "CWSCOUNTL", "CWSCOUNTH", "CCWSCOUNTL", "CCWSCOUNTH",
nxp_ip 4:9a80b6d63005 24 "CWRCOUNTL", "CWRCOUNTH", "CCWRCOUNTL", "CCWRCOUNTH",
nxp_ip 4:9a80b6d63005 25 "EXTRASTEPS0", "EXTRASTEPS1", "RAMPX", "LOOPDLY", "MCNTL"
nxp_ip 4:9a80b6d63005 26 };
nxp_ip 4:9a80b6d63005 27
nxp_ip 4:9a80b6d63005 28 PCA9629::PCA9629(
nxp_ip 4:9a80b6d63005 29 PinName I2C_sda,
nxp_ip 4:9a80b6d63005 30 PinName I2C_scl,
nxp_ip 4:9a80b6d63005 31 char I2C_address
nxp_ip 4:9a80b6d63005 32 ) : i2c( I2C_sda, I2C_scl ), i2c_addr( I2C_address ) {
nxp_ip 4:9a80b6d63005 33
nxp_ip 6:138665018069 34 i2c.frequency( 400 * 1000 );
nxp_ip 4:9a80b6d63005 35 init_registers();
nxp_ip 4:9a80b6d63005 36 }
nxp_ip 4:9a80b6d63005 37
nxp_ip 4:9a80b6d63005 38 void PCA9629::init_registers( void ) {
nxp_ip 4:9a80b6d63005 39 char init_array[] = { 0x80, // register access start address (0x00) with incremental access flag (MSB)
nxp_ip 6:138665018069 40 0x30, 0xE2, 0xE4, 0xE6, 0xE0, 0x02, 0x10, // for registers MODE - WDCNTL (0x00 - 0x06
nxp_ip 6:138665018069 41 0x00, 0x00, // for registers IP and INTSTAT (0x07, 0x08)
nxp_ip 6:138665018069 42 0x07, 0x0F, 0x00, 0x0F, 0x0F, 0x00, 0x03, 0x02, 0x01, // for registers OP - INT_AUTO_CLR (0x09 - 0x11)
nxp_ip 6:138665018069 43 0x00, 0x00, 0x30, 0x00, 0x82, 0x66, 0x82, 0x06, // for registers SETMODE - CCWPWH (0x12 - 0x19)
nxp_ip 6:138665018069 44 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, // for registers CWSCOUNTL - CCWRCOUNTH (0x1A - 0x21)
nxp_ip 6:138665018069 45 0x00, 0x00, // for registers EXTRASTEPS0 and EXTRASTEPS1 (0x22, 0x23)
nxp_ip 6:138665018069 46 0x00, 0x00, 0x00 // for registers RMPCNTL - MCNTL (0x24 - 0x26)
nxp_ip 4:9a80b6d63005 47 };
nxp_ip 4:9a80b6d63005 48
nxp_ip 4:9a80b6d63005 49 set_all_registers( init_array, sizeof( init_array ) );
nxp_ip 4:9a80b6d63005 50 }
nxp_ip 4:9a80b6d63005 51
nxp_ip 6:138665018069 52 void PCA9629::set_all_registers( char *a, char size ) {
nxp_ip 4:9a80b6d63005 53 int error_code;
nxp_ip 4:9a80b6d63005 54
nxp_ip 4:9a80b6d63005 55 error_code = i2c.write( i2c_addr, a, size );
nxp_ip 4:9a80b6d63005 56
nxp_ip 4:9a80b6d63005 57 if ( error_code )
nxp_ip 4:9a80b6d63005 58 error( "error @ initializing PCA9629" );
nxp_ip 4:9a80b6d63005 59 }
nxp_ip 4:9a80b6d63005 60
nxp_ip 4:9a80b6d63005 61 void PCA9629::write( RegisterName register_name, char value ) {
nxp_ip 4:9a80b6d63005 62 int error_code;
nxp_ip 4:9a80b6d63005 63 char cmd[ 2 ];
nxp_ip 4:9a80b6d63005 64
nxp_ip 4:9a80b6d63005 65 cmd[ 0 ] = register_name;
nxp_ip 4:9a80b6d63005 66 cmd[ 1 ] = value;
nxp_ip 4:9a80b6d63005 67
nxp_ip 4:9a80b6d63005 68 error_code = i2c.write( i2c_addr, cmd, 2 );
nxp_ip 4:9a80b6d63005 69
nxp_ip 4:9a80b6d63005 70 if ( error_code )
nxp_ip 4:9a80b6d63005 71 error( "PCA9629 writing failed\r\n" );
nxp_ip 4:9a80b6d63005 72 }
nxp_ip 4:9a80b6d63005 73
nxp_ip 4:9a80b6d63005 74 void PCA9629::write( Register16bits register_name, short value ) {
nxp_ip 4:9a80b6d63005 75 int error_code;
nxp_ip 4:9a80b6d63005 76 char cmd[ 3 ];
nxp_ip 4:9a80b6d63005 77
nxp_ip 4:9a80b6d63005 78 cmd[ 0 ] = register_name;
nxp_ip 4:9a80b6d63005 79 cmd[ 1 ] = value & 0xFF;
nxp_ip 4:9a80b6d63005 80 cmd[ 2 ] = value >> 8;
nxp_ip 4:9a80b6d63005 81
nxp_ip 4:9a80b6d63005 82 error_code = i2c.write( i2c_addr, cmd, 3 );
nxp_ip 4:9a80b6d63005 83
nxp_ip 4:9a80b6d63005 84 if ( error_code )
nxp_ip 4:9a80b6d63005 85 error( "PCA9629 writing failed\r\n" );
nxp_ip 4:9a80b6d63005 86 }
nxp_ip 4:9a80b6d63005 87
nxp_ip 4:9a80b6d63005 88 char PCA9629::read( RegisterName register_name ) {
nxp_ip 4:9a80b6d63005 89 int error_code;
nxp_ip 4:9a80b6d63005 90 char cmd;
nxp_ip 4:9a80b6d63005 91 char data;
nxp_ip 4:9a80b6d63005 92
nxp_ip 4:9a80b6d63005 93 cmd = register_name;
nxp_ip 4:9a80b6d63005 94
nxp_ip 4:9a80b6d63005 95 error_code = i2c.write( i2c_addr, &cmd, 1, false );
nxp_ip 4:9a80b6d63005 96
nxp_ip 4:9a80b6d63005 97 if ( error_code )
nxp_ip 4:9a80b6d63005 98 error( "PCA9629 reading (command phase) failed\r\n" );
nxp_ip 4:9a80b6d63005 99
nxp_ip 4:9a80b6d63005 100 error_code = i2c.read( i2c_addr, &data, 1 );
nxp_ip 4:9a80b6d63005 101
nxp_ip 4:9a80b6d63005 102 if ( error_code )
nxp_ip 4:9a80b6d63005 103 error( "PCA9629 reading (data phase) failed\r\n" );
nxp_ip 4:9a80b6d63005 104
nxp_ip 4:9a80b6d63005 105 return ( data );
nxp_ip 4:9a80b6d63005 106 }
nxp_ip 4:9a80b6d63005 107
nxp_ip 4:9a80b6d63005 108 short PCA9629::read( Register16bits register_name ) {
nxp_ip 4:9a80b6d63005 109 int error_code;
nxp_ip 4:9a80b6d63005 110 char cmd;
nxp_ip 4:9a80b6d63005 111 char data[ 2 ];
nxp_ip 4:9a80b6d63005 112
nxp_ip 4:9a80b6d63005 113 cmd = register_name;
nxp_ip 4:9a80b6d63005 114
nxp_ip 4:9a80b6d63005 115 error_code = i2c.write( i2c_addr, &cmd, 1, false );
nxp_ip 4:9a80b6d63005 116
nxp_ip 4:9a80b6d63005 117 if ( error_code )
nxp_ip 4:9a80b6d63005 118 error( "PCA9629 reading (command phase) failed\r\n" );
nxp_ip 4:9a80b6d63005 119
nxp_ip 4:9a80b6d63005 120 error_code = i2c.read( i2c_addr, data, 2 );
nxp_ip 4:9a80b6d63005 121
nxp_ip 4:9a80b6d63005 122 if ( error_code )
nxp_ip 4:9a80b6d63005 123 error( "PCA9629 reading (data phase) failed\r\n" );
nxp_ip 4:9a80b6d63005 124
nxp_ip 4:9a80b6d63005 125 return ( data[ 1 ] << 8 | data[ 0 ] );
nxp_ip 4:9a80b6d63005 126 }
nxp_ip 4:9a80b6d63005 127
nxp_ip 4:9a80b6d63005 128 void PCA9629::start( Direction dir ) {
nxp_ip 4:9a80b6d63005 129 write( MCNTL, 0xA8 | dir );
nxp_ip 4:9a80b6d63005 130 }
nxp_ip 4:9a80b6d63005 131
nxp_ip 4:9a80b6d63005 132 void PCA9629::stop( void ) {
nxp_ip 4:9a80b6d63005 133 write( MCNTL, 0x00 );
nxp_ip 4:9a80b6d63005 134 }
nxp_ip 4:9a80b6d63005 135
nxp_ip 6:138665018069 136
nxp_ip 4:9a80b6d63005 137 short PCA9629::pps( Direction dir, PrescalerRange prescaler, int pps ) {
nxp_ip 4:9a80b6d63005 138 int step_pulse_width;
nxp_ip 4:9a80b6d63005 139
nxp_ip 4:9a80b6d63005 140 step_pulse_width = STEP_RESOLUTION / ((1 << prescaler) * pps);
nxp_ip 4:9a80b6d63005 141
nxp_ip 4:9a80b6d63005 142 if ( step_pulse_width & 0xE000 ) { //error( "pps setting: out of range" );
nxp_ip 4:9a80b6d63005 143 step_pulse_width = 0x1FFF;
nxp_ip 4:9a80b6d63005 144 printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / ((float)0x1FFF * (float)(1 << prescaler)) );
nxp_ip 4:9a80b6d63005 145 }
nxp_ip 4:9a80b6d63005 146 if ( !step_pulse_width ) { //error( "pps setting: out of range" );
nxp_ip 4:9a80b6d63005 147 step_pulse_width = 0x1;
nxp_ip 4:9a80b6d63005 148 printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / (float)(1 << prescaler) );
nxp_ip 4:9a80b6d63005 149 }
nxp_ip 4:9a80b6d63005 150
nxp_ip 4:9a80b6d63005 151 step_pulse_width |= (prescaler << 13);
nxp_ip 4:9a80b6d63005 152
nxp_ip 4:9a80b6d63005 153 write( (dir == CW) ? CWPW_ : CCWPW_, step_pulse_width );
nxp_ip 4:9a80b6d63005 154
nxp_ip 4:9a80b6d63005 155 return ( step_pulse_width );
nxp_ip 4:9a80b6d63005 156 }
nxp_ip 4:9a80b6d63005 157
nxp_ip 6:138665018069 158 short PCA9629::pps( Direction dir, float pulse_per_second ) {
nxp_ip 6:138665018069 159 char p = 0;
nxp_ip 6:138665018069 160 char ratio;
nxp_ip 6:138665018069 161
nxp_ip 6:138665018069 162 ratio = (char)(40.6901 / pulse_per_second);
nxp_ip 6:138665018069 163
nxp_ip 6:138665018069 164 p = (ratio & 0x01) ? 1 : p;
nxp_ip 6:138665018069 165 p = (ratio & 0x02) ? 2 : p;
nxp_ip 6:138665018069 166 p = (ratio & 0x04) ? 3 : p;
nxp_ip 6:138665018069 167 p = (ratio & 0x08) ? 4 : p;
nxp_ip 6:138665018069 168 p = (ratio & 0x10) ? 5 : p;
nxp_ip 6:138665018069 169 p = (ratio & 0x20) ? 6 : p;
nxp_ip 6:138665018069 170 p = (ratio & 0x40) ? 7 : p;
nxp_ip 6:138665018069 171
nxp_ip 6:138665018069 172 return ( pps( dir, (PrescalerRange)p, (int)pulse_per_second ) );
nxp_ip 6:138665018069 173 }
nxp_ip 6:138665018069 174
nxp_ip 4:9a80b6d63005 175 void PCA9629::rotations( Direction dir, int rotations ) {
nxp_ip 4:9a80b6d63005 176 write( (dir == CW) ? CWRCOUNT_ : CCWRCOUNT_, rotations );
nxp_ip 4:9a80b6d63005 177 }
nxp_ip 4:9a80b6d63005 178
nxp_ip 4:9a80b6d63005 179 void PCA9629::steps( Direction dir, int steps ) {
nxp_ip 4:9a80b6d63005 180 write( (dir == CW) ? CWSCOUNT_ : CCWSCOUNT_, steps );
nxp_ip 4:9a80b6d63005 181 }
nxp_ip 4:9a80b6d63005 182
nxp_ip 4:9a80b6d63005 183
nxp_ip 4:9a80b6d63005 184 void PCA9629::register_dump( void ) {
nxp_ip 4:9a80b6d63005 185 char data[ 0x27 ];
nxp_ip 4:9a80b6d63005 186 char cmd = 0x80;
nxp_ip 4:9a80b6d63005 187 int i;
nxp_ip 4:9a80b6d63005 188 int j;
nxp_ip 4:9a80b6d63005 189
nxp_ip 4:9a80b6d63005 190 i2c.write( i2c_addr, &cmd, 1 );
nxp_ip 4:9a80b6d63005 191 i2c.read( i2c_addr, data, sizeof( data ) );
nxp_ip 4:9a80b6d63005 192
nxp_ip 4:9a80b6d63005 193 printf( "PCA9629 register dump\r\n" );
nxp_ip 4:9a80b6d63005 194
nxp_ip 4:9a80b6d63005 195 for ( i = 0, j = 0x14; i <= 0x12; i++, j++ )
nxp_ip 4:9a80b6d63005 196 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 ] );
nxp_ip 4:9a80b6d63005 197
nxp_ip 4:9a80b6d63005 198 printf( " %-13s (0x%02X): 0x%02X\r\n", reg_name[ 0x13 ], 0x13, data[ 0x13 ] );
nxp_ip 4:9a80b6d63005 199 }
nxp_ip 4:9a80b6d63005 200
nxp_ip 4:9a80b6d63005 201
nxp_ip 4:9a80b6d63005 202 void PCA9629::speed_change( unsigned short pw ) {
nxp_ip 4:9a80b6d63005 203 char cmd0[] = { PCA9629::MCNTL, 0x00}; // data for stop the motor
nxp_ip 4:9a80b6d63005 204 char cmd1[] = { PCA9629::CW__STEP_WIDTH, pw & 0xFF, pw >> 8 }; // data for rewrite pulse width
nxp_ip 4:9a80b6d63005 205 char cmd2[] = { PCA9629::MCNTL, 0xB4}; // start // data for start again
nxp_ip 4:9a80b6d63005 206 wait_us(10);
nxp_ip 4:9a80b6d63005 207
nxp_ip 4:9a80b6d63005 208 i2c.write( i2c_addr, cmd0, sizeof( cmd0 ), true ); // stop the motor
nxp_ip 4:9a80b6d63005 209 wait_us(50);
nxp_ip 4:9a80b6d63005 210 i2c.write( i2c_addr, cmd1, sizeof( cmd1 ), true ); // rewrite pulse width
nxp_ip 4:9a80b6d63005 211 i2c.write( i2c_addr, cmd2, sizeof( cmd2 ), false ); // start again
nxp_ip 4:9a80b6d63005 212 }
nxp_ip 4:9a80b6d63005 213
nxp_ip 4:9a80b6d63005 214
nxp_ip 4:9a80b6d63005 215