grbl

config

  1. Inc\my_machine.h中取消注释进行配置
    开启如下配置进行学习
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#define BOARD_BTT_SKR_20          // F407 based 3D Printer board
#define TRINAMIC_ENABLE 5160 // Trinamic TMC5160 stepper driver support.
#define N_AXIS 6
#define TRINAMIC_DYNAMIC_CURRENT
#define TRINAMIC_EXTENDED_SETTINGS
#define TRINAMIC_POLL_STATUS
// 这些选项需要自行配置,不配做使用默认值
#define TMC_DRVCONF
#define TMC_COOLCONF_SEMIN
#define TMC_COOLCONF_SEMAX
#define TMC_COOLCONF_SEDN
#define TMC_COOLCONF_SEUP
#define TMC_COOLCONF_SEIMIN
#define TMC_CHOPCONF_HSTRT
#define TMC_CHOPCONF_HEND
#define TMC_CHOPCONF_TBL
#define TMC_CHOPCONF_TOFF
#define TMC_CHOPCONF_RDNTF
#define TMC_CHOPCONF_CHM
#define TMC_CHOPCONF_HDEC
#define TMC_CHOPCONF_TFD
#define TMC_CHOPCONF_INTPOL

driver_init 驱动初始化

执行各种初始化操作与注册

1
2
3
4
5
6
7
8
9
bool driver_init (void)
{
#include "grbl/plugins_init.h"

#if TRINAMIC_ENABLE
extern bool trinamic_init (void);
trinamic_init();
#endif
}

grbl_enter 主入口

  1. grbl_enter是main函数的主入口
  2. 执行driver_init()进行初始化
  3. 进入protocol_main_loop()主循环
  4. 执行protocol_execute_realtime()实时执行
  5. 执行protocol_exec_rt_system()系统实时执行
  6. 执行grbl.on_execute_realtime(state_get());函数,在grbl_enter中进行注册;即task_execute
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
// main entry point
int grbl_enter (void)
{
grbl.on_execute_realtime = grbl.on_execute_delay = task_execute;
driver.init = driver_init();
while(looping) {
//开始主循环。处理程序输入并执行它们
if(!(looping = protocol_main_loop()))
looping = hal.driver_release == NULL || hal.driver_release();
}
}
/*
GRBL PRIMARY LOOP:
*/
bool protocol_main_loop (void)
{
// ---------------------------------------------------------------------------------
// 主循环!在系统中止时,这将退出回到 main() 以重置系统。
// 这也是 grblHAL 在等待任务时空闲的地方。
// ---------------------------------------------------------------------------------
while(true) {
if(!protocol_execute_realtime() && sys.abort)
return !sys.flags.exit;
if(settings.flags.sleep_enable)
sleep_check();
}
}
bool protocol_execute_realtime (void)
{
if(protocol_exec_rt_system()) {

sys_state_t state = state_get();

if(sys.suspend)
protocol_exec_rt_suspend(state);

#if NVSDATA_BUFFER_ENABLE
if((state == STATE_IDLE || (state & (STATE_ALARM|STATE_ESTOP))) && settings_dirty.is_dirty && !gc_state.file_run)
nvs_buffer_sync_physical();
#endif
}

return !ABORTED;
}
bool protocol_exec_rt_system (void)
{
grbl.on_execute_realtime(state_get());
}
static void task_execute (sys_state_t state)
{
static uint32_t last_ms = 0;

core_task_t *task;
//紧急任务执行
if(immediate_task && sys.driver_started) {

hal.irq_disable();
task = immediate_task;
immediate_task = NULL;
hal.irq_enable();

do {
void *data = task->data;
foreground_task_ptr fn = task->fn;
task_free(task);
fn(data);
} while((task = task->next));
}

uint32_t now = hal.get_elapsed_ticks();
if(now == last_ms || next_task == systick_task)
return;

last_ms = now;
//系统任务执行
if((task = systick_task)) do {
task->fn(task->data);
} while((task = task->next));
//已超时任务执行
while(next_task && (int32_t)(next_task->time - now) <= 0) {

void *data = next_task->data;
foreground_task_ptr fn = next_task->fn;
task_free(next_task);
next_task = next_task->next;

fn(data);
}
}

