diff --git a/F0-nolib/CANbus_stepper/src/can.c b/F0-nolib/CANbus_stepper/src/can.c index 5439343..150de17 100644 --- a/F0-nolib/CANbus_stepper/src/can.c +++ b/F0-nolib/CANbus_stepper/src/can.c @@ -145,7 +145,7 @@ void CAN_setup(uint16_t speed){ CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */ CAN->MCR |= CAN_MCR_ABOM; /* allow automatically bus-off */ - CAN->BTR |= 2 << 20 | 3 << 16 | (6000/speed) << 0; /* (4) */ + CAN->BTR |= 2 << 20 | 3 << 16 | (6000/speed - 1); /* (4) */ CAN->MCR &=~ CAN_MCR_INRQ; /* (5) */ tmout = 16000000; while((CAN->MSR & CAN_MSR_INAK)==CAN_MSR_INAK) if(--tmout == 0) break; /* (6) */ diff --git a/F0-nolib/CANbus_stepper/src/canstepper.bin b/F0-nolib/CANbus_stepper/src/canstepper.bin index 2233ef3..b2c1abe 100755 Binary files a/F0-nolib/CANbus_stepper/src/canstepper.bin and b/F0-nolib/CANbus_stepper/src/canstepper.bin differ diff --git a/F0-nolib/CANbus_stepper/src/flash.c b/F0-nolib/CANbus_stepper/src/flash.c index d86e29a..2104943 100644 --- a/F0-nolib/CANbus_stepper/src/flash.c +++ b/F0-nolib/CANbus_stepper/src/flash.c @@ -46,9 +46,13 @@ static uint32_t maxCnum = FLASH_BLOCK_SIZE / sizeof(user_conf); #define USERCONF_INITIALIZER { \ .userconf_sz = sizeof(user_conf) \ - ,.defflags = 0 \ + ,.defflags.reverse = 0 \ ,.CANspeed = 100 \ ,.driver_type = DRV_NONE \ + ,.microsteps = 16 \ + ,.accdecsteps = 100 \ + ,.motspd = 10 \ + ,.maxsteps = 50000 \ } static int erase_flash(const void*, const void*); @@ -214,7 +218,6 @@ static int erase_flash(const void *start, const void *end){ void dump_userconf(){ SEND("userconf_addr="); printuhex((uint32_t)Flash_Data); SEND("\nuserconf_sz="); printu(the_conf.userconf_sz); - SEND("\nflags="); printuhex(the_conf.defflags); SEND("\nCANspeed="); printu(the_conf.CANspeed); SEND("\ndriver_type="); const char *p = "NONE"; @@ -230,6 +233,12 @@ void dump_userconf(){ break; } SEND(p); + SEND("\nmicrosteps="); printu(the_conf.microsteps); + SEND("\naccdecsteps="); printu(the_conf.accdecsteps); + SEND("\nmotspd="); printu(the_conf.motspd); + SEND("\nmaxsteps="); printu(the_conf.maxsteps); + //flags + SEND("\nreverse="); bufputchar('0' + the_conf.defflags.reverse); newline(); sendbuf(); } diff --git a/F0-nolib/CANbus_stepper/src/flash.h b/F0-nolib/CANbus_stepper/src/flash.h index 4e57c5c..4f03c15 100644 --- a/F0-nolib/CANbus_stepper/src/flash.h +++ b/F0-nolib/CANbus_stepper/src/flash.h @@ -30,13 +30,21 @@ #define FLASH_SIZE_REG ((uint32_t)0x1FFFF7CC) #define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG) +typedef struct{ + uint8_t reverse : 1; +} defflags_t; + /* * struct to save user configurations */ typedef struct __attribute__((packed, aligned(4))){ + uint32_t maxsteps; // maximal amount of steps from ESW0 to EWS3 uint16_t userconf_sz; // "magick number" uint16_t CANspeed; // default CAN speed - uint8_t defflags; // default flags + uint16_t microsteps; // microsteps amount per step + uint16_t accdecsteps; // amount of steps need for full acceleration/deceleration cycle + uint16_t motspd; // max motor speed ([3000 / motspd] steps per second) + defflags_t defflags; // default flags uint8_t driver_type; // user's settings: type of stepper's driver } user_conf; diff --git a/F0-nolib/CANbus_stepper/src/hardware.c b/F0-nolib/CANbus_stepper/src/hardware.c index ed7a0ac..92d927f 100644 --- a/F0-nolib/CANbus_stepper/src/hardware.c +++ b/F0-nolib/CANbus_stepper/src/hardware.c @@ -18,6 +18,8 @@ #include "hardware.h" +TIM_TypeDef *TIMx = TIM15; // stepper's timer + static uint8_t brdADDR = 0; void Jump2Boot(){ @@ -81,7 +83,7 @@ void gpio_setup(){ | RCC_AHBENR_DMAEN; // setup pins need @start: Vio_ON (PF0, opendrain), ~FAULT (PF1, floating IN), // ~SLEEP (PC15, pushpull), DIR (PA4, pushpull), ~EN (PC13, pushpull) - // ~CS, microstepping2, (PC14, pushpull + // ~CS, microstepping2, (PC14, pushpull) // PA8 - Tx/Rx // PB12..15 - board address, pullup input; PB0..2, PB10 - ESW, pullup inputs (inverse) VIO_OFF(); @@ -115,6 +117,22 @@ void gpio_setup(){ brdADDR = READ_BRD_ADDR(); } +// PA3 (STEP): TIM15_CH2; 48MHz -> 48kHz +void timer_setup(){ + RCC->APB2ENR |= RCC_APB2ENR_TIM15EN; // enable clocking + TIM15->CR1 &= ~TIM_CR1_CEN; // turn off timer + TIM15->CCMR1 = TIM_CCMR1_OC2M_2; // Force inactive + TIM15->PSC = 999; + TIM15->CCER = TIM_CCER_CC2E; + TIM15->CCR1 = 1; // very short pulse + TIM15->ARR = 1000; + // enable IRQ & update values + TIM15->EGR = TIM_EGR_UG; + TIM15->DIER = TIM_DIER_CC2IE; + NVIC_EnableIRQ(TIM15_IRQn); + NVIC_SetPriority(TIM15_IRQn, 0); +} + uint8_t refreshBRDaddr(){ return (brdADDR = READ_BRD_ADDR()); } diff --git a/F0-nolib/CANbus_stepper/src/hardware.h b/F0-nolib/CANbus_stepper/src/hardware.h index 2c87c39..bf434d3 100644 --- a/F0-nolib/CANbus_stepper/src/hardware.h +++ b/F0-nolib/CANbus_stepper/src/hardware.h @@ -68,14 +68,28 @@ #define RESET_UST2() do{GPIOC->BRR = 1<<14;}while(0) #define CS_ACTIVE() do{GPIOC->BRR = 1<<14;}while(0) #define CS_PASSIVE() do{GPIOC->BSRR = 1<<14;}while(0) +// microstepping0 (PA7), 1 (PA5) - set PP +#define UST01_CFG_PP() do{GPIOA->MODER = (GPIOA->MODER & ~(GPIO_MODER_MODER5|GPIO_MODER_MODER7)) | (GPIO_MODER_MODER5_O|GPIO_MODER_MODER7_O);}while(0) +#define SET_UST0() do{GPIOA->BSRR = 1<<7;}while(0) +#define SET_UST1() do{GPIOA->BSRR = 1<<5;}while(0) +#define RESET_UST0() do{GPIOA->BRR = 1<<7;}while(0) +#define RESET_UST1() do{GPIOA->BRR = 1<<5;}while(0) +// end-switches state +#define ESW_STATE() ((GPIOB->IDR & 0x07) | ((GPIOB->IDR>>7) & 0x08)) // configure ~CS as PP output //#define CS_CFG_OUT() do{GPIOC->MODER = (GPIOC->MODER&~GPIO_MODER_MODER14) | GPIO_MODER_MODER14_O; }while(0) // ~CS as floating input -; // Vio_ON, PF0 (inverse) #define VIO_ON() do{GPIOF->BRR = 1;}while(0) #define VIO_OFF() do{GPIOF->BSRR = 1;}while(0) +// turn off timer of STEPS pin +#define STEP_TIMER_OFF() do{TIM15->CR1 &= ~TIM_CR1_CEN;}while(0) + +// timer for stepper +extern TIM_TypeDef *TIMx; +#define timer_isr tim15_isr + extern volatile uint32_t Tms; void Jump2Boot(); @@ -84,4 +98,6 @@ void iwdg_setup(); uint8_t getBRDaddr(); uint8_t refreshBRDaddr(); void sleep(uint16_t ms); +void timer_setup(); + #endif // __HARDWARE_H__ diff --git a/F0-nolib/CANbus_stepper/src/main.c b/F0-nolib/CANbus_stepper/src/main.c index fe31317..aced506 100644 --- a/F0-nolib/CANbus_stepper/src/main.c +++ b/F0-nolib/CANbus_stepper/src/main.c @@ -24,6 +24,7 @@ #include "flash.h" #include "hardware.h" #include "proto.h" +#include "steppers.h" #include "usart.h" #include "usb.h" #include "usb_lib.h" @@ -81,7 +82,7 @@ static char *get_USB(){ } int main(void){ - uint32_t lastT = 0; + uint32_t lastT = 0, ostctr = 0; sysreset(); SysTick_Config(6000, 1); gpio_setup(); // + read board address @@ -120,6 +121,11 @@ int main(void){ } IWDG->KR = IWDG_REFRESH; can_messages_proc(); + if(ostctr != Tms){ // check steppers not more than once in 1ms + ostctr = Tms; + stp_process(); + } + } return 0; } diff --git a/F0-nolib/CANbus_stepper/src/proto.c b/F0-nolib/CANbus_stepper/src/proto.c index a0a3340..cd5c3ca 100644 --- a/F0-nolib/CANbus_stepper/src/proto.c +++ b/F0-nolib/CANbus_stepper/src/proto.c @@ -192,14 +192,45 @@ TRUE_INLINE void userconf_manip(char *txt){ } break; default: - SEND("Wrong argument of userconf manipulation: "); - SEND(txt); + SEND("\nUserconf commands:\n" + "d - userconf dump\n" + "s - userconf store\n" + ); + } +} + +TRUE_INLINE void setdefflags(char *txt){ + const char *needar = "Need argument 0 or 1 for flag"; + txt = omit_spaces(txt); + char ch = *txt; + ++txt; + uint32_t U; + if(txt == getnum(txt, &U)){ + SEND(needar); + return; + } + switch(ch){ + case 'r': + if(U > 1){ + SEND(needar); + return; + } + the_conf.defflags.reverse = U&1; + break; + default: + SEND("\nFlag commands:" + "r - set/clear reverse\n" + ); } } // a set of setters for user_conf TRUE_INLINE void setters(char *txt){ uint32_t U; + uint8_t u8; + const char *drvshould = "Driver type should be one of: 2130, 4988, 8825"; + const char *usshould = "Microsteps amount is a power of two: 1..512"; + const char *motspdshould = "Motor speed should be from 2 to " STR(0xffff/LOWEST_SPEED_DIV); txt = omit_spaces(txt); if(!*txt){ SEND("Setters need more arguments"); @@ -207,6 +238,21 @@ TRUE_INLINE void setters(char *txt){ } char *nxt = getnum(txt + 1, &U); switch(*txt){ + case 'a': // accdecsteps + if(nxt == txt + 1){ + SEND("No accdecsteps value given"); + return; + } + if(U < ACCDECSTEPS_MIN || U > ACCDECSTEPS_MAX){ + SEND("The value should be from" STR(ACCDECSTEPS_MIN) " to " STR(ACCDECSTEPS_MAX)); + return; + } + if(the_conf.accdecsteps != (uint16_t) U){ + the_conf.accdecsteps = (uint16_t) U; + userconf_changed = 1; + SEND("Set accdecsteps to "); printu(U); + } + break; case 'c': // set CAN speed if(nxt == txt + 1){ SEND("No CAN speed given"); @@ -222,54 +268,144 @@ TRUE_INLINE void setters(char *txt){ } if(the_conf.CANspeed != (uint16_t)U){ the_conf.CANspeed = (uint16_t)U; + SEND("Set CAN speed to "); printu(U); userconf_changed = 1; } break; - default: - SEND("Wrong argument of setters: "); - SEND(txt); - } -} - -TRUE_INLINE void driver_commands(char *txt){ - uint32_t U; - char *nxt; - const char *drvshould = "Driver type should be one of: 2130, 4988, 8825"; - txt = omit_spaces(txt); - if(!*txt){ - SEND("Driver commands need more arguments"); - return; - } - switch(*txt){ - case 'i': // init - initDriver(); - break; - case 's': // set type - nxt = getnum(txt + 1, &U); + case 'd': // set driver type if(nxt == txt+1){ SEND(drvshould); break; } + u8 = DRV_NONE; switch(U){ case 2130: - the_conf.driver_type = DRV_2130; + u8 = DRV_2130; SEND("TMC2130"); break; case 4988: - the_conf.driver_type = DRV_4988; + u8 = DRV_4988; SEND("A4988"); break; case 8825: - the_conf.driver_type = DRV_8825; + u8 = DRV_8825; SEND("DRV8825"); break; default: SEND(drvshould); } + if(the_conf.driver_type != u8){ + the_conf.driver_type = u8; + userconf_changed = 1; + } + break; + case 'F': + setdefflags(txt+1); + break; + case 'm': // microsteps + if(nxt == txt + 1){ // no number + SEND(usshould); break; + } + if(U < 1 || U > getMaxUsteps() || (U & (U-1)) != 0){ // U over of range or not power of two + SEND(usshould); break; + } + if(the_conf.microsteps != (uint16_t)U){ + the_conf.microsteps = (uint16_t)U; + userconf_changed = 1; + SEND("Set microsteps to "); printu(U); + } + break; + case 'M': // maxsteps + if(nxt == txt + 1 || U > INT32_MAX){ + SEND("Enter number from 0 (infinity) to INT32_MAX"); break; + } + if(U != the_conf.maxsteps){ + the_conf.maxsteps = U; + userconf_changed = 1; + } + break; + case 's': // motor speed + if(nxt == txt + 1 || U < 2 || U > (0xffff/LOWEST_SPEED_DIV)){ // no number + SEND(motspdshould); break; + } + if(the_conf.motspd != (uint16_t)U){ + the_conf.motspd = (uint16_t)U; + userconf_changed = 1; + SEND("Set motspd to "); printu(U); + } break; default: - SEND("Wrong argument of driver commands: "); - SEND(txt); + SEND("\nSetters commands:\n" + "a - set accdecsteps\n" + "c - set default CAN speed\n" + "d - set driver type\n" + "F - set flags" + "m - set microsteps\n" + "M - set maxsteps\n" + "s - set motspd\n" + ); + } +} + +TRUE_INLINE void driver_commands(char *txt){ + txt = omit_spaces(txt); + if(!*txt){ + SEND("Driver commands need more arguments"); + return; + } + char cmd = *txt++; + txt = omit_spaces(txt); + uint32_t U; + int8_t sign = 1; + if(*txt == '-'){ + ++txt; + sign = -1; + } + char *nxt = getnum(txt, &U); + stp_status st; + switch(cmd){ + case 'e': + SEND("ESW="); + printu(ESW_STATE()); + break; + case 'i': // init + initDriver(); + break; + case 'm': + if(nxt == txt + 1 || U > (INT32_MAX-1)){ + SEND("Give right steps amount: from -INT32_MAX to INT32_MAX"); + return; + } + if(sign > 0) st = stp_move((int32_t)U); + else st = stp_move(-(int32_t)U); + switch(st){ + case STPS_ACTIVE: + SEND("IsMoving"); + break; + case STPS_ONESW: + SEND("OnEndSwitch"); + break; + case STPS_ZEROMOVE: + SEND("ZeroMove"); + break; + case STPS_TOOBIG: + SEND("TooBigNumber"); + break; + default: + SEND("Move to given steps amount"); + } + break; + case 's': + stp_stop(); + SEND("Stop motor"); + break; + default: + SEND("\nDriver commands:\n" + "e - end-switches state\n" + "i - init stepper driver (8825, 4988, 2130)\n" + "m - move N steps\n" + "s - stop\n" + ); } } @@ -363,18 +499,16 @@ void cmd_parser(char *txt, uint8_t isUSB){ "a - get raw ADC values\n" "b - switch to bootloader\n" "d - dump userconf\n" - "Di - init stepper driver (8825, 4988, 2130)\n" - "Ds - set driver type\n" + "D? - stepper driver commands\n" "g - get board address\n" "j - get MCU temperature\n" "k - get U values\n" "m - start/stop monitoring CAN bus\n" "s - send data over CAN: s ID [byte0..7]\n" + "S? - parameter setters\n" "t - send test sequence over RS-485\n" "T - print current time\n" - "Sc - set default CAN speed\n" - "Ud - userconf dump\n" - "Us - userconf store\n" + "U? - options for user configuration\n" ); break; } diff --git a/F0-nolib/CANbus_stepper/src/steppers.c b/F0-nolib/CANbus_stepper/src/steppers.c index 0a5c1fb..9a21a29 100644 --- a/F0-nolib/CANbus_stepper/src/steppers.c +++ b/F0-nolib/CANbus_stepper/src/steppers.c @@ -22,6 +22,28 @@ static drv_type driver = DRV_NONE; +// maximum number of microsteps per driver +static const uint16_t maxusteps[] = { + [DRV_NONE] = 0, + [DRV_NOTINIT] = 0, + [DRV_MAILF] = 0, + [DRV_8825] = 32, + [DRV_4988] = 16, + [DRV_2130] = 256 +}; + +// amount of steps need for full acceleration/deceleration cycle +#define ACCDECSTEPS (the_conf.accdecsteps) +// amount of microsteps in each step +#define USTEPS (the_conf.microsteps) + +int32_t mot_position = -1; // current position of motor (from zero endswitch, -1 means inactive) +uint32_t steps_left = 0; // amount of steps left +stp_state state = STP_SLEEP;// current state of motor +// ARR register values: low (max speed), high (min speed = 10% from max), step (1/50(hi-lo)) +static uint16_t stplowarr, stphigharr, stpsteparr; +static int8_t dir = 0; // moving direction: -1 (negative) or 1 (positive) + /** * @brief checkDrv - test if driver connected */ @@ -42,12 +64,16 @@ static void checkDrv(){ sleep(2); // Check is ~SLEEP is in air oldstate = SLP_STATE(); +#ifdef EBUG if(oldstate) MSG("SLP=1\n"); else MSG("SLP=0\n"); +#endif SLEEP_OFF(); SLP_CFG_OUT(); // sleep -> 1 sleep(2); SLP_CFG_IN(); sleep(2); +#ifdef EBUG if(SLP_STATE()) MSG("SLP=1\n"); else MSG("SLP=0\n"); +#endif if(SLP_STATE() != oldstate){ MSG("~SLP is in air\n"); if(driver != DRV_2130){ @@ -63,13 +89,17 @@ static void checkDrv(){ EN_CFG_IN(); sleep(2); oldstate = EN_STATE(); +#ifdef EBUG if(oldstate) MSG("EN=1\n"); else MSG("EN=0\n"); +#endif DRV_DISABLE(); // EN->1 EN_CFG_OUT(); sleep(2); EN_CFG_IN(); sleep(2); +#ifdef EBUG if(EN_STATE()) MSG("EN=1\n"); else MSG("EN=0\n"); +#endif if(oldstate != EN_STATE()){ MSG("~EN is in air\n"); driver = DRV_NONE; @@ -86,6 +116,47 @@ ret: #endif } +static drv_type ini2130(){ // init 2130: SPI etc. + if(driver != DRV_2130) return DRV_MAILF; + ; + return DRV_MAILF; +} + +static drv_type ini4988_8825(){ // init 4988 or 8825 + if(driver != DRV_4988 && driver != DRV_8825){ + MSG("Wrong drv\n"); + return DRV_MAILF; + } + if(the_conf.microsteps > maxusteps[driver]){ + SEND("Wrong microstepping settings\n"); + return DRV_MAILF; + } + if(the_conf.microsteps == 0){ + SEND("Configure microstepping first\n"); + return DRV_MAILF; + } + // init microstepping pins and set config + UST01_CFG_PP(); + uint8_t PINS = 0; + if(the_conf.microsteps == 16 && driver == DRV_4988) PINS = 7; // microstepping settings for 4988 in 1/16 differs from 8825 + else PINS = (uint8_t)__builtin_ctz(the_conf.microsteps); +#ifdef EBUG + SEND("Microstep PINS="); + printu(PINS); + newline(); sendbuf(); +#endif + // now PINS is M0..M2 settings + if(PINS & 1) SET_UST0(); else RESET_UST0(); + if(PINS & 2) SET_UST1(); else RESET_UST1(); + if(PINS & 4) SET_UST2(); else RESET_UST2(); + // turn on timer + timer_setup(); + // recalculate defaults + stp_chspd(); + SEND("Init OK\n"); + return driver; +} + /** * @brief initDriver - try to init driver * @return driver type @@ -93,12 +164,179 @@ ret: drv_type initDriver(){ if(driver != DRV_NOTINIT){ // reset all settings MSG("clear GPIO & other setup\n"); + STEP_TIMER_OFF(); // TODO: turn off SPI & timer gpio_setup(); // reset pins control } driver = the_conf.driver_type; checkDrv(); - if(driver == DRV_NONE) return driver; - // TODO: some stuff here + if(driver > DRV_MAX-1) return (driver = DRV_NONE); + MSG("init pins\n"); + switch(driver){ + case DRV_2130: + return ini2130(); + break; + case DRV_4988: + case DRV_8825: + return ini4988_8825(); + break; + default: + SEND("Set driver type in config\n"); + return driver; // bad driver type + } return driver; } + +uint16_t getMaxUsteps(){ + if(driver > DRV_MAX-1) return 0; + return maxusteps[driver]; +} + +void stp_chspd(){ + int i; + for(i = 0; i < 2; ++i){ + uint16_t spd = the_conf.motspd; + stplowarr = spd; + stphigharr = spd * LOWEST_SPEED_DIV; + stpsteparr = (spd * (LOWEST_SPEED_DIV - 1)) / ((uint16_t)ACCDECSTEPS) + 1; + } +} + +// check end-switches for stepper motors +void stp_process(){ + // check end-switches; ESW0&ESW3 stops motor + uint8_t esw = ESW_STATE(); + switch(state){ + case STP_MOVE0: // move towards ESW0 + state = STP_SLEEP; + stp_move(-the_conf.maxsteps); // won't move if the_conf.maxsteps == 0 + break; + case STP_MOVE1: // move towards ESW3 + state = STP_SLEEP; + stp_move(the_conf.maxsteps); + break; + case STP_ACCEL: // @ any move check esw + case STP_DECEL: + case STP_MOVE: + case STP_MVSLOW: + if((esw&1) && dir == -1){ // move through ESW0 + state = STP_STOPZERO; // stop @ end-switch + }else if((esw&8) && dir == 1){ // move through ESW3 + state = STP_STOP; // stop @ ESW3 + } + break; + default: // stopping states - do nothing + break; + } +} + +// move motor to `steps` steps, @return 0 if all OK +stp_status stp_move(int32_t steps){ + if(state != STP_SLEEP && state != STP_MOVE0 && state != STP_MOVE1) return STPS_ACTIVE; + if(steps == 0) + return STPS_ZEROMOVE; + if(the_conf.maxsteps && steps > (int32_t)the_conf.maxsteps) return STPS_TOOBIG; + int8_t d; + if(steps < 0){ + d = -1; + steps = -steps; + }else d = 1; // positive direction + // check end-switches + uint8_t esw = ESW_STATE(); + if(((esw&1) && d == -1) || ((esw&8) && d == 1)) return STPS_ONESW; // can't move through esw + dir = d; + // change value of DIR pin + if(the_conf.defflags.reverse){ + if(d>0) + SET_DIR(); + else + CLEAR_DIR(); + }else{ + if(d>0) + CLEAR_DIR(); + else + SET_DIR(); + } + // turn on driver, EN=0 + DRV_ENABLE(); + steps_left = (uint32_t)steps; + // setup timer & start it + TIMx->ARR = stphigharr; + TIMx->CCMR1 = TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1; // PWM mode 1: active->inacive, preload enable + TIMx->CR1 |= TIM_CR1_CEN; + if(steps < ACCDECSTEPS*2) state = STP_MVSLOW; // move without acceleration + else state = STP_ACCEL; // move with acceleration + return STPS_ALLOK; +} + +// change ARR value +void stp_chARR(uint32_t val){ + if(val < 2) val = 2; + TIMx->ARR = (uint32_t)val; +} + +void stp_stop(){ // stop motor by demand or @ end-switch + switch(state){ + case STP_SLEEP: + return; + break; + case STP_MOVE0: + case STP_MOVE1: + state = STP_SLEEP; + break; + default: + state = STP_STOP; + } +} + +void timer_isr(){ + static uint16_t ustep = 0; + uint16_t tmp, arrval; + if(USTEPS == ++ustep){ // prevent stop @ not full step + ustep = 0; + if(state == STP_STOPZERO) + mot_position = 0; + else{ + if(0 == --steps_left) state = STP_STOP; + mot_position += dir; + } + }else return; + switch(state){ + case STP_ACCEL: // acceleration phase + arrval = (uint16_t)TIMx->ARR - stpsteparr; + tmp = stplowarr; + if(arrval <= tmp || arrval > stphigharr){ + arrval = tmp; + state = STP_MOVE; // end of acceleration phase + } + TIMx->ARR = arrval; + break; + case STP_DECEL: // deceleration phase + arrval = (uint16_t)TIMx->ARR + stpsteparr; + tmp = stphigharr; + if(arrval >= tmp || arrval < stplowarr){ + arrval = tmp; + state = STP_MVSLOW; // end of deceleration phase, move @ lowest speed + } + TIMx->ARR = arrval; + break; + case STP_MOVE: // moving with constant speed phases + if(steps_left <= ACCDECSTEPS){ + state = STP_DECEL; // change moving status to decelerate + } + break; + case STP_MVSLOW: + // nothing to do here: all done before switch() + break; + default: // STP_STOP, STP_STOPZERO + ustep = 0; + TIMx->CCMR1 = TIM_CCMR1_OC1M_2; // Force inactive + TIMx->CR1 &= ~TIM_CR1_CEN; // stop timer + DRV_DISABLE(); + dir = 0; + steps_left = 0; + state = STP_SLEEP; + break; + } + TIMx->SR = 0; +} diff --git a/F0-nolib/CANbus_stepper/src/steppers.h b/F0-nolib/CANbus_stepper/src/steppers.h index 7fcfb08..9635696 100644 --- a/F0-nolib/CANbus_stepper/src/steppers.h +++ b/F0-nolib/CANbus_stepper/src/steppers.h @@ -21,16 +21,61 @@ #include +// the lowest speed equal to [max speed] / LOWEST_SPEED_DIV +#define LOWEST_SPEED_DIV 30 +// min/max value of ACCDECSTEPS +#define ACCDECSTEPS_MIN 30 +#define ACCDECSTEPS_MAX 2000 + typedef enum{ DRV_NONE, // driver is absent DRV_NOTINIT,// not initialized DRV_MAILF, // mailfunction - no Vdd when Vio_ON activated DRV_8825, // DRV8825 connected DRV_4988, // A4988 connected - DRV_2130 // TMC2130 connected + DRV_2130, // TMC2130 connected + DRV_MAX // amount of records in enum } drv_type; +// stepper states +typedef enum{ + STP_SLEEP, // don't moving + STP_ACCEL, // start moving with acceleration + STP_MOVE, // moving with constant speed + STP_MVSLOW, // moving with slowest constant speed + STP_DECEL, // moving with deceleration + STP_STOP, // stop motor right now (by demand) + STP_STOPZERO, // stop motor and zero its position (on end-switch) + STP_MOVE0, // move towards 0 endswitch (negative direction) + STP_MOVE1, // move towards 1 endswitch (positive direction) +} stp_state; + +typedef enum{ + STPS_ALLOK, // no errors + STPS_ACTIVE, // motor is still moving + STPS_TOOBIG, // amount of steps too big + STPS_ZEROMOVE, // give 0 steps to move + STPS_ONESW // staying on end-switch & try to move further +} stp_status; + +extern int32_t mot_position; +extern uint32_t steps_left; +extern stp_state state; +#define stp_getstate() (state) + drv_type initDriver(); drv_type getDrvType(); +uint16_t getMaxUsteps(); + +void stp_chspd(); +stp_status stp_move(int32_t steps); +void stp_stop(); +void stp_process(); +void stp_chARR(uint32_t val); #endif // STEPPERS_H__ + + + + + diff --git a/F0-nolib/usbcdc/can.c b/F0-nolib/usbcdc/can.c index d4bffb6..c1b4f53 100644 --- a/F0-nolib/usbcdc/can.c +++ b/F0-nolib/usbcdc/can.c @@ -165,7 +165,7 @@ void CAN_setup(uint16_t speed){ CAN->MCR &=~ CAN_MCR_SLEEP; /* (3) */ CAN->MCR |= CAN_MCR_ABOM; /* allow automatically bus-off */ - CAN->BTR |= 2 << 20 | 3 << 16 | (6000/speed) << 0; /* (4) */ + CAN->BTR |= 2 << 20 | 3 << 16 | (6000/speed - 1); /* (4) */ CAN->MCR &=~ CAN_MCR_INRQ; /* (5) */ tmout = 16000000; while((CAN->MSR & CAN_MSR_INAK)==CAN_MSR_INAK) if(--tmout == 0) break; /* (6) */ diff --git a/F0-nolib/usbcdc/proto.c b/F0-nolib/usbcdc/proto.c index 56c2972..4bbd13b 100644 --- a/F0-nolib/usbcdc/proto.c +++ b/F0-nolib/usbcdc/proto.c @@ -544,8 +544,13 @@ void printu(uint32_t val){ void printuhex(uint32_t val){ addtobuf("0x"); uint8_t *ptr = (uint8_t*)&val + 3; - int8_t i, j; + int8_t i, j, z=1; for(i = 0; i < 4; ++i, --ptr){ + if(*ptr == 0){ // omit leading zeros + if(i == 3) z = 0; + if(z) continue; + } + else z = 0; for(j = 1; j > -1; --j){ uint8_t half = (*ptr >> (4*j)) & 0x0f; if(half < 10) bufputchar(half + '0'); diff --git a/F0-nolib/usbcdc/usbcan.bin b/F0-nolib/usbcdc/usbcan.bin index 6e94de4..dafdef4 100755 Binary files a/F0-nolib/usbcdc/usbcan.bin and b/F0-nolib/usbcdc/usbcan.bin differ