fixed bugs in multistepper: eeprom in flash + adc, tested on TMC2130, but don't work on TMC2230

This commit is contained in:
Edward Emelianov
2023-02-24 23:29:34 +03:00
parent 1a8345d4f0
commit 59d8f8f515
18 changed files with 172 additions and 130 deletions

View File

@@ -175,10 +175,10 @@ static int erase_flash(const void *start, const void *end){
FLASH->AR = (uint32_t)Flash_Data + i * blocksize; FLASH->AR = (uint32_t)Flash_Data + i * blocksize;
FLASH->CR |= FLASH_CR_STRT; FLASH->CR |= FLASH_CR_STRT;
while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH; while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH;
FLASH->SR |= FLASH_SR_EOP; FLASH->SR = FLASH_SR_EOP;
if(FLASH->SR & FLASH_SR_WRPRTERR){ if(FLASH->SR & FLASH_SR_WRPRTERR){
ret = 1; ret = 1;
FLASH->SR |= FLASH_SR_WRPRTERR; FLASH->SR = FLASH_SR_WRPRTERR;
break; break;
} }
} }

View File

@@ -77,7 +77,7 @@ void adc_setup(){
// ADC1: channels 1,2,3,4,16,18; ADC2: channels 1,10 // ADC1: channels 1,2,3,4,16,18; ADC2: channels 1,10
ADC1->SMPR1 = ADC_SMPR1_SMP1 | ADC_SMPR1_SMP2 | ADC_SMPR1_SMP3 | ADC_SMPR1_SMP4; ADC1->SMPR1 = ADC_SMPR1_SMP1 | ADC_SMPR1_SMP2 | ADC_SMPR1_SMP3 | ADC_SMPR1_SMP4;
ADC1->SMPR2 = ADC_SMPR2_SMP16 | ADC_SMPR2_SMP18; ADC1->SMPR2 = ADC_SMPR2_SMP16 | ADC_SMPR2_SMP18;
// 4 conversions in group: 1->2->3->4->16->18 // 6 conversions in group: 1->2->3->4->16->18
ADC1->SQR1 = (1<<6) | (2<<12) | (3<<18) | (4<<24) | (NUMBER_OF_ADC1_CHANNELS-1); ADC1->SQR1 = (1<<6) | (2<<12) | (3<<18) | (4<<24) | (NUMBER_OF_ADC1_CHANNELS-1);
ADC1->SQR2 = (16<<0) | (18<<6); ADC1->SQR2 = (16<<0) | (18<<6);
ADC2->SMPR1 = ADC_SMPR1_SMP1; ADC2->SMPR1 = ADC_SMPR1_SMP1;
@@ -134,8 +134,7 @@ uint16_t getADCval(int nch){
// get voltage @input nch (V) // get voltage @input nch (V)
float getADCvoltage(int nch){ float getADCvoltage(int nch){
float v = getADCval(nch); float v = getADCval(nch) * 3.3;
v *= getVdd();
v /= 4096.f; // 12bit ADC v /= 4096.f; // 12bit ADC
#ifdef EBUG #ifdef EBUG
DBG("v="); printf(v); newline(); DBG("v="); printf(v); newline();
@@ -157,7 +156,7 @@ float getMCUtemp(){
return(temperature); return(temperature);
} }
// return Vdd (V) // return ADC Vref (V)
float getVdd(){ float getVdd(){
float vdd = ((float) *VREFINT_CAL_ADDR) * 3.3f; // 3.3V float vdd = ((float) *VREFINT_CAL_ADDR) * 3.3f; // 3.3V
vdd /= getADCval(ADC_VREF); vdd /= getADCval(ADC_VREF);

View File

@@ -55,17 +55,18 @@ errcodes cu_accel(uint8_t _U_ par, int32_t _U_ *val){
if(ISSETTER(par)){ if(ISSETTER(par)){
if(*val/the_conf.microsteps[n] > ACCELMAXSTEPS || *val < 1) return ERR_BADVAL; if(*val/the_conf.microsteps[n] > ACCELMAXSTEPS || *val < 1) return ERR_BADVAL;
the_conf.accel[n] = *val; the_conf.accel[n] = *val;
update_stepper(n);
} }
*val = the_conf.accel[n]; *val = the_conf.accel[n];
return ERR_OK; return ERR_OK;
} }
static const uint8_t extADCchnl[NUMBER_OF_EXT_ADC_CHANNELS] = {ADC_AIN0, ADC_AIN1, ADC_AIN2, ADC_AIN3}; static const uint8_t extADCchnl[NUMBER_OF_EXT_ADC_CHANNELS] = {ADC_AIN0, ADC_AIN1, ADC_AIN2, ADC_AIN3};
// V*10 // V*100
errcodes cu_adc(uint8_t par, int32_t *val){ errcodes cu_adc(uint8_t par, int32_t *val){
uint8_t n = PARBASE(par); uint8_t n = PARBASE(par);
if(n > NUMBER_OF_EXT_ADC_CHANNELS - 1) return ERR_BADPAR; if(n > NUMBER_OF_EXT_ADC_CHANNELS - 1) return ERR_BADPAR;
float v = getADCvoltage(extADCchnl[n])*10.f; float v = getADCvoltage(extADCchnl[n])*100.f;
*val = (int32_t)v; *val = (int32_t)v;
return ERR_OK; return ERR_OK;
} }
@@ -93,7 +94,9 @@ errcodes cu_emstop(uint8_t _U_ par, int32_t _U_ *val){
errcodes cu_eraseflash(uint8_t _U_ par, int32_t _U_ *val){ errcodes cu_eraseflash(uint8_t _U_ par, int32_t _U_ *val){
NOPARCHK(par); NOPARCHK(par);
if(erase_storage()) return ERR_CANTRUN; if(ISSETTER(par)){
if(erase_storage(*val)) return ERR_BADVAL;
}else if(erase_storage(-1)) return ERR_CANTRUN;
return ERR_OK; return ERR_OK;
} }
@@ -109,6 +112,7 @@ errcodes cu_eswreact(uint8_t _U_ par, int32_t _U_ *val){
if(ISSETTER(par)){ if(ISSETTER(par)){
if(*val < 0 || *val > ESW_AMOUNT-1) return ERR_BADVAL; if(*val < 0 || *val > ESW_AMOUNT-1) return ERR_BADVAL;
the_conf.ESW_reaction[n] = *val; the_conf.ESW_reaction[n] = *val;
update_stepper(n);
} }
*val = geteswreact(n); *val = geteswreact(n);
return ERR_OK; return ERR_OK;
@@ -188,6 +192,7 @@ errcodes cu_maxspeed(uint8_t _U_ par, int32_t _U_ *val){
if(ISSETTER(par)){ if(ISSETTER(par)){
if(*val <= the_conf.minspd[n]) return ERR_BADVAL; if(*val <= the_conf.minspd[n]) return ERR_BADVAL;
the_conf.maxspd[n] = getSPD(n, *val); the_conf.maxspd[n] = getSPD(n, *val);
update_stepper(n);
} }
*val = the_conf.maxspd[n]; *val = the_conf.maxspd[n];
return ERR_OK; return ERR_OK;
@@ -229,6 +234,7 @@ errcodes cu_microsteps(uint8_t _U_ par, int32_t _U_ *val){
if(m != 1<<MSB(m)) return ERR_BADVAL; if(m != 1<<MSB(m)) return ERR_BADVAL;
if(the_conf.maxspd[n] * m > PCLK/(MOTORTIM_PSC+1)/(MOTORTIM_ARRMIN+1)) return ERR_BADVAL; if(the_conf.maxspd[n] * m > PCLK/(MOTORTIM_PSC+1)/(MOTORTIM_ARRMIN+1)) return ERR_BADVAL;
the_conf.microsteps[n] = m; the_conf.microsteps[n] = m;
update_stepper(n);
} }
*val = the_conf.microsteps[n]; *val = the_conf.microsteps[n];
return ERR_OK; return ERR_OK;
@@ -239,6 +245,7 @@ errcodes cu_minspeed(uint8_t _U_ par, int32_t _U_ *val){
if(ISSETTER(par)){ if(ISSETTER(par)){
if(*val >= the_conf.maxspd[n]) return ERR_BADVAL; if(*val >= the_conf.maxspd[n]) return ERR_BADVAL;
the_conf.minspd[n] = getSPD(n, *val); the_conf.minspd[n] = getSPD(n, *val);
update_stepper(n);
} }
*val = the_conf.minspd[n]; *val = the_conf.minspd[n];
return ERR_OK; return ERR_OK;
@@ -248,6 +255,7 @@ errcodes cu_motflags(uint8_t _U_ par, int32_t _U_ *val){
uint8_t n; CHECKN(n, par); uint8_t n; CHECKN(n, par);
if(ISSETTER(par)){ if(ISSETTER(par)){
the_conf.motflags[n] = *((motflags_t*)val); the_conf.motflags[n] = *((motflags_t*)val);
update_stepper(n);
} }
*(motflags_t*)val = the_conf.motflags[n]; *(motflags_t*)val = the_conf.motflags[n];
return ERR_OK; return ERR_OK;
@@ -334,14 +342,14 @@ errcodes cu_usartstatus(uint8_t _U_ par, int32_t _U_ *val){
// V*10 // V*10
errcodes cu_vdrive(uint8_t par, int32_t _U_ *val){ errcodes cu_vdrive(uint8_t par, int32_t _U_ *val){
NOPARCHK(par); NOPARCHK(par);
float v = getADCvoltage(ADC_VDRIVE)*100.f; float v = getADCvoltage(ADC_VDRIVE)*1000.f;
*val = (int32_t)v; *val = (int32_t)v;
return ERR_OK; return ERR_OK;
} }
errcodes cu_vfive(uint8_t par, int32_t *val){ errcodes cu_vfive(uint8_t par, int32_t *val){
NOPARCHK(par); NOPARCHK(par);
float v = getADCvoltage(ADC_VFIVE)*20.f; float v = getADCvoltage(ADC_VFIVE)*200.f;
*val = (int32_t)v; *val = (int32_t)v;
return ERR_OK; return ERR_OK;
} }

View File

@@ -46,7 +46,7 @@ static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here
,.motflags = {DEFMF,DEFMF,DEFMF,DEFMF,DEFMF,DEFMF,DEFMF,DEFMF} \ ,.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} \ ,.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); static int write2flash(const void*, const void*, uint32_t);
// don't write `static` here, or get error: // don't write `static` here, or get error:
// 'memcpy' forming offset 8 is out of the bounds [0, 4] of object '__varsstart' with type 'uint32_t' // 'memcpy' forming offset 8 is out of the bounds [0, 4] of object '__varsstart' with type 'uint32_t'
@@ -89,7 +89,7 @@ static int binarySearch(int r, const uint8_t *start, int stor_size){
*/ */
void flashstorage_init(){ void flashstorage_init(){
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){ if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
uint32_t flsz = FLASH_SIZE * FLASH_blocksize; // size in bytes uint32_t flsz = FLASH_SIZE * 1024; // size in bytes
flsz -= (uint32_t)(&__varsstart) - FLASH_BASE; flsz -= (uint32_t)(&__varsstart) - FLASH_BASE;
maxCnum = flsz / sizeof(user_conf); maxCnum = flsz / sizeof(user_conf);
} }
@@ -107,7 +107,7 @@ int store_userconf(){
// for binarySearch() checking that there's nothing more after it! // for binarySearch() checking that there's nothing more after it!
if(currentconfidx > (int)maxCnum - 3){ // there's no more place if(currentconfidx > (int)maxCnum - 3){ // there's no more place
currentconfidx = 0; currentconfidx = 0;
if(erase_flash(Flash_Data, NULL)) return 1; if(erase_storage(-1)) return 1;
}else ++currentconfidx; // take next data position (0 - within first run after firmware flashing) }else ++currentconfidx; // take next data position (0 - within first run after firmware flashing)
return write2flash((const void*)&Flash_Data[currentconfidx], &the_conf, sizeof(the_conf)); return write2flash((const void*)&Flash_Data[currentconfidx], &the_conf, sizeof(the_conf));
} }
@@ -118,65 +118,81 @@ static int write2flash(const void *start, const void *wrdata, uint32_t stor_size
FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2; FLASH->KEYR = FLASH_KEY2;
} }
while(FLASH->SR & FLASH_SR_BSY); while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH;
if(FLASH->SR & FLASH_SR_WRPERR){
return 1; // write protection
}
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR; // clear all flags FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR; // clear all flags
FLASH->CR |= FLASH_CR_PG; FLASH->CR |= FLASH_CR_PG;
const uint16_t *data = (const uint16_t*) wrdata; const uint16_t *data = (const uint16_t*) wrdata;
volatile uint16_t *address = (volatile uint16_t*) start; volatile uint16_t *address = (volatile uint16_t*) start;
USB_sendstr("Start address="); printuhex((uint32_t)start); newline();
uint32_t i, count = (stor_size + 1) / 2; uint32_t i, count = (stor_size + 1) / 2;
for(i = 0; i < count; ++i){ for(i = 0; i < count; ++i){
IWDG->KR = IWDG_REFRESH; IWDG->KR = IWDG_REFRESH;
*(volatile uint16_t*)(address + i) = data[i]; *(volatile uint16_t*)(address + i) = data[i];
while (FLASH->SR & FLASH_SR_BSY); while (FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH;
if(*(volatile uint16_t*)(address + i) != data[i]){
USB_sendstr("DON'T MATCH!\n");
ret = 1;
break;
}
#ifdef EBUG
else{ USB_sendstr("Written "); printuhex(data[i]); newline();}
#endif
if(FLASH->SR & FLASH_SR_PGERR){ if(FLASH->SR & FLASH_SR_PGERR){
USB_sendstr("Prog err\n");
ret = 1; // program error - meet not 0xffff ret = 1; // program error - meet not 0xffff
break; break;
} }
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR; FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR;
} }
FLASH->CR |= FLASH_CR_LOCK; // lock it back
FLASH->CR &= ~(FLASH_CR_PG); FLASH->CR &= ~(FLASH_CR_PG);
return ret; return ret;
} }
/** // erase Nth page of flash storage (flash should be prepared!)
* @brief erase_flash - erase N pages of flash memory static int erase_pageN(int N){
* @param start - first address
* @param end - last address (or NULL if need to erase all flash remaining)
* @return 0 if succeed
*/
static int erase_flash(const void *start, const void *end){
int ret = 0; int ret = 0;
uint32_t nblocks = 1, flsz = 0; #ifdef EBUG
if(!end){ // erase all remaining USB_sendstr("Erase block #"); printu(N); newline();
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){ #endif
flsz = FLASH_SIZE * FLASH_blocksize; // size in bytes FLASH->AR = (uint32_t)Flash_Data + N*FLASH_blocksize;
flsz -= (uint32_t)start - FLASH_BASE; FLASH->CR |= FLASH_CR_STRT;
} while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH;
}else{ // erase a part FLASH->SR = FLASH_SR_EOP;
flsz = (uint32_t)end - (uint32_t)start; 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*/
}
return ret;
}
// erase full storage (npage < 0) or its nth page; @return 0 if all OK
int erase_storage(int npage){
int ret = 0;
uint32_t end = 1, start = 0, flsz = 0;
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
flsz = FLASH_SIZE * 1024; // size in bytes
flsz -= (uint32_t)Flash_Data - FLASH_BASE;
}
end = flsz / FLASH_blocksize;
if(end == 0 || end >= FLASH_SIZE) return 1;
if(npage > -1){ // erase only one page
if((uint32_t)npage >= end) return 1;
start = npage;
end = start + 1;
} }
if((FLASH->CR & FLASH_CR_LOCK) != 0){ if((FLASH->CR & FLASH_CR_LOCK) != 0){
FLASH->KEYR = FLASH_KEY1; FLASH->KEYR = FLASH_KEY1;
FLASH->KEYR = FLASH_KEY2; FLASH->KEYR = FLASH_KEY2;
} }
nblocks = flsz / FLASH_blocksize; /*USB_sendstr("size/block size/nblocks/FLASH_SIZE: "); printu(flsz);
if(nblocks == 0 || nblocks >= FLASH_SIZE) return 1; USB_putbyte('/'); printu(FLASH_blocksize); USB_putbyte('/');
for(uint32_t i = 0; i < nblocks; ++i){ printu(nblocks); USB_putbyte('/'); printu(FLASH_SIZE); newline(); USB_sendall();*/
IWDG->KR = IWDG_REFRESH; while(FLASH->SR & FLASH_SR_BSY) IWDG->KR = IWDG_REFRESH;
while(FLASH->SR & FLASH_SR_BSY); FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR;
FLASH->SR = FLASH_SR_EOP | FLASH_SR_PGERR | FLASH_SR_WRPERR; FLASH->CR |= FLASH_CR_PER;
FLASH->CR |= FLASH_CR_PER; for(uint32_t i = start; i < end; ++i){
FLASH->AR = (uint32_t)Flash_Data + i*FLASH_blocksize; if(erase_pageN(i)){
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; ret = 1;
FLASH->SR |= FLASH_SR_WRPERR; /* Clear the flag by software by writing it at 1*/
break; break;
} }
} }
@@ -184,9 +200,6 @@ static int erase_flash(const void *start, const void *end){
return ret; return ret;
} }
int erase_storage(){
return erase_flash(Flash_Data, NULL);
}
int fn_dumpconf(uint32_t _U_ hash, char _U_ *args){ // "dumpconf" (3271513185) int fn_dumpconf(uint32_t _U_ hash, char _U_ *args){ // "dumpconf" (3271513185)
#ifdef EBUG #ifdef EBUG

View File

@@ -72,5 +72,5 @@ extern user_conf the_conf; // global user config (read from FLASH to RAM)
void flashstorage_init(); void flashstorage_init();
int store_userconf(); int store_userconf();
int erase_storage(); int erase_storage(int npage);

View File

@@ -18,6 +18,7 @@
#include "flash.h" #include "flash.h"
#include "hardware.h" #include "hardware.h"
#include "steppers.h"
// Buttons: PA9, PA10, PF6, PD3, PD4, PD5, pullup (active - 0) // Buttons: PA9, PA10, PF6, PD3, PD4, PD5, pullup (active - 0)
volatile GPIO_TypeDef* const BTNports[BTNSNO] = {GPIOA, GPIOA, GPIOF, GPIOD, GPIOD, GPIOD}; volatile GPIO_TypeDef* const BTNports[BTNSNO] = {GPIOA, GPIOA, GPIOF, GPIOD, GPIOD, GPIOD};
@@ -76,11 +77,11 @@ static IRQn_Type motirqs[MOTORSNO] = {
uint8_t ESW_state(uint8_t MOTno){ uint8_t ESW_state(uint8_t MOTno){
uint8_t val = 0; uint8_t val = 0;
if(the_conf.isSPI){ // only ESW0 used if(the_conf.isSPI){ // only ESW0 used
val = ((ESWports[MOTno][0]->IDR & ESWpins[MOTno][0]) ? 0 : 1); val = ((ESWports[MOTno][0]->IDR & ESWpins[MOTno][0]) ? 1 : 0);
if(the_conf.motflags[MOTno].eswinv) val ^= 1; if(the_conf.motflags[MOTno].eswinv) val ^= 1;
return val; return val;
}else for(int i = 0; i < 2; ++i){ }else for(int i = 0; i < 2; ++i){
val |= ((ESWports[MOTno][i]->IDR & ESWpins[MOTno][i]) ? 0 : 1) << i; val |= ((ESWports[MOTno][i]->IDR & ESWpins[MOTno][i]) ? 1 : 0) << i;
} }
if(the_conf.motflags[MOTno].eswinv) val ^= 3; if(the_conf.motflags[MOTno].eswinv) val ^= 3;
return val; return val;
@@ -221,9 +222,13 @@ static void setup_mpwm(int i){
} }
void mottimers_setup(){
for(int i = 0; i < MOTORSNO; ++i) setup_mpwm(i);
}
void hw_setup(){ void hw_setup(){
gpio_setup(); gpio_setup();
for(int i = 0; i < MOTORSNO; ++i) setup_mpwm(i); mottimers_setup();
#ifndef EBUG #ifndef EBUG
iwdg_setup(); iwdg_setup();
#endif #endif
@@ -232,34 +237,34 @@ void hw_setup(){
// timers for motors: 0:t15c1, 1:t16c1, 2:t17c1, 3:t2ch1, 4:t8ch1, 5:t4c1, 6:t1c1, 7:t3c3 // timers for motors: 0:t15c1, 1:t16c1, 2:t17c1, 3:t2ch1, 4:t8ch1, 5:t4c1, 6:t1c1, 7:t3c3
void tim1_cc_isr(){ void tim1_cc_isr(){
// addmicrostep(6); addmicrostep(6);
TIM1->SR = 0; TIM1->SR = 0;
} }
void tim2_isr(){ void tim2_isr(){
// addmicrostep(3); addmicrostep(3);
TIM2->SR = 0; TIM2->SR = 0;
} }
void tim3_isr(){ void tim3_isr(){
// addmicrostep(7); addmicrostep(7);
TIM3->SR = 0; TIM3->SR = 0;
} }
void tim4_isr(){ void tim4_isr(){
// addmicrostep(5); addmicrostep(5);
TIM4->SR = 0; TIM4->SR = 0;
} }
void tim8_cc_isr(){ void tim8_cc_isr(){
// addmicrostep(4); addmicrostep(4);
TIM8->SR = 0; TIM8->SR = 0;
} }
void tim1_brk_tim15_isr(){ void tim1_brk_tim15_isr(){
// addmicrostep(0); addmicrostep(0);
TIM15->SR = 0; TIM15->SR = 0;
} }
void tim1_up_tim16_isr(){ void tim1_up_tim16_isr(){
// addmicrostep(1); addmicrostep(1);
TIM16->SR = 0; TIM16->SR = 0;
} }
void tim1_trg_com_tim17_isr(){ void tim1_trg_com_tim17_isr(){
// addmicrostep(2); addmicrostep(2);
TIM17->SR = 0; TIM17->SR = 0;
} }

View File

@@ -20,9 +20,10 @@
#include <stm32f3.h> #include <stm32f3.h>
// PCLK frequency // "PCLK" frequency
// really APB1=36M -> TIM2/3/4/6/7 f=72M, APB2=72M -> TIM1/8/15/16/17/20 f=72M
#ifndef PCLK #ifndef PCLK
#define PCLK (48000000) #define PCLK (72000000)
#endif #endif
// motors' timer PSC = PCLK/Tfreq - 1, Tfreq=16MHz // motors' timer PSC = PCLK/Tfreq - 1, Tfreq=16MHz
@@ -33,8 +34,10 @@
// USB pullup: PA8 // USB pullup: PA8
#define USBPU_port GPIOA #define USBPU_port GPIOA
#define USBPU_pin (1<<8) #define USBPU_pin (1<<8)
#define USBPU_ON() pin_clear(USBPU_port, USBPU_pin) //#define USBPU_ON() pin_clear(USBPU_port, USBPU_pin)
#define USBPU_OFF() pin_set(USBPU_port, USBPU_pin) //#define USBPU_OFF() pin_set(USBPU_port, USBPU_pin)
#define USBPU_ON() pin_set(USBPU_port, USBPU_pin)
#define USBPU_OFF() pin_clear(USBPU_port, USBPU_pin)
// temporary LED: PD9 // temporary LED: PD9
#define LED_blink() pin_toggle(GPIOD, 1<<9) #define LED_blink() pin_toggle(GPIOD, 1<<9)
@@ -86,4 +89,4 @@ extern volatile uint32_t Tms;
uint8_t ESW_state(uint8_t MOTno); uint8_t ESW_state(uint8_t MOTno);
uint8_t MSB(uint16_t val); uint8_t MSB(uint16_t val);
void hw_setup(); void hw_setup();
void mottimers_setup();

View File

@@ -54,6 +54,8 @@ 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_dumpmotflags(_U_ uint32_t hash, _U_ char *args) WAL; // "dumpmotflags" (36159640)
int fn_dumpstates(_U_ uint32_t hash, _U_ char *args) WAL; // "dumpstates" (4235564367)
int fn_emstop(_U_ uint32_t hash, _U_ char *args) WAL; // "emstop" (2965919005) int fn_emstop(_U_ uint32_t hash, _U_ char *args) WAL; // "emstop" (2965919005)
int fn_eraseflash(_U_ uint32_t hash, _U_ char *args) WAL; // "eraseflash" (3177247267) int fn_eraseflash(_U_ uint32_t hash, _U_ char *args) WAL; // "eraseflash" (3177247267)
@@ -205,6 +207,9 @@ int parsecmd(const char *str){
case CMD_DUMPMOTFLAGS: case CMD_DUMPMOTFLAGS:
return fn_dumpmotflags(h, args); return fn_dumpmotflags(h, args);
break; break;
case CMD_DUMPSTATES:
return fn_dumpstates(h, args);
break;
case CMD_EMSTOP: case CMD_EMSTOP:
return fn_emstop(h, args); return fn_emstop(h, args);
break; break;

View File

@@ -35,6 +35,7 @@ int parsecmd(const char *cmdwargs);
#define CMD_DUMPCONF (3271513185) #define CMD_DUMPCONF (3271513185)
#define CMD_DUMPERR (1223989764) #define CMD_DUMPERR (1223989764)
#define CMD_DUMPMOTFLAGS (36159640) #define CMD_DUMPMOTFLAGS (36159640)
#define CMD_DUMPSTATES (4235564367)
#define CMD_EMSTOP (2965919005) #define CMD_EMSTOP (2965919005)
#define CMD_ERASEFLASH (3177247267) #define CMD_ERASEFLASH (3177247267)
#define CMD_ESW (2963094612) #define CMD_ESW (2963094612)

View File

@@ -20,8 +20,9 @@
"dumpcmd - dump command codes\n" "dumpcmd - dump command codes\n"
"dumpconf - dump current configuration\n" "dumpconf - dump current configuration\n"
"dumpmotflags - dump motor flags' bits\n" "dumpmotflags - dump motor flags' bits\n"
"dumpstates - dump motors' state codes\n"
"emstop[N] - emergency stop motor N or all\n" "emstop[N] - emergency stop motor N or all\n"
"eraseflash - erase flash data storage\n" "eraseflash [=N] - erase flash data storage (full or only N'th page of it)\n"
"esw[N] - G end-switches state\n" "esw[N] - G end-switches state\n"
"eswreactN - GS end-switches reaction (0 - ignore, 1 - stop@any, 2 - stop@zero)\n" "eswreactN - GS end-switches reaction (0 - ignore, 1 - stop@any, 2 - stop@zero)\n"
"gotoN - GS move motor to given absolute position\n" "gotoN - GS move motor to given absolute position\n"

View File

@@ -20,6 +20,7 @@ dumperr
dumpcmd dumpcmd
dumpconf dumpconf
dumpmotflags dumpmotflags
dumpstates
emstop emstop
eraseflash eraseflash
esw esw

View File

@@ -22,6 +22,7 @@
#include "flash.h" #include "flash.h"
#include "hardware.h" #include "hardware.h"
#include "proto.h" #include "proto.h"
#include "steppers.h"
#include "usb.h" #include "usb.h"
#define MAXSTRLEN RBINSZ #define MAXSTRLEN RBINSZ
@@ -40,9 +41,10 @@ int main(void){
StartHSI(); StartHSI();
SysTick_Config((uint32_t)48000); // 1ms SysTick_Config((uint32_t)48000); // 1ms
} }
//flashstorage_init();
hw_setup(); // GPIO, ADC, timers, watchdog etc.
USBPU_OFF(); // make a reconnection USBPU_OFF(); // make a reconnection
flashstorage_init();
hw_setup(); // GPIO, ADC, timers, watchdog etc.
init_steppers();
USB_setup(); USB_setup();
CAN_setup(the_conf.CANspeed); CAN_setup(the_conf.CANspeed);
adc_setup(); adc_setup();
@@ -57,6 +59,7 @@ int main(void){
} }
CAN_proc(); CAN_proc();
USB_proc(); USB_proc();
process_steppers();
if(CAN_get_status() == CAN_FIFO_OVERRUN){ if(CAN_get_status() == CAN_FIFO_OVERRUN){
USB_sendstr("CAN bus fifo overrun occured!\n"); USB_sendstr("CAN bus fifo overrun occured!\n");
} }

View File

@@ -448,6 +448,24 @@ int fn_dumperr(uint32_t _U_ hash, char _U_ *args){ // "dumperr" (1223989764)
return RET_GOOD; return RET_GOOD;
} }
static const char* motstates[STP_STATE_AMOUNT] = {
[STP_RELAX] = "relax",
[STP_ACCEL] = "acceleration",
[STP_MOVE] = "moving",
[STP_MVSLOW] = "moving at lowest speed",
[STP_DECEL] = "deceleration",
[STP_STALL] = "stalled (not used here!)",
[STP_ERR] = "error"
};
int fn_dumpstates(uint32_t _U_ hash, char _U_ *args){ // "dumpstates" (4235564367)
USND("Motor's state codes:");
for(int i = 0; i < STP_STATE_AMOUNT; ++i){
printu(i); USB_sendstr(" - ");
USB_sendstr(motstates[i]); newline();
}
return RET_GOOD;
}
int fn_canid(uint32_t _U_ hash, char *args){ // "canid" (2040257924) int fn_canid(uint32_t _U_ hash, char *args){ // "canid" (2040257924)
if(args && *args){ if(args && *args){
int good = FALSE; int good = FALSE;
@@ -481,13 +499,13 @@ static int canusb_function(uint32_t hash, char *args){
return RET_GOOD; return RET_GOOD;
} }
par = (uint8_t) N; par = (uint8_t) N;
n = strchr(n, '='); }
if(n){ n = strchr(n, '=');
const char *nxt = getnum(n+1, &N); if(n){
if(nxt != n){ // give flag issetter ++n;
val = (int32_t) N; const char *nxt = getint(n, &val);
par |= SETTERFLAG; if(nxt != n){ // set setter flag
} par |= SETTERFLAG;
} }
} }
} }
@@ -521,7 +539,7 @@ static int canusb_function(uint32_t hash, char *args){
USB_putbyte('='); USB_sendstr(u2str(getADCval(par))); USB_putbyte('='); USB_sendstr(u2str(getADCval(par)));
f = getADCvoltage(par); f = getADCvoltage(par);
USB_sendstr("\nADCv");USB_putbyte('0'+par); USB_sendstr("\nADCv");USB_putbyte('0'+par);
USB_putbyte('='); USB_sendstr(float2str(f, 1)); USB_putbyte('='); USB_sendstr(float2str(f, 2));
newline(); newline();
return RET_GOOD; return RET_GOOD;
break; break;

View File

@@ -30,22 +30,12 @@ typedef enum{
M0SLOW // slowest move from ESW M0SLOW // slowest move from ESW
} mvto0state; } mvto0state;
typedef enum{
STALL_NO, // moving OK
STALL_ONCE, // Nstalled < limit
STALL_STOP // Nstalled >= limit
} t_stalled;
#ifdef EBUG #ifdef EBUG
static uint8_t stp[MOTORSNO] = {0}; static uint8_t stp[MOTORSNO] = {0};
#endif #endif
static t_stalled stallflags[MOTORSNO];
// motors' direction: 1 for positive, -1 for negative (we need it as could be reverse) // motors' direction: 1 for positive, -1 for negative (we need it as could be reverse)
static int8_t motdir[MOTORSNO]; 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 // current position (in steps) by STP counter
static volatile int32_t stppos[MOTORSNO] = {0}; static volatile int32_t stppos[MOTORSNO] = {0};
// previous position when check (set to current in start of moving) // previous position when check (set to current in start of moving)
@@ -67,8 +57,6 @@ static stp_state state[MOTORSNO];
// move to zero state // move to zero state
static mvto0state mvzerostate[MOTORSNO]; static mvto0state mvzerostate[MOTORSNO];
static int8_t Nstalled[MOTORSNO] = {0}; // counter of STALL
// lowest ARR value (highest speed), highest (lowest speed) // lowest ARR value (highest speed), highest (lowest speed)
//static uint16_t stphighARR[MOTORSNO]; //static uint16_t stphighARR[MOTORSNO];
// microsteps=1<<ustepsshift // microsteps=1<<ustepsshift
@@ -88,20 +76,26 @@ TRUE_INLINE void recalcARR(int i){
curspeed[i] = (((PCLK/(MOTORTIM_PSC+1)) / (ARR+1)) >> ustepsshift[i]); // recalculate speed due to new val curspeed[i] = (((PCLK/(MOTORTIM_PSC+1)) / (ARR+1)) >> ustepsshift[i]); // recalculate speed due to new val
} }
// update stepper's settings
void update_stepper(uint8_t i){
if(i >= MOTORSNO) return;
accdecsteps[i] = (the_conf.maxspd[i] * the_conf.maxspd[i]) / the_conf.accel[i] / 2;
ustepsshift[i] = MSB(the_conf.microsteps[i]);
ESW_reaction[i] = the_conf.ESW_reaction[i];
}
// run this function after each steppers parameters changing // run this function after each steppers parameters changing
void init_steppers(){ void init_steppers(){
mottimers_setup(); // reinit timers
// init variables // init variables
for(int i = 0; i < MOTORSNO; ++i){ for(int i = 0; i < MOTORSNO; ++i){
stalleddir[i] = 0; // clear old stall direction
stopflag[i] = 0; stopflag[i] = 0;
motdir[i] = 0; motdir[i] = 0;
curspeed[i] = 0; curspeed[i] = 0;
accdecsteps[i] = (the_conf.maxspd[i] * the_conf.maxspd[i]) / the_conf.accel[i] / 2;
state[i] = STP_RELAX; state[i] = STP_RELAX;
ustepsshift[i] = MSB(the_conf.microsteps[i]);
if(!the_conf.motflags[i].donthold) MOTOR_EN(i); if(!the_conf.motflags[i].donthold) MOTOR_EN(i);
else MOTOR_DIS(i); else MOTOR_DIS(i);
ESW_reaction[i] = the_conf.ESW_reaction[i]; update_stepper(i);
} }
} }
@@ -176,7 +170,7 @@ static int esw_block(uint8_t i){
break; break;
case ESW_STOPMINUS: // stop only @ given direction case ESW_STOPMINUS: // stop only @ given direction
if(motdir[i] == -1 && (s & 1)) ret = TRUE; // stop @ESW0 if(motdir[i] == -1 && (s & 1)) ret = TRUE; // stop @ESW0
if(motdir[i] == 1 && (s & 3)) ret = TRUE; // stop @ESW1 if(motdir[i] == 1 && (s & 2)) ret = TRUE; // stop @ESW1
break; break;
default: // ESW_IGNORE default: // ESW_IGNORE
break; break;
@@ -194,11 +188,6 @@ errcodes motor_absmove(uint8_t i, int32_t newpos){
case STP_RELAX: case STP_RELAX:
break; break;
case STP_STALL: 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; break;
default: // moving state default: // moving state
DBG("Is moving"); DBG("Is moving");
@@ -213,7 +202,6 @@ errcodes motor_absmove(uint8_t i, int32_t newpos){
DBG("Block by ESW"); DBG("Block by ESW");
return ERR_CANTRUN; // on end-switch 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; stopflag[i] = 0;
targstppos[i] = newpos; targstppos[i] = newpos;
prevstppos[i] = stppos[i]; prevstppos[i] = stppos[i];
@@ -221,10 +209,10 @@ errcodes motor_absmove(uint8_t i, int32_t newpos){
state[i] = STP_ACCEL; state[i] = STP_ACCEL;
calcacceleration(i); calcacceleration(i);
#ifdef EBUG #ifdef EBUG
USND("MOTOR"); USB_putbyte('0'+i); USB_sendstr("MOTOR"); USB_putbyte('0'+i);
USND(" targstppos="); printi(targstppos[i]); USB_sendstr(" targstppos="); printi(targstppos[i]);
USND(", decelstart="); printi(decelstartpos[i]); USB_sendstr(", decelstart="); printi(decelstartpos[i]);
USND(", accdecsteps="); printu(accdecsteps[i]); newline(); USB_sendstr(", accdecsteps="); printu(accdecsteps[i]); newline();
#endif #endif
MOTOR_EN(i); MOTOR_EN(i);
mottimers[i]->CR1 |= TIM_CR1_CEN; // start timer mottimers[i]->CR1 |= TIM_CR1_CEN; // start timer
@@ -288,12 +276,7 @@ void addmicrostep(uint8_t i){
stopflag[i] = 0; stopflag[i] = 0;
if(the_conf.motflags[i].donthold) if(the_conf.motflags[i].donthold)
MOTOR_DIS(i); // turn off power MOTOR_DIS(i); // turn off power
if(stallflags[i] == STALL_STOP){ state[i] = STP_RELAX;
stallflags[i] = STALL_NO;
state[i] = STP_STALL;
}else{
state[i] = STP_RELAX;
}
#ifdef EBUG #ifdef EBUG
stp[i] = 1; stp[i] = 1;
#endif #endif
@@ -305,8 +288,8 @@ void addmicrostep(uint8_t i){
#define TODECEL() do{state[i] = STP_DECEL; \ #define TODECEL() do{state[i] = STP_DECEL; \
startspeed[i] = curspeed[i]; \ startspeed[i] = curspeed[i]; \
Taccel[i] = Tms; \ Taccel[i] = Tms; \
USND("MOTOR"); USB_putbyte('0'+i); \ USB_sendstr("MOTOR"); USB_putbyte('0'+i); \
USND(" -> DECEL@"); printi(stppos[i]); USND(", V="); printu(curspeed[i]); newline(); \ USB_sendstr(" -> DECEL@"); printi(stppos[i]); USB_sendstr(", V="); printu(curspeed[i]); newline(); \
}while(0) }while(0)
#else #else
#define TODECEL() do{state[i] = STP_DECEL; \ #define TODECEL() do{state[i] = STP_DECEL; \
@@ -322,22 +305,22 @@ static void chkstepper(int i){
#ifdef EBUG #ifdef EBUG
if(stp[i]){ if(stp[i]){
stp[i] = 0; stp[i] = 0;
// motor state could be changed outside of interrupt, so return it to relax or leave in STALL // motor state could be changed outside of interrupt, so return it to relax
state[i] = STP_RELAX; state[i] = STP_RELAX;
USND("MOTOR"); USB_putbyte('0'+i); USND(" stop @"); printi(stppos[i]); USB_sendstr("MOTOR"); USB_putbyte('0'+i); USB_sendstr(" stop @"); printi(stppos[i]);
USND(", curstate="); printu(state[i]); newline(); USB_sendstr(", V="); printu(curspeed[i]);
USB_sendstr(", curstate="); printu(state[i]); newline();
} }
#endif #endif
switch(state[i]){ switch(state[i]){
case STP_ACCEL: // acceleration to max speed 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; 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 if(i32 >= the_conf.maxspd[i]){ // max speed reached -> move with it
curspeed[i] = the_conf.maxspd[i]; curspeed[i] = the_conf.maxspd[i];
state[i] = STP_MOVE; state[i] = STP_MOVE;
#ifdef EBUG #ifdef EBUG
USND("MOTOR"); USB_putbyte('0'+i); USB_sendstr("MOTOR"); USB_putbyte('0'+i);
USND(" -> MOVE@"); printi(stppos[i]); USND(", V="); printu(curspeed[i]); newline(); USB_sendstr(" -> MOVE@"); printi(stppos[i]); USB_sendstr(", V="); printu(curspeed[i]); newline();
#endif #endif
}else{ // increase speed }else{ // increase speed
curspeed[i] = i32; curspeed[i] = i32;
@@ -375,8 +358,8 @@ static void chkstepper(int i){
curspeed[i] = the_conf.minspd[i]; curspeed[i] = the_conf.minspd[i];
state[i] = STP_MVSLOW; state[i] = STP_MVSLOW;
#ifdef EBUG #ifdef EBUG
USND("MOTOR"); USB_putbyte('0'+i); USB_sendstr("MOTOR"); USB_putbyte('0'+i);
USND(" -> MVSLOW@"); printi(stppos[i]); newline(); USB_sendstr(" -> MVSLOW@"); printi(stppos[i]); newline();
#endif #endif
} }
recalcARR(i); recalcARR(i);
@@ -388,11 +371,11 @@ static void chkstepper(int i){
case M0FAST: case M0FAST:
if(state[i] == STP_RELAX || state[i] == STP_STALL){ // stopped -> move to + if(state[i] == STP_RELAX || state[i] == STP_STALL){ // stopped -> move to +
#ifdef EBUG #ifdef EBUG
USB_putbyte('M'); USB_putbyte('0'+i); USND("FAST: motor stopped\n"); USB_putbyte('M'); USB_putbyte('0'+i); USB_sendstr("FAST: motor stopped\n");
#endif #endif
if(ERR_OK != motor_relslow(i, 1000)){ if(ERR_OK != motor_relslow(i, 1000)){
#ifdef EBUG #ifdef EBUG
USND("Can't move\n"); USND("Can't move");
#endif #endif
DBG("->ERR"); DBG("->ERR");
state[i] = STP_ERR; state[i] = STP_ERR;
@@ -410,7 +393,7 @@ static void chkstepper(int i){
} }
if((state[i] == STP_RELAX || state[i] == STP_STALL) && ++stopctr[i] > 5){ // wait at least 50ms if((state[i] == STP_RELAX || state[i] == STP_STALL) && ++stopctr[i] > 5){ // wait at least 50ms
#ifdef EBUG #ifdef EBUG
USB_putbyte('M'); USB_putbyte('0'+i); USND("SLOW: motor stopped\n"); USB_putbyte('M'); USB_putbyte('0'+i); USND("SLOW: motor stopped");
#endif #endif
ESW_reaction[i] = the_conf.ESW_reaction[i]; ESW_reaction[i] = the_conf.ESW_reaction[i];
prevstppos[i] = targstppos[i] = stppos[i] = 0; prevstppos[i] = targstppos[i] = stppos[i] = 0;

View File

@@ -36,7 +36,8 @@ typedef enum{
STP_MVSLOW, // 3 - moving with slowest constant speed (end of moving) STP_MVSLOW, // 3 - moving with slowest constant speed (end of moving)
STP_DECEL, // 4 - moving with deceleration STP_DECEL, // 4 - moving with deceleration
STP_STALL, // 5 - stalled (UNUSED) STP_STALL, // 5 - stalled (UNUSED)
STP_ERR // 6 - wrong/error state STP_ERR , // 6 - wrong/error state
STP_STATE_AMOUNT
} stp_state; } stp_state;
// end-switches reaction // end-switches reaction
@@ -52,8 +53,9 @@ enum{
void addmicrostep(uint8_t i); void addmicrostep(uint8_t i);
void init_steppers(); void init_steppers();
errcodes setmotpos(uint8_t i, int32_t position); void update_stepper(uint8_t i);
errcodes setmotpos(uint8_t i, int32_t position);
errcodes getpos(uint8_t i, int32_t *position); errcodes getpos(uint8_t i, int32_t *position);
errcodes getremainsteps(uint8_t i, int32_t *position); errcodes getremainsteps(uint8_t i, int32_t *position);
errcodes motor_absmove(uint8_t i, int32_t abssteps); errcodes motor_absmove(uint8_t i, int32_t abssteps);

View File

@@ -31,7 +31,7 @@
#define STR(s) STR_HELPER(s) #define STR(s) STR_HELPER(s)
#ifdef EBUG #ifdef EBUG
#define DBG(str) do{USB_sendstr(__FILE__ " (L" STR(__LINE__) "): " str);}while(0) #define DBG(str) do{USB_sendstr(__FILE__ " (L" STR(__LINE__) "): " str); newline();}while(0)
#else #else
#define DBG(str) #define DBG(str)
#endif #endif

View File

@@ -1,2 +1,2 @@
#define BUILD_NUMBER "56" #define BUILD_NUMBER "80"
#define BUILD_DATE "2023-02-21" #define BUILD_DATE "2023-02-24"