task API

  • 这些任务是循环执行的,通过task_execute()函数执行
1
2
3
4
5
bool task_add_immediate (foreground_task_ptr fn, void *data);
bool task_add_delayed (foreground_task_ptr fn, void *data, uint32_t delay_ms);
void task_delete (foreground_task_ptr fn, void *data);
bool task_add_systick (foreground_task_ptr fn, void *data);
void task_delete_systick (foreground_task_ptr fn, void *data);

task_add_systick 添加系统任务

  1. 进入中断屏蔽
  2. 通过task_alloc()分配任务,静态数组中分配
  3. 注册执行函数和数据
  4. 任务链表为空则直接添加,否则遍历到链表尾部添加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
ISR_CODE bool ISR_FUNC(task_add_systick)(foreground_task_ptr fn, void *data)
{
core_task_t *task = NULL;

hal.irq_disable();

if(fn && (task = task_alloc())) {

task->fn = fn;
task->data = data;
task->next = NULL;

if(systick_task == NULL)
systick_task = task;
else {
core_task_t *t = systick_task;
while(t->next)
t = t->next;
t->next = task;
}
}

hal.irq_enable();

return task != NULL;
}

gcode G代码解析

gc_execute_block 执行G代码块

  1. grbl.user_mcode.execute(state_get(), &gc_block);执行用户自定义M代码
    • 该部分是TMC注册的mcode_execute执行的地方
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
status_code_t gc_execute_block (char *block)
{
// [9a. User defined M commands ]:
if(gc_block.user_mcode && !check_mode) {

if(gc_block.user_mcode_sync)
protocol_buffer_synchronize(); // Ensure user defined mcode is executed when specified in program.

gc_block.words.mask = user_words.mask;
gc_block.values.f = single_meaning_value.f;
gc_block.values.o = single_meaning_value.o;
gc_block.values.s = single_meaning_value.s;
gc_block.values.t = single_meaning_value.t;
grbl.user_mcode.execute(state_get(), &gc_block);
gc_block.words.mask = 0;
}

}

trinamic

工作模式

  1. StealthChop 2™ 无噪声、高精度斩波算法,用于电机的静止和运动状态下的静音控制。StealthChop2在 StealthChop 的基础上,加快了电机运动加减速特性,降低了所需的电流最小值。
  2. spreadCycle™ 高精度斩波算法,用于高动态电机运动和产生绝对干净的电流波。低噪音、低共振和低振动斩波器。
  3. DcStep™ 与负载相关的速度控制。电机尽可能快地移动,不失步
  4. StallGuard2™ 无传感器的堵转检测和机械负载测量。
  5. CoolStep™ 根据负载自适应电流,可将能耗降低 75 %。
  6. MicroPlyer™ 细分内插器,用于从全步开始,以较低细分输入获得 256 微步的平滑度
  7. StealthChop 2 & SpreadCycle 驱动
    StealthChop 是电压斩波器的原理。除了电机机械滚轮轴承产生的噪音,它特别保证了电机在静止和慢速运行时能绝对安静。不同于其他电压模式斩波器, StealthChop 2 不需要任何配置。通电后,它会在第一次运动中自动学习最佳设置,并进一步优化后续运动中的设置。初始的归零过程足以使系统完成StealthChop 最佳配置。也可以配置初始参数加快自学习过程。StealthChop 2 通过对电机速度的变化立即做出反应,允许高的电机动态

数据结构 *

  1. TMC5160的寄存器地址和数据结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
typedef union {
uint8_t value;
struct {
uint8_t
idx :7,
write :1;
};
} TMC_addr_t;
//数据载荷
typedef union {
uint32_t value;
uint8_t data[4];
} TMC_payload_t;
//将地址和数据结构合并传输
typedef struct {
TMC_addr_t addr;
TMC_payload_t payload;
} TMC_spi_datagram_t;
//将寄存器地址和数据结构读取后,不需要手动解析
tmc_spi_read(driver->config.motor, (TMC_spi_datagram_t *)&driver->drv_status);

