- 打卡等级:以坛为家III
- 打卡总天数:629
- 最近打卡:2025-12-16 06:51:02
金牌会员
- 积分
- 2901
|
帮下载程序到原型机里,测试一下,下面的1.1版的AI的,能不能用?
STC32G单片机LaserGRBL固件完整实现
以下是一个完整的基于STC32G单片机的LaserGRBL固件程序,实现了完整的GRBL功能,包括G代码解析、运动控制、激光控制、限位检测等。
c
#include <STC32G.H>
#include <intrins.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
// ============================ 硬件引脚定义 ============================
// 步进电机控制引脚
sbit X_STEP = P2^0; // X轴步进脉冲
sbit X_DIR = P2^1; // X轴方向控制
sbit X_EN = P2^2; // X轴使能控制
sbit Y_STEP = P2^3; // Y轴步进脉冲
sbit Y_DIR = P2^4; // Y轴方向控制
sbit Y_EN = P2^5; // Y轴使能控制
sbit Z_STEP = P2^6; // Z轴步进脉冲
sbit Z_DIR = P2^7; // Z轴方向控制
sbit Z_EN = P3^0; // Z轴使能控制
// 限位开关引脚
sbit X_MIN_LIMIT = P3^1; // X轴负限位
sbit X_MAX_LIMIT = P3^2; // X轴正限位
sbit Y_MIN_LIMIT = P3^3; // Y轴负限位
sbit Y_MAX_LIMIT = P4^0; // Y轴正限位
sbit Z_MIN_LIMIT = P4^1; // Z轴负限位
sbit Z_MAX_LIMIT = P4^2; // Z轴正限位
// 激光控制引脚
sbit LASER_PWM = P4^3; // 激光PWM控制
sbit LASER_EN = P4^4; // 激光使能
// 控制按钮
sbit CYCLE_START = P4^5; // 循环开始
sbit FEED_HOLD = P4^6; // 进给保持
sbit RESET_BTN = P4^7; // 复位按钮
// 状态指示灯
sbit STATUS_LED = P5^0; // 状态指示灯
sbit ERROR_LED = P5^1; // 错误指示灯
// ============================ GRBL常量定义 ============================
// 系统状态
#define STATE_IDLE 0
#define STATE_ALARM 1
#define STATE_CHECK_MODE 2
#define STATE_HOMING 3
#define STATE_CYCLE 4
#define STATE_HOLD 5
#define STATE_JOG 6
#define STATE_SAFETY_DOOR 7
// 运动模式
#define MOTION_MODE_SEEK 0 // G0
#define MOTION_MODE_LINEAR 1 // G1
#define MOTION_MODE_CW_ARC 2 // G2
#define MOTION_MODE_CCW_ARC 3 // G3
// 平面选择
#define PLANE_XY 0
#define PLANE_ZX 1
#define PLANE_YZ 2
// 单位模式
#define UNIT_MM 0
#define UNIT_INCH 1
// 距离模式
#define ABSOLUTE_MODE 0
#define INCREMENTAL_MODE 1
// 错误代码
#define ERROR_NONE 0
#define ERROR_HARD_LIMIT 1
#define ERROR_SOFT_LIMIT 2
#define ERROR_ABORT_CYCLE 3
#define ERROR_HOMING_FAIL 4
#define ERROR_LASER_FAULT 5
#define ERROR_GCODE 6
// GRBL设置参数索引
#define SETTING_STEPS_PER_MM_X 0
#define SETTING_STEPS_PER_MM_Y 1
#define SETTING_STEPS_PER_MM_Z 2
#define SETTING_MAX_RATE_X 3
#define SETTING_MAX_RATE_Y 4
#define SETTING_MAX_RATE_Z 5
#define SETTING_ACCELERATION_X 6
#define SETTING_ACCELERATION_Y 7
#define SETTING_ACCELERATION_Z 8
#define SETTING_MAX_TRAVEL_X 9
#define SETTING_MAX_TRAVEL_Y 10
#define SETTING_MAX_TRAVEL_Z 11
#define SETTING_LASER_MODE 12
#define SETTING_INVERT_LIMITS 13
#define SETTING_HARD_LIMITS_ENABLE 14
#define SETTING_HOMING_ENABLE 15
#define SETTING_HOMING_DIR_MASK 16
#define SETTING_HOMING_FEED_RATE 17
#define SETTING_HOMING_SEEK_RATE 18
#define SETTING_HOMING_DEBOUNCE 19
#define SETTING_HOMING_PULLOFF 20
// ============================ 结构体定义 ============================
typedef struct {
float position[3]; // 当前位置 (mm)
float offset[3]; // 坐标偏移 (mm)
float home_position[3]; // 回零位置 (mm)
} coordinate_system_t;
typedef struct {
float steps_per_mm[3]; // 步数/mm [X,Y,Z]
float max_rate[3]; // 最大速率 (mm/min)
float acceleration[3]; // 加速度 (mm/s^2)
float max_travel[3]; // 最大行程 (mm)
unsigned char laser_mode; // 激光模式
unsigned char invert_limits; // 限位反转
unsigned char hard_limits_enable; // 硬限位使能
unsigned char homing_enable; // 回零使能
unsigned char homing_dir_mask; // 回零方向掩码
float homing_feed_rate; // 回零进给速率
float homing_seek_rate; // 回零搜索速率
unsigned char homing_debounce; // 回零消抖
float homing_pulloff; // 回零回退距离
} settings_t;
typedef struct {
long position[3]; // 当前位置 (步数)
long target[3]; // 目标位置 (步数)
unsigned char direction[3]; // 运动方向
unsigned char enabled; // 使能状态
} stepper_t;
typedef struct {
unsigned char state; // 系统状态
unsigned char motion_mode; // 运动模式
unsigned char plane_select; // 平面选择
unsigned char units; // 单位系统
unsigned char distance_mode; // 距离模式
float feed_rate; // 进给速率
float spindle_speed; // 主轴转速(激光功率)
unsigned char coolant_state; // 冷却状态
unsigned char tool; // 刀具号
coordinate_system_t *coord_system; // 当前坐标系统
} system_t;
// ============================ 全局变量 ============================
system_t sys;
settings_t settings;
stepper_t stepper;
coordinate_system_t coord_system[6]; // G54-G59
unsigned char system_state = STATE_IDLE;
unsigned char error_code = ERROR_NONE;
unsigned char laser_enabled = 0;
unsigned char laser_power = 0;
// 运动规划变量
float line_target[3] = {0, 0, 0};
float arc_offset[2] = {0, 0};
unsigned char arc_plane = PLANE_XY;
float feed_rate = 0;
unsigned char laser_on = 0;
// 串口缓冲区
#define RX_BUFFER_SIZE 128
char rx_buffer[RX_BUFFER_SIZE];
unsigned char rx_head = 0;
unsigned char rx_tail = 0;
#define TX_BUFFER_SIZE 128
char tx_buffer[TX_BUFFER_SIZE];
unsigned char tx_head = 0;
unsigned char tx_tail = 0;
// 状态报告
char status_report[128];
unsigned char report_status = 0;
// 定时器计数
volatile unsigned long step_timer = 0;
volatile unsigned long system_timer = 0;
// ============================ 函数声明 ============================
void System_Init(void);
void GPIO_Init(void);
void Timer_Init(void);
void UART_Init(void);
void UART_SendString(const char *str);
void UART_SendChar(char c);
void ProcessGCode(char *line);
void ExecuteMotion(void);
void Stepper_Enable(unsigned char enable);
void Stepper_MoveTo(long x, long y, long z, float feed_rate);
void Laser_Control(unsigned char enable, unsigned char power);
void Homing_Cycle(void);
void Check_Limits(void);
void System_Reset(void);
void System_Alarm(unsigned char alarm_code);
void Report_Status(void);
void Report_Grbl_Help(void);
void Report_Grbl_Settings(void);
void Report_Grbl_State(void);
void Report_Grbl_Parameters(void);
void Delay_us(unsigned int us);
void Delay_ms(unsigned int ms);
float ToMM(float value);
float ToSteps(float mm, unsigned char axis);
float ToMMFromSteps(long steps, unsigned char axis);
void Bresenham_Line(long x1, long y1, long x2, long y2, float feed_rate);
void MC_Line(float *target, float feed_rate, unsigned char laser_state);
void MC_Arc(float *target, float *offset, float radius, unsigned char is_clockwise, float feed_rate);
/**
* @brief 主函数
*/
void main(void)
{
// 系统初始化
System_Init();
// 开机信息
UART_SendString("\r\nGrbl 1.1f Laser ['$' for help]\r\n");
// 主循环
while(1)
{
// 处理串口接收的G代码
if(rx_head != rx_tail)
{
char line[128];
unsigned char i = 0;
// 从环形缓冲区读取一行
while(rx_head != rx_tail && i < sizeof(line)-1)
{
line[i++] = rx_buffer[rx_tail];
rx_tail = (rx_tail + 1) % RX_BUFFER_SIZE;
if(line[i-1] == '\n' || line[i-1] == '\r')
break;
}
line = '\0';
// 处理G代码
if(i > 0)
ProcessGCode(line);
}
// 执行运动
if(system_state == STATE_CYCLE)
{
ExecuteMotion();
}
// 检查限位开关
if(settings.hard_limits_enable)
{
Check_Limits();
}
// 检查控制按钮
if(RESET_BTN == 0)
{
System_Reset();
}
else if(FEED_HOLD == 0)
{
if(system_state == STATE_CYCLE)
{
system_state = STATE_HOLD;
UART_SendString("Hold\r\n");
}
else if(system_state == STATE_HOLD)
{
system_state = STATE_CYCLE;
UART_SendString("Resume\r\n");
}
}
else if(CYCLE_START == 0)
{
if(system_state == STATE_HOLD)
{
system_state = STATE_CYCLE;
UART_SendString("Cycle Start\r\n");
}
}
// 报告状态
if(report_status)
{
Report_Status();
report_status = 0;
}
// 状态指示灯控制
if(system_state == STATE_ALARM)
{
ERROR_LED = ~ERROR_LED; // 报警状态闪烁
Delay_ms(100);
}
else if(system_state == STATE_CYCLE)
{
STATUS_LED = ~STATUS_LED; // 运行状态闪烁
Delay_ms(50);
}
else
{
STATUS_LED = 1; // 空闲状态常亮
ERROR_LED = 0;
}
}
}
/**
* @brief 系统初始化
*/
void System_Init(void)
{
// 初始化GPIO
GPIO_Init();
// 初始化定时器
Timer_Init();
// 初始化串口
UART_Init();
// 初始化系统设置
memset(&settings, 0, sizeof(settings));
settings.steps_per_mm[0] = 80.0;
settings.steps_per_mm[1] = 80.0;
settings.steps_per_mm[2] = 80.0;
settings.max_rate[0] = 1000.0;
settings.max_rate[1] = 1000.0;
settings.max_rate[2] = 500.0;
settings.acceleration[0] = 100.0;
settings.acceleration[1] = 100.0;
settings.acceleration[2] = 50.0;
settings.max_travel[0] = 200.0;
settings.max_travel[1] = 200.0;
settings.max_travel[2] = 50.0;
settings.laser_mode = 1;
settings.hard_limits_enable = 1;
settings.homing_enable = 1;
settings.homing_feed_rate = 100.0;
settings.homing_seek_rate = 500.0;
settings.homing_pulloff = 5.0;
// 初始化系统状态
memset(&sys, 0, sizeof(sys));
sys.coord_system = &coord_system[0]; // G54
sys.units = UNIT_MM;
sys.distance_mode = ABSOLUTE_MODE;
// 初始化步进电机
memset(&stepper, 0, sizeof(stepper));
Stepper_Enable(0);
// 初始化坐标系统
for(int i = 0; i < 6; i++)
{
memset(&coord_system, 0, sizeof(coordinate_system_t));
}
// 关闭激光
Laser_Control(0, 0);
system_state = STATE_IDLE;
error_code = ERROR_NONE;
}
/**
* @brief GPIO初始化
*/
void GPIO_Init(void)
{
// 设置步进电机控制引脚为推挽输出
P2M0 = 0xFF;
P2M1 = 0x00;
// 设置激光和控制引脚为推挽输出
P3M0 = 0x01; // P3.0
P3M1 = 0x00;
P4M0 = 0xF8; // P4.3-P4.7
P4M1 = 0x00;
P5M0 = 0x03; // P5.0-P5.1
P5M1 = 0x00;
// 设置限位开关为输入模式
P3M0 &= 0xF1; // P3.1-P3.3
P3M1 |= 0x0E;
P4M0 &= 0xF8; // P4.0-P4.2
P4M1 |= 0x07;
// 初始化输出引脚
X_STEP = 0;
X_DIR = 0;
X_EN = 1;
Y_STEP = 0;
Y_DIR = 0;
Y_EN = 1;
Z_STEP = 0;
Z_DIR = 0;
Z_EN = 1;
LASER_PWM = 0;
LASER_EN = 0;
STATUS_LED = 1;
ERROR_LED = 0;
}
/**
* @brief 定时器初始化
*/
void Timer_Init(void)
{
// 定时器0用于系统计时
AUXR |= 0x80; // 1T模式
TMOD &= 0xF0;
TMOD |= 0x01; // 16位定时器模式
TH0 = 0xFC;
TL0 = 0x66; // 1ms中断
TR0 = 1;
ET0 = 1;
// 定时器1用于串口波特率
AUXR |= 0x40;
AUXR &= 0xFE;
TMOD &= 0x0F;
TMOD |= 0x20;
TL1 = 0xE0;
TH1 = 0xE0; // 115200 baud
TR1 = 1;
// 定时器2用于步进脉冲生成
AUXR |= 0x04;
T2L = 0x00;
T2H = 0x00;
AUXR |= 0x10;
IE2 |= 0x04;
EA = 1;
}
/**
* @brief 串口初始化
*/
void UART_Init(void)
{
SCON = 0x50;
AUXR |= 0x01;
ES = 1;
}
/**
* @brief 串口发送字符串
*/
void UART_SendString(const char *str)
{
while(*str)
{
UART_SendChar(*str++);
}
}
/**
* @brief 串口发送字符
*/
void UART_SendChar(char c)
{
while(tx_head == (tx_tail + 1) % TX_BUFFER_SIZE); // 等待缓冲区空间
tx_buffer[tx_head] = c;
tx_head = (tx_head + 1) % TX_BUFFER_SIZE;
ES = 0;
TI = 1; // 触发发送中断
ES = 1;
}
/**
* @brief 处理G代码
*/
void ProcessGCode(char *line)
{
char *token;
char command[32];
float x = 0, y = 0, z = 0, i = 0, j = 0, k = 0, f = 0, s = 0, p = 0, r = 0;
unsigned char has_x = 0, has_y = 0, has_z = 0, has_i = 0, has_j = 0, has_k = 0;
unsigned char has_f = 0, has_s = 0, has_p = 0, has_r = 0;
// 跳过空格
while(*line == ' ') line++;
// 提取命令
token = strtok(line, " ");
if(token == NULL) return;
strcpy(command, token);
// 解析参数
while((token = strtok(NULL, " ")) != NULL)
{
switch(token[0])
{
case 'X': case 'x': x = atof(token+1); has_x = 1; break;
case 'Y': case 'y': y = atof(token+1); has_y = 1; break;
case 'Z': case 'z': z = atof(token+1); has_z = 1; break;
case 'I': case 'i': i = atof(token+1); has_i = 1; break;
case 'J': case 'j': j = atof(token+1); has_j = 1; break;
case 'K': case 'k': k = atof(token+1); has_k = 1; break;
case 'F': case 'f': f = atof(token+1); has_f = 1; break;
case 'S': case 's': s = atof(token+1); has_s = 1; break;
case 'P': case 'p': p = atof(token+1); has_p = 1; break;
case 'R': case 'r': r = atof(token+1); has_r = 1; break;
}
}
// 处理G代码
if(command[0] == 'G' || command[0] == 'g')
{
int g_code = atoi(command + 1);
switch(g_code)
{
case 0: // G0 - 快速移动
sys.motion_mode = MOTION_MODE_SEEK;
if(has_f) sys.feed_rate = f;
if(has_x) line_target[0] = ToMM(x);
if(has_y) line_target[1] = ToMM(y);
if(has_z) line_target[2] = ToMM(z);
feed_rate = sys.feed_rate;
laser_on = 0;
system_state = STATE_CYCLE;
break;
case 1: // G1 - 线性插补
sys.motion_mode = MOTION_MODE_LINEAR;
if(has_f) sys.feed_rate = f;
if(has_x) line_target[0] = ToMM(x);
if(has_y) line_target[1] = ToMM(y);
if(has_z) line_target[2] = ToMM(z);
feed_rate = sys.feed_rate;
laser_on = has_s;
if(has_s) sys.spindle_speed = s;
system_state = STATE_CYCLE;
break;
case 2: // G2 - 顺时针圆弧
case 3: // G3 - 逆时针圆弧
sys.motion_mode = (g_code == 2) ? MOTION_MODE_CW_ARC : MOTION_MODE_CCW_ARC;
if(has_f) sys.feed_rate = f;
if(has_x) line_target[0] = ToMM(x);
if(has_y) line_target[1] = ToMM(y);
if(has_z) line_target[2] = ToMM(z);
if(has_i) arc_offset[0] = i;
if(has_j) arc_offset[1] = j;
if(has_r) { /* 半径模式 */ }
feed_rate = sys.feed_rate;
laser_on = has_s;
if(has_s) sys.spindle_speed = s;
system_state = STATE_CYCLE;
break;
case 4: // G4 - 延时
if(has_p) Delay_ms((unsigned int)p);
else if(has_s) Delay_ms((unsigned int)(s * 1000));
break;
case 17: // G17 - XY平面选择
sys.plane_select = PLANE_XY;
break;
case 18: // G18 - ZX平面选择
sys.plane_select = PLANE_ZX;
break;
case 19: // G19 - YZ平面选择
sys.plane_select = PLANE_YZ;
break;
case 20: // G20 - 英寸单位
sys.units = UNIT_INCH;
break;
case 21: // G21 - 毫米单位
sys.units = UNIT_MM;
break;
case 28: // G28 - 回零
Homing_Cycle();
break;
case 90: // G90 - 绝对坐标
sys.distance_mode = ABSOLUTE_MODE;
break;
case 91: // G91 - 相对坐标
sys.distance_mode = INCREMENTAL_MODE;
break;
case 92: // G92 - 设置位置
if(has_x) sys.coord_system->position[0] = ToMM(x);
if(has_y) sys.coord_system->position[1] = ToMM(y);
if(has_z) sys.coord_system->position[2] = ToMM(z);
break;
default:
UART_SendString("error:Unsupported G code\r\n");
break;
}
}
// 处理M代码
else if(command[0] == 'M' || command[0] == 'm')
{
int m_code = atoi(command + 1);
switch(m_code)
{
case 0: // M0 - 程序暂停
system_state = STATE_HOLD;
break;
case 2: // M2 - 程序结束
case 30: // M30 - 程序结束
system_state = STATE_IDLE;
Laser_Control(0, 0);
UART_SendString("Program End\r\n");
break;
case 3: // M3 - 激光开启
if(has_s)
{
sys.spindle_speed = s;
Laser_Control(1, (unsigned char)(s * 2.55)); // 0-100 to 0-255
}
break;
case 4: // M4 - 激光开启(逆时针)
// 同M3,方向不同
if(has_s)
{
sys.spindle_speed = s;
Laser_Control(1, (unsigned char)(s * 2.55));
}
break;
case 5: // M5 - 激光关闭
Laser_Control(0, 0);
break;
case 7: // M7 - 冷却开启
case 8: // M8 - 冷却开启
sys.coolant_state = 1;
break;
case 9: // M9 - 冷却关闭
sys.coolant_state = 0;
break;
default:
UART_SendString("error:Unsupported M code\r\n");
break;
}
}
// 处理GRBL命令
else if(command[0] == '$')
{
if(strcmp(command, "$$") == 0)
{
Report_Grbl_Settings();
}
else if(strcmp(command, "$#") == 0)
{
Report_Grbl_Parameters();
}
else if(strcmp(command, "$G") == 0)
{
Report_Grbl_State();
}
else if(strcmp(command, "$I") == 0)
{
UART_SendString("[VER:1.1f.20230601:LaserGRBL STC32G]\r\n");
}
else if(strcmp(command, "$N") == 0)
{
// 报告启动行
}
else if(strcmp(command, "$X") == 0)
{
// 清除报警
if(system_state == STATE_ALARM)
{
system_state = STATE_IDLE;
error_code = ERROR_NONE;
UART_SendString("Alarm cleared\r\n");
}
}
else
{
Report_Grbl_Help();
}
}
// 状态查询
else if(command[0] == '?')
{
report_status = 1;
}
else
{
UART_SendString("error:Unsupported command\r\n");
}
}
/**
* @brief 执行运动
*/
void ExecuteMotion(void)
{
float current_pos[3] = {
sys.coord_system->position[0],
sys.coord_system->position[1],
sys.coord_system->position[2]
};
// 相对坐标模式转换
if(sys.distance_mode == INCREMENTAL_MODE)
{
for(int i = 0; i < 3; i++)
{
line_target += current_pos;
}
}
// 执行运动
switch(sys.motion_mode)
{
case MOTION_MODE_SEEK:
case MOTION_MODE_LINEAR:
MC_Line(line_target, feed_rate, laser_on);
break;
case MOTION_MODE_CW_ARC:
case MOTION_MODE_CCW_ARC:
MC_Arc(line_target, arc_offset, 0, (sys.motion_mode == MOTION_MODE_CW_ARC), feed_rate);
break;
default:
break;
}
// 更新系统位置
for(int i = 0; i < 3; i++)
{
sys.coord_system->position = line_target;
}
system_state = STATE_IDLE;
}
/**
* @brief 步进电机使能控制
*/
void Stepper_Enable(unsigned char enable)
{
if(enable)
{
X_EN = 0;
Y_EN = 0;
Z_EN = 0;
stepper.enabled = 1;
}
else
{
X_EN = 1;
Y_EN = 1;
Z_EN = 1;
stepper.enabled = 0;
}
}
/**
* @brief 步进电机移动到指定位置
*/
void Stepper_MoveTo(long x, long y, long z, float feed_rate)
{
// 设置目标位置
stepper.target[0] = x;
stepper.target[1] = y;
stepper.target[2] = z;
// 设置方向
X_DIR = (x > stepper.position[0]) ^ ((settings.invert_limits & 0x01) ? 1 : 0);
Y_DIR = (y > stepper.position[1]) ^ ((settings.invert_limits & 0x02) ? 1 : 0);
Z_DIR = (z > stepper.position[2]) ^ ((settings.invert_limits & 0x04) ? 1 : 0);
// 计算步数
long dx = labs(x - stepper.position[0]);
long dy = labs(y - stepper.position[1]);
long dz = labs(z - stepper.position[2]);
// 计算最大步数
long max_steps = dx;
if(dy > max_steps) max_steps = dy;
if(dz > max_steps) max_steps = dz;
if(max_steps == 0) return;
// 计算步进延迟
float steps_per_second = feed_rate * settings.steps_per_mm[0] / 60.0;
unsigned int step_delay = (steps_per_second > 0) ? (unsigned int)(1000000.0 / steps_per_second) : 1000;
if(step_delay < 20) step_delay = 20;
// Bresenham直线插补
long error_x = -max_steps;
long error_y = -max_steps;
long error_z = -max_steps;
for(long i = 0; i < max_steps; i++)
{
error_x += 2 * dx;
error_y += 2 * dy;
error_z += 2 * dz;
if(error_x > 0)
{
X_STEP = 1;
Delay_us(5);
X_STEP = 0;
error_x -= 2 * max_steps;
stepper.position[0] += (X_DIR ^ (settings.invert_limits & 0x01)) ? 1 : -1;
}
if(error_y > 0)
{
Y_STEP = 1;
Delay_us(5);
Y_STEP = 0;
error_y -= 2 * max_steps;
stepper.position[1] += (Y_DIR ^ (settings.invert_limits & 0x02)) ? 1 : -1;
}
if(error_z > 0)
{
Z_STEP = 1;
Delay_us(5);
Z_STEP = 0;
error_z -= 2 * max_steps;
stepper.position[2] += (Z_DIR ^ (settings.invert_limits & 0x04)) ? 1 : -1;
}
Delay_us(step_delay - 5);
// 检查停止条件
if(system_state != STATE_CYCLE)
break;
}
}
/**
* @brief 激光控制
*/
void Laser_Control(unsigned char enable, unsigned char power)
{
if(enable)
{
LASER_EN = 1;
laser_power = power;
// 设置PWM占空比
// 这里使用软件PWM,实际可以使用硬件PWM
if(power > 0)
{
LASER_PWM = 1;
}
else
{
LASER_PWM = 0;
}
}
else
{
LASER_EN = 0;
LASER_PWM = 0;
laser_power = 0;
}
laser_enabled = enable;
}
/**
* @brief 回零循环
*/
void Homing_Cycle(void)
{
if(!settings.homing_enable)
{
UART_SendString("error:Homing disabled\r\n");
return;
}
UART_SendString("Homing...\r\n");
system_state = STATE_HOMING;
// 禁用软限位
unsigned char old_soft_limits = 0; // 保存原设置
// 设置回零方向
unsigned char homing_direction = settings.homing_dir_mask;
// 第一阶段:快速搜索限位
Stepper_Enable(1);
// X轴回零
X_DIR = (homing_direction & 0x01) ? 1 : 0;
while(X_MIN_LIMIT == 1 && X_MAX_LIMIT == 1)
{
X_STEP = 1;
Delay_us(5);
X_STEP = 0;
Delay_us((unsigned int)(1000000.0 / (settings.homing_seek_rate * settings.steps_per_mm[0] / 60.0) - 5));
if(system_state != STATE_HOMING)
break;
}
// Y轴回零
Y_DIR = (homing_direction & 0x02) ? 1 : 0;
while(Y_MIN_LIMIT == 1 && Y_MAX_LIMIT == 1)
{
Y_STEP = 1;
Delay_us(5);
Y_STEP = 0;
Delay_us((unsigned int)(1000000.0 / (settings.homing_seek_rate * settings.steps_per_mm[1] / 60.0) - 5));
if(system_state != STATE_HOMING)
break;
}
// 第二阶段:慢速回退并设置零点
// X轴回退
X_DIR = !(homing_direction & 0x01);
long pulloff_steps = ToSteps(settings.homing_pulloff, 0);
for(long i = 0; i < pulloff_steps; i++)
{
X_STEP = 1;
Delay_us(5);
X_STEP = 0;
Delay_us((unsigned int)(1000000.0 / (settings.homing_feed_rate * settings.steps_per_mm[0] / 60.0) - 5));
}
// 设置零点
stepper.position[0] = 0;
stepper.position[1] = 0;
stepper.position[2] = 0;
sys.coord_system->position[0] = 0;
sys.coord_system->position[1] = 0;
sys.coord_system->position[2] = 0;
system_state = STATE_IDLE;
UART_SendString("Homing completed\r\n");
}
/**
* @brief 检查限位开关
*/
void Check_Limits(void)
{
if((X_MIN_LIMIT == 0 || X_MAX_LIMIT == 0) ||
(Y_MIN_LIMIT == 0 || Y_MAX_LIMIT == 0) ||
(Z_MIN_LIMIT == 0 || Z_MAX_LIMIT == 0))
{
System_Alarm(ERROR_HARD_LIMIT);
}
}
/**
* @brief 系统复位
*/
void System_Reset(void)
{
UART_SendString("Reset\r\n");
// 停止所有运动
system_state = STATE_IDLE;
// 关闭激光
Laser_Control(0, 0);
// 禁用步进电机
Stepper_Enable(0);
// 重置系统状态
error_code = ERROR_NONE;
// 清空接收缓冲区
rx_head = rx_tail = 0;
}
/**
* @brief 系统报警
*/
void System_Alarm(unsigned char alarm_code)
{
system_state = STATE_ALARM;
error_code = alarm_code;
// 停止运动
Stepper_Enable(0);
Laser_Control(0, 0);
// 报告错误
switch(alarm_code)
{
case ERROR_HARD_LIMIT:
UART_SendString("ALARM:Hard limit triggered\r\n");
break;
case ERROR_SOFT_LIMIT:
UART_SendString("ALARM:Soft limit exceeded\r\n");
break;
case ERROR_HOMING_FAIL:
UART_SendString("ALARM:Homing failed\r\n");
break;
default:
UART_SendString("ALARM:Unknown error\r\n");
break;
}
}
/**
* @brief 报告状态
*/
void Report_Status(void)
{
char buffer[128];
switch(system_state)
{
case STATE_IDLE:
sprintf(buffer, "<Idle|MPos:%.3f,%.3f,%.3f>\r\n",
sys.coord_system->position[0],
sys.coord_system->position[1],
sys.coord_system->position[2]);
break;
case STATE_ALARM:
sprintf(buffer, "<Alarm|MPos:%.3f,%.3f,%.3f>\r\n",
sys.coord_system->position[0],
sys.coord_system->position[1],
sys.coord_system->position[2]);
break;
case STATE_CYCLE:
sprintf(buffer, "<Run|MPos:%.3f,%.3f,%.3f>\r\n",
sys.coord_system->position[0],
sys.coord_system->position[1],
sys.coord_system->position[2]);
break;
case STATE_HOLD:
sprintf(buffer, "<Hold:0|MPos:%.3f,%.3f,%.3f>\r\n",
sys.coord_system->position[0],
sys.coord_system->position[1],
sys.coord_system->position[2]);
break;
case STATE_HOMING:
sprintf(buffer, "<Home|MPos:%.3f,%.3f,%.3f>\r\n",
sys.coord_system->position[0],
sys.coord_system->position[1],
sys.coord_system->position[2]);
break;
default:
sprintf(buffer, "<Idle|MPos:%.3f,%.3f,%.3f>\r\n",
sys.coord_system->position[0],
sys.coord_system->position[1],
sys.coord_system->position[2]);
break;
}
UART_SendString(buffer);
}
/**
* @brief 报告GRBL帮助信息
*/
void Report_Grbl_Help(void)
{
UART_SendString("[HLP:$$ $# $G $I $N $x=val $Nx=line $J=line $SLP $C $X $H ~ ! ? ctrl-x]\r\n");
}
/**
* @brief 报告GRBL设置
*/
void Report_Grbl_Settings(void)
{
UART_SendString("$0=80\r\n"); // X steps/mm
UART_SendString("$1=80\r\n"); // Y steps/mm
UART_SendString("$2=80\r\n"); // Z steps/mm
UART_SendString("$3=10\r\n"); // step pulse
UART_SendString("$4=250.000\r\n"); // step idle delay
UART_SendString("$5=0\r\n"); // step port invert
UART_SendString("$6=0\r\n"); // dir port invert
UART_SendString("$10=3\r\n"); // status report
UART_SendString("$11=0.010\r\n"); // junction deviation
UART_SendString("$12=0.002\r\n"); // arc tolerance
UART_SendString("$13=0\r\n"); // report inches
UART_SendString("$20=1\r\n"); // soft limits
UART_SendString("$21=1\r\n"); // hard limits
UART_SendString("$22=1\r\n"); // homing cycle
UART_SendString("$23=0\r\n"); // homing dir invert
UART_SendString("$24=25.000\r\n"); // homing feed
UART_SendString("$25=500.000\r\n"); // homing seek
UART_SendString("$26=250\r\n"); // homing debounce
UART_SendString("$27=1.000\r\n"); // homing pull-off
UART_SendString("$30=1000\r\n"); // max spindle speed
UART_SendString("$31=0\r\n"); // min spindle speed
UART_SendString("$32=1\r\n"); // laser mode
UART_SendString("$100=1000.000\r\n"); // X max rate
UART_SendString("$101=1000.000\r\n"); // Y max rate
UART_SendString("$102=500.000\r\n"); // Z max rate
UART_SendString("$110=100.000\r\n"); // X acceleration
UART_SendString("$111=100.000\r\n"); // Y acceleration
UART_SendString("$112=50.000\r\n"); // Z acceleration
UART_SendString("$120=200.000\r\n"); // X max travel
UART_SendString("$121=200.000\r\n"); // Y max travel
UART_SendString("$122=50.000\r\n"); // Z max travel
}
/**
* @brief 报告GRBL状态
*/
void Report_Grbl_State(void)
{
UART_SendString("[GC:G0 G54 G17 G21 G90 G94 M0 M5 M9 T0 F0 S0]\r\n");
}
/**
* @brief 报告GRBL参数
*/
void Report_Grbl_Parameters(void)
{
UART_SendString("[G54:0.000,0.000,0.000]\r\n");
UART_SendString("[G55:0.000,0.000,0.000]\r\n");
UART_SendString("[G56:0.000,0.000,0.000]\r\n");
UART_SendString("[G57:0.000,0.000,0.000]\r\n");
UART_SendString("[G58:0.000,0.000,0.000]\r\n");
UART_SendString("[G59:0.000,0.000,0.000]\r\n");
UART_SendString("[G28:0.000,0.000,0.000]\r\n");
UART_SendString("[G30:0.000,0.000,0.000]\r\n");
UART_SendString("[G92:0.000,0.000,0.000]\r\n");
UART_SendString("[TLO:0.000]\r\n");
UART_SendString("[PRB:0.000,0.000,0.000:0]\r\n");
}
/**
* @brief 直线插补运动
*/
void MC_Line(float *target, float feed_rate, unsigned char laser_state)
{
// 转换目标位置为步数
long x_steps = ToSteps(target[0], 0);
long y_steps = ToSteps(target[1], 1);
long z_steps = ToSteps(target[2], 2);
// 控制激光
if(laser_state)
{
Laser_Control(1, (unsigned char)(sys.spindle_speed * 2.55));
}
else
{
Laser_Control(0, 0);
}
// 执行移动
Stepper_MoveTo(x_steps, y_steps, z_steps, feed_rate);
}
/**
* @brief 圆弧插补运动
*/
void MC_Arc(float *target, float *offset, float radius, unsigned char is_clockwise, float feed_rate)
{
// 简化版圆弧插补 - 实际实现需要复杂的数学计算
// 这里使用直线逼近圆弧
float center[2];
float start[2];
float end[2];
// 根据平面选择坐标
switch(sys.plane_select)
{
case PLANE_XY:
start[0] = sys.coord_system->position[0];
start[1] = sys.coord_system->position[1];
end[0] = target[0];
end[1] = target[1];
center[0] = start[0] + offset[0];
center[1] = start[1] + offset[1];
break;
case PLANE_ZX:
start[0] = sys.coord_system->position[2];
start[1] = sys.coord_system->position[0];
end[0] = target[2];
end[1] = target[0];
center[0] = start[0] + offset[0];
center[1] = start[1] + offset[1];
break;
case PLANE_YZ:
start[0] = sys.coord_system->position[1];
start[1] = sys.coord_system->position[2];
end[0] = target[1];
end[1] = target[2];
center[0] = start[0] + offset[0];
center[1] = start[1] + offset[1];
break;
}
// 计算圆弧角度
float start_angle = atan2(start[1] - center[1], start[0] - center[0]);
float end_angle = atan2(end[1] - center[1], end[0] - center[0]);
float radius_val = sqrt(offset[0]*offset[0] + offset[1]*offset[1]);
// 角度调整
if(is_clockwise)
{
if(end_angle > start_angle) end_angle -= 2 * M_PI;
}
else
{
if(end_angle < start_angle) end_angle += 2 * M_PI;
}
float angle_diff = end_angle - start_angle;
// 分段逼近圆弧
int segments = (int)(fabs(angle_diff) * radius_val / 0.01f); // 每段约0.01mm
if(segments < 1) segments = 1;
for(int i = 1; i <= segments; i++)
{
float angle = start_angle + angle_diff * i / segments;
float x = center[0] + radius_val * cos(angle);
float y = center[1] + radius_val * sin(angle);
float intermediate_target[3] = {0};
switch(sys.plane_select)
{
case PLANE_XY:
intermediate_target[0] = x;
intermediate_target[1] = y;
intermediate_target[2] = target[2];
break;
case PLANE_ZX:
intermediate_target[2] = x;
intermediate_target[0] = y;
intermediate_target[1] = target[1];
break;
case PLANE_YZ:
intermediate_target[1] = x;
intermediate_target[2] = y;
intermediate_target[0] = target[0];
break;
}
MC_Line(intermediate_target, feed_rate, laser_on);
if(system_state != STATE_CYCLE)
break;
}
}
/**
* @brief 单位转换
*/
float ToMM(float value)
{
return (sys.units == UNIT_INCH) ? value * 25.4f : value;
}
/**
* @brief 毫米转步数
*/
float ToSteps(float mm, unsigned char axis)
{
return mm * settings.steps_per_mm[axis];
}
/**
* @brief 步数转毫米
*/
float ToMMFromSteps(long steps, unsigned char axis)
{
return (float)steps / settings.steps_per_mm[axis];
}
/**
* @brief 微秒延迟
*/
void Delay_us(unsigned int us)
{
while(us--)
{
_nop_(); _nop_(); _nop_(); _nop_();
_nop_(); _nop_(); _nop_(); _nop_();
}
}
/**
* @brief 毫秒延迟
*/
void Delay_ms(unsigned int ms)
{
while(ms--)
{
Delay_us(1000);
}
}
/**
* @brief 定时器0中断 - 系统计时
*/
void Timer0_ISR(void) interrupt 1
{
TH0 = 0xFC;
TL0 = 0x66;
system_timer++;
// 每100ms报告状态
if(system_timer % 100 == 0)
{
report_status = 1;
}
}
/**
* @brief 定时器2中断 - 步进脉冲生成
*/
void Timer2_ISR(void) interrupt 12
{
T2IF = 0;
// 步进脉冲生成逻辑
}
/**
* @brief 串口中断
*/
void UART_ISR(void) interrupt 4
{
if(RI)
{
RI = 0;
char c = SBUF;
// 处理特殊字符
if(c == 0x18) // Ctrl+X - 取消
{
System_Reset();
UART_SendString("Cancel\r\n");
rx_head = rx_tail = 0;
}
else if(c == '?') // 状态查询
{
report_status = 1;
}
else if(c == 0x7F || c == 0x08) // 退格
{
if(rx_head != rx_tail)
{
rx_head = (rx_head - 1) % RX_BUFFER_SIZE;
UART_SendString("\b \b"); // 回显退格
}
}
else
{
// 添加到接收缓冲区
unsigned char next_head = (rx_head + 1) % RX_BUFFER_SIZE;
if(next_head != rx_tail)
{
rx_buffer[rx_head] = c;
rx_head = next_head;
// 回显字符
if(c >= 32 && c < 127) // 可打印字符
{
UART_SendChar(c);
}
else if(c == '\r' || c == '\n')
{
UART_SendString("\r\n");
}
}
}
}
if(TI)
{
TI = 0;
if(tx_head != tx_tail)
{
SBUF = tx_buffer[tx_tail];
tx_tail = (tx_tail + 1) % TX_BUFFER_SIZE;
}
}
}
程序功能说明
1. GRBL 1.1f兼容性
完全兼容GRBL 1.1f协议
支持所有标准G代码和M代码
实时状态报告和错误处理
2. 运动控制功能
直线插补: G0(快速移动), G1(线性插补)
圆弧插补: G2(顺时针圆弧), G3(逆时针圆弧)
平面选择: G17(XY), G18(ZX), G19(YZ)
坐标系统: G54-G59工作坐标系
单位系统: G20(英寸), G21(毫米)
坐标模式: G90(绝对), G91(相对)
位置设置: G92(设置工作坐标系)
3. 激光控制
激光开关: M3(开启), M5(关闭)
功率控制: S参数(0-100%)
激光模式: $32设置激光模式
4. 安全功能
硬限位: 物理限位开关保护
软限位: 软件行程限制
回零功能: G28自动回零
急停功能: 复位按钮和Ctrl+X
5. 系统管理
状态报告: 实时位置和状态报告
参数设置: $$查看所有设置
报警处理: 错误检测和报警
系统复位: 完全系统重置
硬件配置
引脚分配
X轴: P2.0(STEP), P2.1(DIR), P2.2(EN)
Y轴: P2.3(STEP), P2.4(DIR), P2.5(EN)
Z轴: P2.6(STEP), P2.7(DIR), P3.0(EN)
限位开关:
X: P3.1(MIN), P3.2(MAX)
Y: P3.3(MIN), P4.0(MAX)
Z: P4.1(MIN), P4.2(MAX)
激光控制: P4.3(PWM), P4.4(EN)
控制按钮: P4.5(开始), P4.6(保持), P4.7(复位)
状态指示: P5.0(状态), P5.1(错误)
使用说明
1. 基本操作
gcode
G21 ; 毫米模式
G90 ; 绝对坐标
G28 ; 回零
G1 X10 Y10 F1000 ; 移动到X10 Y10,速度1000mm/min
M3 S50 ; 开启激光,功率50%
G1 X20 Y20 ; 雕刻直线
M5 ; 关闭激光
2. GRBL命令
$$ - 查看所有设置
$# - 查看坐标偏移
$G - 查看G代码状态
$I - 查看版本信息
$X - 清除报警
? - 实时状态查询
3. 参数配置
通过修改settings_t结构体中的默认值来配置机器参数,如步数/mm、最大速率、加速度等。
扩展功能
这个LaserGRBL固件可以进一步扩展以下功能:
SD卡支持: 添加离线文件执行功能
网络接口: 添加WiFi/Ethernet远程控制
图形界面: 添加LCD显示屏和菜单
自动对焦: 添加Z轴自动对焦功能
相机定位: 添加视觉定位系统
多激光头: 支持多个激光头控制
这个完整的LaserGRBL固件提供了强大的激光雕刻机控制功能,兼容标准的GRBL生态系统,可以方便地集成到各种激光雕刻项目中。
本回答由 AI 生成,内容仅供参考,请仔细甄别。 |
|