48 uint16_t run_current_ma, uint16_t hold_current_ma, uint8_t& irun, uint8_t& ihold,
49 uint16_t& global_scaler)
noexcept {
51 if (sense_resistor_mohm == 0 || supply_voltage_mv == 0) {
56 if (run_current_ma == 0) {
57 run_current_ma = motor_spec.rated_current_ma;
59 if (run_current_ma == 0) {
64 if (hold_current_ma == 0) {
65 float hold_current_float = run_current_ma * 0.3F;
66 hold_current_ma =
static_cast<uint16_t
>(hold_current_float);
78 float i_rms_max_ma = ((VFS_MV /
static_cast<float>(sense_resistor_mohm)) / SQRT2) * 1000.0F;
81 if (
static_cast<float>(run_current_ma) > i_rms_max_ma * 1.1F) {
100 float global_scaler_float =
101 (
static_cast<float>(run_current_ma) * 256.0F) / std::max(i_rms_max_ma, 1.0F);
104 auto calculated_scaler =
static_cast<uint16_t
>(std::round(global_scaler_float));
105 calculated_scaler = std::max<uint16_t>(calculated_scaler, 32);
106 calculated_scaler = std::min<uint16_t>(calculated_scaler, 256);
110 uint8_t optimal_irun = 31;
111 uint16_t optimal_scaler = calculated_scaler;
113 if (calculated_scaler >= 200) {
115 for (uint8_t test_irun = 30; test_irun >= 16; --test_irun) {
117 float test_scaler_float =
118 (
static_cast<float>(run_current_ma) * 256.0F * 32.0F) /
119 (
static_cast<float>(test_irun + 1) * std::max(i_rms_max_ma, 1.0F));
120 auto test_scaler =
static_cast<uint16_t
>(std::round(test_scaler_float));
122 if (test_scaler >= 32 && test_scaler <= 200) {
123 optimal_irun = test_irun;
124 optimal_scaler = test_scaler;
131 if (optimal_irun < 8) {
135 (
static_cast<float>(run_current_ma) * 256.0F * 32.0F) / (9.0F * std::max(i_rms_max_ma, 1.0F));
136 optimal_scaler =
static_cast<uint16_t
>(std::round(scaler_float));
137 optimal_scaler = std::max<uint16_t>(optimal_scaler, 32);
138 optimal_scaler = std::min<uint16_t>(optimal_scaler, 256);
147 ((
static_cast<float>(hold_current_ma) * 256.0F * 32.0F) /
148 (
static_cast<float>(optimal_scaler) * std::max(i_rms_max_ma, 1.0F))) -
151 auto calculated_ihold =
static_cast<uint8_t
>(std::round(ihold_float));
154 calculated_ihold = std::min<uint8_t>(calculated_ihold, 31);
155 if (calculated_ihold >= optimal_irun) {
156 calculated_ihold = (optimal_irun > 0) ? (optimal_irun - 1) : 0;
160 ihold = calculated_ihold;
161 global_scaler = optimal_scaler;
184 uint8_t pwm_freq, uint32_t f_clk = 12000000U) noexcept {
190 constexpr std::array<uint8_t, 4> blank_times = {16, 24, 36, 54};
191 const uint8_t tbl_index = std::min(tbl,
static_cast<uint8_t
>(3));
192 uint8_t t_blank = blank_times[tbl_index];
195 constexpr std::array<uint32_t, 4> pwm_divisors = {1024, 683, 512, 410};
196 const uint8_t pwm_freq_index = std::min(pwm_freq,
static_cast<uint8_t
>(3));
197 uint32_t pwm_divisor = pwm_divisors[pwm_freq_index];
201 float f_pwm = (2.0F *
static_cast<float>(f_clk)) /
static_cast<float>(pwm_divisor);
208 float t_blank_sec =
static_cast<float>(t_blank) /
static_cast<float>(f_clk);
209 float i_lower_ma = (t_blank_sec * f_pwm *
static_cast<float>(supply_voltage_mv)) /
212 return static_cast<uint16_t
>(i_lower_ma);
301 if (voltage_mv == 0) {
306 if (voltage_mv < 400 || voltage_mv > 2000) {
311 if (supply_voltage_mv > 52000 && voltage_mv < 1200) {
319 if (voltage_mv <= 625) {
321 if (voltage_mv < 400) {
324 float level = 2.0F + ((
static_cast<float>(voltage_mv - 400) / 225.0F) * 4.0F);
325 return static_cast<uint8_t
>(std::round(level));
328 float level = 6.0F + ((
static_cast<float>(voltage_mv - 625) / 935.0F) * 9.0F);
329 auto calculated =
static_cast<uint8_t
>(std::round(level));
330 return std::min(
static_cast<uint8_t
>(15), std::max(
static_cast<uint8_t
>(2), calculated));
uint8_t CalculateS2GLevel(uint16_t voltage_mv, uint32_t supply_voltage_mv=0) noexcept
Calculate S2G_LEVEL register value from voltage threshold.
Definition tmc51x0_motor_calc.hpp:300
uint8_t CalculateShortDelay(uint8_t delay_us_x10) noexcept
Calculate shortdelay register bit from detection delay time.
Definition tmc51x0_motor_calc.hpp:347
uint8_t CalculateS2VSLevel(uint16_t voltage_mv) noexcept
Calculate S2VS_LEVEL register value from voltage threshold.
Definition tmc51x0_motor_calc.hpp:253
bool CalculateMotorCurrent(const MotorSpec &motor_spec, uint32_t sense_resistor_mohm, uint32_t supply_voltage_mv, uint16_t run_current_ma, uint16_t hold_current_ma, uint8_t &irun, uint8_t &ihold, uint16_t &global_scaler) noexcept
Calculate motor current settings from physical parameters.
Definition tmc51x0_motor_calc.hpp:47
uint16_t CalculateStealthChopLowerLimit(const MotorSpec &motor_spec, uint32_t supply_voltage_mv, uint8_t tbl, uint8_t pwm_freq, uint32_t f_clk=12000000U) noexcept
Calculate StealthChop lower current limit.
Definition tmc51x0_motor_calc.hpp:183