TMC SPI

TMC_SPI_Read 读取TMC寄存器

  1. 常规的SPI读取操作;片选拉低,读取数据,片选拉高
  2. 需注意的是,TMC5160的SPI读取是先写入地址读取一次数据;是空数据;第二次读取才是真实数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
TMC_spi_status_t tmc_spi_read (trinamic_motor_t driver, TMC_spi_datagram_t *datagram)
{
TMC_spi_status_t status;

DIGITAL_OUT(cs[driver.id].port, cs[driver.id].pin, 0);
//第一次读取是空数据
datagram->payload.value = 0;

datagram->addr.write = 0;
spi_put_byte(datagram->addr.value);
spi_put_byte(0);
spi_put_byte(0);
spi_put_byte(0);
spi_put_byte(0);

DIGITAL_OUT(cs[driver.id].port, cs[driver.id].pin, 1);
delay();
DIGITAL_OUT(cs[driver.id].port, cs[driver.id].pin, 0);
//第二次读取是真实数据
status = spi_put_byte(datagram->addr.value);
datagram->payload.data[3] = spi_get_byte();
datagram->payload.data[2] = spi_get_byte();
datagram->payload.data[1] = spi_get_byte();
datagram->payload.data[0] = spi_get_byte();

DIGITAL_OUT(cs[driver.id].port, cs[driver.id].pin, 1);

return status;
}

数据结构

  • spi传入数据结构,包含地址和数据
1
2
3
4
5
6
7
typedef struct {
uint8_t id; // motor id
uint8_t axis; // axis index
uint8_t address; // UART address
uint8_t seq; // optional motor sequence number (for chained SPI drivers)
void *cs_pin; // optional CS pin data for the stepper driver
} trinamic_motor_t;

TMC5160.c

TMC5160 文件结构

  1. TMC5160.c中包含了TMC5160的所有操作函数
  2. TMC5160_hal.c中包含了TMC5160的所有操作函数,对TMC5160.c进行了封装,与tmchal_t结构体进行了绑定

TMC5160_Init 初始化TMC5160

  1. 通过SPI读取drv_status寄存器,检查是否读取到值,判断SPI是否正常
  2. 执行状态寄存器读取以清除重置标志
  3. 写入配置寄存器

tmc_microsteps_to_mres 微步转分辨率

TMC5160_SetDefaults 设置TMC5160默认值

1
2
static const TMC5160_t tmc5160_defaults ;
//通过默认的结构体传入默认值

TMC5160_AddMotor 添加TMC5160电机

1
const tmchal_t *TMC5160_AddMotor (motor_map_t motor, uint16_t current, uint8_t microsteps, uint8_t r_sense);

stealthChop 斩波器配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
static void stealthChop (uint8_t motor, bool on)
{
tmcdriver[motor]->config.mode = on ? TMCMode_StealthChop : TMCMode_CoolStep;

if(on)
stealthChopEnable(motor);
else
coolStepEnable(motor);
}
static void stealthChopEnable (uint8_t motor)
{
TMC5160_t *driver = tmcdriver[motor];

driver->gconf.reg.diag1_stall = false;
driver->gconf.reg.en_pwm_mode = true; // stealthChop
tmc_spi_write(driver->config.motor, (TMC_spi_datagram_t *)&driver->gconf);

driver->pwmconf.reg.pwm_autoscale = true;
tmc_spi_write(driver->config.motor, (TMC_spi_datagram_t *)&driver->pwmconf);

setTCoolThrsRaw(motor, 0);
}

static void coolStepEnable (uint8_t motor)
{
TMC5160_t *driver = tmcdriver[motor];

driver->gconf.reg.en_pwm_mode = false; // stealthChop
tmc_spi_write(driver->config.motor, (TMC_spi_datagram_t *)&driver->gconf);

driver->pwmconf.reg.pwm_autoscale = false;
tmc_spi_write(driver->config.motor, (TMC_spi_datagram_t *)&driver->pwmconf);

setTCoolThrsRaw(motor, 0);
}

