Sample code for PCA9629 operation
What is "PCA9629" ?
Information
The stepper motor controller PCA9629A is available now!
This "A-version (PCA9629A)" is a feature extended version on "non-A (PCA9629)".
If you are thinking new design, the PCA9629A can be a good option.
The PCA9629A has several new features like on-the-fly speed change, extended ramp controls, filter settings for GPIO port inputs, braking and releasing by timeout.. and more.
Please find detail information here.
The "A-version" chip is pin-compatible to "non-A". So it can be replaced easily.
The register mapping and bit fields are re-defined. Those should be cared by software.
A sample code and a class library are available for mbed.
Import programPCA9629A_Hello
Hello program for PCA9629A. Demonstrates basic operations of PCA9629A component library.
Import libraryPCA9629A
PCA9629A component library
A Stepper motor controller
PCA9629 (x5) demo board: PCA9629, 4x FETs and stepper motor
The PCA9629 is an I2C-bus controlled low-power CMOS device that provides all the logic and control required to drive a four phase stepper motor. PCA9629 is intended to be used with external high current drivers to drive the motor coils. The PCA9629 supports three stepper motor drive formats: one-phase (wave drive), two-phase, and half-step. In addition, when used as inputs, four General Purpose Input/Outputs (GPIOs) allow sensing of logic level output from optical interrupter modules and generate active LOW interrupt signal on the INT pin of PCA9629. This is a useful feature in sensing home position of motor shaft or reference for step pulses. Upon interrupt, the PCA9629 can be programmed to automatically stop the motor or reverse the direction of rotation of motor.
Communicate with mbed through I2C. The motor can be operated by register settings
Output wave train is programmable using control registers. The control registers are programmed via the I2C-bus. Features built into the PCA9629 provide highly flexible control of stepper motor, off-load bus master/micro and significantly reduce I2C-bus traffic. These include control of step size, number of steps per single command, number of full rotations and direction of rotation. A ramp-up on start and/or ramp-down on stop is also provided.
Waveforms: Lower 2 lines are I2C bus. Upper 4 lines are output for motor driver stage
Motor moving 16 steps with acceleration and deceleration after register setting via I2C
The PCA9629 is available in a 16-pin TSSOP package and is specified over the -40 deg-C to +85 deg-C industrial temperature range.
TSSOP16 package
Datasheet is available at next URL.
http://www.nxp.com/documents/data_sheet/PCA9629.pdf
Hardware
A sample schematic diagram is shown in next picture.
This schematic diagram shows a sample of the PF35T-48C stepper motor. It is using 12V supply voltage for motor and driving by SI3812DV FETs.
Pull-up resisters: For /RESET and /INT pins : 4.7K-ohms, for I2C signals (SDA and SCL) : >1.3k-ohms.
NOTE
For the correct operation of the "auto interrupt" demo, the GPIO port P0(pin1) and P1(pin2) must be connected to sensor input. signal edge of those pins are treated as the interrupt.
Sample code
This sample code operates the PCA9629 using its class library.
For the details of the library, please find information in library page.
Import libraryPCA9629
PCA9629 a stepper motor controller class library
API details are available in here
This program targets PCA9629 which has I2C address of 0x42 on I2C bus on pin28 and pin27 of mbed. 4 types motor actions are demonstrated in sequence (following 1..4 steps in loop).
- Simple motor turn demo
- Motor moved 96 steps with 100pps (pulse persecond) speed
- Then the motor turn reversed, move 48 steps by 50pps.
- Ramp control demo
- total operation time = 2 seconds, initial speed = 40.69pps, rotations = 5turns+0steps, ramp-up enable = enable, ramp-down enable = enable, rotate direction = CW
- The ramp control can be done with several register settings. The setting value calculation can be done by register setting tool (an Excel worksheet) from NXP.
- Auto interrupt demo
- The GPIO inputs can be used as interrupt for PCA9629. The operation can be stopped or change the direction of turn.
- This is turn direction auto reversing demo. Motor will switch the direction 12 steps after interrupt signal assertion.
- The register setting of interrupt operation can be done by register setting tool also.
- This demo works correctly only when sensor signals available on P0(pin1) and P1(pin2) input pins.
- Speed change demo
- Changing motor speed in 5 steps from 55pps to 275pps.
main.cpp@1:cab53217fcc1, 2012-04-24 (annotated)
- Committer:
- nxp_ip
- Date:
- Tue Apr 24 08:19:06 2012 +0000
- Revision:
- 1:cab53217fcc1
- Parent:
- 0:4f93f6ecf23c
- Child:
- 2:2e75cedf6565
version 1.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
nxp_ip | 0:4f93f6ecf23c | 1 | /** A sample/demo code for PCA9629 |
nxp_ip | 0:4f93f6ecf23c | 2 | * |
nxp_ip | 1:cab53217fcc1 | 3 | * @author Akifumi (Tedd) OKANO, NXP Semiconductors |
nxp_ip | 0:4f93f6ecf23c | 4 | * @version 1.0 |
nxp_ip | 1:cab53217fcc1 | 5 | * @date 24-Apr-2011 |
nxp_ip | 0:4f93f6ecf23c | 6 | * |
nxp_ip | 0:4f93f6ecf23c | 7 | * Released under the MIT License: http://mbed.org/license/mit |
nxp_ip | 0:4f93f6ecf23c | 8 | * |
nxp_ip | 0:4f93f6ecf23c | 9 | * An operation sample of PCU9629 stepper motor controller. |
nxp_ip | 0:4f93f6ecf23c | 10 | * The mbed accesses the PCU9629 registers through I2C. |
nxp_ip | 0:4f93f6ecf23c | 11 | * |
nxp_ip | 0:4f93f6ecf23c | 12 | * This sample code demonstrates 4 type of PCA9629 operation |
nxp_ip | 0:4f93f6ecf23c | 13 | */ |
nxp_ip | 0:4f93f6ecf23c | 14 | |
nxp_ip | 0:4f93f6ecf23c | 15 | #include "mbed.h" |
nxp_ip | 0:4f93f6ecf23c | 16 | #include "PCA9629.h" |
nxp_ip | 0:4f93f6ecf23c | 17 | |
nxp_ip | 0:4f93f6ecf23c | 18 | BusOut leds( LED4, LED3, LED2, LED1 ); |
nxp_ip | 0:4f93f6ecf23c | 19 | PCA9629 motor_controller( p28, p27, 0x42 ); |
nxp_ip | 0:4f93f6ecf23c | 20 | |
nxp_ip | 0:4f93f6ecf23c | 21 | void motor_action_0( void ); |
nxp_ip | 0:4f93f6ecf23c | 22 | void motor_action_1( void ); |
nxp_ip | 0:4f93f6ecf23c | 23 | void motor_action_2( void ); |
nxp_ip | 0:4f93f6ecf23c | 24 | void motor_action_3( void ); |
nxp_ip | 0:4f93f6ecf23c | 25 | void motor_action_CDE( void ); |
nxp_ip | 0:4f93f6ecf23c | 26 | |
nxp_ip | 0:4f93f6ecf23c | 27 | int main() { |
nxp_ip | 0:4f93f6ecf23c | 28 | printf( "PCA9629 simple sample program\r\n" ); |
nxp_ip | 0:4f93f6ecf23c | 29 | |
nxp_ip | 0:4f93f6ecf23c | 30 | while ( 1 ) { |
nxp_ip | 0:4f93f6ecf23c | 31 | leds = 0x1; |
nxp_ip | 0:4f93f6ecf23c | 32 | motor_action_0(); |
nxp_ip | 0:4f93f6ecf23c | 33 | |
nxp_ip | 0:4f93f6ecf23c | 34 | leds = 0x3; |
nxp_ip | 0:4f93f6ecf23c | 35 | motor_action_1(); |
nxp_ip | 0:4f93f6ecf23c | 36 | |
nxp_ip | 0:4f93f6ecf23c | 37 | leds = 0x7; |
nxp_ip | 0:4f93f6ecf23c | 38 | motor_action_2(); |
nxp_ip | 0:4f93f6ecf23c | 39 | |
nxp_ip | 0:4f93f6ecf23c | 40 | leds = 0xF; |
nxp_ip | 0:4f93f6ecf23c | 41 | motor_action_3(); |
nxp_ip | 0:4f93f6ecf23c | 42 | } |
nxp_ip | 0:4f93f6ecf23c | 43 | } |
nxp_ip | 0:4f93f6ecf23c | 44 | |
nxp_ip | 0:4f93f6ecf23c | 45 | void motor_action_0( void ) { |
nxp_ip | 0:4f93f6ecf23c | 46 | |
nxp_ip | 0:4f93f6ecf23c | 47 | // simple motor operation |
nxp_ip | 0:4f93f6ecf23c | 48 | // the motor spins 2 times (100pps) for clockwise (CW), 1 time (50pps) for counter-clockwise. |
nxp_ip | 0:4f93f6ecf23c | 49 | |
nxp_ip | 0:4f93f6ecf23c | 50 | motor_controller.stop(); |
nxp_ip | 0:4f93f6ecf23c | 51 | motor_controller.init_registers(); |
nxp_ip | 0:4f93f6ecf23c | 52 | |
nxp_ip | 0:4f93f6ecf23c | 53 | motor_controller.pps( PCA9629::CW, PCA9629::PRESCALER_FROM_40_TO_333333, 100 ); |
nxp_ip | 0:4f93f6ecf23c | 54 | motor_controller.steps( PCA9629::CW, 96 ); |
nxp_ip | 0:4f93f6ecf23c | 55 | |
nxp_ip | 0:4f93f6ecf23c | 56 | motor_controller.pps( PCA9629::CCW, PCA9629::PRESCALER_FROM_40_TO_333333, 50 ); |
nxp_ip | 0:4f93f6ecf23c | 57 | motor_controller.steps( PCA9629::CCW, 48 ); |
nxp_ip | 0:4f93f6ecf23c | 58 | |
nxp_ip | 0:4f93f6ecf23c | 59 | for ( int i = 0; i < 2; i++ ) { |
nxp_ip | 0:4f93f6ecf23c | 60 | motor_controller.start( PCA9629::CW ); |
nxp_ip | 0:4f93f6ecf23c | 61 | wait( 2.0 ); |
nxp_ip | 0:4f93f6ecf23c | 62 | |
nxp_ip | 0:4f93f6ecf23c | 63 | motor_controller.start( PCA9629::CCW ); |
nxp_ip | 0:4f93f6ecf23c | 64 | wait( 2.0 ); |
nxp_ip | 0:4f93f6ecf23c | 65 | } |
nxp_ip | 0:4f93f6ecf23c | 66 | } |
nxp_ip | 0:4f93f6ecf23c | 67 | |
nxp_ip | 0:4f93f6ecf23c | 68 | void motor_action_1( void ) { |
nxp_ip | 0:4f93f6ecf23c | 69 | |
nxp_ip | 0:4f93f6ecf23c | 70 | // ramp control demo |
nxp_ip | 0:4f93f6ecf23c | 71 | |
nxp_ip | 0:4f93f6ecf23c | 72 | motor_controller.stop(); |
nxp_ip | 0:4f93f6ecf23c | 73 | motor_controller.init_registers(); |
nxp_ip | 0:4f93f6ecf23c | 74 | |
nxp_ip | 0:4f93f6ecf23c | 75 | // auto generated example code for PCA9629 on mbed |
nxp_ip | 0:4f93f6ecf23c | 76 | // setting: total operation time = 2, initial speed = 40.69, rotations = 5, steps = 0, ramp-up enable = enable, ramp-down enable = enable, rotate direction = CW |
nxp_ip | 0:4f93f6ecf23c | 77 | |
nxp_ip | 0:4f93f6ecf23c | 78 | // motor_controller.write( PCA9629::STEPS_PER_ROATION, 48 ); |
nxp_ip | 0:4f93f6ecf23c | 79 | motor_controller.write( PCA9629::CW__STEP_WIDTH, 1175 ); |
nxp_ip | 0:4f93f6ecf23c | 80 | motor_controller.write( PCA9629::CW__STEP_COUNT, 35 ); |
nxp_ip | 0:4f93f6ecf23c | 81 | motor_controller.write( PCA9629::CW__ROTATION_COUNT, 2 ); |
nxp_ip | 0:4f93f6ecf23c | 82 | motor_controller.write( PCA9629::RAMPCNTL, 0x37 ); |
nxp_ip | 0:4f93f6ecf23c | 83 | |
nxp_ip | 0:4f93f6ecf23c | 84 | for ( int i = 0; i < 2; i++ ) { |
nxp_ip | 0:4f93f6ecf23c | 85 | motor_controller.write( PCA9629::MCNTL, 0xA8 ); // start |
nxp_ip | 0:4f93f6ecf23c | 86 | wait( 2.5 ); |
nxp_ip | 0:4f93f6ecf23c | 87 | } |
nxp_ip | 0:4f93f6ecf23c | 88 | } |
nxp_ip | 0:4f93f6ecf23c | 89 | |
nxp_ip | 0:4f93f6ecf23c | 90 | void motor_action_2( void ) { |
nxp_ip | 0:4f93f6ecf23c | 91 | |
nxp_ip | 0:4f93f6ecf23c | 92 | // interrupt operation demo |
nxp_ip | 0:4f93f6ecf23c | 93 | |
nxp_ip | 0:4f93f6ecf23c | 94 | motor_controller.stop(); |
nxp_ip | 0:4f93f6ecf23c | 95 | |
nxp_ip | 0:4f93f6ecf23c | 96 | // this array is a sample for PCA9629 local interrupt operation |
nxp_ip | 0:4f93f6ecf23c | 97 | // the P0 and P1 inputs enabled for interrupt in. |
nxp_ip | 0:4f93f6ecf23c | 98 | // motor rotation will be reversed by interrupt signals. |
nxp_ip | 0:4f93f6ecf23c | 99 | // the motor direction will be changed 12 steps after when the interrupt happened |
nxp_ip | 0:4f93f6ecf23c | 100 | // |
nxp_ip | 0:4f93f6ecf23c | 101 | // CW = 40.69pps, CCW = 81.38pps |
nxp_ip | 0:4f93f6ecf23c | 102 | |
nxp_ip | 0:4f93f6ecf23c | 103 | char init_array2[] = { 0x80, |
nxp_ip | 0:4f93f6ecf23c | 104 | 0x20, 0xE2, 0xE4, 0xE6, 0xE0, 0xFF, 0x10, // for registers MODE - WDCNTL (0x00 - 0x06 |
nxp_ip | 0:4f93f6ecf23c | 105 | 0x00, 0x00, // for registers IP and INTSTAT (0x07, 0x08) |
nxp_ip | 0:4f93f6ecf23c | 106 | 0x0F, 0x03, 0x0C, 0x0F, 0x03, 0x01, 0x03, 0x03, 0x01, // for registers OP - INT_AUTO_CLR (0x09 - 0x11) |
nxp_ip | 0:4f93f6ecf23c | 107 | 0x00, 0x00, 0x30, 0x00, 0xFF, 0x1F, 0xFF, 0x0F, // for registers SETMODE - CCWPWH (0x12 - 0x19) |
nxp_ip | 0:4f93f6ecf23c | 108 | 0xFF, 0xFF, 0xFF, 0xFF, 0x0A, 0x00, 0x0A, 0x00, // for registers CWSCOUNTL - CCWRCOUNTH (0x1A - 0x21) |
nxp_ip | 0:4f93f6ecf23c | 109 | 0x0C, 0x0C, // for registers EXTRASTEPS0 and EXTRASTEPS1 (0x22, 0x23) |
nxp_ip | 0:4f93f6ecf23c | 110 | 0x00, 0x00, 0xA8 // for registers RMPCNTL - MCNTL (0x24 - 0x26) |
nxp_ip | 0:4f93f6ecf23c | 111 | }; |
nxp_ip | 0:4f93f6ecf23c | 112 | |
nxp_ip | 0:4f93f6ecf23c | 113 | motor_controller.set_all_registers( init_array2, sizeof( init_array2 )); |
nxp_ip | 0:4f93f6ecf23c | 114 | wait( 5.0 ); |
nxp_ip | 0:4f93f6ecf23c | 115 | |
nxp_ip | 0:4f93f6ecf23c | 116 | motor_controller.stop(); |
nxp_ip | 0:4f93f6ecf23c | 117 | wait( 0.5 ); |
nxp_ip | 0:4f93f6ecf23c | 118 | |
nxp_ip | 0:4f93f6ecf23c | 119 | } |
nxp_ip | 0:4f93f6ecf23c | 120 | |
nxp_ip | 0:4f93f6ecf23c | 121 | void motor_action_3( void ) { |
nxp_ip | 0:4f93f6ecf23c | 122 | |
nxp_ip | 0:4f93f6ecf23c | 123 | // speed change sample while the motor is running |
nxp_ip | 0:4f93f6ecf23c | 124 | |
nxp_ip | 0:4f93f6ecf23c | 125 | motor_controller.stop(); |
nxp_ip | 0:4f93f6ecf23c | 126 | motor_controller.init_registers(); |
nxp_ip | 0:4f93f6ecf23c | 127 | |
nxp_ip | 0:4f93f6ecf23c | 128 | motor_controller.rotations( PCA9629::CCW, 0xFFFF ); |
nxp_ip | 0:4f93f6ecf23c | 129 | |
nxp_ip | 0:4f93f6ecf23c | 130 | for ( int i = 0; i < 2; i++ ) { |
nxp_ip | 0:4f93f6ecf23c | 131 | for ( int s = 1; s <= 5; s++ ) { |
nxp_ip | 0:4f93f6ecf23c | 132 | motor_controller.pps( PCA9629::CCW, PCA9629::PRESCALER_FROM_40_TO_333333, 55 * s ); |
nxp_ip | 0:4f93f6ecf23c | 133 | motor_controller.start( PCA9629::CCW ); |
nxp_ip | 0:4f93f6ecf23c | 134 | wait( 1.0 ); |
nxp_ip | 0:4f93f6ecf23c | 135 | motor_controller.stop(); |
nxp_ip | 0:4f93f6ecf23c | 136 | } |
nxp_ip | 0:4f93f6ecf23c | 137 | } |
nxp_ip | 0:4f93f6ecf23c | 138 | } |
nxp_ip | 0:4f93f6ecf23c | 139 | |
nxp_ip | 0:4f93f6ecf23c | 140 | void motor_action_CDE( void ) { |
nxp_ip | 0:4f93f6ecf23c | 141 | char scale[ 8 ] = { 4, 6, 8, 9, 11, 13, 15, 16 }; // CDEFGABC from A |
nxp_ip | 0:4f93f6ecf23c | 142 | float freq[ 8 ]; |
nxp_ip | 0:4f93f6ecf23c | 143 | |
nxp_ip | 0:4f93f6ecf23c | 144 | for ( int i = 0; i < 8; i++ ) |
nxp_ip | 0:4f93f6ecf23c | 145 | freq[ i ] = 55.0 * pow( 2.0, (float)(scale[ i ]) / 12.0 ); |
nxp_ip | 0:4f93f6ecf23c | 146 | |
nxp_ip | 0:4f93f6ecf23c | 147 | motor_controller.stop(); |
nxp_ip | 0:4f93f6ecf23c | 148 | motor_controller.init_registers(); |
nxp_ip | 0:4f93f6ecf23c | 149 | motor_controller.rotations( PCA9629::CCW, 0xFFFF ); |
nxp_ip | 0:4f93f6ecf23c | 150 | motor_controller.write( PCA9629::PHCNTL,0x1 ); |
nxp_ip | 0:4f93f6ecf23c | 151 | |
nxp_ip | 0:4f93f6ecf23c | 152 | for ( int i = 0; i < 2; i++ ) { |
nxp_ip | 0:4f93f6ecf23c | 153 | motor_controller.stop(); |
nxp_ip | 0:4f93f6ecf23c | 154 | for ( int s = 0; s < 8; s++ ) { |
nxp_ip | 0:4f93f6ecf23c | 155 | motor_controller.pps( PCA9629::CCW, PCA9629::PRESCALER_FROM_40_TO_333333, (int)(freq[ s ]) ); |
nxp_ip | 0:4f93f6ecf23c | 156 | motor_controller.start( PCA9629::CCW ); |
nxp_ip | 0:4f93f6ecf23c | 157 | wait( 1 ); |
nxp_ip | 0:4f93f6ecf23c | 158 | |
nxp_ip | 0:4f93f6ecf23c | 159 | motor_controller.stop(); |
nxp_ip | 0:4f93f6ecf23c | 160 | } |
nxp_ip | 0:4f93f6ecf23c | 161 | } |
nxp_ip | 0:4f93f6ecf23c | 162 | } |
nxp_ip | 0:4f93f6ecf23c | 163 |