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:
Mon Jul 23 04:57:38 2012 +0000
Revision:
7:199f109eb0c6
Parent:
6:138665018069
version 1.1

Who changed what in which revision?

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