trinamic.c

trinamic_drivers_init 驱动初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
static void trinamic_drivers_init (axes_signals_t axes)
{
bool ok = axes.value != 0;
uint_fast8_t motor = n_motors, n_enabled = 0, seq = 0;

memset(stepper, 0, sizeof(stepper));
// 获取电机的数量与使能掩码
do {
if(bit_istrue(axes.mask, bit(motor_map[--motor].axis)))
seq++;
} while(motor);

motor = n_motors;
*min_current = '\0';
// 配置电机
do {
if(bit_istrue(axes.mask, bit(motor_map[--motor].axis))) {
if((ok = trinamic_driver_config(motor_map[motor], --seq))) {
n_enabled++;
if(*min_current == '\0') {
strcpy(min_current, uitoa(stepper[motor_map[motor].id]->get_current(motor_map[motor].id, TMCCurrent_Min)));
strcpy(max_current, uitoa(stepper[motor_map[motor].id]->get_current(motor_map[motor].id, TMCCurrent_Max)));
}
}
}
} while(ok && motor);
//如果 ok 为真,则传递 n_enabled;否则传递 0
tmc_motors_set(ok ? n_enabled : 0);

if(!ok) {
driver_enabled.mask = 0;
memset(stepper, 0, sizeof(stepper));
}
#if TRINAMIC_POLL_STATUS || TRINAMIC_DYNAMIC_CURRENT
else {
#if TRINAMIC_POLL_STATUS
//添加轮询状态任务
task_add_delayed(trinamic_poll_status, NULL, TRINAMIC_POLL_INTERVAL);
#endif
#if TRINAMIC_DYNAMIC_CURRENT
//先调用dynamic_current_pulse_start中判断电流并设置后再去调用stepper_block_start
if(stepper_block_start == NULL) {
stepper_block_start = hal.stepper.pulse_start;
hal.stepper.pulse_start = dynamic_current_pulse_start;
}
#endif
}
#endif
}

set_axis_setting 轴设置

  1. 可以通过此配置函数设置电机的电流、保持电流、微步数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
// Parse and set driver specific parameters
static status_code_t set_axis_setting (setting_id_t setting, uint_fast16_t value)
{
uint_fast8_t axis, motor = n_motors;
status_code_t status = Status_OK;

switch(settings_get_axis_base(setting, &axis)) {

case Setting_AxisStepperCurrent:
trinamic.driver[axis].current = (uint16_t)value;
do {
motor--;
if(stepper[motor] && stepper[motor]->get_config(motor)->motor.axis == axis) {
stepper[motor]->set_current(motor, trinamic.driver[axis].current, trinamic.driver[axis].hold_current_pct);
#if TRINAMIC_DYNAMIC_CURRENT
reduced_current[motor] = trinamic.driver[axis].current * trinamic.driver[axis].hold_current_pct / 100;
#endif
}
} while(motor);
break;

case TMCsetting_HoldCurrentPct: // Hold current percentage
if(value > 100)
value = 100;
trinamic.driver[axis].hold_current_pct = (uint16_t)value;
do {
motor--;
if(stepper[motor] && stepper[motor]->get_config(motor)->motor.axis == axis) {
stepper[motor]->set_current(motor, trinamic.driver[axis].current, trinamic.driver[axis].hold_current_pct);
#if TRINAMIC_DYNAMIC_CURRENT
reduced_current[motor] = trinamic.driver[axis].current * trinamic.driver[axis].hold_current_pct / 100;
#endif
}
} while(motor);
break;

case Setting_AxisMicroSteps:
do {
motor--;
if(stepper[motor] && stepper[motor]->get_config(motor)->motor.axis == axis) {
if(stepper[motor]->microsteps_isvalid(motor, (uint16_t)value)) {
trinamic.driver[axis].microsteps = value;
stepper[motor]->set_microsteps(motor, trinamic.driver[axis].microsteps);
if(report.sg_status_motormask.mask & bit(axis))
report.msteps = trinamic.driver[axis].microsteps;
} else {
status = Status_InvalidStatement;
break;
}
}
} while(motor);
break;

default:
status = Status_Unhandled;
break;
}

return status;
}

