Design-in of LPC11U24 (lqfp48) of mbed as Steppermotor controller with USB control.
Mbed repository of Stepper Motor Control board. Using mbed LPC11U24 chip with HID USB.
Hardware in copy repo on bitbucket https://bitbucket.org/jeroen3/stepper-motor-board
SMC.cpp
- Committer:
- jeroen3
- Date:
- 2013-10-28
- Revision:
- 0:d0306c0cbee6
File content as of revision 0:d0306c0cbee6:
/** * @file SMC.cpp * @brief Stepper motor control module uses 1/8 microstepping * * @author Jeroen Lodder * @date Oktober 2013 * * @{ */ #include "mbed.h" #include "smc.h" #include "CT32B0_PWM.h" #define PWM_PERIOD 513 /**< @brief PWM period integer */ #define MIN_STEPTIME_US 100 /**< @brief Minimum time required for one microstep, derived from Hi-side driver latency (in uS) */ /* Motor Control IO */ DigitalOut HIFET_1(P0_16); /**< @brief Hi Side FET 1 of bridge 1 */ DigitalOut HIFET_2(P0_17); /**< @brief Hi Side FET 2 of bridge 1 */ DigitalOut HIFET_3(P0_18); /**< @brief Hi Side FET 3 of bridge 2 */ DigitalOut HIFET_4(P0_19); /**< @brief Hi Side FET 4 of bridge 2 */ /* Motor Control stepcontrol */ Ticker smc; volatile static int smc_walker = 0; /**< @brief Motor control LUT index */ volatile static int smc_dir = 1; /**< @brief Director in lookup table (unused) */ volatile static int smc_steps = -1; /**< @brief Remaining steps */ volatile static int smc_free = 1; /**< @brief Argument to free motor when done */ volatile static int smc_abort = 0; /**< @brief Set when motor control should quit by itself */ volatile static int smc_steptime = 0; /**< @brief Time used to make 1 step */ volatile static int smc_isPaused = 0; /**< @brief Boolean for paused state of control */ /** * @brief Initializes Stepper Motor Control */ void SMC_init(void){ // Hi fet low HIFET_1 = 0; HIFET_2 = 0; HIFET_3 = 0; HIFET_4 = 0; // Wait minimum // Lo fet low CT32B0_initpwm(PWM_PERIOD,0); // Start pwm CT32B0_start(); } /** * @brief De-Initializes Stepper Motor Control */ void SMC_deinit(void){ smc.detach(); CT32B0_deinit(0); HIFET_1 = 0; HIFET_2 = 0; HIFET_3 = 0; HIFET_4 = 0; smc_walker = 0; smc_dir = 1; smc_steps = -1; smc_free = 1; smc_abort = 0; smc_isPaused = 0; } /** * @brief Routine called by interrupt to modify H-Bridge states */ void SMC_routine(void){ #define i smc_walker CT32B0_wait_refresh(); __disable_irq(); // Phase 1 A // If sin +, H1->L2 // If sin -, H2->L1 // If direction -1, swap motor A channels, this changes direction. // Reversing lookup table is not effective if(smc_dir > 0){ HIFET_1 = LUT_H1[i]; HIFET_2 = LUT_H2[i]; if(LUT_L1[i] == 0) CT32B0_set(0, (PWM_PERIOD+1) ); else CT32B0_set(0, PWM_PERIOD-LUT_L1[i] ); if(LUT_L2[i] == 0) CT32B0_set(1, (PWM_PERIOD+1) ); else CT32B0_set(1, PWM_PERIOD-LUT_L2[i] ); }else{ // Reversed for dir -1 HIFET_1 = LUT_H2[i]; HIFET_2 = LUT_H1[i]; if(LUT_L2[i] == 0) CT32B0_set(0, (PWM_PERIOD+1) ); else CT32B0_set(0, PWM_PERIOD-LUT_L2[i] ); if(LUT_L1[i] == 0) CT32B0_set(1, (PWM_PERIOD+1) ); else CT32B0_set(1, PWM_PERIOD-LUT_L1[i] ); } // Phase 1 A // If sin +, H1->L2 // If sin -, H2->L1 HIFET_3 = LUT_H3[i]; HIFET_4 = LUT_H4[i]; if(LUT_L3[i] == 0) CT32B0_set(2, (PWM_PERIOD+1) ); else CT32B0_set(2, PWM_PERIOD-LUT_L3[i] ); if(LUT_L4[i] == 0) CT32B0_set(3, (PWM_PERIOD+1) ); else CT32B0_set(3, PWM_PERIOD-LUT_L4[i] ); if(i==9) CT32B0_stage(1); if(i==24) CT32B0_stage(0); CT32B0_reload_mat(); /* volatile static uint8_t hifet[4] = {0,0,0,0}; hifet[0] = HIFET_1; hifet[1] = HIFET_2; hifet[2] = HIFET_3; hifet[3] = HIFET_4; volatile static uint8_t lofet[4] = {0,0,0,0}; if(LUT_L1[i]) lofet[0] = 1; else lofet[0] = 0; if(LUT_L2[i]) lofet[1] = 1; else lofet[1] = 0; if(LUT_L3[i]) lofet[2] = 1; else lofet[2] = 0; if(LUT_L4[i]) lofet[3] = 1; else lofet[3] = 0; volatile static uint8_t errfet[4] = {0,0,0,0}; errfet[0] = hifet[0] & lofet[0]; errfet[1] = hifet[1] & lofet[1]; errfet[2] = hifet[2] & lofet[2]; errfet[3] = hifet[3] & lofet[3]; if( errfet[0] | errfet[1] | errfet[2] | errfet[3] ){ // ILLEGAL MODE // smc_abort = 1; __NOP(); } */ #undef i /* Walk */ smc_walker += 1; //abs(smc_dir); if(smc_walker > 31) smc_walker = 0; //if(smc_walker < 0) //smc_walker = 31; /* Coutdown */ if(smc_steps != -1){ if(smc_steps == 0 || smc_abort == 1){ if(smc_free || smc_abort == 1){ // motor free HIFET_1 = 0; HIFET_2 = 0; HIFET_3 = 0; HIFET_4 = 0; CT32B0_deinit(0); }else{ // motor locked } smc.detach(); smc_abort = 0; smc_isPaused = 0; } smc_steps--; } __enable_irq(); } /** * @brief Stepper motor control main command * * @param[in] steps Number of steps to take * @param[in] dir Direction to step in, 1 or 0 * @param[in] time_ms Time to take for these steps * @param[in] free Free or lock motor when done 1 or 0 respectively * @return -1 when illegal command or mode */ int SMC_step(int steps, uint8_t dir, uint32_t time_ms, uint8_t free){ // steps = number of microsteps (8 microsteps per full step) // dir = -1 or 1 // time_us = completion time in s uint32_t steptime = (time_ms*1000)/steps; // Parameter check if(smc_steps != -1) return -1; // Only if motor idle if(steps < 1) return -1; // At least one step if(dir) dir = 1; // Round dir to bool if(free) free = 1; // Round free to bool if(steptime < MIN_STEPTIME_US) // Verify steptime return -1; if(dir == 0) smc_dir = -1; else smc_dir = 1; // Configure stepper smc_steps = steps; smc_free = free; smc_steptime = steptime; smc_isPaused = 0; // Initiate SMC_init(); smc.attach_us(&SMC_routine, smc_steptime); return 0; } /** * @brief Return 1 of stepper motor control is idle */ uint32_t SMC_idle(void){ if(smc_steps == -1) return 1; else return 0; } /** * @brief Puts motor in brake mode, enable all low-side mosfets */ void SMC_brake(void){ // Do not brake when active control if(smc_walker > 0) return; // Regular deinit SMC_deinit(); // Re-enable low side CT32B0_deinit(1); } /** * @brief Puts motor in free mode, disables all mosfets */ void SMC_free(void){ // Do not free when active control if(smc_walker > 0) return; // Regular deinit SMC_deinit(); // Re-enable low side CT32B0_deinit(0); } /** * @brief Pause current stepping command */ void SMC_pause(void){ if( !SMC_idle() ){ smc.detach(); smc_isPaused = 1; } } /** * @brief Continue from pause */ void SMC_continue(void){ if( !SMC_idle() && smc_isPaused==1 ){ smc.attach_us(&SMC_routine, smc_steptime); smc_isPaused = 0; } } /** * @brief Return remaining steps, negative if paused */ int SMC_getState(void){ if( smc_steps < 0 ){ return 0; }else{ if(smc_isPaused) return (-1*smc_steps); else return (1*smc_steps); } } /** * @brief Egg, open it to find out */ void SMC_egg(void){ const uint16_t rr[] = { 627 , 1045 , 122 , 785 , 887 , 187 , 233 , 166 , 788 , 752 , 1157 }; int rri=0; // Egg for(int i=0;i<2; i++){ SMC_step(rr[rri++] , 1, 685, 1); // 83 - 987 while( !SMC_idle()) ; // - wait_ms(1); SMC_step(rr[rri++] , 1, 965, 1); // 85 - 1108 while( !SMC_idle()) ; // - wait_ms(1); SMC_step(rr[rri++] , 1, 245, 1); // 78 - 739 while( !SMC_idle()) ; // - wait_ms(1); SMC_step(rr[rri++] , 1, 725, 1); // 85 - 1108 while( !SMC_idle()) ; // - wait_ms(1); SMC_step(rr[rri++] , 1, 710, 1); // 87 - 1244 while( !SMC_idle()) ; // - wait_ms(1); SMC_step(rr[rri++] , 1, 125, 1); // 90 - 1479 while( !SMC_idle()) ; // - wait_ms(1); SMC_step(rr[rri++] , 1, 175, 1); // 88 - 1318 while( !SMC_idle()) ; // - wait_ms(1); SMC_step(rr[rri++] , 1, 133, 1); // 87 - 1244 while( !SMC_idle()) ; // - wait_ms(1); SMC_step(rr[rri++] , 1, 860, 1); // 83 - 987 while( !SMC_idle()) ; // - wait_ms(1); SMC_step(rr[rri++] , 1, 695, 1); // 85 - 1108 while( !SMC_idle()) ; // - wait_ms(1); SMC_step(rr[rri++] , 1, 2315, 1); // 78 - 739 while( !SMC_idle()) ; // - wait_ms(1); rri=0; } } /** *@} */