From f880421d9eabe27ea989fe8303d8b1cd6dd21dbc Mon Sep 17 00:00:00 2001 From: Edward Emelianov Date: Mon, 20 Feb 2023 21:07:47 +0300 Subject: [PATCH] add some more, need a lot of tests --- F3:F303/Multistepper/commonproto.c | 326 +++++++++++++--- F3:F303/Multistepper/commonproto.h | 68 ++-- F3:F303/Multistepper/flash.c | 72 ++-- F3:F303/Multistepper/flash.h | 11 +- F3:F303/Multistepper/hardware.c | 23 +- F3:F303/Multistepper/hardware.h | 33 +- F3:F303/Multistepper/hashgen/hdr.c | 30 +- F3:F303/Multistepper/hashgen/hdr.h | 6 +- F3:F303/Multistepper/main.c | 2 +- F3:F303/Multistepper/multistepper.bin | Bin 20800 -> 25356 bytes F3:F303/Multistepper/multistepper.files | 1 + F3:F303/Multistepper/proto.c | 219 ++++++++--- F3:F303/Multistepper/steppers.c | 470 ++++++++++++++++++++++++ F3:F303/Multistepper/steppers.h | 7 +- F3:F303/Multistepper/usb.c | 3 +- F3:F303/Multistepper/version.inc | 4 +- 16 files changed, 1034 insertions(+), 241 deletions(-) create mode 100644 F3:F303/Multistepper/steppers.c diff --git a/F3:F303/Multistepper/commonproto.c b/F3:F303/Multistepper/commonproto.c index 41df7bb..3ca156b 100644 --- a/F3:F303/Multistepper/commonproto.c +++ b/F3:F303/Multistepper/commonproto.c @@ -19,53 +19,50 @@ #include "adc.h" #include "buttons.h" #include "commonproto.h" +#include "flash.h" #include "hardware.h" #include "hdr.h" #include "proto.h" +#include "steppers.h" #include "usb.h" #define NOPARCHK(par) do{if(PARBASE(par) != CANMESG_NOPAR) return ERR_BADPAR;}while(0) +#define CHECKN(val, par) do{val = PARBASE(par); \ + if(val > MOTORSNO-1) return ERR_BADPAR;}while(0) + extern volatile uint32_t Tms; // common functions for CAN and USB (or CAN only functions) -static errcodes cu_nosuchfn(_U_ uint8_t par, _U_ int32_t *val){ return ERR_BADCMD; } +static errcodes cu_nosuchfn(uint8_t _U_ par, int32_t _U_ *val){ + return ERR_BADCMD; +} -errcodes cu_ping(_U_ uint8_t par, _U_ int32_t *val){ +errcodes cu_abspos(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + stopmotor(n); return ERR_OK; } -static errcodes cu_reset(uint8_t par, _U_ int32_t *val){ - NOPARCHK(par); - NVIC_SystemReset(); - return ERR_OK; -} -static errcodes cu_time(uint8_t par, int32_t *val){ - NOPARCHK(par); - *val = Tms; +errcodes cu_accel(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + if(ISSETTER(par)){ + if(*val/the_conf.microsteps[n] > ACCELMAXSTEPS || *val < 1) return ERR_BADVAL; + the_conf.accel[n] = *val; + } + *val = the_conf.accel[n]; return ERR_OK; } -errcodes cu_mcut(uint8_t par, int32_t *val){ - NOPARCHK(par); - float f = getMCUtemp(); - *val = (uint32_t)(f*10.f); - return ERR_OK; -} -errcodes cu_mcuvdd(uint8_t par, int32_t *val){ - NOPARCHK(par); - float f = getVdd(); - *val = (uint32_t)(f*10.f); - return ERR_OK; -} errcodes cu_adc(uint8_t par, int32_t *val){ uint8_t n = PARBASE(par); if(n > NUMBER_OF_ADC_CHANNELS-1) return ERR_BADPAR; *val = getADCval(n); return ERR_OK; } + // NON-STANDARD COMMAND!!!!!!! // errcode == keystate, value = last time!!!! errcodes cu_button(uint8_t par, int32_t *val){ @@ -77,44 +74,259 @@ errcodes cu_button(uint8_t par, int32_t *val){ return (uint8_t) keystate(n, (uint32_t*)val); } -// par - motor number, val - 0/1 for ESW0/1 -errcodes cu_esw(uint8_t par, int32_t *val){ - uint8_t n = PARBASE(par), l = *val; - if(n >= MOTORSNO || l > 1){ - *val = CANMESG_NOPAR; // the only chance to understand error - return ERR_BADPAR; - } - *val = ESW_state(n, l); +errcodes cu_diagn(uint8_t _U_ par, int32_t _U_ *val){ + return ERR_BADCMD; +} + +errcodes cu_emstop(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + emstopmotor(n); return ERR_OK; } -errcodes cu_abspos(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_accel(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_diagn(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_emstop(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_eraseflash(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_eswreact(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_goto(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_gotoz(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_gpio(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_gpioconf(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_maxspeed(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_maxsteps(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_microsteps(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_minspeed(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_motflags(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_motmul(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_motreinit(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_relpos(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_relslow(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_saveconf(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_screen(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_speedlimit(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_state(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_stop(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_tmcbus(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_udata(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} -errcodes cu_usartstatus(_U_ uint8_t par, _U_ int32_t *val){return ERR_BADCMD;} +errcodes cu_eraseflash(uint8_t _U_ par, int32_t _U_ *val){ + NOPARCHK(par); + if(erase_storage()) return ERR_CANTRUN; + return ERR_OK; +} + +// par - motor number +errcodes cu_esw(uint8_t par, int32_t *val){ + uint8_t n; CHECKN(n, par); + *val = ESW_state(n); + return ERR_OK; +} + +errcodes cu_eswreact(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + if(ISSETTER(par)){ + if(*val < 0 || *val > ESW_AMOUNT-1) return ERR_BADVAL; + the_conf.ESW_reaction[n] = *val; + } + *val = geteswreact(n); + return ERR_OK; +} + +errcodes cu_goto(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + errcodes ret = ERR_OK; + if(ISSETTER(par)){ + ret = setmotpos(n, *val); + } + getpos(n, val); + return ret; +} + +errcodes cu_gotoz(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + return motor_goto0(n); +} + +TRUE_INLINE void setextpar(uint8_t val, uint8_t i){ + switch(val){ + case 0: + EXT_CLEAR(i); + break; + case 1: + EXT_SET(i); + break; + default: + EXT_TOGGLE(i); + } +} + +// TODO: do it right +errcodes cu_gpio(uint8_t _U_ par, int32_t _U_ *val){ +#if EXTNO > 4 +#error "change the code!!!" +#endif + uint8_t n = PARBASE(par); +#ifdef EBUG + USND("par="); printu(par); + USND(", n="); USB_putbyte('0'+n); newline(); +#endif + if(n == CANMESG_NOPAR){ // all +#ifdef EBUG + USND("ALL\n"); +#endif + uint8_t *arr = (uint8_t*)val; + if(ISSETTER(par)){ + for(int i = 0; i < EXTNO; ++i) + setextpar(arr[i], i); + } + for(int i = 0; i < EXTNO; ++i){ + arr[i] = EXT_CHK(i); + } + return ERR_OK; + }else if(n > EXTNO-1) return ERR_BADPAR; + if(ISSETTER(par)) + setextpar((uint8_t)*val, n); + *val = (int32_t) EXT_CHK(n); + return ERR_OK; +} + +// TODO: configure PU/PD, IN/OUT +errcodes cu_gpioconf(uint8_t _U_ par, int32_t _U_ *val){ + return ERR_BADCMD; +} + +// 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; +} + +errcodes cu_maxspeed(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + if(ISSETTER(par)){ + if(*val <= the_conf.minspd[n]) return ERR_BADVAL; + the_conf.maxspd[n] = getSPD(n, *val); + } + *val = the_conf.maxspd[n]; + return ERR_OK; +} + +errcodes cu_maxsteps(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + if(ISSETTER(par)){ + if(*val < 1) return ERR_BADVAL; + the_conf.maxsteps[n] = *val; + } + *val = the_conf.maxsteps[n]; + return ERR_OK; +} + +errcodes cu_mcut(uint8_t par, int32_t *val){ + NOPARCHK(par); + float f = getMCUtemp(); + *val = (uint32_t)(f*10.f); + return ERR_OK; +} + +errcodes cu_mcuvdd(uint8_t par, int32_t *val){ + NOPARCHK(par); + float f = getVdd(); + *val = (uint32_t)(f*10.f); + return ERR_OK; +} + +errcodes cu_microsteps(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + if(ISSETTER(par)){ +#if MICROSTEPSMAX > 512 +#error "Change the code anywhere!" +#endif + uint16_t m = (uint16_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]; + return ERR_OK; +} + +errcodes cu_minspeed(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + 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; +} + +errcodes cu_motflags(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + if(ISSETTER(par)){ + the_conf.motflags[n] = *((motflags_t*)val); + } + *(motflags_t*)val = the_conf.motflags[n]; + return ERR_OK; +} + +errcodes cu_motmul(uint8_t _U_ par, int32_t _U_ *val){ + return ERR_BADCMD; +} + +errcodes cu_motreinit(uint8_t _U_ par, int32_t _U_ *val){ + NOPARCHK(par); + init_steppers(); + return ERR_OK; +} + +errcodes cu_ping(uint8_t _U_ par, int32_t _U_ *val){ + return ERR_OK; +} + +errcodes cu_relpos(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + if(ISSETTER(par)) return motor_relmove(n, *val); + return getremainsteps(n, val); +} + +errcodes cu_relslow(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + if(ISSETTER(par)) return motor_relslow(n, *val); + return getremainsteps(n, val); +} + +static errcodes cu_reset(uint8_t par, int32_t _U_ *val){ + NOPARCHK(par); + NVIC_SystemReset(); + return ERR_OK; +} + +errcodes cu_saveconf(uint8_t _U_ par, int32_t _U_ *val){ + NOPARCHK(par); + if(store_userconf()) return ERR_CANTRUN; + return ERR_OK; +} + +errcodes cu_screen(uint8_t _U_ par, int32_t _U_ *val){ + return ERR_BADCMD; +} + +errcodes cu_speedlimit(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + *val = getSPD(n, 0xffff); + return ERR_OK; +} + +errcodes cu_state(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + *val = getmotstate(n); + return ERR_OK; +} + +errcodes cu_stop(uint8_t _U_ par, int32_t _U_ *val){ + uint8_t n; CHECKN(n, par); + stopmotor(n); + return ERR_OK; +} + +static errcodes cu_time(uint8_t par, int32_t *val){ + NOPARCHK(par); + *val = Tms; + return ERR_OK; +} + +errcodes cu_tmcbus(uint8_t _U_ par, int32_t _U_ *val){ + return ERR_BADCMD; +} + +errcodes cu_udata(uint8_t _U_ par, int32_t _U_ *val){ + return ERR_BADCMD; +} + +errcodes cu_usartstatus(uint8_t _U_ par, int32_t _U_ *val){ + return ERR_BADCMD; +} const fpointer cancmdlist[CCMD_AMOUNT] = { diff --git a/F3:F303/Multistepper/commonproto.h b/F3:F303/Multistepper/commonproto.h index 8d82e67..c1463ec 100644 --- a/F3:F303/Multistepper/commonproto.h +++ b/F3:F303/Multistepper/commonproto.h @@ -94,38 +94,38 @@ extern const fpointer cancmdlist[CCMD_AMOUNT]; extern const char* cancmds[CCMD_AMOUNT]; // all common functions -errcodes cu_ping(_U_ uint8_t par, _U_ int32_t *val); +errcodes cu_ping(uint8_t par, int32_t *val); // not realized yet -errcodes cu_abspos(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_accel(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_adc(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_button(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_canid(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_diagn(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_emstop(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_eraseflash(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_esw(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_eswreact(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_goto(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_gotoz(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_gpio(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_gpioconf(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_maxspeed(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_maxsteps(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_mcut(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_mcuvdd(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_microsteps(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_minspeed(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_motflags(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_motmul(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_motreinit(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_relpos(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_relslow(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_saveconf(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_screen(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_speedlimit(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_state(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_stop(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_tmcbus(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_udata(_U_ uint8_t par, _U_ int32_t *val); -errcodes cu_usartstatus(_U_ uint8_t par, _U_ int32_t *val); +errcodes cu_abspos(uint8_t par, int32_t *val); +errcodes cu_accel(uint8_t par, int32_t *val); +errcodes cu_adc(uint8_t par, int32_t *val); +errcodes cu_button(uint8_t par, int32_t *val); +errcodes cu_canid(uint8_t par, int32_t *val); +errcodes cu_diagn(uint8_t par, int32_t *val); +errcodes cu_emstop(uint8_t par, int32_t *val); +errcodes cu_eraseflash(uint8_t par, int32_t *val); +errcodes cu_esw(uint8_t par, int32_t *val); +errcodes cu_eswreact(uint8_t par, int32_t *val); +errcodes cu_goto(uint8_t par, int32_t *val); +errcodes cu_gotoz(uint8_t par, int32_t *val); +errcodes cu_gpio(uint8_t par, int32_t *val); +errcodes cu_gpioconf(uint8_t par, int32_t *val); +errcodes cu_maxspeed(uint8_t par, int32_t *val); +errcodes cu_maxsteps(uint8_t par, int32_t *val); +errcodes cu_mcut(uint8_t par, int32_t *val); +errcodes cu_mcuvdd(uint8_t par, int32_t *val); +errcodes cu_microsteps(uint8_t par, int32_t *val); +errcodes cu_minspeed(uint8_t par, int32_t *val); +errcodes cu_motflags(uint8_t par, int32_t *val); +errcodes cu_motmul(uint8_t par, int32_t *val); +errcodes cu_motreinit(uint8_t par, int32_t *val); +errcodes cu_relpos(uint8_t par, int32_t *val); +errcodes cu_relslow(uint8_t par, int32_t *val); +errcodes cu_saveconf(uint8_t par, int32_t *val); +errcodes cu_screen(uint8_t par, int32_t *val); +errcodes cu_speedlimit(uint8_t par, int32_t *val); +errcodes cu_state(uint8_t par, int32_t *val); +errcodes cu_stop(uint8_t par, int32_t *val); +errcodes cu_tmcbus(uint8_t par, int32_t *val); +errcodes cu_udata(uint8_t par, int32_t *val); +errcodes cu_usartstatus(uint8_t par, int32_t *val); diff --git a/F3:F303/Multistepper/flash.c b/F3:F303/Multistepper/flash.c index 28165ed..c0dd0b4 100644 --- a/F3:F303/Multistepper/flash.c +++ b/F3:F303/Multistepper/flash.c @@ -32,22 +32,19 @@ static const uint32_t FLASH_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, .donthold = 1, .eswinv = 1, .keeppos = 1} +#define DEFMF {.donthold = 1} #define USERCONF_INITIALIZER { \ .userconf_sz = sizeof(user_conf) \ ,.CANspeed = 100 \ ,.CANID = 0xaa \ - ,.microsteps = {32, 32, 32} \ - ,.accel = {500, 500, 500} \ - ,.maxspd = {2000, 2000, 2000} \ - ,.minspd = {20, 20, 20} \ - ,.maxsteps = {500000, 500000, 500000} \ - ,.encrev = {4000,4000,4000} \ - ,.encperstepmin = {17,17,17} \ - ,.encperstepmax = {23,23,23} \ - ,.motflags = {DEFMF,DEFMF,DEFMF} \ - ,.ESW_reaction = {ESW_IGNORE, ESW_IGNORE, ESW_IGNORE} \ + ,.microsteps = {32,32,32,32,32,32,32,32}\ + ,.accel = {500,500,500,500,500,500,500,500} \ + ,.maxspd = {2000,2000,2000,2000,2000,2000,2000,2000} \ + ,.minspd = {20,20,20,20,20,20,20,20} \ + ,.maxsteps = {500000,500000,500000,500000,500000,500000,500000,500000}\ + ,.motflags = {DEFMF,DEFMF,DEFMF,DEFMF,DEFMF,DEFMF,DEFMF,DEFMF} \ + ,.ESW_reaction = {ESW_IGNORE,ESW_IGNORE,ESW_IGNORE,ESW_IGNORE,ESW_IGNORE,ESW_IGNORE,ESW_IGNORE,ESW_IGNORE} \ } static int erase_flash(const void*, const void*); static int write2flash(const void*, const void*, uint32_t); @@ -121,7 +118,7 @@ static int write2flash(const void *start, const void *wrdata, uint32_t stor_size FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY2; } - while (FLASH->SR & FLASH_SR_BSY); + while(FLASH->SR & FLASH_SR_BSY); if(FLASH->SR & FLASH_SR_WRPERR){ return 1; // write protection } @@ -130,14 +127,14 @@ static int write2flash(const void *start, const void *wrdata, uint32_t stor_size const uint16_t *data = (const uint16_t*) wrdata; volatile uint16_t *address = (volatile uint16_t*) start; uint32_t i, count = (stor_size + 1) / 2; - for (i = 0; i < count; ++i){ + for(i = 0; i < count; ++i){ IWDG->KR = IWDG_REFRESH; *(volatile uint16_t*)(address + i) = data[i]; while (FLASH->SR & FLASH_SR_BSY); - if(FLASH->SR & FLASH_SR_PGERR){ + if(FLASH->SR & FLASH_SR_PGERR){ ret = 1; // program error - meet not 0xffff break; - }else while (!(FLASH->SR & FLASH_SR_EOP)); + } FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR; } FLASH->CR |= FLASH_CR_LOCK; // lock it back @@ -162,41 +159,28 @@ static int erase_flash(const void *start, const void *end){ }else{ // erase a part flsz = (uint32_t)end - (uint32_t)start; } + if((FLASH->CR & FLASH_CR_LOCK) != 0){ + FLASH->KEYR = FLASH_KEY1; + FLASH->KEYR = FLASH_KEY2; + } nblocks = flsz / FLASH_blocksize; if(nblocks == 0 || nblocks >= FLASH_SIZE) return 1; for(uint32_t i = 0; i < nblocks; ++i){ IWDG->KR = IWDG_REFRESH; - /* (1) Wait till no operation is on going */ - /* (2) Clear error & EOP bits */ - /* (3) Check that the Flash is unlocked */ - /* (4) Perform unlock sequence */ - while ((FLASH->SR & FLASH_SR_BSY) != 0){} /* (1) */ - FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR; /* (2) */ - /* if (FLASH->SR & FLASH_SR_EOP){ - FLASH->SR |= FLASH_SR_EOP; - }*/ - if ((FLASH->CR & FLASH_CR_LOCK) != 0){ /* (3) */ - FLASH->KEYR = FLASH_KEY1; /* (4) */ - FLASH->KEYR = FLASH_KEY2; - } - /* (1) Set the PER bit in the FLASH_CR register to enable page erasing */ - /* (2) Program the FLASH_AR register to select a page to erase */ - /* (3) Set the STRT bit in the FLASH_CR register to start the erasing */ - /* (4) Wait until the EOP flag in the FLASH_SR register set */ - /* (5) Clear EOP flag by software by writing EOP at 1 */ - /* (6) Reset the PER Bit to disable the page erase */ - FLASH->CR |= FLASH_CR_PER; /* (1) */ - FLASH->AR = (uint32_t)Flash_Data + i*FLASH_blocksize; /* (2) */ - FLASH->CR |= FLASH_CR_STRT; /* (3) */ - while(!(FLASH->SR & FLASH_SR_EOP)); - FLASH->SR |= FLASH_SR_EOP; /* (5)*/ + while(FLASH->SR & FLASH_SR_BSY); + FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR; + FLASH->CR |= FLASH_CR_PER; + FLASH->AR = (uint32_t)Flash_Data + i*FLASH_blocksize; + FLASH->CR |= FLASH_CR_STRT; + while(FLASH->SR & FLASH_SR_BSY); + FLASH->SR = FLASH_SR_EOP; if(FLASH->SR & FLASH_SR_WRPERR){ /* Check Write protection error */ ret = 1; FLASH->SR |= FLASH_SR_WRPERR; /* Clear the flag by software by writing it at 1*/ break; } - FLASH->CR &= ~FLASH_CR_PER; /* (6) */ } + FLASH->CR &= ~FLASH_CR_PER; return ret; } @@ -204,7 +188,7 @@ int erase_storage(){ return erase_flash(Flash_Data, NULL); } -int fn_dumpconf(_U_ uint32_t hash, _U_ char *args){ // "dumpconf" (3271513185) +int fn_dumpconf(uint32_t _U_ hash, char _U_ *args){ // "dumpconf" (3271513185) #ifdef EBUG USB_sendstr("flashsize="); printu(FLASH_SIZE); USB_putbyte('*'); printu(FLASH_blocksize); USB_putbyte('='); printu(FLASH_SIZE*FLASH_blocksize); @@ -229,12 +213,6 @@ int fn_dumpconf(_U_ uint32_t hash, _U_ char *args){ // "dumpconf" (3271513185) printu(the_conf.minspd[i]); PROPNAME("maxsteps"); printu(the_conf.maxsteps[i]); - PROPNAME("encperrev"); - printu(the_conf.encrev[i]); - PROPNAME("encperstepmin"); - printu(the_conf.encperstepmin[i]); - PROPNAME("encperstepmax"); - printu(the_conf.encperstepmax[i]); PROPNAME("motflags"); printuhex(*((uint8_t*)&the_conf.motflags[i])); PROPNAME("eswreaction"); diff --git a/F3:F303/Multistepper/flash.h b/F3:F303/Multistepper/flash.h index 3ce14f6..e9523b5 100644 --- a/F3:F303/Multistepper/flash.h +++ b/F3:F303/Multistepper/flash.h @@ -38,14 +38,15 @@ #define FLASH_SIZE *((uint16_t*)FLASH_SIZE_REG) +#define MOTFLAGS_AMOUNT 6 // motor flags typedef struct{ 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 encreverse : 1; // bit1 - reversing encoder rotation - NOT USED HERE!!! + uint8_t haveencoder : 1; // bit2 - have encoder - NOT USED HERE!!! uint8_t donthold : 1; // bit3 - clear power @ stop (don't hold motor when stopped) uint8_t eswinv : 1; // bit4 - inverse end-switches - uint8_t keeppos : 1; // bit5 - keep current position (as servo motor) + uint8_t keeppos : 1; // bit5 - keep current position (as servo motor) - NOT USED HERE!!! } motflags_t; /* @@ -60,11 +61,9 @@ typedef struct __attribute__((packed, aligned(4))){ 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 - uint16_t encperstepmax[MOTORSNO]; // max amount of encoder ticks per one step motflags_t motflags[MOTORSNO]; // motor's flags uint8_t ESW_reaction[MOTORSNO]; // end-switches reaction (esw_react) + uint8_t isSPI; // ==1 if there's SPI drivers instead of UART } user_conf; extern user_conf the_conf; // global user config (read from FLASH to RAM) diff --git a/F3:F303/Multistepper/hardware.c b/F3:F303/Multistepper/hardware.c index c79e38a..3523aa5 100644 --- a/F3:F303/Multistepper/hardware.c +++ b/F3:F303/Multistepper/hardware.c @@ -46,6 +46,14 @@ const uint32_t ESWpins[MOTORSNO][ESWNO] = { {1<<7, 1<<8}, // 7 }; +// GPIO pins: PB11, PE15, PE14 +volatile GPIO_TypeDef *EXTports[EXTNO] = { + GPIOB, GPIOE, GPIOE +}; +const uint32_t EXTpins[EXTNO] = { + 1<<11, 1<<15, 1<<14 +}; + // motors: DIR/EN // EN: 0:PF10, 1:PE1, 2:PB6, 3:PD2, 4:PC9, 5:PD14, 6:PE13, 7:PB1 volatile GPIO_TypeDef *ENports[MOTORSNO] = { @@ -64,10 +72,17 @@ const uint8_t mottchannels[MOTORSNO] = {1,1,1,1,1,1,1,3}; static IRQn_Type motirqs[MOTORSNO] = { TIM15_IRQn, TIM16_IRQn, TIM17_IRQn, TIM2_IRQn, TIM8_CC_IRQn, TIM4_IRQn, TIM1_CC_IRQn, TIM3_IRQn}; -// state 1 - pressed, 0 - released (pin active is zero) -uint8_t ESW_state(uint8_t MOTno, uint8_t ESWno){ - uint8_t val = ((ESWports[MOTno][ESWno]->IDR & ESWpins[MOTno][ESWno]) ? 0 : 1); - if(the_conf.motflags[ESWno].eswinv) val = !val; +// return two bits: 0 - ESW0, 1 - ESW1 (if inactive -> 1; if active -> 0) +uint8_t ESW_state(uint8_t MOTno){ + uint8_t val = 0; + if(the_conf.isSPI){ // only ESW0 used + val = ((ESWports[MOTno][0]->IDR & ESWpins[MOTno][0]) ? 0 : 1); + if(the_conf.motflags[MOTno].eswinv) val ^= 1; + return val; + }else for(int i = 0; i < 2; ++i){ + val |= ((ESWports[MOTno][i]->IDR & ESWpins[MOTno][i]) ? 0 : 1) << i; + } + if(the_conf.motflags[MOTno].eswinv) val ^= 3; return val; } diff --git a/F3:F303/Multistepper/hardware.h b/F3:F303/Multistepper/hardware.h index 365af27..ab7f766 100644 --- a/F3:F303/Multistepper/hardware.h +++ b/F3:F303/Multistepper/hardware.h @@ -20,6 +20,11 @@ #include +// PCLK frequency +#ifndef PCLK +#define PCLK (48000000) +#endif + // motors' timer PSC = PCLK/Tfreq - 1, Tfreq=16MHz #define MOTORTIM_PSC (2) // minimal ARR value - 99 for 5000 steps per second @ 32 microsteps/step @@ -42,8 +47,22 @@ extern const uint32_t BTNpins[BTNSNO]; // state 1 - pressed, 0 - released (pin active is zero) #define BTN_state(x) ((BTNports[x]->IDR & BTNpins[x]) ? 0 : 1) -// motors amount +// motors: #define MOTORSNO (8) +extern volatile GPIO_TypeDef *ENports[MOTORSNO]; +extern const uint32_t ENpins[MOTORSNO]; +#define MOTOR_EN(x) do{ pin_clear(ENports[x], ENpins[x]); }while(0) +#define MOTOR_DIS(x) do{ pin_set(ENports[x], ENpins[x]); }while(0) +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) +// interval of velocity checking (10ms) +#define MOTCHKINTERVAL (10) +// maximal ticks of encoder per step +#define MAXENCTICKSPERSTEP (100) +// amount of full steps per revolution +#define STEPSPERREV (200) // Limit switches: 2 for each motor #define ESWNO (2) @@ -51,10 +70,20 @@ extern const uint32_t BTNpins[BTNSNO]; extern volatile GPIO_TypeDef *ESWports[MOTORSNO][ESWNO]; extern const uint32_t ESWpins[MOTORSNO][ESWNO]; +// extpins amount +#define EXTNO (3) +extern volatile GPIO_TypeDef *EXTports[EXTNO]; +extern const uint32_t EXTpins[EXTNO]; +#define EXT_SET(x) do{ pin_set(EXTports[x], EXTpins[x]); }while(0) +#define EXT_CLEAR(x) do{ pin_clear(EXTports[x], EXTpins[x]); }while(0) +#define EXT_TOGGLE(x) do{ pin_toggle(EXTports[x], EXTpins[x]); }while(0) +#define EXT_CHK(x) (pin_read(EXTports[x], EXTpins[x])) + +extern volatile TIM_TypeDef *mottimers[MOTORSNO]; extern volatile uint32_t Tms; -uint8_t ESW_state(uint8_t MOTno, uint8_t ESWno); +uint8_t ESW_state(uint8_t MOTno); uint8_t MSB(uint16_t val); void hw_setup(); diff --git a/F3:F303/Multistepper/hashgen/hdr.c b/F3:F303/Multistepper/hashgen/hdr.c index ee79f94..574f9a5 100644 --- a/F3:F303/Multistepper/hashgen/hdr.c +++ b/F3:F303/Multistepper/hashgen/hdr.c @@ -44,8 +44,6 @@ int fn_canspeed(_U_ uint32_t hash, _U_ char *args) WAL; // "canspeed" (54926599 int fn_canstat(_U_ uint32_t hash, _U_ char *args) WAL; // "canstat" (237384179) -int fn_delignlist(_U_ uint32_t hash, _U_ char *args) WAL; // "delignlist" (2235834164) - int fn_diagn(_U_ uint32_t hash, _U_ char *args) WAL; // "diagn" (2334137736) int fn_dumpcmd(_U_ uint32_t hash, _U_ char *args) WAL; // "dumpcmd" (1223955823) @@ -54,16 +52,10 @@ int fn_dumpconf(_U_ uint32_t hash, _U_ char *args) WAL; // "dumpconf" (32715131 int fn_dumperr(_U_ uint32_t hash, _U_ char *args) WAL; // "dumperr" (1223989764) +int fn_dumpmotflags(_U_ uint32_t hash, _U_ char *args) WAL; // "dumpmotflags" (36159640) + int fn_emstop(_U_ uint32_t hash, _U_ char *args) WAL; // "emstop" (2965919005) -int fn_encpos(_U_ uint32_t hash, _U_ char *args) WAL; // "encpos" (3208428301) - -int fn_encrev(_U_ uint32_t hash, _U_ char *args) WAL; // "encrev" (3208460296) - -int fn_encstepmax(_U_ uint32_t hash, _U_ char *args) WAL; // "encstepmax" (1022989757) - -int fn_encstepmin(_U_ uint32_t hash, _U_ char *args) WAL; // "encstepmin" (1022990779) - int fn_eraseflash(_U_ uint32_t hash, _U_ char *args) WAL; // "eraseflash" (3177247267) int fn_esw(_U_ uint32_t hash, _U_ char *args) WAL; // "esw" (2963094612) @@ -194,9 +186,6 @@ int parsecmd(const char *str){ case CMD_CANSTAT: return fn_canstat(h, args); break; - case CMD_DELIGNLIST: - return fn_delignlist(h, args); - break; case CMD_DIAGN: return fn_diagn(h, args); break; @@ -209,21 +198,12 @@ int parsecmd(const char *str){ case CMD_DUMPERR: return fn_dumperr(h, args); break; + case CMD_DUMPMOTFLAGS: + return fn_dumpmotflags(h, args); + break; case CMD_EMSTOP: return fn_emstop(h, args); break; - case CMD_ENCPOS: - return fn_encpos(h, args); - break; - case CMD_ENCREV: - return fn_encrev(h, args); - break; - case CMD_ENCSTEPMAX: - return fn_encstepmax(h, args); - break; - case CMD_ENCSTEPMIN: - return fn_encstepmin(h, args); - break; case CMD_ERASEFLASH: return fn_eraseflash(h, args); break; diff --git a/F3:F303/Multistepper/hashgen/hdr.h b/F3:F303/Multistepper/hashgen/hdr.h index 9d46183..d2fd0b9 100644 --- a/F3:F303/Multistepper/hashgen/hdr.h +++ b/F3:F303/Multistepper/hashgen/hdr.h @@ -30,16 +30,12 @@ int parsecmd(const char *cmdwargs); #define CMD_CANSEND (237136225) #define CMD_CANSPEED (549265992) #define CMD_CANSTAT (237384179) -#define CMD_DELIGNLIST (2235834164) #define CMD_DIAGN (2334137736) #define CMD_DUMPCMD (1223955823) #define CMD_DUMPCONF (3271513185) #define CMD_DUMPERR (1223989764) +#define CMD_DUMPMOTFLAGS (36159640) #define CMD_EMSTOP (2965919005) -#define CMD_ENCPOS (3208428301) -#define CMD_ENCREV (3208460296) -#define CMD_ENCSTEPMAX (1022989757) -#define CMD_ENCSTEPMIN (1022990779) #define CMD_ERASEFLASH (3177247267) #define CMD_ESW (2963094612) #define CMD_ESWREACT (1614224995) diff --git a/F3:F303/Multistepper/main.c b/F3:F303/Multistepper/main.c index 9153a29..1dcaab7 100644 --- a/F3:F303/Multistepper/main.c +++ b/F3:F303/Multistepper/main.c @@ -40,7 +40,7 @@ int main(void){ StartHSI(); SysTick_Config((uint32_t)48000); // 1ms } - flashstorage_init(); + //flashstorage_init(); hw_setup(); // GPIO, ADC, timers, watchdog etc. USBPU_OFF(); // make a reconnection USB_setup(); diff --git a/F3:F303/Multistepper/multistepper.bin b/F3:F303/Multistepper/multistepper.bin index 2dec223184bd2115daa10ec8e86c0a7f148f6383..68e9670c5e4f6c9c1206befe8db13f00a990acd5 100755 GIT binary patch delta 12630 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%0D_9D>>479p5_PW{-M^w6Dimq6sM= z<_jVG&Fmr;rSm4ep49VLmO7to~kNjA=+u)uJOjJ}ECguYv%qv<1uzp>1(X3(fGxpvZZwJ1y$XdE*p5nSP4+2F%91A? z^GizRKZo|tSL9{O=Q|cJT=K7aVJRWJGj|*x$j#zsJX{=h0-MGez&(Ng$HVcxA1_(D zWC70Z*B^oJu?-?r88;KEi+M+ubFAbGcYp^&tbFP!1LU! z!FYDgN`}Yy+3%|Ogn~Bb9()Bx`<36@kgI@d;0VwFoCeMUlyCv*<)BP;`UUy-Uz=m` zb(wx~rg`*Bb2^X>JOa!B3V>o@Ij|C_$i%k15dtl+ji&fNiHx5XdKJ!R2Qks<-@RWu zL;vpS?hyKSPmd+^@7|Al3olC$_pJ9M%f4v(ch3+*=-<8HeT4qq`(MSR & CAN_MSR_INAK){ USB_sendstr("CAN bus is off, try to restart it\n"); return RET_GOOD; @@ -305,7 +306,7 @@ int fn_cansend(_U_ uint32_t hash, char *args){ return RET_GOOD; } -int fn_canfloodt(_U_ uint32_t hash, char *args){ +int fn_canfloodt(uint32_t _U_ hash, char *args){ uint32_t N; const char *n = getnum(args, &N); if(args == n){ @@ -316,7 +317,7 @@ int fn_canfloodt(_U_ uint32_t hash, char *args){ return RET_GOOD; } -int fn_canstat(_U_ uint32_t hash, _U_ char *args){ +int fn_canstat(uint32_t _U_ hash, char _U_ *args){ USB_sendstr("CAN_MSR="); printuhex(CAN->MSR); USB_sendstr("\nCAN_TSR="); @@ -329,18 +330,18 @@ int fn_canstat(_U_ uint32_t hash, _U_ char *args){ return RET_GOOD; } -int fn_canerrcodes(_U_ uint32_t hash, _U_ char *args){ +int fn_canerrcodes(uint32_t _U_ hash, char _U_ *args){ CAN_printerr(); return RET_GOOD; } -int fn_canincrflood(_U_ uint32_t hash, _U_ char *args){ +int fn_canincrflood(uint32_t _U_ hash, char _U_ *args){ CAN_flood(NULL, 1); USB_sendstr("Incremental flooding is ON ('F' to off)\n"); return RET_GOOD; } -int fn_canspeed(_U_ uint32_t hash, _U_ char *args){ +int fn_canspeed(uint32_t _U_ hash, char _U_ *args){ uint32_t N; const char *n = getnum(args, &N); if(args == n){ @@ -363,20 +364,20 @@ int fn_canspeed(_U_ uint32_t hash, _U_ char *args){ return RET_GOOD; } -int fn_canpause(_U_ uint32_t hash, _U_ char *args){ +int fn_canpause(uint32_t _U_ hash, char _U_ *args){ ShowMsgs = TRUE; USND("Pause CAN messages"); return RET_GOOD; } -int fn_canresume(_U_ uint32_t hash, _U_ char *args){ +int fn_canresume(uint32_t _U_ hash, char _U_ *args){ ShowMsgs = FALSE; USND("RESUME CAN messages"); return RET_GOOD; } // dump base commands codes (for CAN protocol) -int fn_dumpcmd(_U_ uint32_t hash, _U_ char *args){ // "dumpcmd" (1223955823) +int fn_dumpcmd(uint32_t _U_ hash, char _U_ *args){ // "dumpcmd" (1223955823) USB_sendstr("CANbus commands list:\n"); for(uint16_t i = 1; i < CCMD_AMOUNT; ++i){ if(!cancmds[i]) continue; @@ -388,20 +389,48 @@ int fn_dumpcmd(_U_ uint32_t hash, _U_ char *args){ // "dumpcmd" (1223955823) return RET_GOOD; } -int fn_reset(_U_ uint32_t hash, _U_ char *args){ // "reset" (1907803304) +int fn_reset(uint32_t _U_ hash, char _U_ *args){ // "reset" (1907803304) USB_sendstr("Soft reset\n"); USB_sendall(); // wait until everything will gone NVIC_SystemReset(); return RET_GOOD; } -int fn_time(_U_ uint32_t hash, _U_ char *args){ // "time" (19148340) +int fn_time(uint32_t _U_ hash, char _U_ *args){ // "time" (19148340) USB_sendstr("Time (ms): "); printu(Tms); USB_putbyte('\n'); return RET_GOOD; } + +static const char* motfl[MOTFLAGS_AMOUNT] = { + "reverse - invert motor's rotation", + "[reserved]", + "[reserved]", + "donthold - clear motor's power after stop", + "eswinv - inverse end-switches (1->0 instead of 0->1)", + "[reserved]" +}; +static const char *eswfl[ESW_AMOUNT] = { + [ESW_IGNORE] = "ignore end-switches", + [ESW_ANYSTOP] = "stop @ esw in any moving direction", + [ESW_STOPMINUS] = "stop only when moving in given direction (e.g. to minus @ESW0)" +}; +int fn_dumpmotflags(uint32_t _U_ hash, char _U_ *args){ // "dumpmotflags" (36159640) + USB_sendstr("Motor flags:"); + for(int i = 0; i < MOTFLAGS_AMOUNT; ++i){ + USB_sendstr("\nbit"); printu(i); USB_sendstr(" - "); + USB_sendstr(motfl[i]); + } + USND("\nEnd-switches reaction:"); + for(int i = 0; i < ESW_AMOUNT; ++i){ + printu(i); USB_sendstr(" - "); + USB_sendstr(eswfl[i]); newline(); + } + return RET_GOOD; +} + static const char* errtxt[ERR_AMOUNT] = { [ERR_OK] = "all OK", [ERR_BADPAR] = "wrong parameter's value", @@ -410,7 +439,7 @@ static const char* errtxt[ERR_AMOUNT] = { [ERR_BADCMD] = "unknown command", [ERR_CANTRUN] = "temporary can't run given command", }; -int fn_dumperr(_U_ uint32_t hash, _U_ char *args){ // "dumperr" (1223989764) +int fn_dumperr(uint32_t _U_ hash, char _U_ *args){ // "dumperr" (1223989764) USND("Error codes:"); for(int i = 0; i < ERR_AMOUNT; ++i){ printu(i); USB_sendstr(" - "); @@ -419,7 +448,7 @@ int fn_dumperr(_U_ uint32_t hash, _U_ char *args){ // "dumperr" (1223989764) return RET_GOOD; } -int fn_canid(_U_ uint32_t hash, char *args){ // "canid" (2040257924) +int fn_canid(uint32_t _U_ hash, char *args){ // "canid" (2040257924) if(args && *args){ int good = FALSE; uint32_t N; @@ -442,6 +471,8 @@ static int canusb_function(uint32_t hash, char *args){ int32_t val = 0; uint8_t par = CANMESG_NOPAR; float f; + USB_sendstr("CMD: hash="); printu(hash); USB_sendstr(", args="); + USND(args); if(*args){ const char *n = getnum(args, &N); if(n != args){ // get parameter @@ -452,7 +483,7 @@ static int canusb_function(uint32_t hash, char *args){ par = (uint8_t) N; n = strchr(n, '='); if(n){ - const char *nxt = getnum(n, &N); + const char *nxt = getnum(n+1, &N); if(nxt != n){ // give flag issetter val = (int32_t) N; par |= SETTERFLAG; @@ -460,6 +491,8 @@ static int canusb_function(uint32_t hash, char *args){ } } } + USB_sendstr("par="); printuhex(par); + USB_sendstr(", val="); printi(val); newline(); switch(hash){ case CMD_PING: e = cu_ping(par, &val); @@ -521,7 +554,89 @@ static int canusb_function(uint32_t hash, char *args){ case CMD_ESW: e = cu_esw(par, &val); break; + case CMD_ERASEFLASH: + e = cu_eraseflash(par, &val); + break; + case CMD_ACCEL: + e = cu_accel(par, &val); + break; + case CMD_ABSPOS: + e = cu_abspos(par, &val); + break; + case CMD_DIAGN: + e = cu_diagn(par, &val); + break; + case CMD_EMSTOP: + e = cu_emstop(par, &val); + break; + case CMD_ESWREACT: + e = cu_eswreact(par, &val); + break; + case CMD_GOTO: + e = cu_goto(par, &val); + break; + case CMD_GOTOZ: + e = cu_gotoz(par, &val); + break; + case CMD_GPIO: + e = cu_gpio(par, &val); + break; + case CMD_GPIOCONF: + e = cu_gpioconf(par, &val); + break; + case CMD_MAXSPEED: + e = cu_maxspeed(par, &val); + break; + case CMD_MAXSTEPS: + e = cu_maxsteps(par, &val); + break; + case CMD_MICROSTEPS: + e = cu_microsteps(par, &val); + break; + case CMD_MINSPEED: + e = cu_minspeed(par, &val); + break; + case CMD_MOTFLAGS: + e = cu_motflags(par, &val); + break; + case CMD_MOTMUL: + e = cu_motmul(par, &val); + break; + case CMD_MOTREINIT: + e = cu_motreinit(par, &val); + break; + case CMD_RELPOS: + e = cu_relpos(par, &val); + break; + case CMD_RELSLOW: + e = cu_relslow(par, &val); + break; + case CMD_SAVECONF: + e = cu_saveconf(par, &val); + break; + case CMD_SCREEN: + e = cu_screen(par, &val); + break; + case CMD_SPEEDLIMIT: + e = cu_speedlimit(par, &val); + break; + case CMD_STATE: + e = cu_state(par, &val); + break; + case CMD_STOP: + e = cu_stop(par, &val); + break; + case CMD_TMCBUS: + e = cu_tmcbus(par, &val); + break; + case CMD_UDATA: + e = cu_udata(par, &val); + break; + case CMD_USARTSTATUS: + e = cu_usartstatus(par, &val); + break; default: + e = ERR_BADCMD; break; } @@ -541,40 +656,40 @@ static int canusb_function(uint32_t hash, char *args){ #define AL __attribute__ ((alias ("canusb_function"))) // COMMON with CAN -int fn_ping(_U_ uint32_t hash, _U_ char *args) AL; // "ping" (10561715) +int fn_ping(uint32_t _U_ hash, char _U_ *args) AL; // "ping" (10561715) // not realized yet -int fn_abspos(_U_ uint32_t hash, _U_ char *args) AL; //* "abspos" (3056382221) -int fn_accel(_U_ uint32_t hash, _U_ char *args) AL; //* "accel" (1490521981) -int fn_adc(_U_ uint32_t hash, _U_ char *args) AL; // "adc" (2963026093) -int fn_button(_U_ uint32_t hash, _U_ char *args) AL; // "button" (1093508897) -int fn_diagn(_U_ uint32_t hash, _U_ char *args) AL; //* "diagn" (2334137736) -int fn_emstop(_U_ uint32_t hash, _U_ char *args) AL; //* "emstop" (2965919005) -int fn_eraseflash(_U_ uint32_t hash, _U_ char *args) AL; //* "eraseflash" (3177247267) -int fn_esw(_U_ uint32_t hash, _U_ char *args) AL; // "esw" (2963094612) -int fn_eswreact(_U_ uint32_t hash, _U_ char *args) AL; //* "eswreact" (1614224995) -int fn_goto(_U_ uint32_t hash, _U_ char *args) AL; //* "goto" (4286309438) -int fn_gotoz(_U_ uint32_t hash, _U_ char *args) AL; //* "gotoz" (3178103736) -int fn_gpio(_U_ uint32_t hash, _U_ char *args) AL; //* "gpio" (4286324660) -int fn_gpioconf(_U_ uint32_t hash, _U_ char *args) AL; //* "gpioconf" (1309721562) -int fn_maxspeed(_U_ uint32_t hash, _U_ char *args) AL; //* "maxspeed" (1498078812) -int fn_maxsteps(_U_ uint32_t hash, _U_ char *args) AL; //* "maxsteps" (1506667002) -int fn_mcut(_U_ uint32_t hash, _U_ char *args) AL; // "mcut" (4022718) -int fn_mcuvdd(_U_ uint32_t hash, _U_ char *args) AL; // "mcuvdd" (2517587080) -int fn_microsteps(_U_ uint32_t hash, _U_ char *args) AL; //* "microsteps" (3974395854) -int fn_minspeed(_U_ uint32_t hash, _U_ char *args) AL; //* "minspeed" (3234848090) -int fn_motflags(_U_ uint32_t hash, _U_ char *args) AL; //* "motflags" (2153634658) -int fn_motmul(_U_ uint32_t hash, _U_ char *args) AL; //* "motmul" (1543400099) -int fn_motreinit(_U_ uint32_t hash, _U_ char *args) AL; //* "motreinit" (199682784) -int fn_relpos(_U_ uint32_t hash, _U_ char *args) AL; //* "relpos" (1278646042) -int fn_relslow(_U_ uint32_t hash, _U_ char *args) AL; //* "relslow" (1742971917) -int fn_saveconf(_U_ uint32_t hash, _U_ char *args) AL; //* "saveconf" (141102426) -int fn_screen(_U_ uint32_t hash, _U_ char *args) AL; //* "screen" (2100809349) -int fn_speedlimit(_U_ uint32_t hash, _U_ char *args) AL; //* "speedlimit" (1654184245) -int fn_state(_U_ uint32_t hash, _U_ char *args) AL; //* "state" (2216628902) -int fn_stop(_U_ uint32_t hash, _U_ char *args) AL; //* "stop" (17184971) -int fn_tmcbus(_U_ uint32_t hash, _U_ char *args) AL; //* "tmcbus" (1906135955) -int fn_udata(_U_ uint32_t hash, _U_ char *args) AL; //* "udata" (2736127636) -int fn_usartstatus(_U_ uint32_t hash, _U_ char *args) AL; //* "usartstatus" (4007098968) +int fn_abspos(uint32_t _U_ hash, char _U_ *args) AL; //* "abspos" (3056382221) +int fn_accel(uint32_t _U_ hash, char _U_ *args) AL; //* "accel" (1490521981) +int fn_adc(uint32_t _U_ hash, char _U_ *args) AL; // "adc" (2963026093) +int fn_button(uint32_t _U_ hash, char _U_ *args) AL; // "button" (1093508897) +int fn_diagn(uint32_t _U_ hash, char _U_ *args) AL; //* "diagn" (2334137736) +int fn_emstop(uint32_t _U_ hash, char _U_ *args) AL; //* "emstop" (2965919005) +int fn_eraseflash(uint32_t _U_ hash, char _U_ *args) AL; //* "eraseflash" (3177247267) +int fn_esw(uint32_t _U_ hash, char _U_ *args) AL; // "esw" (2963094612) +int fn_eswreact(uint32_t _U_ hash, char _U_ *args) AL; //* "eswreact" (1614224995) +int fn_goto(uint32_t _U_ hash, char _U_ *args) AL; //* "goto" (4286309438) +int fn_gotoz(uint32_t _U_ hash, char _U_ *args) AL; //* "gotoz" (3178103736) +int fn_gpio(uint32_t _U_ hash, char _U_ *args) AL; //* "gpio" (4286324660) +int fn_gpioconf(uint32_t _U_ hash, char _U_ *args) AL; //* "gpioconf" (1309721562) +int fn_maxspeed(uint32_t _U_ hash, char _U_ *args) AL; //* "maxspeed" (1498078812) +int fn_maxsteps(uint32_t _U_ hash, char _U_ *args) AL; //* "maxsteps" (1506667002) +int fn_mcut(uint32_t _U_ hash, char _U_ *args) AL; // "mcut" (4022718) +int fn_mcuvdd(uint32_t _U_ hash, char _U_ *args) AL; // "mcuvdd" (2517587080) +int fn_microsteps(uint32_t _U_ hash, char _U_ *args) AL; //* "microsteps" (3974395854) +int fn_minspeed(uint32_t _U_ hash, char _U_ *args) AL; //* "minspeed" (3234848090) +int fn_motflags(uint32_t _U_ hash, char _U_ *args) AL; //* "motflags" (2153634658) +int fn_motmul(uint32_t _U_ hash, char _U_ *args) AL; //* "motmul" (1543400099) +int fn_motreinit(uint32_t _U_ hash, char _U_ *args) AL; //* "motreinit" (199682784) +int fn_relpos(uint32_t _U_ hash, char _U_ *args) AL; //* "relpos" (1278646042) +int fn_relslow(uint32_t _U_ hash, char _U_ *args) AL; //* "relslow" (1742971917) +int fn_saveconf(uint32_t _U_ hash, char _U_ *args) AL; //* "saveconf" (141102426) +int fn_screen(uint32_t _U_ hash, char _U_ *args) AL; //* "screen" (2100809349) +int fn_speedlimit(uint32_t _U_ hash, char _U_ *args) AL; //* "speedlimit" (1654184245) +int fn_state(uint32_t _U_ hash, char _U_ *args) AL; //* "state" (2216628902) +int fn_stop(uint32_t _U_ hash, char _U_ *args) AL; //* "stop" (17184971) +int fn_tmcbus(uint32_t _U_ hash, char _U_ *args) AL; //* "tmcbus" (1906135955) +int fn_udata(uint32_t _U_ hash, char _U_ *args) AL; //* "udata" (2736127636) +int fn_usartstatus(uint32_t _U_ hash, char _U_ *args) AL; //* "usartstatus" (4007098968) /** diff --git a/F3:F303/Multistepper/steppers.c b/F3:F303/Multistepper/steppers.c new file mode 100644 index 0000000..53abeab --- /dev/null +++ b/F3:F303/Multistepper/steppers.c @@ -0,0 +1,470 @@ +/* + * This file is part of the multistepper project. + * Copyright 2023 Edward V. Emelianov . + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "flash.h" +#include "hardware.h" +#include "proto.h" +#include "steppers.h" +#include "strfunc.h" +#include "usb.h" + +// goto zero stages +typedef enum{ + M0RELAX, // normal moving + M0FAST, // fast move to zero + M0SLOW // slowest move from ESW +} mvto0state; + +typedef enum{ + STALL_NO, // moving OK + STALL_ONCE, // Nstalled < limit + STALL_STOP // Nstalled >= limit +} t_stalled; + +#ifdef EBUG +static uint8_t stp[MOTORSNO] = {0}; +#endif + +static t_stalled stallflags[MOTORSNO]; + +// motors' direction: 1 for positive, -1 for negative (we need it as could be reverse) +static int8_t motdir[MOTORSNO]; +// direction of moving when stalled (forbid moving in that direction before go out of position) +static int8_t stalleddir[MOTORSNO] = {0}; +// current position (in steps) by STP counter +static volatile int32_t stppos[MOTORSNO] = {0}; +// previous position when check (set to current in start of moving) +static int32_t prevstppos[MOTORSNO]; +// target stepper position +static int32_t targstppos[MOTORSNO] = {0}; +// position to start deceleration +static int32_t decelstartpos[MOTORSNO]; +// ESW reaction - local copy +static uint8_t ESW_reaction[MOTORSNO]; + +// current speed +static uint16_t curspeed[MOTORSNO]; +static uint16_t startspeed[MOTORSNO]; // speed when deceleration starts +// ==1 to stop @ nearest step +static uint8_t stopflag[MOTORSNO]; +// motor state +static stp_state state[MOTORSNO]; +// move to zero state +static mvto0state mvzerostate[MOTORSNO]; + +static int8_t Nstalled[MOTORSNO] = {0}; // counter of STALL + +// lowest ARR value (highest speed), highest (lowest speed) +//static uint16_t stphighARR[MOTORSNO]; +// microsteps=1<> 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 +} + +// run this function after each steppers parameters changing +void init_steppers(){ + // init variables + for(int i = 0; i < MOTORSNO; ++i){ + stalleddir[i] = 0; // clear old stall direction + stopflag[i] = 0; + motdir[i] = 0; + curspeed[i] = 0; + 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]); + if(!the_conf.motflags[i].donthold) MOTOR_EN(i); + else MOTOR_DIS(i); + ESW_reaction[i] = the_conf.ESW_reaction[i]; + } +} + +// set absolute position of motor `i` +errcodes setmotpos(uint8_t i, int32_t position){ + if(state[i] != STP_RELAX) return ERR_CANTRUN; + if(position > (int32_t)the_conf.maxsteps[i] || position < -(int32_t)the_conf.maxsteps[i]) + return ERR_BADVAL; // too big position or zero + if(position == stppos[i]) return ERR_OK; + return ERR_OK; +} + +// get current position +errcodes getpos(uint8_t i, int32_t *position){ + *position = stppos[i]; + return ERR_OK; +} + +errcodes getremainsteps(uint8_t i, int32_t *position){ + *position = targstppos[i] - stppos[i]; + return ERR_OK; +} + +// calculate acceleration/deceleration parameters for motor i +static void calcacceleration(uint8_t i){ + switch(state[i]){ // do nothing in case of error/stopping + case STP_ERR: + case STP_RELAX: + case STP_STALL: + return; + break; + default: + break; + } + int32_t delta = targstppos[i] - stppos[i]; + if(delta > 0){ // positive direction + if(delta > 2*(int32_t)accdecsteps[i]){ // can move by trapezoid + decelstartpos[i] = targstppos[i] - accdecsteps[i]; + }else{ // triangle speed profile + decelstartpos[i] = stppos[i] + delta/2; + } + if(the_conf.motflags[i].reverse) MOTOR_CCW(i); + else MOTOR_CW(i); + }else{ // negative direction + delta = -delta; + if(delta > 2*(int32_t)accdecsteps[i]){ // can move by trapezoid + decelstartpos[i] = targstppos[i] + accdecsteps[i]; + }else{ // triangle speed profile + decelstartpos[i] = stppos[i] - delta/2; + } + if(the_conf.motflags[i].reverse) MOTOR_CW(i); + else MOTOR_CCW(i); + } + if(state[i] != STP_MVSLOW){ + DBG("->accel"); + state[i] = STP_ACCEL; + } + startspeed[i] = curspeed[i]; + Taccel[i] = Tms; + recalcARR(i); +} + +// check if end-switch is blocking the moving of i'th motor +// @return TRUE if motor can't move +static int esw_block(uint8_t i){ + int ret = FALSE; + uint8_t s = ESW_state(i); + if(s){ // ESW active + switch(ESW_reaction[i]){ + case ESW_ANYSTOP: // stop motor in any direction + ret = TRUE; + break; + case ESW_STOPMINUS: // stop only @ given direction + if(motdir[i] == -1 && (s & 1)) ret = TRUE; // stop @ESW0 + if(motdir[i] == 1 && (s & 3)) ret = TRUE; // stop @ESW1 + break; + default: // ESW_IGNORE + break; + } + } + return ret; +} + +// move to absolute position +errcodes motor_absmove(uint8_t i, int32_t newpos){ + //if(i >= MOTORSNO) return ERR_BADPAR; // bad motor number + int8_t dir = (newpos > stppos[i]) ? 1 : -1; + switch(state[i]){ + case STP_ERR: + case STP_RELAX: + break; + case STP_STALL: + DBG("Move from STALL"); + if(dir == stalleddir[i]){ + DBG("Move to stalled direction!"); + return ERR_CANTRUN; // can't run into stalled direction + } + break; + default: // moving state + DBG("Is moving"); + return ERR_CANTRUN; + } + if(newpos > (int32_t)the_conf.maxsteps[i] || newpos < -(int32_t)the_conf.maxsteps[i] || newpos == stppos[i]){ + DBG("Too much steps"); + return ERR_BADVAL; // too big position or zero + } + motdir[i] = dir; // should be before limit switch check + if(esw_block(i)){ + DBG("Block by ESW"); + return ERR_CANTRUN; // on end-switch + } + Nstalled[i] = (state[i] == STP_STALL) ? -(NSTALLEDMAX*4) : 0; // give some more chances to go out of stall state + stopflag[i] = 0; + targstppos[i] = newpos; + prevstppos[i] = stppos[i]; + curspeed[i] = the_conf.minspd[i]; + state[i] = STP_ACCEL; + calcacceleration(i); +#ifdef EBUG + USND("MOTOR"); USB_putbyte('0'+i); + USND(" targstppos="); printi(targstppos[i]); + USND(", decelstart="); printi(decelstartpos[i]); + USND(", accdecsteps="); printu(accdecsteps[i]); newline(); +#endif + MOTOR_EN(i); + mottimers[i]->CR1 |= TIM_CR1_CEN; // start timer + return ERR_OK; +} + +// move i'th motor for relsteps +errcodes motor_relmove(uint8_t i, int32_t relsteps){ + return motor_absmove(i, stppos[i] + relsteps); +} + +errcodes motor_relslow(uint8_t i, int32_t relsteps){ + errcodes e = motor_absmove(i, stppos[i] + relsteps); + if(ERR_OK == e){ + DBG("-> MVSLOW"); + state[i] = STP_MVSLOW; + } + return e; +} + +// emergency stop and clear errors +void emstopmotor(uint8_t i){ + switch(state[i]){ + case STP_ERR: // clear error state + case STP_STALL: + DBG("-> RELAX"); + state[i] = STP_RELAX; + // fallthrough + case STP_RELAX: // do nothing in stopping state + return; + default: + break; + } + stopflag[i] = 1; +} + +stp_state getmotstate(uint8_t i){ + return state[i]; +} + +// count steps @tim 14/15/16 +void addmicrostep(uint8_t i){ + static volatile uint16_t microsteps[MOTORSNO] = {0}; // current microsteps position + if(esw_block(i)) stopflag[i] = 1; // turn on stop flag if end-switch was active + if(++microsteps[i] == the_conf.microsteps[i]){ + microsteps[i] = 0; + stppos[i] += motdir[i]; + uint8_t stop_at_pos = 0; + if(motdir[i] > 0){ + if(stppos[i] >= targstppos[i]){ // reached stop position + stop_at_pos = 1; + } + }else{ + if(stppos[i] <= targstppos[i]){ + stop_at_pos = 1; + } + } + if(stopflag[i] || stop_at_pos){ // stop NOW + mottimers[i]->CR1 &= ~TIM_CR1_CEN; // stop timer + if(stopflag[i]) targstppos[i] = stppos[i]; // keep position (for keep flag) + stopflag[i] = 0; + if(the_conf.motflags[i].donthold) + MOTOR_DIS(i); // turn off power + if(stallflags[i] == STALL_STOP){ + stallflags[i] = STALL_NO; + state[i] = STP_STALL; + }else{ + state[i] = STP_RELAX; + } +#ifdef EBUG + stp[i] = 1; +#endif + } + } +} + +#ifdef EBUG +#define TODECEL() do{state[i] = STP_DECEL; \ + startspeed[i] = curspeed[i]; \ + Taccel[i] = Tms; \ + USND("MOTOR"); USB_putbyte('0'+i); \ + USND(" -> DECEL@"); printi(stppos[i]); USND(", V="); printu(curspeed[i]); newline(); \ + }while(0) +#else +#define TODECEL() do{state[i] = STP_DECEL; \ + startspeed[i] = curspeed[i]; \ + Taccel[i] = Tms; \ + }while(0) +#endif + +// check state of i`th stepper +static void chkstepper(int i){ + int32_t i32; + static uint8_t stopctr[MOTORSNO] = {0}; // counters for encoders/position zeroing after stopping @ esw +#ifdef EBUG + if(stp[i]){ + stp[i] = 0; + // motor state could be changed outside of interrupt, so return it to relax or leave in STALL + state[i] = STP_RELAX; + USND("MOTOR"); USB_putbyte('0'+i); USND(" stop @"); printi(stppos[i]); + USND(", curstate="); printu(state[i]); newline(); + } +#endif + switch(state[i]){ + case STP_ACCEL: // acceleration to max speed + //newspeed = curspeed[i] + dV[i]; + i32 = the_conf.minspd[i] + (the_conf.accel[i] * (Tms - Taccel[i])) / 1000; + if(i32 >= the_conf.maxspd[i]){ // max speed reached -> move with it + curspeed[i] = the_conf.maxspd[i]; + state[i] = STP_MOVE; +#ifdef EBUG + USND("MOTOR"); USB_putbyte('0'+i); + USND(" -> MOVE@"); printi(stppos[i]); USND(", V="); printu(curspeed[i]); newline(); +#endif + }else{ // increase speed + curspeed[i] = i32; + } + recalcARR(i); + // check position for triangle profile + if(motdir[i] > 0){ + if(stppos[i] >= decelstartpos[i]){ // reached end of acceleration + TODECEL(); + } + }else{ + if(stppos[i] <= decelstartpos[i]){ + TODECEL(); + } + } + break; + case STP_MOVE: // move @ constant speed until need to decelerate + // check position + if(motdir[i] > 0){ + if(stppos[i] >= decelstartpos[i]){ // reached start of deceleration + TODECEL(); + } + }else{ + if(stppos[i] <= decelstartpos[i]){ + TODECEL(); + } + } + break; + case STP_DECEL: + //newspeed = curspeed[i] - dV[i]; + i32 = startspeed[i] - (the_conf.accel[i] * (Tms - Taccel[i])) / 1000; + if(i32 > the_conf.minspd[i]){ + curspeed[i] = i32; + }else{ + curspeed[i] = the_conf.minspd[i]; + state[i] = STP_MVSLOW; +#ifdef EBUG + USND("MOTOR"); USB_putbyte('0'+i); + USND(" -> MVSLOW@"); printi(stppos[i]); newline(); +#endif + } + recalcARR(i); + break; + default: // do nothing, check mvzerostate + break; + } + switch(mvzerostate[i]){ + case M0FAST: + if(state[i] == STP_RELAX || state[i] == STP_STALL){ // stopped -> move to + +#ifdef EBUG + USB_putbyte('M'); USB_putbyte('0'+i); USND("FAST: motor stopped\n"); +#endif + if(ERR_OK != motor_relslow(i, 1000)){ +#ifdef EBUG + USND("Can't move\n"); +#endif + DBG("->ERR"); + state[i] = STP_ERR; + mvzerostate[i] = M0RELAX; + ESW_reaction[i] = the_conf.ESW_reaction[i]; + }else{ + mvzerostate[i] = M0SLOW; + stopctr[i] = 0; + } + } + break; + case M0SLOW: + if(0 == ESW_state(i)){ // moved out of limit switch - can stop + emstopmotor(i); + } + if((state[i] == STP_RELAX || state[i] == STP_STALL) && ++stopctr[i] > 5){ // wait at least 50ms +#ifdef EBUG + USB_putbyte('M'); USB_putbyte('0'+i); USND("SLOW: motor stopped\n"); +#endif + ESW_reaction[i] = the_conf.ESW_reaction[i]; + prevstppos[i] = targstppos[i] = stppos[i] = 0; + mvzerostate[i] = M0RELAX; + } + break; + default: // RELAX, STALL: do nothing + break; + } +} + +errcodes motor_goto0(uint8_t i){ + errcodes e = motor_absmove(i, -the_conf.maxsteps[i]); + if(ERR_OK != e){ + if(!ESW_state(i)) return e; // not @ limit switch -> error + }else ESW_reaction[i] = ESW_STOPMINUS; + mvzerostate[i] = M0FAST; + return e; +} + +// smooth motor stopping +void stopmotor(uint8_t i){ + switch(state[i]){ + case STP_MVSLOW: // immeditially stop on slowest speed + stopflag[i] = 1; + return; + break; + case STP_MOVE: // stop only in moving states + case STP_ACCEL: + break; + default: // do nothing in other states + return; + } + int32_t newstoppos = stppos[i]; // calculate steps need for stop (we can be @acceleration phase!) + int32_t add = (curspeed[i] * curspeed[i]) / the_conf.accel[i] / 2; + if(motdir[i] > 0){ + newstoppos += add; + if(newstoppos < (int32_t)the_conf.maxsteps[i]) targstppos[i] = newstoppos; + }else{ + newstoppos -= add; + if(newstoppos > -((int32_t)the_conf.maxsteps[i])) targstppos[i] = newstoppos; + } + TODECEL(); +} + +void process_steppers(){ + static uint32_t Tlast = 0; + if(Tms - Tlast < MOTCHKINTERVAL) return; // hit every 10ms + Tlast = Tms; + for(int i = 0; i < MOTORSNO; ++i){ + chkstepper(i); + } +} + +uint8_t geteswreact(uint8_t i){ + return ESW_reaction[i]; +} diff --git a/F3:F303/Multistepper/steppers.h b/F3:F303/Multistepper/steppers.h index 1b82651..044906d 100644 --- a/F3:F303/Multistepper/steppers.h +++ b/F3:F303/Multistepper/steppers.h @@ -35,7 +35,7 @@ typedef enum{ STP_MOVE, // 2 - moving with constant speed STP_MVSLOW, // 3 - moving with slowest constant speed (end of moving) STP_DECEL, // 4 - moving with deceleration - STP_STALL, // 5 - stalled + STP_STALL, // 5 - stalled (UNUSED) STP_ERR // 6 - wrong/error state } stp_state; @@ -43,18 +43,15 @@ typedef enum{ enum{ ESW_IGNORE, // don't stop @ end-switch ESW_ANYSTOP, // stop @ esw in any moving direction - ESW_STOPMINUS, // stop only in negative moving + ESW_STOPMINUS, // stop only when moving in given direction (e.g. to minus @ESW0) ESW_AMOUNT // number of records }; // find zero stages: fast -> 0, slow -> +, slow -> 0 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 setmotpos(uint8_t i, int32_t position); errcodes getpos(uint8_t i, int32_t *position); diff --git a/F3:F303/Multistepper/usb.c b/F3:F303/Multistepper/usb.c index 73e5eea..590a33e 100644 --- a/F3:F303/Multistepper/usb.c +++ b/F3:F303/Multistepper/usb.c @@ -171,6 +171,7 @@ void USB_proc(){ } break; default: // USB_STATE_CONNECTED - send next data portion - if(!usbON) return; + // if(!usbON) return; // WTF? + break; } } diff --git a/F3:F303/Multistepper/version.inc b/F3:F303/Multistepper/version.inc index f3c69a2..d7eede4 100644 --- a/F3:F303/Multistepper/version.inc +++ b/F3:F303/Multistepper/version.inc @@ -1,2 +1,2 @@ -#define BUILD_NUMBER "30" -#define BUILD_DATE "2023-02-16" +#define BUILD_NUMBER "54" +#define BUILD_DATE "2023-02-20"