trinamic_settings_get_defaults 获取默认设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
static void trinamic_settings_get_defaults (bool cap_only)
{
const trinamic_cfg_params_t *params;

params = TMC5160_GetConfigDefaults();

memcpy(&cfg_cap, &params->cap, sizeof(trinamic_cfg_t));

if(!cap_only)
memcpy(cfg_params, &params->dflt, sizeof(trinamic_cfg_t));
//这些选项允许在编译时覆盖默认设置
#ifdef TMC_DRVCONF
cfg_params->drvconf = TMC_DRVCONF;
#endif
#ifdef TMC_COOLCONF_SEMIN
cfg_params->coolconf.semin = TMC_COOLCONF_SEMIN & cfg_cap.coolconf.semin;
#endif
#ifdef TMC_COOLCONF_SEMAX
cfg_params->coolconf.semax = TMC_COOLCONF_SEMAX & cfg_cap.coolconf.semax;
#endif
#ifdef TMC_COOLCONF_SEDN
cfg_params->coolconf.sedn = TMC_COOLCONF_SEDN & cfg_cap.coolconf.sedn;
#endif
#ifdef TMC_COOLCONF_SEUP
cfg_params->coolconf.seup = TMC_COOLCONF_SEUP & cfg_cap.coolconf.seup;
#endif
#ifdef TMC_COOLCONF_SEIMIN
cfg_params->coolconf.seimin = TMC_COOLCONF_SEIMIN & cfg_cap.coolconf.seimin;
#endif

#ifdef TMC_CHOPCONF_HSTRT
cfg_params->chopconf.hstrt = (TMC_CHOPCONF_HSTRT - 1) & cfg_cap.chopconf.hstrt;
#endif
#ifdef TMC_CHOPCONF_HEND
cfg_params->chopconf.hend = (TMC_CHOPCONF_HEND + 3) & cfg_cap.chopconf.hend;
#endif
#ifdef TMC_CHOPCONF_TBL
cfg_params->chopconf.tbl = TMC_CHOPCONF_TBL & cfg_cap.chopconf.tbl;
#endif
#ifdef TMC_CHOPCONF_TOFF
cfg_params->chopconf.toff = TMC_CHOPCONF_TOFF & cfg_cap.chopconf.toff;
#endif
#ifdef TMC_CHOPCONF_RDNTF
cfg_params->chopconf.rndtf = TMC_CHOPCONF_RDNTF & cfg_cap.chopconf.rndtf;
#endif
#ifdef TMC_CHOPCONF_CHM
cfg_params->chopconf.chm = TMC_CHOPCONF_CHM & cfg_cap.chopconf.chm;
#endif
#ifdef TMC_CHOPCONF_HDEC
cfg_params->chopconf.hdec = TMC_CHOPCONF_HDEC & cfg_cap.chopconf.hdec;
#endif
#ifdef TMC_CHOPCONF_TFD
cfg_params->chopconf.tfd = TMC_CHOPCONF_TFD & cfg_cap.chopconf.tfd;
#endif
#ifdef TMC_CHOPCONF_INTPOL
cfg_params->chopconf.intpol = TMC_CHOPCONF_INTPOL & cfg_cap.chopconf.intpol;
#endif

vsense[0] = params->vsense[0] / 1000.0f;
vsense[1] = params->vsense[1] / 1000.0f;
custom_drvconf = cfg_params->drvconf != params->dflt.drvconf;
}

trinamic_driver_config 驱动器配置

  1. cfg.settings = &trinamic.driver[motor.axis];trinamic从set_axis_setting函数中配置
  2. cfg_params参数通过trinamic_settings_get_defaults配置为默认值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
