From 4b50e9583898600269d7605268c320b9aaddf23f Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Tue, 16 Nov 2021 00:28:20 +0300 Subject: [PATCH] First approximation to steppers run --- F0-nolib/3steppersLB/Makefile | 2 +- F0-nolib/3steppersLB/commonproto.c | 60 ++++++++- F0-nolib/3steppersLB/commonproto.h | 4 + F0-nolib/3steppersLB/flash.c | 15 ++- F0-nolib/3steppersLB/flash.h | 12 +- F0-nolib/3steppersLB/hardware.c | 54 +++++---- F0-nolib/3steppersLB/hardware.h | 19 ++- F0-nolib/3steppersLB/steppers.bin | Bin 20756 -> 22796 bytes F0-nolib/3steppersLB/steppers.c | 188 ++++++++++++++++++----------- F0-nolib/3steppersLB/steppers.h | 5 +- F0-nolib/3steppersLB/strfunct.c | 17 +++ F0-nolib/3steppersLB/version.inc | 4 +- 12 files changed, 257 insertions(+), 123 deletions(-) diff --git a/F0-nolib/3steppersLB/Makefile b/F0-nolib/3steppersLB/Makefile index 33d49ea..ed0fd91 100644 --- a/F0-nolib/3steppersLB/Makefile +++ b/F0-nolib/3steppersLB/Makefile @@ -106,7 +106,7 @@ $(STARTUP): $(INC_DIR)/startup/vector.c $(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $< $(VERSION_FILE): *.[ch] - @echo "Generate version: $(NEXTVER) for date $(BUILDDATE)" + @echo " Generate version: $(NEXTVER) for date $(BUILDDATE)" @sed -i "s/#define BUILD_NUMBER.*/#define BUILD_NUMBER \"$(NEXTVER)\"/" $(VERSION_FILE) @sed -i "s/#define BUILD_DATE.*/#define BUILD_DATE \"$(BUILDDATE)\"/" $(VERSION_FILE) diff --git a/F0-nolib/3steppersLB/commonproto.c b/F0-nolib/3steppersLB/commonproto.c index 3e56758..b7cb621 100644 --- a/F0-nolib/3steppersLB/commonproto.c +++ b/F0-nolib/3steppersLB/commonproto.c @@ -171,6 +171,7 @@ static errcodes ustepsparser(uint8_t par, int32_t *val){ if(m < 1 || m > MICROSTEPSMAX) return ERR_BADVAL; // find most significant bit if(m != 1< PCLK/(MOTORTIM_PSC+1)/(MOTORTIM_ARRMIN+1)) return ERR_BADVAL; the_conf.microsteps[n] = m; } *val = the_conf.microsteps[n]; @@ -210,21 +211,42 @@ static errcodes accparser(uint8_t par, int32_t *val){ return ERR_OK; } +// calculate ARR value for given speed, return nearest possible speed +static uint16_t getSPD(uint8_t n, int32_t speed){ + uint32_t ARR = PCLK/(MOTORTIM_PSC+1) / the_conf.microsteps[n] / speed - 1; + if(ARR < MOTORTIM_ARRMIN) ARR = MOTORTIM_ARRMIN; + else if(ARR > 0xffff) ARR = 0xffff; + speed = PCLK/(MOTORTIM_PSC+1) / the_conf.microsteps[n] / (ARR + 1); + if(speed > 0xffff) speed = 0xffff; + return (uint16_t)speed; +} + static errcodes maxspdparser(uint8_t par, int32_t *val){ uint8_t n = PARBASE(par); if(n > MOTORSNO-1) return ERR_BADPAR; if(ISSETTER(par)){ - if(*val/the_conf.microsteps[n] > MAXMAXSPD || *val < 1) return ERR_BADVAL; - the_conf.maxspd[n] = *val; + if(*val <= the_conf.minspd[n]) return ERR_BADVAL; + the_conf.maxspd[n] = getSPD(n, *val); } *val = the_conf.maxspd[n]; return ERR_OK; } +static errcodes minspdparser(uint8_t par, int32_t *val){ + uint8_t n = PARBASE(par); + if(n > MOTORSNO-1) return ERR_BADPAR; + if(ISSETTER(par)){ + if(*val >= the_conf.maxspd[n]) return ERR_BADVAL; + the_conf.minspd[n] = getSPD(n, *val); + } + *val = the_conf.minspd[n]; + return ERR_OK; +} + static errcodes spdlimparser(uint8_t par, int32_t *val){ uint8_t n = PARBASE(par); if(n > MOTORSNO-1) return ERR_BADPAR; - *val = MOTORFREQ / the_conf.microsteps[n]; + *val = getSPD(n, 0xffff); return ERR_OK; } @@ -251,6 +273,16 @@ static errcodes encrevparser(uint8_t par, int32_t *val){ return ERR_OK; } +static errcodes motflagsparser(uint8_t par, int32_t *val){ + uint8_t n = PARBASE(par); + if(n > MOTORSNO-1) return ERR_BADPAR; + if(ISSETTER(par)){ + the_conf.motflags[n] = *((motflags_t*)val); + } + *(motflags_t*)val = the_conf.motflags[n]; + return ERR_OK; +} + static errcodes saveconfparser(uint8_t _U_ par, int32_t _U_ *val){ if(store_userconf()) return ERR_CANTRUN; return ERR_OK; @@ -284,6 +316,24 @@ static errcodes relstepsparser(uint8_t par, int32_t *val){ if(ISSETTER(par)) return motor_relmove(n, *val); return getremainsteps(n, val); } + +static errcodes motstateparser(uint8_t par, int32_t *val){ + uint8_t n = PARBASE(par); + if(n > MOTORSNO-1) return ERR_BADPAR; + *val = getmotstate(n); + return ERR_OK; +} + +static errcodes encposparser(uint8_t par, int32_t *val){ + uint8_t n = PARBASE(par); + if(n > MOTORSNO-1) return ERR_BADPAR; + errcodes ret = ERR_OK; + if(ISSETTER(par)){ + if(!setencpos(n, *val)) ret = ERR_CANTRUN; + } + *val = encoder_position(n); + return ret; +} /******************* END of motors' parsers *******************/ /* @@ -314,13 +364,17 @@ const commands cmdlist[CMD_AMOUNT] = { [CMD_MICROSTEPS] = {"microsteps", ustepsparser, "set/get microsteps settings"}, [CMD_ACCEL] = {"accel", accparser, "set/get accel/decel (steps/s^2)"}, [CMD_MAXSPEED] = {"maxspeed", maxspdparser, "set/get max speed (steps per sec)"}, + [CMD_MINSPEED] = {"minspeed", minspdparser, "set/get min speed (steps per sec)"}, [CMD_SPEEDLIMIT] = {"speedlimit", spdlimparser, "get limiting speed for current microsteps"}, [CMD_MAXSTEPS] = {"maxsteps", maxstepsparser, "set/get max steps (from zero)"}, [CMD_ENCREV] = {"encrev", encrevparser, "set/get max encoder's pulses per revolution"}, + [CMD_MOTFLAGS] = {"motflags", motflagsparser, "set/get motorN flags"}, // motor's commands [CMD_ABSPOS] = {"abspos", curposparser, "set/get position (in steps)"}, [CMD_RELPOS] = {"relpos", relstepsparser, "set relative steps, get remaining"}, [CMD_STOPMOTOR] = {"stop", mstopparser, "stop motor now"}, [CMD_REINITMOTORS] = {"motreinit", reinitmparser, "re-init motors after configuration changed"}, + [CMD_MOTORSTATE] = {"state", motstateparser, "get motor state"}, + [CMD_ENCPOS] = {"encpos", encposparser, "set/get encoder's position"}, }; diff --git a/F0-nolib/3steppersLB/commonproto.h b/F0-nolib/3steppersLB/commonproto.h index 0f928f8..524f252 100644 --- a/F0-nolib/3steppersLB/commonproto.h +++ b/F0-nolib/3steppersLB/commonproto.h @@ -76,13 +76,17 @@ enum{ ,CMD_MICROSTEPS // get/set microsteps ,CMD_ACCEL // set/get acceleration/deceleration ,CMD_MAXSPEED // set/get maximal speed + ,CMD_MINSPEED // set/get minimal speed ,CMD_SPEEDLIMIT // get limit of speed for current microsteps settings ,CMD_MAXSTEPS // max steps (-max..+max) ,CMD_ENCREV // encoder's pulses per revolution + ,CMD_MOTFLAGS // motor flags ,CMD_REINITMOTORS // re-init motors after configuration changing ,CMD_ABSPOS // current position (set/get) ,CMD_RELPOS // set relative steps or get steps left ,CMD_STOPMOTOR // stop moving NOW + ,CMD_MOTORSTATE // motor state + ,CMD_ENCPOS // position of encoder (independing on settings) //,CMD_STOPDECEL //,CMD_RELMOVE //,CMD_ABSMOVE diff --git a/F0-nolib/3steppersLB/flash.c b/F0-nolib/3steppersLB/flash.c index c0aefc4..2d9e7a4 100644 --- a/F0-nolib/3steppersLB/flash.c +++ b/F0-nolib/3steppersLB/flash.c @@ -34,19 +34,20 @@ static const uint32_t blocksize = (uint32_t)&_BLOCKSIZE; // max amount of Config records stored (will be recalculate in flashstorage_init() static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here -#define DEFMF {.haveencoder = 1} +#define DEFMF {.haveencoder = 1, .donthold = 1, .eswinv = 1} #define USERCONF_INITIALIZER { \ .userconf_sz = sizeof(user_conf) \ ,.CANspeed = 100 \ ,.CANID = 0xaa \ ,.microsteps = {32, 32, 32} \ - ,.accel = {160, 160, 160} \ - ,.maxspd = {1000, 1000, 1000} \ - ,.maxsteps = {50000, 50000, 50000} \ + ,.accel = {500, 500, 500} \ + ,.maxspd = {3000, 3000, 3000} \ + ,.minspd = {20, 20, 20} \ + ,.maxsteps = {500000, 500000, 500000} \ ,.encrev = {4000,4000,4000} \ - ,.encperstepmin = {16,16,16} \ - ,.encperstepmax = {24,24,24} \ + ,.encperstepmin = {5,5,5} \ + ,.encperstepmax = {50,50,50} \ ,.motflags = {DEFMF,DEFMF,DEFMF} \ ,.ESW_reaction = {ESW_ANYSTOP, ESW_ANYSTOP, ESW_ANYSTOP} \ } @@ -224,6 +225,8 @@ void dump_userconf(_U_ char *txt){ printu(the_conf.accel[i]); PROPNAME("maxspeed"); printu(the_conf.maxspd[i]); + PROPNAME("minspeed"); + printu(the_conf.minspd[i]); PROPNAME("maxsteps"); printu(the_conf.maxsteps[i]); PROPNAME("encperrev"); diff --git a/F0-nolib/3steppersLB/flash.h b/F0-nolib/3steppersLB/flash.h index 065209a..aa9cc53 100644 --- a/F0-nolib/3steppersLB/flash.h +++ b/F0-nolib/3steppersLB/flash.h @@ -34,8 +34,6 @@ #define MICROSTEPSMAX (512) // (STEPS per second^2) #define ACCELMAXSTEPS (1000) -// max speed IN STEPS! -#define MAXMAXSPD (10000) // max encoder steps per rev #define MAXENCREV (100000) @@ -48,10 +46,11 @@ blocksizeASH_SIZE_REG ((uint32_t)0x1FFFF7CC) // motor flags typedef struct{ - uint8_t reverse : 1; // reversing motor rotation - uint8_t encreverse : 1; // reversing encoder rotation TODO: configure encoder's timer to downcounting - uint8_t haveencoder : 1; // have encoder - uint8_t donthold : 1; // clear power @ stop (don't hold motor when stopped) + uint8_t reverse : 1; // bit0 - reversing motor rotation + uint8_t encreverse : 1; // bit1 - reversing encoder rotation TODO: configure encoder's timer to downcounting + uint8_t haveencoder : 1; // bit2 - have encoder + uint8_t donthold : 1; // bit3 - clear power @ stop (don't hold motor when stopped) + uint8_t eswinv : 1; // bit4 - invers end-switches } motflags_t; /* @@ -64,6 +63,7 @@ typedef struct __attribute__((packed, aligned(4))){ uint16_t microsteps[MOTORSNO]; // microsteps amount per step uint16_t accel[MOTORSNO]; // acceleration/deceleration (steps/s^2) uint16_t maxspd[MOTORSNO]; // max motor speed (steps per second) + uint16_t minspd[MOTORSNO]; // min motor speed (steps per second) uint32_t maxsteps[MOTORSNO]; // maximal amount of steps uint16_t encrev[MOTORSNO]; // encoders' counts per revolution uint16_t encperstepmin[MOTORSNO]; // min amount of encoder ticks per one step diff --git a/F0-nolib/3steppersLB/hardware.c b/F0-nolib/3steppersLB/hardware.c index af69647..1cbee6a 100644 --- a/F0-nolib/3steppersLB/hardware.c +++ b/F0-nolib/3steppersLB/hardware.c @@ -86,16 +86,21 @@ static IRQn_Type motirqs[MOTORSNO] = {TIM15_IRQn, TIM14_IRQn, TIM16_IRQn}; // motor's PWM static void setup_mpwm(int i){ volatile TIM_TypeDef *TIM = mottimers[i]; - TIM->CR1 = 0; - TIM->PSC = MOTORTIM_PSC - 1; // 64kHz - // PWM mode 1 (OCxM = 110), preload enable - TIM->CCMR1 = TIM_CCMR1_OC1M_2; // Force inactive - TIM->CCER = TIM_CCER_CC1E; // turn it on, active high - TIM->CCR1 = 1; // 20.8us for pulse duration, according to datasheet 1.9us is enough - TIM->BDTR |= TIM_BDTR_MOE; // enable main output - TIM->EGR |= TIM_EGR_UG; // force update generation - TIM->DIER = TIM_DIER_CC1IE; // allow CC interrupt (we should count steps) + TIM->CR1 = TIM_CR1_ARPE; // buffered ARR + TIM->PSC = MOTORTIM_PSC; // 64kHz + // PWM mode 1 (active -> inactive) + TIM->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; +#if MOTORTIM_ARRMIN < 5 +#error "change the code!" +#endif + TIM->CCR1 = MOTORTIM_ARRMIN - 3; // ~10us for pulse duration TIM->CNT = 0; + TIM->ARR = 0xffff; +// TIM->EGR = TIM_EGR_UG; // generate update to refresh ARR + TIM->BDTR |= TIM_BDTR_MOE; // enable main output + TIM->CCER = TIM_CCER_CC1E; // turn it on, active high + TIM->DIER = TIM_DIER_CC1IE; // allow CC interrupt (we should count steps) + //TIM->CR1 = TIM_CR1_CEN; NVIC_EnableIRQ(motirqs[i]); } @@ -128,17 +133,20 @@ void timers_setup(){ RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN | RCC_APB1ENR_TIM14EN; RCC->APB2ENR |= RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM15EN | RCC_APB2ENR_TIM16EN | RCC_APB2ENR_TIM17EN; // enable clocking // setup PWM @ TIM17 - single PWM channel + // PWM mode 1 (active -> inactive) + TIM17->CCMR1 = TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; TIM17->PSC = 5; // 8MHz for 31kHz PWM TIM17->ARR = 254; // ARR for 8-bit PWM + TIM17->CCR1 = 0; // level=0 TIM17->BDTR |= TIM_BDTR_MOE; // enable main output TIM17->CCER = TIM_CCER_CC1E; // enable PWM output - TIM17->CR1 |= TIM_CR1_CEN; // enable timer + TIM17->CR1 = TIM_CR1_CEN; // enable timer for(int i = 0; i < MOTORSNO; ++i) setup_mpwm(i); for(int i = 0; i < MOTORSNO; ++i){ - if(the_conf.motflags[i].haveencoder){ // motor have the encoder + //if(the_conf.motflags[i].haveencoder){ // motor have the encoder setup_enc(i); - } + //} } } @@ -189,23 +197,27 @@ uint8_t MSB(uint16_t val){ return ((uint8_t)r + bval[val]); } +// state 1 - pressed, 0 - released (pin active is zero) +uint8_t ESW_state(uint8_t x){ + uint8_t val = ((ESWports[x]->IDR & ESWpins[x]) ? 0 : 1); + if(the_conf.motflags[x].eswinv) val = !val; + return val; +} + void tim14_isr(){ + //TIM14->CR1 &= ~TIM_CR1_CEN; + addmicrostep(1); TIM14->SR = 0; - TIM14->CR1 &= TIM_CR1_CEN; - DBG("UP1"); - //addmicrostep(1); } void tim15_isr(){ + //TIM15->CR1 &= ~TIM_CR1_CEN; + addmicrostep(0); TIM15->SR = 0; - TIM15->CR1 &= TIM_CR1_CEN; - DBG("UP0"); - //addmicrostep(0); } void tim16_isr(){ + //TIM16->CR1 &= ~TIM_CR1_CEN; + addmicrostep(2); TIM16->SR = 0; - TIM16->CR1 &= TIM_CR1_CEN; - DBG("UP2"); - //addmicrostep(2); } diff --git a/F0-nolib/3steppersLB/hardware.h b/F0-nolib/3steppersLB/hardware.h index 9f0405b..267a895 100644 --- a/F0-nolib/3steppersLB/hardware.h +++ b/F0-nolib/3steppersLB/hardware.h @@ -26,12 +26,10 @@ #ifndef PCLK #define PCLK (48000000) #endif -// motor frequency in mictosteps - 96kHz -#ifndef MOTORFREQ -#define MOTORFREQ (96000) -#endif -// motors' timer PSC -#define MOTORTIM_PSC (PCLK/MOTORFREQ) +// motors' timer PSC = PCLK/Tfreq - 1, Tfreq=16MHz +#define MOTORTIM_PSC (2) +// minimal ARR value - 99 for 5000 steps per second @ 32 microsteps/step +#define MOTORTIM_ARRMIN (99) // default CAN bus speed in kbaud #define DEFAULT_CAN_SPEED (250) @@ -168,8 +166,6 @@ extern const uint32_t BTNpins[BTNSNO]; // ESW ports & pins extern volatile GPIO_TypeDef *ESWports[ESWNO]; extern const uint32_t ESWpins[ESWNO]; -// state 1 - pressed, 0 - released (pin active is zero) -#define ESW_state(x) ((ESWports[x]->IDR & ESWpins[x]) ? 0 : 1) // motors #define MOTORSNO (3) @@ -181,12 +177,12 @@ extern volatile GPIO_TypeDef *DIRports[MOTORSNO]; extern const uint32_t DIRpins[MOTORSNO]; #define MOTOR_CW(x) do{ pin_set(DIRports[x], DIRpins[x]); }while(0) #define MOTOR_CCW(x) do{ pin_clear(DIRports[x], DIRpins[x]); }while(0) -// minimal motor speed - steps per second -#define MOTORMINSPEED (10) // interval of velocity checking (10ms) #define MOTCHKINTERVAL (10) // maximal ticks of encoder per step -#define MAXENCTICKSPERSTEP (100) +#define MAXENCTICKSPERSTEP (100) +// amount of full steps per revolution +#define STEPSPERREV (200) extern volatile uint32_t Tms; @@ -195,6 +191,7 @@ extern volatile TIM_TypeDef *mottimers[]; // timers for encoders extern volatile TIM_TypeDef *enctimers[]; +uint8_t ESW_state(uint8_t x); void gpio_setup(); void iwdg_setup(); void timers_setup(); diff --git a/F0-nolib/3steppersLB/steppers.bin b/F0-nolib/3steppersLB/steppers.bin index 369c4845535c928d5c38b4026631731938ce9dd6..d307e48ff67116a5bb06d8c6f8eecedc7c5c525b 100755 GIT binary patch delta 8996 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 = (MOTORFREQ / curspeed[i]) >> ustepsshift[i]; + uint32_t ARR = (((PCLK/(MOTORTIM_PSC+1)) / curspeed[i]) >> ustepsshift[i]) - 1; + if(ARR < MOTORTIM_ARRMIN) ARR = MOTORTIM_ARRMIN; + else if(ARR > 0xffff) ARR = 0xffff; + mottimers[i]->ARR = ARR; + curspeed[i] = (((PCLK/(MOTORTIM_PSC+1)) / (ARR+1)) >> ustepsshift[i]); // recalculate speed due to new val + //SEND("New ARR["); bufputchar('0'+i); SEND("]="); printu(ARR); NL(); } // run this function after each steppers parameters changing @@ -83,30 +92,40 @@ void init_steppers(){ stopflag[i] = 0; motdir[i] = 1; curspeed[i] = 0; - dV[i] = the_conf.accel[i] * MOTCHKINTERVAL; - dV[i] /= 1000; // interval in ms, but accel in steps/s^2 - if(dV[i] == 0) dV[i] = 1; + accdecsteps[i] = (the_conf.maxspd[i] * the_conf.maxspd[i]) / the_conf.accel[i] / 2; state[i] = STP_RELAX; ustepsshift[i] = MSB(the_conf.microsteps[i]); - encperstep[i] = the_conf.encrev[i] / 200; + encperstep[i] = the_conf.encrev[i] / STEPSPERREV; if(!the_conf.motflags[i].donthold) MOTOR_EN(i); else MOTOR_DIS(i); } } // get absolute position by encoder -static int32_t encoder_position(uint8_t i){ +int32_t encoder_position(uint8_t i){ int32_t pos = encpos[i]; if(the_conf.motflags[i].encreverse) pos -= enctimers[i]->CNT; else pos += enctimers[i]->CNT; return pos; } +// set encoder's position, return 0 if false (motor's state != relax) +int setencpos(uint8_t i, int32_t position){ + if(state[i] != STP_RELAX) return FALSE; + int32_t remain = position % the_conf.encrev[i]; + if(remain < 0) remain += the_conf.encrev[i]; + enctimers[i]->CNT = remain; + encpos[i] = position - remain; + SEND("position=");printi(position);SEND(", remain=");printi(remain);SEND(", CNT=");printu(enctimers[i]->CNT);SEND(", pos=");printi(encpos[i]);NL(); + return TRUE; +} + // get current position errcodes getpos(uint8_t i, int32_t *position){ - if(the_conf.motflags[i].haveencoder){ + /*if(the_conf.motflags[i].haveencoder){ *position = encoder_position(i) / encperstep[i]; - }else *position = stppos[i]; + }else */ + *position = stppos[i]; return ERR_OK; } @@ -121,11 +140,13 @@ errcodes motor_absmove(uint8_t i, int32_t newpos){ if(state[i] != STP_RELAX) return ERR_CANTRUN; // can't move: motor isn't stopping if(newpos > (int32_t)the_conf.maxsteps[i] || newpos < -(int32_t)the_conf.maxsteps[i] || newpos == stppos[i]) return ERR_BADVAL; // too big position or zero + Nstalled = 0; targstppos[i] = newpos; prevencpos[i] = encoder_position(i); prevstppos[i] = stppos[i]; uint8_t inv = the_conf.motflags[i].reverse; int32_t delta = newpos - stppos[i]; + SEND("delta="); printi(delta); if(delta > 0){ // positive direction if(delta > 2*(int32_t)accdecsteps[i]){ // can move by trapezoid decelstartpos[i] = targstppos[i] - accdecsteps[i]; @@ -146,11 +167,15 @@ errcodes motor_absmove(uint8_t i, int32_t newpos){ if(inv) MOTOR_CW(i); else MOTOR_CCW(i); } - curspeed[i] = MOTORMINSPEED; + SEND("\ntargstppos="); printi(targstppos[i]); + SEND("\ndecelstart="); printi(decelstartpos[i]); + SEND("\naccdecsteps="); printu(accdecsteps[i]); NL(); + curspeed[i] = the_conf.minspd[i]; recalcARR(i); MOTOR_EN(i); mottimers[i]->CR1 |= TIM_CR1_CEN; // start timer state[i] = STP_ACCEL; + Taccel[i] = Tms; return ERR_OK; } @@ -170,33 +195,29 @@ stp_state getmotstate(uint8_t i){ // count steps @tim 14/15/16 void addmicrostep(uint8_t i){ static volatile uint16_t microsteps[MOTORSNO] = {0}; // current microsteps position - if(mottimers[i]->SR & TIM_SR_UIF){ - DBG("MOTUP"); - if(ESW_state(i)){ // ESW active - switch(the_conf.ESW_reaction[i]){ - case ESW_ANYSTOP: // stop motor in any direction - stopflag[i] = 1; - break; - case ESW_STOPMINUS: // stop only @ minus - if(motdir[i] == -1) stopflag[i] = 1; - break; - default: // ESW_IGNORE - break; - } - } - if(++microsteps[i] == the_conf.microsteps[i]){ - microsteps[i] = 0; - stppos[i] += motdir[i]; - if(stopflag[i] || stppos[i] == targstppos[i]){ // stop NOW - stopflag[i] = 0; - mottimers[i]->CR1 &= ~TIM_CR1_CEN; // stop timer - if(the_conf.motflags[i].donthold) - MOTOR_DIS(i); // turn off power - state[i] = STP_RELAX; - } + if(ESW_state(i)){ // ESW active + switch(the_conf.ESW_reaction[i]){ + case ESW_ANYSTOP: // stop motor in any direction + stopflag[i] = 1; + break; + case ESW_STOPMINUS: // stop only @ minus + if(motdir[i] == -1) stopflag[i] = 1; + break; + default: // ESW_IGNORE + break; + } + } + if(++microsteps[i] == the_conf.microsteps[i]){ + microsteps[i] = 0; + stppos[i] += motdir[i]; + if(stopflag[i] || stppos[i] == targstppos[i]){ // stop NOW + stopflag[i] = 0; + mottimers[i]->CR1 &= ~TIM_CR1_CEN; // stop timer + if(the_conf.motflags[i].donthold) + MOTOR_DIS(i); // turn off power + state[i] = STP_RELAX; } } - mottimers[i]->SR = 0; } void encoders_UPD(uint8_t i){ @@ -214,44 +235,55 @@ void encoders_UPD(uint8_t i){ // @return 0 if moving OK, static t_stalled chkSTALL(uint8_t i){ if(!the_conf.motflags[i].haveencoder) return STALL_NO; - static uint8_t Nstalled = 0; // counter of STALL int32_t curencpos = encoder_position(i), Denc = curencpos - prevencpos[i]; int32_t curstppos = stppos[i], Dstp = curstppos - prevstppos[i]; - prevencpos[i] = curencpos; - if(Dstp == 0){ // veird things - stopmotor(i); - return STALL_STOP; + if(Denc < 0) Denc = -Denc; + if(Dstp < 0) Dstp = -Dstp; + if(Dstp < 10){ // didn't move even @ 10 steps + return STALL_NO; } - if(Denc < the_conf.encperstepmin[i]*Dstp || the_conf.encperstepmax[i]*Dstp < Denc){ // stall? - if(++Nstalled >= NSTALLEDMAX){ - stopflag[i] = 1; - Nstalled = 0; - return STALL_STOP; - }else{ - uint16_t spd = curspeed[i] >> 1; // speed / 2 - curspeed[i] = (spd > MOTORMINSPEED) ? spd : MOTORMINSPEED; - recalcARR(i); - if(state[i] == STP_MOVE) - state[i] = STP_ACCEL; - return STALL_ONCE; - } - }else Nstalled = 0; + prevencpos[i] = curencpos; curstppos = curencpos / encperstep[i]; // recalculate current position stppos[i] = curstppos; prevstppos[i] = curstppos; + if(Denc < the_conf.encperstepmin[i]*Dstp || the_conf.encperstepmax[i]*Dstp < Denc){ // stall? + SEND("Denc="); printu(Denc); SEND(", Dstp="); printu(Dstp); NL(); + if(++Nstalled >= NSTALLEDMAX){ + stopflag[i] = 1; + Nstalled = 0; + DBG("STALL!"); + return STALL_STOP; + }else{ + uint16_t spd = curspeed[i] >> 1; // speed / 2 + curspeed[i] = (spd > the_conf.minspd[i]) ? spd : the_conf.minspd[i]; + recalcARR(i); + if(state[i] == STP_MOVE) + state[i] = STP_ACCEL; + SEND("pre-stall, speed="); printu(curspeed[i]); NL(); + return STALL_ONCE; + } + } + Nstalled = 0; return STALL_NO; } +#define TODECEL() do{state[i] = STP_DECEL; \ + decstartspeed[i] = curspeed[i]; \ + Taccel[i] = Tms; \ + SEND(" -> DECEL@"); printi(stppos[i]); SEND(", V="); printu(curspeed[i]); NL();}while(0) + // check state of i`th stepper static void chkstepper(int i){ int32_t newspeed; switch(state[i]){ case STP_ACCEL: // acceleration to max speed if(STALL_NO == chkSTALL(i)){ - newspeed = curspeed[i] + dV[i]; + //newspeed = curspeed[i] + dV[i]; + newspeed = the_conf.minspd[i] + (the_conf.accel[i] * (Tms - Taccel[i])) / 1000; if(newspeed >= the_conf.maxspd[i]){ // max speed reached -> move with it curspeed[i] = the_conf.maxspd[i]; state[i] = STP_MOVE; + SEND(" -> MOVE@"); printi(stppos[i]); SEND(", V="); printu(curspeed[i]); NL(); }else{ // increase speed curspeed[i] = newspeed; } @@ -259,45 +291,57 @@ static void chkstepper(int i){ } // check position for triangle profile if(motdir[i] > 0){ - if(stppos[i] >= decelstartpos[i]) // reached end of acceleration - state[i] = STP_DECEL; + if(stppos[i] >= decelstartpos[i]){ // reached end of acceleration + TODECEL(); + } }else{ - if(stppos[i] <= decelstartpos[i]) - state[i] = STP_DECEL; + if(stppos[i] <= decelstartpos[i]){ + TODECEL(); + } } break; case STP_MOVE: // move @ constant speed until need to decelerate if(STALL_NO == chkSTALL(i)){ // check position if(motdir[i] > 0){ - if(stppos[i] >= decelstartpos[i]) // reached start of deceleration - state[i] = STP_DECEL; + if(stppos[i] >= decelstartpos[i]){ // reached start of deceleration + TODECEL(); + } }else{ - if(stppos[i] <= decelstartpos[i]) - state[i] = STP_DECEL; + if(stppos[i] <= decelstartpos[i]){ + TODECEL(); + } } } break; case STP_DECEL: if(STALL_NO == chkSTALL(i)){ - newspeed = curspeed[i] - dV[i]; - if(newspeed > MOTORMINSPEED){ + //newspeed = curspeed[i] - dV[i]; + newspeed = decstartspeed[i] - (the_conf.accel[i] * (Tms - Taccel[i])) / 1000; + if(newspeed > the_conf.minspd[i]){ curspeed[i] = newspeed; }else{ - curspeed[i] = MOTORMINSPEED; + curspeed[i] = the_conf.minspd[i]; state[i] = STP_MVSLOW; + SEND(" -> MVSLOW@"); printi(stppos[i]); NL(); } recalcARR(i); + //SEND("spd="); printu(curspeed[i]); SEND(", pos="); printi(stppos[i]); newline(); } // fallthrough - case STP_MVSLOW: + case STP_MVSLOW: // position check is in add_microstep + /* if(motdir[i] > 0){ - if(stppos[i] >= targstppos[i]) // reached start of deceleration + if(stppos[i] >= targstppos[i]){ // reached start of deceleration stopflag[i] = 0; + SEND(" -> STOP@"); printi(stppos[i]); NL(); + } }else{ - if(stppos[i] <= targstppos[i]) + if(stppos[i] <= targstppos[i]){ stopflag[i] = 0; - } + SEND(" -> STOP@"); printi(stppos[i]); NL(); + } + }*/ break; default: // RELAX, STALL, ERR -> do nothing return; diff --git a/F0-nolib/3steppersLB/steppers.h b/F0-nolib/3steppersLB/steppers.h index a155d89..d313e7f 100644 --- a/F0-nolib/3steppersLB/steppers.h +++ b/F0-nolib/3steppersLB/steppers.h @@ -24,7 +24,7 @@ #include "commonproto.h" // amount of tries to detect motor stall -#define NSTALLEDMAX (5) +#define NSTALLEDMAX (55) // stepper states typedef enum{ @@ -50,6 +50,9 @@ void addmicrostep(uint8_t i); void encoders_UPD(uint8_t i); void init_steppers(); +int32_t encoder_position(uint8_t i); +int setencpos(uint8_t i, int32_t position); + errcodes getpos(uint8_t i, int32_t *position); errcodes getremainsteps(uint8_t i, int32_t *position); errcodes motor_absmove(uint8_t i, int32_t abssteps); diff --git a/F0-nolib/3steppersLB/strfunct.c b/F0-nolib/3steppersLB/strfunct.c index 68cd287..afc3f95 100644 --- a/F0-nolib/3steppersLB/strfunct.c +++ b/F0-nolib/3steppersLB/strfunct.c @@ -397,6 +397,22 @@ void wdcheck(_U_ char *txt){ while(1){nop();} } +void stp_check(char *txt){ + uint8_t N = *txt - '0'; + if(N < 3){ + MOTOR_EN(N); + MOTOR_CW(N); + mottimers[N]->ARR = 300; + mottimers[N]->CR1 |= TIM_CR1_CEN; + }else{ + for(N = 0; N < 3; ++N){ + MOTOR_DIS(N); + MOTOR_CCW(N); + mottimers[N]->CR1 &= ~TIM_CR1_CEN; + } + } +} + typedef void(*specfpointer)(char *arg); typedef struct{ @@ -420,6 +436,7 @@ const speccommands scmdlist[] = { {"dumpconf", dump_userconf, "dump current configuration"}, {"getctr", getcounter, "get TIM1/2/3 counters"}, {"wd", wdcheck, "check watchdog"}, + {"st", stp_check, "check steppers"}, {NULL, NULL, NULL} }; diff --git a/F0-nolib/3steppersLB/version.inc b/F0-nolib/3steppersLB/version.inc index 38cb263..d76b5ec 100644 --- a/F0-nolib/3steppersLB/version.inc +++ b/F0-nolib/3steppersLB/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "43" -#define BUILD_DATE "2021-11-14" +#define BUILD_NUMBER "97" +#define BUILD_DATE "2021-11-16"