16#define MAX_TMC_DRIVERS 3
19 .name =
"TMC4671 (CS 1)",
30 .name =
"TMC4671 (CS 2)" ,
56 spiConfig.peripheral.Mode = SPI_MODE_MASTER;
57 spiConfig.peripheral.Direction = SPI_DIRECTION_2LINES;
58 spiConfig.peripheral.DataSize = SPI_DATASIZE_8BIT;
59 spiConfig.peripheral.CLKPolarity = SPI_POLARITY_HIGH;
60 spiConfig.peripheral.CLKPhase = SPI_PHASE_2EDGE;
62 spiConfig.peripheral.BaudRatePrescaler =
spiPort.getClosestPrescaler(8e6,0,10e6).first;
63 spiConfig.peripheral.FirstBit = SPI_FIRSTBIT_MSB;
64 spiConfig.peripheral.TIMode = SPI_TIMODE_DISABLE;
65 spiConfig.peripheral.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
68#ifdef TMC4671_SPI_DATA_IDLENESS
69 spiConfig.peripheral.MasterInterDataIdleness = TMC4671_SPI_DATA_IDLENESS;
95 this->
flashAddrs =
TMC4671FlashAddrs({ADR_TMC1_MOTCONF, ADR_TMC1_CPR, ADR_TMC1_ENCA, ADR_TMC1_OFFSETFLUX, ADR_TMC1_TORQUE_P, ADR_TMC1_TORQUE_I, ADR_TMC1_FLUX_P, ADR_TMC1_FLUX_I,ADR_TMC1_ADC_I0_OFS,ADR_TMC1_ADC_I1_OFS,ADR_TMC1_ENC_OFFSET,ADR_TMC1_PHIE_OFS,ADR_TMC1_TRQ_FILT});
96 }
else if (address == 2)
98 this->
flashAddrs =
TMC4671FlashAddrs({ADR_TMC2_MOTCONF, ADR_TMC2_CPR, ADR_TMC2_ENCA, ADR_TMC2_OFFSETFLUX, ADR_TMC2_TORQUE_P, ADR_TMC2_TORQUE_I, ADR_TMC2_FLUX_P, ADR_TMC2_FLUX_I,ADR_TMC2_ADC_I0_OFS,ADR_TMC2_ADC_I1_OFS,ADR_TMC2_ENC_OFFSET,ADR_TMC2_PHIE_OFS,ADR_TMC2_TRQ_FILT});
99 }
else if (address == 3)
101 this->
flashAddrs =
TMC4671FlashAddrs({ADR_TMC3_MOTCONF, ADR_TMC3_CPR, ADR_TMC3_ENCA, ADR_TMC3_OFFSETFLUX, ADR_TMC3_TORQUE_P, ADR_TMC3_TORQUE_I, ADR_TMC3_FLUX_P, ADR_TMC3_FLUX_I,ADR_TMC3_ADC_I0_OFS,ADR_TMC3_ADC_I1_OFS,ADR_TMC3_ENC_OFFSET,ADR_TMC3_PHIE_OFS,ADR_TMC3_TRQ_FILT});
163 this->
abnconf.posOffsetFromIndex = (int16_t)encofs;
197 return (intV > 10000) && (
getExtV() > 10000) && (intV < 78000);
228 return(
readReg(0) == 0x34363731);
236 uint32_t agpiA_VM =
readReg(0x02);
237 agpiA_VM = (agpiA_VM & 0xFFFF) - 0x7FFF -
conf.hwconf.adcOffset;
239 return ((
float)agpiA_VM *
conf.hwconf.vmScaler) * 1000;
267 this->
spiConfig.peripheral.BaudRatePrescaler =
spiPort.getClosestPrescaler(1e6).first;
353 if(!this->
conf.hwconf.thermistorSettings.temperatureEnabled){
359 int32_t adcval = ((
readReg(0x02)) & 0xffff) - 0x7fff;
380 for(uint8_t i = 0;i<50;i++){
382 total += (ft.first+ft.second);
385 return(abs(total / 50) < 100);
464 static uint8_t powerCheckCounter = 0;
467 powerCheckCounter = 0;
540 uint32_t tick = HAL_GetTick();
546 bool tmc_en = ((pins >> 15) & 0x01) && pins != 0xffffffff;
555 if(
conf.hwconf.thermistorSettings.temperatureEnabled){
557 if(
temp >
conf.hwconf.thermistorSettings.temp_limit){
572 bool tmc_en = ((pins >> 15) & 0x01) && pins != 0xffffffff;
657 if(!
conf.hwconf.flags.analog_enc_skip_cal){
688 int16_t targetflux_p = targetflux * 0.75;
694 while(
fluxP < 20000){
698 if(flux > targetflux_p){
700 }
else if(flux > targetflux * 0.5){
711 uint32_t measuretime = 50;
712 uint16_t step_i = 64;
715 while(
fluxI < 20000){
717 uint32_t tick = HAL_GetTick();
718 int32_t peakflux = 0;
721 while(HAL_GetTick() - tick < measuretime){
723 peakflux = std::max<int32_t>(peakflux, flux);
726 uint8_t timeout = 100;
727 while(timeout-- && flux > 10){
732 if(peakflux > (targetflux + ( targetflux * TMC4671_ITUNE_CUTOFF)))
737 if(peakflux < targetflux*0.95){
786 if(newState != this->
state){
798 int32_t actualPos =
readReg(0x6B);
799 int32_t targetPos =
readReg(0x68);
800 if( abs(targetPos - actualPos) < tolerance){
808 int32_t npos = (int32_t)
readReg(0x28);
809 int32_t npos_M = (npos * 0xffff) /
abnconf.cpr;
812 abnconf.phiEoffset += npos_M*
conf.motconf.pole_pairs;
814 uint32_t phiEphiM =
readReg(0x29);
815 int16_t phiE = ((phiEphiM >> 16) & 0xffff);
816 int16_t phiM = phiEphiM & 0xffff;
850 int32_t timeout = 1000;
885 updateReg(0x25, zeroEncoder ? 1 : 0, 0x1, 9);
940 int64_t phiE_t = (int64_t)
drvEncoder->getPosAbs() * 0xffff;
941 if(this->
conf.encoderReversed){
944 int32_t phiE = (phiE_t / (int64_t)
drvEncoder->getCpr());
945 phiE = (phiE *
conf.motconf.pole_pairs) & 0xffff;
971 uint8_t phiEoffsetReg = 0;
973 phiEoffsetReg = 0x29;
979 phiEoffsetReg = 0x45;
1000 int16_t phiE_abn_old = 0;
1003 while(still < 30 && c++ < 1000){
1005 if(abs(phiE_enc - phiE_abn_old) < 100){
1010 phiE_abn_old = phiE_enc;
1021 int16_t phiEoffset = phiEpos-phiE_enc;
1023 if(phiEoffset == 0){
1029 updateReg(phiEoffsetReg, phiEoffset, 0xffff, 16);
1033 abnconf.phiEoffset = phiEoffset;
1070 uint32_t minVal_0 = 0xffff, minVal_1 = 0xffff, minVal_2 = 0xffff;
1071 uint32_t maxVal_0 = 0, maxVal_1 = 0, maxVal_2 = 0;
1072 int32_t minpos = -0x8fff/std::max<int32_t>(1,std::min<int32_t>(this->
aencconf.cpr/4,20)), maxpos = 0x8fff/std::max<int32_t>(1,std::min<int32_t>(this->
aencconf.cpr/4,20));
1073 uint32_t speed = std::max<uint32_t>(1,20/std::max<uint32_t>(1,this->
aencconf.cpr/10));
1082 int32_t
poles =
conf.motconf.pole_pairs;
1083 int32_t initialDirPos = 0;
1091 aencconf.AENC0_offset = ((maxVal_0 + minVal_0) / 2);
1092 aencconf.AENC0_scale = 0xF6FF00 / (maxVal_0 - minVal_0);
1094 aencconf.AENC1_offset = ((maxVal_1 + minVal_1) / 2);
1095 aencconf.AENC1_scale = 0xF6FF00 / (maxVal_1 - minVal_1);
1098 aencconf.AENC2_offset = ((maxVal_2 + minVal_2) / 2);
1099 aencconf.AENC2_scale = 0xF6FF00 / (maxVal_2 - minVal_2);
1107 initialDirPos =
readReg(0x41);
1117 uint32_t aencUX =
readReg(0x02)>>16;
1119 uint32_t aencWY_VN =
readReg(0x02) ;
1120 uint32_t aencWY = aencWY_VN >> 16;
1121 uint32_t aencVN = aencWY_VN & 0xffff;
1123 minVal_0 = std::min(minVal_0,aencUX);
1124 minVal_1 = std::min(minVal_1,aencVN);
1125 minVal_2 = std::min(minVal_2,aencWY);
1127 maxVal_0 = std::max(maxVal_0,aencUX);
1128 maxVal_1 = std::max(maxVal_1,aencVN);
1129 maxVal_2 = std::max(maxVal_2,aencWY);
1132 aencconf.AENC0_offset = ((maxVal_0 + minVal_0) / 2);
1133 aencconf.AENC0_scale = 0xF6FF00 / (maxVal_0 - minVal_0);
1135 aencconf.AENC1_offset = ((maxVal_1 + minVal_1) / 2);
1136 aencconf.AENC1_scale = 0xF6FF00 / (maxVal_1 - minVal_1);
1138 aencconf.AENC2_offset = ((maxVal_2 + minVal_2) / 2);
1139 aencconf.AENC2_scale = 0xF6FF00 / (maxVal_2 - minVal_2);
1140 int32_t newDirPos =
readReg(0x41);
1141 aencconf.rdir = (initialDirPos - newDirPos) > 0;
1157 return (int16_t)(
readReg(0x2A)>>16);
1159 return (int16_t)(
readReg(0x46)>>16);
1161 return (int16_t)(
readReg(0x39)>>16);
1180 const uint16_t maxcount = 50;
1181 const uint16_t maxfail = 10;
1183 const int16_t targetAngle = 0x3FFF;
1196 int16_t phiE_enc = 0;
1197 uint16_t failcount = 0;
1198 int16_t revCount = 0;
1199 for(int16_t angle = 0;angle<targetAngle;angle+=0x00ff){
1204 int16_t
err = abs(phiE_enc - angle);
1205 int16_t nErr = abs(phiE_enc + angle);
1207 while(
err > 2000 && nErr > 2000 && c++ < 50){
1209 err = abs(phiE_enc - angle);
1210 nErr = abs(angle - phiE_enc);
1218 if(failcount > maxfail){
1240 for(int16_t angle = targetAngle;angle>0;angle -= 0x00ff){
1245 int16_t
err = abs(phiE_enc - angle);
1246 int16_t nErr = abs(phiE_enc + angle);
1248 while(
err > 2500 && nErr > 2500 && c++ < 50){
1250 err = abs(phiE_enc - angle);
1251 nErr = abs(angle - phiE_enc);
1259 if(failcount > maxfail){
1268 if(revCount > maxcount){
1277 this->
conf.encoderReversed = !this->
conf.encoderReversed;
1296 this->
conf.encoderReversed = encconf.
rdir;
1299 (encconf.
bpol << 1) |
1300 (encconf.
npol << 2) |
1303 (encconf.
rdir << 12));
1319 this->
conf.encoderReversed = encconf.
rdir;
1330 uint32_t mode = encconf.
uvwmode & 0x1;
1331 mode |= (encconf.
rdir & 0x1) << 12;
1348 uint32_t posB = (uint16_t)
hallconf.pos120 | (uint16_t)
hallconf.pos180 << 16;
1350 uint32_t posC = (uint16_t)
hallconf.pos240 | (uint16_t)
hallconf.pos300 << 16;
1353 uint32_t phiOffsets = (uint16_t)
hallconf.phiMoffset | (uint16_t)
hallconf.phiEoffset << 16;
1366 uint16_t measuretime_idle = time;
1367 uint32_t measurements_idle = 0;
1370 bool allowTemp =
conf.hwconf.thermistorSettings.temperatureEnabled;
1371 conf.hwconf.thermistorSettings.temperatureEnabled =
false;
1377 uint16_t lastrawA=
conf.adc_I0_offset, lastrawB=
conf.adc_I1_offset;
1382 uint32_t tick = HAL_GetTick();
1383 while(HAL_GetTick() - tick < measuretime_idle){
1385 uint32_t adcraw =
readReg(0x02);
1386 uint16_t rawA = adcraw & 0xffff;
1387 uint16_t rawB = (adcraw >> 16) & 0xffff;
1389 if(abs(lastrawA-rawA) < 10000 && abs(lastrawB-rawB) < 10000){
1392 measurements_idle++;
1400 int32_t offsetAidle = totalA / (measurements_idle);
1401 int32_t offsetBidle = totalB / (measurements_idle);
1404 if(totalA < 100 || totalB < 100 || ((abs(offsetAidle - 0x7fff) > TMC_ADCOFFSETFAIL) || (abs(offsetBidle - 0x7fff) > TMC_ADCOFFSETFAIL)) ){
1410 conf.hwconf.thermistorSettings.temperatureEnabled = allowTemp;
1413 conf.adc_I0_offset = offsetAidle;
1414 conf.adc_I1_offset = offsetBidle;
1421 conf.hwconf.thermistorSettings.temperatureEnabled = allowTemp;
1455 if(!
conf.hwconf.flags.analog_enc_skip_cal){
1526 this->
conf.motconf.enctype = type;
1594 conf.motconf.phiEsource = type;
1601 writeReg(0x52, (uint8_t)type & 0xff);
1620 updateReg(0x63, (uint8_t)mode, 0xff, 0);
1750 if(
conf.hwconf.fluxDissipationScaler &&
conf.enableFluxDissipation){
1752 if(dissipationFlux != 0){
1753 flux = dissipationFlux;
1765 this->
conf.motconf.pos_sel = psel;
1773 uint32_t vselMode = ((uint8_t)vsel & 0xff) | ((mode & 0xff) << 8);
1775 this->
conf.motconf.vel_sel = vsel;
1783 uint8_t modeReg = 0;
1789 modeReg = 0b1100111;
break;
1791 modeReg = 0b0000111;
break;
1793 modeReg = 0b0000001;
break;
1795 modeReg = 0b0010001;
break;
1797 modeReg = 0b0001001;
break;
1799 modeReg = 0b0011001;
break;
1817 uint32_t
reg = pins << 16;
1827 std::string reply =
"";
1829 uint32_t nameInt =
readReg(0);
1830 if(nameInt == 0 || nameInt == 0xffffffff){
1831 reply =
"No driver connected";
1832 return std::pair<uint32_t,std::string>(0,reply);
1835 nameInt = __REV(nameInt);
1836 char*
name =
reinterpret_cast<char*
>(&nameInt);
1837 std::string namestring = std::string(
name,
sizeof(nameInt));
1840 uint32_t versionInt =
readReg(0);
1842 std::string versionstring = std::to_string((versionInt >> 16) && 0xffff) +
"." + std::to_string((versionInt) && 0xffff);
1844 reply +=
"TMC" + namestring +
" v" + versionstring;
1845 return std::pair<uint32_t,std::string>(versionInt,reply);
1852 return static_cast<Encoder*
>(
this);
1877 int32_t tmcpos =
readReg(0x6B);
1878 int32_t
offset = (tmcpos -
pos) % 0xffff;
1946 return enc*(0xffff /
abnconf.cpr);
1962 conf.adc_I0_offset = adc_I0_offset;
1963 conf.adc_I1_offset = adc_I1_offset;
1965 updateReg(0x09, adc_I0_offset, 0xffff, 0);
1966 updateReg(0x08, adc_I1_offset, 0xffff, 0);
1970 conf.adc_I0_scale = adc_I0_scale;
1971 conf.adc_I1_scale = adc_I1_scale;
1973 updateReg(0x09, adc_I0_scale, 0xffff, 16);
1974 updateReg(0x08, adc_I1_scale, 0xffff, 16);
1991 updateReg(0x63, (uint8_t)mode, 0xff, 16);
1999 curPids.sequentialPI = sequential;
2000 updateReg(0x63, sequential ? 1 : 0, 0x1, 31);
2026 if(!
conf.hwconf.isMotSupported(motor)){
2033 conf.motconf.motor_type = motor;
2035 uint32_t
mtype =
poles | ( ((uint8_t)motor&0xff) << 16);
2062 return readReg(0x64) && 0xffff;
2068#ifdef TMC4671_TORQUE_USE_ASYNC
2086 uint16_t startFlux =
readReg(0x64) & 0xffff;
2087 int32_t stepsize = (target - startFlux) / std::max<uint16_t>(1, time_ms/2);
2089 stepsize = startFlux < target ? 1 : -1;
2091 uint16_t flux = startFlux;
2092 while(abs(target - flux) >= abs(stepsize)){
2114 curPids = {(uint16_t)(f&0xffff),(uint16_t)(f>>16),(uint16_t)(t&0xffff),(uint16_t)(t>>16),(uint16_t)(v&0xffff),(uint16_t)(v>>16),(uint16_t)(p&0xffff),(uint16_t)(p>>16)};
2127 this->
curLimits.pid_torque_flux = limit;
2287 uint32_t val = low | (high << 16);
2309 int16_t phiE_abn =
readReg(0x2A)>>16;
2310 int16_t phiE_abn_old = 0;
2311 int16_t rcount=0,c = 0;
2312 uint16_t highcount = 0;
2315 for(int16_t p = 0;p<0x0fff;p+=0x2f){
2319 phiE_abn_old = phiE_abn;
2322 if(phiE_abn < phiE_abn_old){
2325 if((
readReg(0x76) & 0x04) >> 2){
2335 bool npol = highcount > c/2;
2361 int16_t phiE_enc_old = 0;
2362 int16_t rcount=0,c = 0;
2365 for(int16_t p = 0;p<0x0fff;p+=0x2f){
2369 phiE_enc_old = phiE_enc;
2372 if(phiE_enc < phiE_enc_old){
2382 conf.encoderReversed = !
conf.encoderReversed;
2405 this->
conf.bbmH = bbmH;
2406 this->
conf.bbmL = bbmL;
2407 uint32_t bbmr = bbmL | (bbmH << 8);
2423 conf.motconf.svpwm = enable;
2436 return (4.0 * this->
conf.hwconf.clockfreq) / (this->
conf.pwmcnt +1);
2445 maxcnt =
clip(maxcnt, 255, 4095);
2446 this->
conf.pwmcnt = maxcnt;
2458 uint16_t maxcnt = ((4.0 * this->
conf.hwconf.clockfreq) / freq) -1;
2464 uint32_t dat = mdecA | (mdecB << 16);
2470 updateReg(0x04, mclkA == 0 ? 0 : 1, 0x1, 4);
2471 updateReg(0x04, mclkB == 0 ? 0 : 1, 0x1, 20);
2481 uint32_t tfluxa =
readReg(0x69);
2482 int16_t af = (tfluxa & 0xffff);
2483 int16_t at = (tfluxa >> 16);
2484 return std::pair<int16_t,int16_t>(af,at);
2491 uint32_t tfluxa =
readReg(0x69);
2492 int16_t af = (tfluxa & 0xffff);
2500 uint32_t tfluxa =
readReg(0x69);
2501 int16_t at = (tfluxa >> 16);
2509 uint8_t req[5] = {(uint8_t)(0x7F &
reg),0,0,0,0};
2512 spiPort.transmitReceive(req, tbuf, 5,
this, SPITIMEOUT);
2542#ifdef TMC4671_ALLOW_DMA
2551 uint32_t t =
readReg(
reg) & ~(mask << shift);
2552 t |= ((dat & mask) << shift);
2569 uint32_t flags =
readReg(0x7C);
2637 mot.
svpwm = !(val & 0x4);
2643 uint16_t val = (uint8_t)mconf.
motor_type & 0x3;
2644 val |= !mconf.
svpwm ? 0x4 : 0;
2645 val |= ((uint8_t)mconf.
enctype & 0x7) << 3;
2652 val |= (this->
abnconf.npol) & 0x01;
2653 val |= (this->
conf.encoderReversed & 0x01) << 1;
2656 val |= (this->
abnconf.ab_as_n & 0x01) << 2;
2660 val |= (this->
abnconf.useIndex) << 5;
2662 val |= (this->
conf.combineEncoder) << 6;
2663 val |= (this->
conf.invertForce) << 7;
2665 val |= ((this->
conf.enableFluxDissipation & 0x01) << 8);
2666 val |= (this->
hallconf.interpolation & 0x01) << 9;
2668 val |= (this->
curPids.sequentialPI & 0x01) << 10;
2671 val |= ((uint8_t)this->
conf.hwconf.hwVersion & 0x1F) << 11;
2678 this->
abnconf.apol = (val) & 0x01;
2683 this->
conf.encoderReversed = (val>>1) & 0x01;
2688 this->
abnconf.ab_as_n = (val>>2) & 0x01;
2696 this->
abnconf.useIndex = (val>>5) & 0x01;
2697 this->
conf.combineEncoder = (val>>6) & 0x01;
2698 this->
conf.invertForce = ((val>>7) & 0x01) && this->
conf.combineEncoder;
2700 this->
conf.enableFluxDissipation = ((val>>8) & 0x01);
2701 this->
hallconf.interpolation = (val>>9) & 0x01;
2702 this->
curPids.sequentialPI = (val>>10) & 0x01;
2704 setHwType((uint8_t)((val >> 11) & 0x1F));
2719 if(type == newConf.hwVersion){
2720 this->
conf.hwconf = newConf;
2729 setBBM(this->
conf.hwconf.bbm,this->conf.hwconf.bbm);
2731 setMotorType(this->
conf.motconf.motor_type, this->conf.motconf.pole_pairs);
2741 if(this->
canChangeHwType || c.hwVersion == this->conf.hwconf.hwVersion){
2742 replies.emplace_back( std::to_string((uint8_t)c.hwVersion) +
":" + c.name,(uint8_t)c.hwVersion);
2800 if(!this->
conf.combineEncoder){
2801 this->
conf.invertForce =
false;
2815 replies.emplace_back((uint32_t)
getState());
2830 replies.emplace_back((uint8_t)this->
conf.motconf.motor_type);
2834 std::string rplstr =
"";
2836 if(confflags->
mot_none) rplstr +=
"NONE=0,";
2837 if(confflags->
mot_dc) rplstr +=
"DC=1,";
2838 if(confflags->
mot_stepper) rplstr +=
"Stepper 2Ph=2,";
2839 if(confflags->
mot_bldc) rplstr +=
"BLDC 3Ph=3";
2840 replies.emplace_back(rplstr);
2846 replies.emplace_back((uint8_t)this->
conf.motconf.enctype);
2850 std::string rplstr =
"";
2852 if(confflags->
enc_none) rplstr +=
"NONE=0,";
2853 if(confflags->
enc_abn) rplstr +=
"ABN=1,";
2854 if(confflags->
enc_sincos) rplstr +=
"SinCos=2,";
2855 if(confflags->
enc_uvw) rplstr +=
"UVW=3,";
2856 if(confflags->
enc_hall) rplstr +=
"HALL=4,";
2858 replies.emplace_back(rplstr);
2864 replies.push_back((uint8_t)
conf.hwconf.hwVersion);
2887 replies.emplace_back(this->
conf.motconf.pole_pairs);
2902 replies.emplace_back(this->
curLimits.pid_uq_ud);
2964 std::pair<uint32_t,std::string> ver =
getTmcType();
2965 replies.emplace_back(ver.second,ver.first);
2975 replies.emplace_back(this->
pidPrecision.current_I | (this->pidPrecision.current_P << 1));
2984 replies.emplace_back((uint8_t)this->
getPhiEtype());
2988 replies.emplace_back(
"ext=1,openloop=2,abn=3,hall=5,aenc=6,aencE=7");
2996 replies.emplace_back(this->
curPids.sequentialPI);
3003 replies.emplace_back(std::to_string(this->
conf.hwconf.currentScaler));
3008 replies.emplace_back(this->
abnconf.rdir);
3017 replies.emplace_back(this->
abnconf.npol);
3027 replies.emplace_back((int32_t)(this->
getTemp()*100.0));
3049 replies.emplace_back(
conf.motconf.svpwm);
3067 replies.emplace_back(
"OFF=0,Lowpass=1,Notch=2,Peak=3");
3131 extEncUpdater = std::make_unique<TMC_ExternalEncoderUpdateThread>(
this);
3151 if(
tmc->usingExternalEncoder() && !
tmc->spiPort.isTaken()){
3152 tmc->writeRegAsync(0x1C, (
tmc->getPhiEfromExternalEncoder()));
3158 if(
tmc->initialized)
TIM_HandleTypeDef TIM_TMC
static CommandStatus handleGetFuncSetFunc(const ParsedCommand &cmd, std::vector< CommandReply > &replies, TVal(cls1::*getfunc)(), void(cls2::*setfunc)(TVal), cls *obj)
void registerCommand(const char *cmd, const ID cmdid, const char *help=nullptr, uint32_t flags=0)
virtual void setCommandsEnabled(bool enable)
static CommandStatus handleGetSet(const ParsedCommand &cmd, std::vector< CommandReply > &replies, TVal &value)
void broadcastCommandReply(CommandReply reply, uint32_t cmdId, CMDtype type)
CommandHandler(const char *clsname, uint16_t clsid, uint8_t instance=0)
static void clearError(const Error &error)
static void addError(const Error &error)
std::shared_ptr< Encoder > drvEncoder
SPIDevice(SPIPort &port, OutputPin csPin)
TMC_ExternalEncoderUpdateThread(TMC4671 *tmc)
void writeReg(uint8_t reg, uint32_t dat)
static ClassIdentifier info
void beginSpiTransfer(SPIPort *port)
void setFluxTorque(int16_t flux, int16_t torque)
void saveFlash() override
void setBBM(uint8_t bbml, uint8_t bbmh)
int16_t controlFluxDissipate()
int16_t externalEncoderPhieOffset
TMC_ControlState getState()
void setExternalEncoderAllowed(bool allow)
bool externalEncoderAllowed()
bool allowExternalEncoder
void setLimits(TMC4671Limits limits)
void runOpenLoop(uint16_t ud, uint16_t uq, int32_t speed, int32_t accel, bool torqueMode=false)
bool hasIntegratedEncoder() override
volatile bool encoderIndexHitFlag
void setupFeedForwardVelocity(int32_t gain, int32_t constant)
CommandStatus command(const ParsedCommand &cmd, std::vector< CommandReply > &replies)
uint8_t calibrationFailCount
bool fullCalibrationInProgress
void setEncoderIndexFlagEnabled(bool enabled, bool zeroEncoder=false)
void initializeWithPower()
static std::span< const TMC4671HardwareTypeConf > tmc4671_hw_configs
void setPos(int32_t pos) override
void bangInitEnc(int16_t power)
bool reachedPosition(uint16_t tolerance)
void setPids(TMC4671PIDConf pids)
MotionMode lastMotionMode
const float fluxDissipationLimit
TMC_ControlState requestedState
bool usingExternalEncoder()
void setUdUq(int16_t ud, int16_t uq)
void changeState(TMC_ControlState newState, bool force=false)
const Error lowVoltageError
void replyHardwareVersions(const std::span< const TMC4671HardwareTypeConf > &versions, std::vector< CommandReply > &replies)
void setVelSel(VelSelection vsel, uint8_t mode=0)
void setEncoderType(EncoderType_TMC type)
TIM_HandleTypeDef * externalEncoderTimer
TMC4671BiquadFilters curFilters
MotionMode getMotionMode()
TMC_ControlState laststate
void setBrakeLimits(uint16_t low, uint16_t high)
TMC4671PidPrecision pidPrecision
bool recalibrationRequired
uint16_t encodeEncHallMisc()
void setPhiE_ext(int16_t phiE)
int32_t getTargetVelocity()
void timerElapsed(TIM_HandleTypeDef *htim)
void setStatusFlags(uint32_t flags)
void setFluxTorqueFF(int16_t flux, int16_t torque)
void setBiquadVel(const TMC4671Biquad &filter)
void restoreEncHallMisc(uint16_t val)
static uint16_t encodeMotToInt(TMC4671MotConf mconf)
void setTorque(int16_t torque)
bool calibrateAdcOffset(uint16_t time=500)
int32_t getPosAbs() override
void setStatusMask(StatusFlags mask)
void zeroAbnUsingPhiM(bool offsetPhiE=false)
void setSequentialPI(bool sequential)
const float fluxFilterFreq
const Error indexNotHitError
void setup_AENC(TMC4671AENCConf encconf)
Encoder * getEncoder() override
void setGpioPins(uint8_t pins)
void setMotionMode(MotionMode mode, bool force=false)
void setTargetPos(int32_t pos)
void setMotorType(MotorType motor, uint16_t poles)
int32_t getPos() override
void rampFlux(uint16_t target, uint16_t time_ms)
void setPwm(uint8_t val, uint16_t maxcnt, uint8_t bbmL, uint8_t bbmH)
void setGpioMode(TMC_GpioMode mode)
void endSpiTransfer(SPIPort *port)
void errorCallback(const Error &error, bool cleared)
bool motorEnabledRequested
void setTorqueFilter(TMC4671Biquad_conf &conf)
void emergencyStop(bool reset)
std::pair< int32_t, int32_t > getActualTorqueFlux()
void setup_HALL(TMC4671HALLConf hallconf)
TMC_StartupType startupType
void setTmcPos(int32_t pos)
void setFFMode(FFMode mode)
void setTargetVelocity(int32_t vel)
void setupFeedForwardTorque(int32_t gain, int32_t constant)
void setPhiEtype(PhiE type)
TMC4671(SPIPort &spiport, OutputPin cspin, uint8_t address=1)
void setOpenLoopSpeedAccel(int32_t speed, uint32_t accel)
TMC4671Limits getLimits()
void restoreFlash() override
void updateReg(uint8_t reg, uint32_t dat, uint32_t mask, uint8_t shift)
void setup_ABN_Enc(TMC4671ABNConf encconf)
void setAdcOffset(uint32_t adc_I0_offset, uint32_t adc_I1_offset)
void setPwmMaxCnt(uint16_t maxcnt)
void setCpr(uint32_t cpr)
const Error communicationError
void setBiquadTorque(const TMC4671Biquad &filter)
void setBiquadFlux(const TMC4671Biquad &filter)
uint32_t posToEnc(uint32_t pos)
StatusFlags readFlags(bool maskedOnly=true)
void setUqUdLimit(uint16_t limit)
std::pair< uint32_t, std::string > getTmcType()
void setAddress(uint8_t address)
void exti(uint16_t GPIO_Pin)
void initAdc(uint16_t mdecA, uint16_t mdecB, uint32_t mclkA, uint32_t mclkB)
void setHwType(uint8_t type)
TMC4671Biquad_conf torqueFilterConf
void setPosSel(PosSelection psel)
void setPwmFreq(float freq)
void writeRegAsync(uint8_t reg, uint32_t dat)
int16_t getPhiEfromExternalEncoder()
std::unique_ptr< TMC_ExternalEncoderUpdateThread > extEncUpdater
void setSvPwm(bool enable)
TMC4671FlashAddrs flashAddrs
const ClassIdentifier getInfo()
void setFlux(int16_t flux)
void setPidPrecision(TMC4671PidPrecision setting)
EncoderType getEncoderType() override
MotionMode nextMotionMode
uint32_t readReg(uint8_t reg)
int32_t getActualTorque()
void setBiquadPos(const TMC4671Biquad &filter)
void setAdcScale(uint32_t adc_I0_scale, uint32_t adc_I1_scale)
bool findEncoderIndex(int32_t speed=10, uint16_t power=2500, bool offsetPhiM=false, bool zeroCount=false)
void setEncoder(std::shared_ptr< Encoder > &encoder) override
uint32_t encToPos(uint32_t enc)
void setPositionExt(int32_t pos)
static TMC4671MotConf decodeMotFromInt(uint16_t val)
void setTorqueLimit(uint16_t limit)
static ClassIdentifier info
static bool isCreatable()
static bool isCreatable()
static ClassIdentifier info
uint32_t WaitForNotification(TickType_t Timeout=portMAX_DELAY)
void Delay(const TickType_t Delay)
Thread(const std::string Name, uint16_t StackDepth, UBaseType_t Priority)
bool Flash_Write(uint16_t adr, uint16_t dat)
bool Flash_Read(uint16_t adr, uint16_t *buf, bool checkempty=true)
void blinkClipLed(uint16_t period, uint16_t blinks)
static void * memcpy(void *dst, const void *src, size_t n)
ThermistorSettings thermistorSettings
uint16_t pid_torque_flux_ddt
void setVSenseMult(float vSenseMultiplier)