static bool trinamic_driver_config (motor_map_t motor, uint8_t seq)
{
bool ok = false;
trinamic_driver_config_t cfg = {
.address = motor.id,
.settings = &trinamic.driver[motor.axis]
};
// 驱动程序需要进行读取的预配置,则进行进去操作
if(driver_if.on_driver_preinit)
driver_if.on_driver_preinit(motor, &cfg);

#if TRINAMIC_ENABLE == 5160
//通过TMC5160_AddMotor添加电机,将电机的操作指针保存到stepper[motor.id]中
ok = (stepper[motor.id] = TMC5160_AddMotor(motor, cfg.settings->current, cfg.settings->microsteps, cfg.settings->r_sense)) != NULL;
#endif

if(!ok) {
//流数据打印信息
protocol_enqueue_foreground_task(report_warning, "Could not communicate with stepper driver!");
return false;
}
//设置电机的序列号
stepper[motor.id]->get_config(motor.id)->motor.seq = seq;
//设置使能掩码
driver_enabled.mask |= bit(motor.axis);
//启用扩展设置,并且用户配置了drvconf,则执行写入drvconf寄存器
#if TRINAMIC_EXTENDED_SETTINGS
if(cfg_cap.drvconf && custom_drvconf)
stepper[motor.id]->write_register(motor.id, stepper[motor.id]->drvconf_address, cfg_params->drvconf);
#endif
//设置StallGuard2 滤波器使能,写入coolconf寄存器中
//! 注意开启后,无法更快的响应,就是速度会变慢
stepper[motor.id]->sg_filter(motor.id, 1);

stepper[motor.id]->coolconf(motor.id, cfg_params->coolconf);
// 斩波器配置
stepper[motor.id]->chopper_timing(motor.id, cfg_params->chopconf);
// stealthChop 和 coolStep配置;二选一
if(stepper[motor.id]->stealthChop)
stepper[motor.id]->stealthChop(motor.id, cfg.settings->mode == TMCMode_StealthChop);
else if(cfg.settings->mode == TMCMode_StealthChop)
cfg.settings->mode = TMCMode_CoolStep;

#if PWM_THRESHOLD_VELOCITY > 0
//spreadCycle 高动态设置
stepper[motor.id]->set_tpwmthrs(motor.id, (float)PWM_THRESHOLD_VELOCITY / 60.0f, settings.axis[motor.axis].steps_per_mm);
#endif
stepper[motor.id]->set_current(motor.id, cfg.settings->current, cfg.settings->hold_current_pct);
stepper[motor.id]->set_microsteps(motor.id, cfg.settings->microsteps);

#if TRINAMIC_DYNAMIC_CURRENT
//动态电流设置
reduced_current[motor.id] = cfg.settings->current * cfg.settings->hold_current_pct / 100;
#endif

if(driver_if.on_driver_postinit)
driver_if.on_driver_postinit(motor, stepper[motor.id]);

return true;
}

trinamic_poll_status 轮询状态 ???

??? st_wake_up 和 st_go_idle是什么
??? CMD_FEED_HOLD

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

