Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
PCA9629A.cpp
00001 /** A sample code for PCA9629A 00002 * 00003 * @author Akifumi (Tedd) OKANO, NXP Semiconductors 00004 * @version 1.1 00005 * @date 12-Sep-2012 00006 * 00007 * revision history (PCA9629A) 00008 * version 0.1 (05-Jun-2013) : PCA9629"A" initial version 00009 * version 0.2 (05-Jun-2013) : register name fix, register description added 00010 * version 1.0 (23-Apr-2014) : unnecessary parameter for constructor has been removed 00011 * version 1.1 (12-Sep-2014) : constructor variation added. ramp parameter API added 00012 * 00013 * Released under the Apache 2 license License 00014 * 00015 * An operation sample of PCU9629A stepper motor controller. 00016 * The mbed accesses the PCU9629A registers through I2C. 00017 * 00018 * About PCA9629A: 00019 * http://www.nxp.com/products/interface_and_connectivity/i2c/i2c_bus_controller_and_bridge_ics/PCA9629APW.html 00020 */ 00021 00022 #include "mbed.h" 00023 #include "PCA9629A.h" 00024 00025 #define STEP_RESOLUTION 333333 // 1/(3e-6) = 333333 00026 00027 char *reg_name[] = { 00028 "MODE", "WDTOI", "WDCNTL", "IO_CFG", 00029 "INTMODE", "MSK", "INTSTAT", "IP", "INT_MTR_ACT", "EXTRASTEPS0", "EXTRASTEPS1", 00030 "OP_CFG", "OP_STAT_PHS", 00031 "RUCNTL", "RDCNTL", 00032 "PMA", "LOOPDLY_CW", "LOOPDLY_CCW", 00033 "CWSCOUNTL", "CWSCOUNTH", "CCWSCOUNTL", "CCWSCOUNTH", 00034 "CWPWL", "CWPWH", "CCWPWL", "CCWPWH", 00035 "MCNTL", 00036 "SUBADR1", "SUBADR2", "SUBADR3", "ALLCALLADR", 00037 "STEPCOUNT0", "STEPCOUNT1", "STEPCOUNT2", "STEPCOUNT3" 00038 }; 00039 00040 PCA9629A::PCA9629A( 00041 PinName I2C_sda, 00042 PinName I2C_scl, 00043 char I2C_address 00044 ) : i2c_p( new I2C( I2C_sda, I2C_scl ) ), i2c( *i2c_p ), i2c_addr( I2C_address ) 00045 { 00046 i2c.frequency( I2C_SCL_FREQUENCY ); 00047 init_registers(); 00048 } 00049 00050 PCA9629A::PCA9629A( 00051 I2C &i2c_, 00052 char I2C_address 00053 ) : i2c_p( NULL ), i2c( i2c_ ), i2c_addr( I2C_address ) 00054 { 00055 init_registers(); 00056 } 00057 00058 PCA9629A::~PCA9629A() 00059 { 00060 if ( NULL != i2c_p ) 00061 delete i2c_p; 00062 } 00063 00064 void PCA9629A::software_reset( void ) 00065 { 00066 char v = 0x06; 00067 00068 i2c.write( 0x00, &v, 1 ); 00069 wait_ms( 1 ); 00070 } 00071 00072 void PCA9629A::init_registers( void ) 00073 { 00074 char init_array[] = { 0x80, // register access start address (0x00) with incremental access flag (MSB) 00075 0x20, 0x0A, 0x00, 0x03, 0x13, 0x1C, // for registers MODE - MSK (0x00 - 0x07 00076 0x00, 0x00, 0x68, 0x00, 0x00, // for registers INTSTAT - EXTRASTEPS1 (0x06, 0xA) 00077 0x10, 0x80, // for registers OP_CFG_PHS and OP_STAT_TO (0x0B - 0xC) 00078 0x09, 0x09, 0x01, 0x7D, 0x7D, // for registers RUCNTL - LOOPDLY_CCW (0xD- 0x10) 00079 0xFF, 0x01, 0xFF, 0x01, 0x05, 0x0D, 0x05, 0x0D, // for registers CWSCOUNTL - MCNTL (0x12 - 0x1A) 00080 0x20, // for register MCNTL (0x1A) 00081 0xE2, 0xE4, 0xE6, 0xE0 // for registers SUBADR1 - ALLCALLADR (0x1B - 0x1E) 00082 }; 00083 00084 set_all_registers( init_array, sizeof( init_array ) ); 00085 } 00086 00087 void PCA9629A::set_all_registers( char *a, char size ) 00088 { 00089 int error_code; 00090 00091 error_code = i2c.write( i2c_addr, a, size ); 00092 00093 if ( error_code ) 00094 error( "error @ initializing PCA9629A" ); 00095 } 00096 00097 void PCA9629A::write( RegisterName register_name, char value ) 00098 { 00099 int error_code; 00100 char cmd[ 2 ]; 00101 00102 cmd[ 0 ] = register_name; 00103 cmd[ 1 ] = value; 00104 00105 error_code = i2c.write( i2c_addr, cmd, 2 ); 00106 00107 if ( error_code ) 00108 error( "PCA9629A writing failed\r\n" ); 00109 } 00110 00111 void PCA9629A::write( RegisterNameFor16bitAccess register_name, short value ) 00112 { 00113 int error_code; 00114 char cmd[ 3 ]; 00115 00116 cmd[ 0 ] = register_name; 00117 cmd[ 1 ] = value & 0xFF; 00118 cmd[ 2 ] = value >> 8; 00119 00120 error_code = i2c.write( i2c_addr, cmd, 3 ); 00121 00122 if ( error_code ) 00123 error( "PCA9629A writing failed\r\n" ); 00124 } 00125 00126 char PCA9629A::read( RegisterName register_name ) 00127 { 00128 int error_code; 00129 char cmd; 00130 char data; 00131 00132 cmd = register_name; 00133 00134 error_code = i2c.write( i2c_addr, &cmd, 1, false ); 00135 00136 if ( error_code ) 00137 error( "PCA9629A reading (command phase) failed\r\n" ); 00138 00139 error_code = i2c.read( i2c_addr, &data, 1 ); 00140 00141 if ( error_code ) 00142 error( "PCA9629A reading (data phase) failed\r\n" ); 00143 00144 return ( data ); 00145 } 00146 00147 short PCA9629A::read( RegisterNameFor16bitAccess register_name ) 00148 { 00149 int error_code; 00150 char cmd; 00151 char data[ 2 ]; 00152 00153 cmd = register_name; 00154 00155 error_code = i2c.write( i2c_addr, &cmd, 1, false ); 00156 00157 if ( error_code ) 00158 error( "PCA9629A reading (command phase) failed\r\n" ); 00159 00160 error_code = i2c.read( i2c_addr, data, 2 ); 00161 00162 if ( error_code ) 00163 error( "PCA9629A reading (data phase) failed\r\n" ); 00164 00165 return ( data[ 1 ] << 8 | data[ 0 ] ); 00166 } 00167 00168 long PCA9629A::read( RegisterNameFor32bitAccess register_name ) 00169 { 00170 int error_code; 00171 char cmd; 00172 char data[ 4 ]; 00173 00174 cmd = register_name | 0x80; 00175 00176 error_code = i2c.write( i2c_addr, &cmd, 1, false ); 00177 00178 if ( error_code ) 00179 error( "PCA9629A reading (command phase) failed\r\n" ); 00180 00181 error_code = i2c.read( i2c_addr, data, 4 ); 00182 00183 if ( error_code ) 00184 error( "PCA9629A reading (data phase) failed\r\n" ); 00185 00186 printf( "0x %02X %02X %02X %02X\r\n", data[3], data[2], data[1], data[0] ); 00187 00188 return ( data[ 3 ] << 24 | data[ 2 ] << 16 | data[ 1 ] << 8 | data[ 0 ] ); 00189 } 00190 00191 void PCA9629A::start( Direction dir ) 00192 { 00193 write( MCNTL, 0xC0 | dir ); 00194 } 00195 00196 void PCA9629A::stop( void ) 00197 { 00198 write( MCNTL, 0xA0 ); 00199 } 00200 00201 00202 short PCA9629A::pps( Direction dir, PrescalerRange prescaler, int pps ) 00203 { 00204 int step_pulse_width; 00205 00206 step_pulse_width = STEP_RESOLUTION / ((1 << prescaler) * pps); 00207 00208 if ( step_pulse_width & 0xE000 ) { //error( "pps setting: out of range" ); 00209 step_pulse_width = 0x1FFF; 00210 printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / ((float)0x1FFF * (float)(1 << prescaler)) ); 00211 } 00212 if ( !step_pulse_width ) { //error( "pps setting: out of range" ); 00213 step_pulse_width = 0x1; 00214 printf( "the pps forced in to the range that user specified.. %fpps\r\n", (float)STEP_RESOLUTION / (float)(1 << prescaler) ); 00215 } 00216 00217 step_pulse_width |= (prescaler << 13); 00218 00219 write( (dir == CW) ? CW__STEP_WIDTH : CCW_STEP_WIDTH, step_pulse_width ); 00220 00221 return ( step_pulse_width ); 00222 } 00223 00224 short PCA9629A::pps( Direction dir, float pulse_per_second ) 00225 { 00226 char p = 0; 00227 char ratio; 00228 00229 ratio = (char)(40.6901 / pulse_per_second); 00230 00231 p = (ratio & 0x01) ? 1 : p; 00232 p = (ratio & 0x02) ? 2 : p; 00233 p = (ratio & 0x04) ? 3 : p; 00234 p = (ratio & 0x08) ? 4 : p; 00235 p = (ratio & 0x10) ? 5 : p; 00236 p = (ratio & 0x20) ? 6 : p; 00237 p = (ratio & 0x40) ? 7 : p; 00238 00239 return ( pps( dir, (PrescalerRange)p, (int)pulse_per_second ) ); 00240 } 00241 00242 void PCA9629A::steps( Direction dir, int step_count ) 00243 { 00244 write( (dir == CW) ? CW__STEP_COUNT : CCW_STEP_COUNT, step_count ); 00245 } 00246 00247 void PCA9629A::ramp_up( char rate ) 00248 { 00249 write( RUCNTL, rate ? (0x30 | (rate -1)) : 0x00 ); 00250 } 00251 00252 void PCA9629A::ramp_down( char rate ) 00253 { 00254 write( RDCNTL, rate ? (0x30 | (rate -1)) : 0x00 ); 00255 } 00256 00257 void PCA9629A::register_dump( void ) 00258 { 00259 char data[ 0x23 ]; 00260 char cmd = 0x80; 00261 int i; 00262 int j; 00263 00264 i2c.write( i2c_addr, &cmd, 1 ); 00265 i2c.read( i2c_addr, data, sizeof( data ) ); 00266 00267 printf( "PCA9629A register dump\r\n" ); 00268 00269 for ( i = 0, j = 0x14; i <= 0x12; i++, j++ ) 00270 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 ] ); 00271 00272 printf( " %-13s (0x%02X): 0x%02X\r\n", reg_name[ 0x13 ], 0x13, data[ 0x13 ] ); 00273 } 00274 00275 00276 void PCA9629A::speed_change( unsigned short pw ) 00277 { 00278 #ifdef MBED_PCA9629 00279 // this is for PCA9629(non-A version) 00280 char cmd0[] = { PCA9629A::MCNTL, 0x00}; // data for stop the motor 00281 char cmd1[] = { PCA9629A::CW__STEP_WIDTH, pw & 0xFF, pw >> 8 }; // data for rewrite pulse width 00282 char cmd2[] = { PCA9629A::MCNTL, 0xB4}; // start // data for start again 00283 wait_us(10); 00284 00285 i2c.write( i2c_addr, cmd0, sizeof( cmd0 ), true ); // stop the motor 00286 wait_us(50); 00287 i2c.write( i2c_addr, cmd1, sizeof( cmd1 ), true ); // rewrite pulse width 00288 i2c.write( i2c_addr, cmd2, sizeof( cmd2 ), false ); // start again 00289 #else 00290 char cmd1[] = { PCA9629A::CW__STEP_WIDTH, pw & 0xFF, pw >> 8 }; // data for rewrite pulse width 00291 00292 i2c.write( i2c_addr, cmd1, sizeof( cmd1 ), true ); // rewrite pulse width 00293 #endif 00294 }
Generated on Thu Jul 14 2022 06:46:52 by
1.7.2
PCA9629A Advanced stepper motor controller