找回密码
 立即注册
楼主: wskhsm

将GRBL移植到32G系列上,做了个写字机

[复制链接]
  • 打卡等级:以坛为家II
  • 打卡总天数:498
  • 最近打卡:2025-12-15 22:19:44
已绑定手机

23

主题

489

回帖

1446

积分

金牌会员

积分
1446
发表于 2024-10-11 13:27:13 | 显示全部楼层
这个东西很有代表性,感谢楼主分享,我也下载过来学习一下{:5_332:}
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:424
  • 最近打卡:2025-12-16 01:07:00
已绑定手机

26

主题

357

回帖

765

积分

高级会员

积分
765
发表于 2024-10-22 00:23:19 | 显示全部楼层
赞一个
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:192
  • 最近打卡:2025-12-08 19:49:09

16

主题

96

回帖

950

积分

高级会员

积分
950
发表于 2024-11-14 23:10:05 | 显示全部楼层
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:572
  • 最近打卡:2025-12-15 07:24:53

8

主题

291

回帖

780

积分

高级会员

积分
780
发表于 2024-11-15 07:25:40 | 显示全部楼层
楼主厉害
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:424
  • 最近打卡:2025-12-16 01:07:00
已绑定手机

26

主题

357

回帖

765

积分

高级会员

积分
765
发表于 2024-11-15 09:44:59 | 显示全部楼层
厉害了,值得学习。
回复

使用道具 举报 送花

  • 打卡等级:常住居民III
  • 打卡总天数:122
  • 最近打卡:2025-12-15 16:41:52
已绑定手机

0

主题

7

回帖

498

积分

中级会员

积分
498
发表于 2024-11-28 17:25:39 | 显示全部楼层
我爱国芯
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:629
  • 最近打卡:2025-12-16 06:51:02

4

主题

509

回帖

2901

积分

金牌会员

积分
2901
发表于 2024-12-1 07:02:10 | 显示全部楼层
支持
回复

使用道具 举报 送花

  • 打卡等级:常住居民I
  • 打卡总天数:67
  • 最近打卡:2025-12-15 00:07:30

2

主题

2

回帖

148

积分

注册会员

积分
148
发表于 2025-6-1 00:24:57 | 显示全部楼层
牛蛙牛蛙大佬这也行
回复

使用道具 举报 送花

  • 打卡等级:以坛为家II
  • 打卡总天数:473
  • 最近打卡:2025-12-16 06:50:34

0

主题

196

回帖

2418

积分

金牌会员

积分
2418
发表于 2025-9-8 10:05:28 | 显示全部楼层
好,好,好
回复

使用道具 举报 送花

  • 打卡等级:以坛为家III
  • 打卡总天数:629
  • 最近打卡:2025-12-16 06:51:02

4

主题

509

回帖

2901

积分

金牌会员

积分
2901
发表于 7 天前 | 显示全部楼层
帮下载程序到原型机里,测试一下,下面的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 生成,内容仅供参考,请仔细甄别。
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2025-12-16 07:57 , Processed in 0.133495 second(s), 99 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表