PCA9629 a stepper motor controller class library
Embed:
(wiki syntax)
Show/hide line numbers
PCA9629.cpp
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 #include "mbed.h" 00022 #include "PCA9629.h" 00023 00024 #define STEP_RESOLUTION 333333 // 1/(3e-6) = 333333 00025 00026 char *reg_name[] = { 00027 "MODE", "SUBADR1", "SUBADR2", "SUBADR3", "ALLCALLADR", "WDTC", "WDMOD", "IP", 00028 "INTSTAT", "OP", "IOC", "MSK", "CLRINT", "INTMODE1", "INTMODE2", "INT_ACT_SETUP", 00029 "INT_MRT_SETUP", "INT_ES_SETUP", "SETMODE", "PHCNTL", "SROTNL", "SROTNH", 00030 "CWPWL", "CWPWH", "CCWPWL", "CCWPWH", 00031 "CWSCOUNTL", "CWSCOUNTH", "CCWSCOUNTL", "CCWSCOUNTH", 00032 "CWRCOUNTL", "CWRCOUNTH", "CCWRCOUNTL", "CCWRCOUNTH", 00033 "EXTRASTEPS0", "EXTRASTEPS1", "RAMPX", "LOOPDLY", "MCNTL" 00034 }; 00035 00036 PCA9629::PCA9629( 00037 PinName I2C_sda, 00038 PinName I2C_scl, 00039 short steps_per_rotation, 00040 char I2C_address 00041 ) : i2c( I2C_sda, I2C_scl ), i2c_addr( I2C_address ) { 00042 00043 i2c.frequency( 400 * 1000 ); 00044 software_reset(); 00045 init_registers(); 00046 } 00047 00048 void PCA9629::software_reset( void ) { 00049 char v = 0x06; 00050 00051 i2c.write( 0x00, &v, 1 ); 00052 wait_ms( 1 ); 00053 } 00054 00055 void PCA9629::init_registers( void ) { 00056 char init_array[] = { 0x80, // register access start address (0x00) with incremental access flag (MSB) 00057 0x30, 0xE2, 0xE4, 0xE6, 0xE0, 0x02, 0x10, // for registers MODE - WDCNTL (0x00 - 0x06 00058 0x00, 0x00, // for registers IP and INTSTAT (0x07, 0x08) 00059 0x07, 0x0F, 0x00, 0x0F, 0x0F, 0x00, 0x03, 0x02, 0x01, // for registers OP - INT_AUTO_CLR (0x09 - 0x11) 00060 0x00, 0x00, 0x30, 0x00, 0x82, 0x66, 0x82, 0x06, // for registers SETMODE - CCWPWH (0x12 - 0x19) 00061 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, // for registers CWSCOUNTL - CCWRCOUNTH (0x1A - 0x21) 00062 0x00, 0x00, // for registers EXTRASTEPS0 and EXTRASTEPS1 (0x22, 0x23) 00063 0x00, 0x00, 0x00 // for registers RMPCNTL - MCNTL (0x24 - 0x26) 00064 }; 00065 00066 set_all_registers( init_array, sizeof( init_array ) ); 00067 } 00068 00069 void PCA9629::set_all_registers( char *a, char size ) { 00070 int error_code; 00071 00072 error_code = i2c.write( i2c_addr, a, size ); 00073 00074 if ( error_code ) 00075 error( "error @ initializing PCA9629" ); 00076 } 00077 00078 void PCA9629::write( RegisterName register_name, char value ) { 00079 int error_code; 00080 char cmd[ 2 ]; 00081 00082 cmd[ 0 ] = register_name; 00083 cmd[ 1 ] = value; 00084 00085 error_code = i2c.write( i2c_addr, cmd, 2 ); 00086 00087 if ( error_code ) 00088 error( "PCA9629 writing failed\r\n" ); 00089 } 00090 00091 void PCA9629::write( RegisterNameFor16bitAccess register_name, short value ) { 00092 int error_code; 00093 char cmd[ 3 ]; 00094 00095 cmd[ 0 ] = register_name; 00096 cmd[ 1 ] = value & 0xFF; 00097 cmd[ 2 ] = value >> 8; 00098 00099 error_code = i2c.write( i2c_addr, cmd, 3 ); 00100 00101 if ( error_code ) 00102 error( "PCA9629 writing failed\r\n" ); 00103 } 00104 00105 char PCA9629::read( RegisterName register_name ) { 00106 int error_code; 00107 char cmd; 00108 char data; 00109 00110 cmd = register_name; 00111 00112 error_code = i2c.write( i2c_addr, &cmd, 1, false ); 00113 00114 if ( error_code ) 00115 error( "PCA9629 reading (command phase) failed\r\n" ); 00116 00117 error_code = i2c.read( i2c_addr, &data, 1 ); 00118 00119 if ( error_code ) 00120 error( "PCA9629 reading (data phase) failed\r\n" ); 00121 00122 return ( data ); 00123 } 00124 00125 short PCA9629::read( RegisterNameFor16bitAccess register_name ) { 00126 int error_code; 00127 char cmd; 00128 char data[ 2 ]; 00129 00130 cmd = register_name; 00131 00132 error_code = i2c.write( i2c_addr, &cmd, 1, false ); 00133 00134 if ( error_code ) 00135 error( "PCA9629 reading (command phase) failed\r\n" ); 00136 00137 error_code = i2c.read( i2c_addr, data, 2 ); 00138 00139 if ( error_code ) 00140 error( "PCA9629 reading (data phase) failed\r\n" ); 00141 00142 return ( data[ 1 ] << 8 | data[ 0 ] ); 00143 } 00144 00145 void PCA9629::start( Direction dir ) { 00146 write( MCNTL, 0xA8 | dir ); 00147 } 00148 00149 void PCA9629::stop( void ) { 00150 write( MCNTL, 0x00 ); 00151 } 00152 00153 00154 short PCA9629::pps( Direction dir, PrescalerRange prescaler, int pps ) { 00155 int step_pulse_width; 00156 00157 step_pulse_width = STEP_RESOLUTION / ((1 << prescaler) * pps); 00158 00159 if ( step_pulse_width & 0xE000 ) { //error( "pps setting: out of range" ); 00160 step_pulse_width = 0x1FFF; 00161 printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / ((float)0x1FFF * (float)(1 << prescaler)) ); 00162 } 00163 if ( !step_pulse_width ) { //error( "pps setting: out of range" ); 00164 step_pulse_width = 0x1; 00165 printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / (float)(1 << prescaler) ); 00166 } 00167 00168 step_pulse_width |= (prescaler << 13); 00169 00170 write( (dir == CW) ? CW__STEP_WIDTH : CCW_STEP_WIDTH, step_pulse_width ); 00171 00172 return ( step_pulse_width ); 00173 } 00174 00175 short PCA9629::pps( Direction dir, float pulse_per_second ) { 00176 char p = 0; 00177 char ratio; 00178 00179 ratio = (char)(40.6901 / pulse_per_second); 00180 00181 p = (ratio & 0x01) ? 1 : p; 00182 p = (ratio & 0x02) ? 2 : p; 00183 p = (ratio & 0x04) ? 3 : p; 00184 p = (ratio & 0x08) ? 4 : p; 00185 p = (ratio & 0x10) ? 5 : p; 00186 p = (ratio & 0x20) ? 6 : p; 00187 p = (ratio & 0x40) ? 7 : p; 00188 00189 return ( pps( dir, (PrescalerRange)p, (int)pulse_per_second ) ); 00190 } 00191 00192 void PCA9629::rotations( Direction dir, int rotation_count ) { 00193 write( (dir == CW) ? CW__ROTATION_COUNT : CCW_ROTATION_COUNT, rotation_count ); 00194 } 00195 00196 void PCA9629::steps( Direction dir, int step_count ) { 00197 write( (dir == CW) ? CW__STEP_COUNT : CCW_STEP_COUNT, step_count ); 00198 } 00199 00200 void PCA9629::rotations_and_steps( Direction dir, int rotation_count, int step_count ) { 00201 rotations( dir, rotation_count ); 00202 steps( dir, step_count ); 00203 } 00204 00205 void PCA9629::register_dump( void ) { 00206 char data[ 0x27 ]; 00207 char cmd = 0x80; 00208 int i; 00209 int j; 00210 00211 i2c.write( i2c_addr, &cmd, 1 ); 00212 i2c.read( i2c_addr, data, sizeof( data ) ); 00213 00214 printf( "PCA9629 register dump\r\n" ); 00215 00216 for ( i = 0, j = 0x14; i <= 0x12; i++, j++ ) 00217 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 ] ); 00218 00219 printf( " %-13s (0x%02X): 0x%02X\r\n", reg_name[ 0x13 ], 0x13, data[ 0x13 ] ); 00220 } 00221 00222 00223 void PCA9629::speed_change( unsigned short pw ) { 00224 char cmd0[] = { PCA9629::MCNTL, 0x00}; // data for stop the motor 00225 char cmd1[] = { PCA9629::CW__STEP_WIDTH, pw & 0xFF, pw >> 8 }; // data for rewrite pulse width 00226 char cmd2[] = { PCA9629::MCNTL, 0xB4}; // start // data for start again 00227 wait_us(10); 00228 00229 i2c.write( i2c_addr, cmd0, sizeof( cmd0 ), true ); // stop the motor 00230 wait_us(50); 00231 i2c.write( i2c_addr, cmd1, sizeof( cmd1 ), true ); // rewrite pulse width 00232 i2c.write( i2c_addr, cmd2, sizeof( cmd2 ), false ); // start again 00233 } 00234 00235 00236
Generated on Wed Jul 13 2022 21:18:11 by