static void trinamic_poll_status (void *data)
{
static bool error_active = false, error_hold = false;
static uint32_t error_count = 0;
static hold_state_t holding_state = Hold_NotHolding;

uint_fast8_t motor = n_motors;
uint8_t stall_fault = 0, otpw_fault = 0;
sys_state_t current_state = state_get(); // 获取当前系统状态

// 调度下一次轮询
task_add_delayed(trinamic_poll_status, NULL, TRINAMIC_POLL_INTERVAL);

do {
if(stepper[--motor]) { // 检查电机是否存在

// 如果系统处于空闲状态,检查驱动器状态
if(current_state == STATE_IDLE)
status[motor] = stepper[motor]->get_drv_status(motor);
// 处理保持状态
else if(current_state == STATE_HOLD && holding_state == Hold_Pending && sys.holding_state == Hold_Complete) {
holding_state == Hold_Complete; // 如果主轴正在运行并由于重力下拉而降低自己,这可能是危险的,所以暂时禁用。
st_go_idle(); // 进入空闲状态
}

// 检查是否有过温警告
if(status[motor].otpw)
otpw_fault |= (1 << motor);
/* if(status[motor].stallguard) // 检查是否卡住
stall_fault |= (1 << motor); */

#if TRINAMIC_DYNAMIC_CURRENT
uint_fast8_t axis = motor_map[motor].axis;
// 如果系统处于空闲或报警/保持状态,调整电流
if((current_state == STATE_IDLE || (current_state & (STATE_ALARM|STATE_HOLD))) && dynamic_current[motor] == trinamic.driver[axis].current)
stepper[motor]->set_current(motor, (dynamic_current[motor] = reduced_current[motor]), trinamic.driver[axis].hold_current_pct);
#endif
}
} while(motor); // 遍历所有电机

// 处理故障
if(stall_fault || otpw_fault) {
if(++error_count > 2 && !error_active) { // 如果错误计数超过2且错误未激活
error_active = true;
if(current_state & (STATE_CYCLE|STATE_HOMING|STATE_JOG)) {
// holding_state == Hold_Pending;
grbl.enqueue_realtime_command(CMD_FEED_HOLD); // 发送实时命令以暂停进给
}
task_add_immediate(trinamic_status_report, NULL); // 立即添加任务以报告状态,流数据打印信息
}
} else if(error_active) { // 如果错误已激活
error_active = false;
error_count = 0;
if(holding_state != Hold_NotHolding) {
holding_state = Hold_NotHolding;
st_wake_up(); // 唤醒系统
}
}
}

trinamic_init 初始化

// motor_iterator通过driver_init中注册

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
bool trinamic_init (void)
{
// 注册电机配置
static setting_details_t settings_details = {
// 电机配置
.settings = trinamic_settings,
// 电机配置数量
.n_settings = sizeof(trinamic_settings) / sizeof(setting_detail_t),
#ifndef NO_SETTINGS_DESCRIPTIONS //不需要描述信息
.descriptions = trinamic_settings_descr, // 电机配置描述
.n_descriptions = sizeof(trinamic_settings_descr) / sizeof(setting_descr_t),
#endif
.load = trinamic_settings_load, // 电机配置加载
.save = trinamic_settings_save, // 电机配置保存
.restore = trinamic_settings_restore // 电机配置恢复
};
// 几个电机需要配置,通过此逻辑进行配置
if(hal.stepper.motor_iterator) { //动态配置电机,依靠motor_iterator传递
hal.stepper.motor_iterator(count_motors);
if((motor_map = malloc(n_motors * sizeof(motor_map_t)))) {
n_motors = 0;
hal.stepper.motor_iterator(assign_motors);
}
} else { //静态配置电机 依靠Inc\my_machine.h中的配置
motor_map = malloc(N_AXIS * sizeof(motor_map_t));
if(motor_map) {
uint_fast8_t idx;
// n_motors = N_AXIS;
for(idx = 0; idx < N_AXIS; idx++) {
motor_map[idx].id = idx;
motor_map[idx].axis = idx;
}
n_motors = idx;
}
}
// 注册一堆函数
if(motor_map && (nvs_address = nvs_alloc(sizeof(trinamic_settings_t)))) {

memcpy(&user_mcode, &grbl.user_mcode, sizeof(user_mcode_ptrs_t));

grbl.user_mcode.check = mcode_check;
grbl.user_mcode.validate = mcode_validate;
grbl.user_mcode.execute = mcode_execute;

on_realtime_report = grbl.on_realtime_report;
grbl.on_realtime_report = onRealtimeReport;

on_report_options = grbl.on_report_options;
grbl.on_report_options = onReportOptions;

driver_setup = hal.driver_setup;
hal.driver_setup = onDriverSetup;

settings_changed = hal.settings_changed;
hal.settings_changed = onSettingsChanged;

limits_enable = hal.limits.enable;
hal.limits.enable = limitsEnable;

hal.homing.get_feedrate = homingGetFeedrate;

settings_register(&settings_details);

#if TRINAMIC_I2C
stepper_enable = hal.stepper.enable;
hal.stepper.enable = stepperEnable;
#endif
}
}

mcode_execute M代码执行