论坛元老
- 积分
- 3155
- 金钱
- 3155
- 注册时间
- 2013-12-8
- 在线时间
- 432 小时
|
楼主 |
发表于 2017-4-10 10:39:32
|
显示全部楼层
二、 G_Code代码解析:
1. G_Code文件的获取
我现在的G_Code是存储在SD卡上的,在GUI的FileList控件中通过触摸屏选择需要文件的路径,在FATFS中打开文件
[mw_shl_code=applescript,true]/********************************************
函数:FileLoad
功能:文件读取
参数:message:需要读取的文件信息
返回:无
********************************************/
void FileLoad(u32 message)
{
u8* Path;
GUI_FileListStruct *FL_T;
u8 chgchar[2]={0X5C,0X00};//转义符 等效"\"
GCodeStruct GCode_One;
FL_T = (GUI_FileListStruct *)((message&0xffffff)|RAM_ADDRESS); //获取文件名信息
//需增加文件类型判断
Path = mymalloc(sizeof(FL_T->path)+sizeof(FL_T->fname));
strcpy((char*)Path,(const char*)FL_T->path); //拷贝path到pname里面
strcat((char*)Path,(const char*)chgchar); //添加转义符
strcat((char*)Path,(const char*)FL_T->fname); //添加新增的名字
f_res = f_open(filescr, (const TCHAR*)Path, FA_OPEN_DEFAULT); //打开文件
myfree(Path); //释放内存
if(f_res == FR_OK) //读取文件正常
{
DK.File_B_P->Open =1; //文件打开标志
DK.File_B_P->NeedRead = 1; //文件需要继续读取
DK.File_B_P->NotEnd = 1; //设置文件没有结束标志
FileRead = 0; //
FileBuffNum = 0;
Page_DK_File();
ReadFile(); //读取数据到缓存中
DK.File_B_P->ReadStart = 1; //文件开始读取标志
while(DK.File_B_P->NotEnd)
{
if(ReadOneLine()==0)
{
TransformGCode(OneLine,&GCode_One);
ShowRun(&GCode_One,Green);
}
}
f_res = f_lseek(filescr, 0);
FileRead = 0;
FileBuffNum = 0;
DK.File_B_P->Open =1; //文件打开标志
DK.File_B_P->NeedRead = 1; //需要读取文件
DK.File_B_P->NotEnd = 1;
ReadFile(); //读取数据到缓存中
DK.File_B_P->ReadStart = 1; //文件开始读取标志
DK.Ctrl = CTRL_PAUSE; //停止
OS.Timer.Start(TimerMessageHandle,10,DK_File_Start);
}
else
{
DK.Ctrl = CTRL_STOP; //停止
}
}[/mw_shl_code]
在FileLoad中先进行一遍G代码的解析(TransformGCode(OneLine,&GCode_One);)和在TFT显示绿色的刀路(ShowRun(&GCode_One,Green); ),在开始雕刻前方便知道选择的CNC文件是否正确。
然后跳转到DK_File_Start中等待开始雕刻的命令。
[mw_shl_code=applescript,true]/********************************************
函数:DK_File_Start
功能:雕刻机脱机SD卡文件开始雕刻
参数:无
返回:无
********************************************/
void DK_File_Start(void)
{
// NRF_GCode_Struct *NRF_GCode_P;
DK.N = 0;
while(DK.File_B_P->NotEnd)
{
if(DK.Ctrl == CTRL_STOP) return; //停止
if(DK.Alarm) return; //有故障退出自动
if(NRF.Send == 0) //等待上次发送完成
{
if(DK.NRF.queue < 5) //从机的队列小于5个
{
if(!ReadOneLine()) //正常读到数据
{
if(!TransformGCode(OneLine,&G_Code)) //数据解析正常
{
ShowRun(&G_Code,Red); //红色显示倒路
Send_GCode(&G_Code);
}
}
else
{
//sd卡数据读取错误
}
}
else
{
Send_DK_Action(NRF_CX_STATE); //查询DK状态;
}
}
else
{
OS.DelayTimeTick(5);
}
}
}[/mw_shl_code]
当触摸屏开始按钮按下后,开始正式的G代码解析和雕刻。
2. G_Code的解析
由于我自己的雕刻机最大的雕刻尺寸为15mm*15mm,将坐标位置放大100倍对能够满足雕刻机0.01mm的精度,所以没有使用浮点运算,直接通过对浮动数放大100倍来用整型运算,小于0.01的坐标直接放弃,这样所有运算为整型计算,提高运算速度。直线插补和圆弧插补使用逐点插补运算,没有使用复杂的浮点运算全部为整型计算。
坐标位置X 1.01 Y 2.02 对应的值为整型 X 101 Y 202 。
这样对移植可能有点问题,但对于我自己的机器精度完全足够
这个是G_Code的结构体,我只取我需要使用的坐标代码。
[mw_shl_code=applescript,true]typedef struct
{
u8 Action; //功能码
u16 ValueWords; //位标志,对应X,Y等有数据坐标的对应位置1
s32 X;
s32 Y;
s32 I;
s32 J;
s32 Z;
u32 N;
}GCodeStruct;[/mw_shl_code]
TransformGCode是将line中的一条ASC码存储的G代码转换成自己需要的控制代码。
a) 流程是先判断是否为注释,如果是注释则直接返回。
b) 对控制码G和M全部遍历一遍,应为在G代码中会出现如G00 G90 G94 G71 G40 G54 G80这样的代码,对于设置的代码则直接处理掉。
c) 对坐标代码遍历一遍,并对数据的对应标志位置1(SetBit(Queue->ValueWords,word_bit); ),因为在简化的G代码控制中有时候坐标是缺省的,如G01 X62.65 Y57.71;G01 X59.44第二个G代码中Y坐标就省略了。这样在插补的时候知道那个坐标需要使用原来的而不是0.
当G代码转换完成后且没有出错就开始通过NRF发送到主机进行运行。(函数:Send_GCode(&G_Code);)
[mw_shl_code=applescript,true]u8 TransformGCode(u8 *line,GCodeStruct * Queue)//parser_state_t *G_Code)
{
u8 char_counter = 1;
u8 letter;
s32 value_f;
s32 value_i;
u8 word_bit = 0; //跟踪变量的位值
DK.GC_Status = 0;
mymemset(Queue,0,sizeof(GCodeStruct));
if (line[1] == ';'
|| line[1] == '('
|| line[1] == '%'
)
return GCSTATUS_OK; // comments
DK.N++;
// Pass 1: Commands
while (next_statement(&letter, &value_f,&value_i, line, &char_counter))
{
switch (letter)
{
case 'N':
break;
case 'G':
SetBit(Queue->ValueWords,WORD_GM);
switch (value_i)
{
case 0: Queue->Action = GC_SEEK_G0; break; //快速移动
case 1: Queue->Action = GC_LINEAR_G1; break; //直线移动
case 2: Queue->Action = GC_CW_ARC; break;
case 3: Queue->Action = GC_CCW_ARC; break;
case 4: Queue->Action = GC_DWELL_G4; break; //暂停
case 20: DK.State_B_P->Inches_Mode = true; break;
case 21: DK.State_B_P->Inches_Mode = false; break;
case 28: Queue->Action = GC_GO_HOME_G28; break;//移动到原点
case 90: DK.State_B_P->Absolute_Mode = true; break;
case 91: DK.State_B_P->Absolute_Mode = false;break;
case 92: Queue->Action = GC_RESET_XYZ_G92; break;
//G92:定义当前位置 例如:G92X10允许编程的绝对零点,通过重置当前位置为指定的值。这将设置机器的X坐标为10;若没有指定坐标的G92将重置所有轴为零。
case 30:
case 64:
case 40:
case 17: // G17 蔓犷?疣犷麇?镫铖觐耱?X-Y
case 94: // Feedrate per minute
case 98: // Feedrate per minute (group type A)
case 97: // Constant spindle speed M T Takes an S address integer, which is interpreted as rev/min (rpm). The default speed mode per system parameter if no mode is programmed.
case 49: // Tool length offset compensation cancel
case 80: // Cancel canned cycle
break;
default: FAIL(GCSTATUS_UNSUPPORTED_STATEMENT);
}
break;
case 'M':
SetBit(Queue->ValueWords,WORD_GM);
switch (value_i)
{
case 112: // Emergency Stop
case 0:
case 1:
case 2:
case 30:
case 60:
Queue->Action = GC_STOP;
break;
case 3: Queue->Action = GC_M03; break;
// case 4: G_Code->spindle_direction = -1; break;
case 5: Queue->Action = GC_M05; break;
case 23: // Thread gradual pullout ON
case 24: // Thread gradual pullout OFF
case 52: // Unload Last tool from spindle
case 49: // Feedrate override NOT allowed
case 48: // Feedrate override allowed
case 8: // Coolant on
case 9: // Coolant off
case 105: // M105: Get Extruder Temperature Example: M105 Request the temperature of the current extruder and the build base in degrees Celsius. The temperatures are returned to the host computer. For example, the line sent to the host in response to this command looks like
case 106: // M106: Fan On Example: M106 S127 Turn on the cooling fan at half speed. Optional parameter 'S' declares the PWM value (0-255)
case 107: // Fan Off
case 108: // M108: Set Extruder Speed Sets speed of extruder motor. (Deprecated in current firmware, see M113)
case 110: // Set Current Line Number
case 113: // Set Extruder PWM
case 140: // Bed Temperature (Fast) Example: M140 S55 Set the temperature of the build bed to 55oC
case 141: //Chamber Temperature (Fast) Example: M141 S30 Set the temperature of the chamber to 30oC
case 142: // Holding Pressure Example: M142 S1 Set the holding pressure of the bed to 1 bar.
case 6:
return DK.GC_Status;
default: FAIL(GCSTATUS_UNSUPPORTED_STATEMENT);
}
break;
}
if (DK.GC_Status)
return (DK.GC_Status);
}
if (DK.GC_Status)
return(DK.GC_Status);
char_counter = 1;
while (next_statement(&letter, &value_f, &value_i,line, &char_counter))
{
double unit_millimeters_value = to_millimeters(value_f);
switch (letter)
{
case 'X':
word_bit = WORD_X;
if (DK.State_B_P->Absolute_Mode)
Queue->X = unit_millimeters_value;
else
Queue->X += unit_millimeters_value;
break;
case 'Y':
word_bit = WORD_Y;
if (DK.State_B_P->Absolute_Mode)
Queue->Y = unit_millimeters_value;
else
Queue->Y += unit_millimeters_value;
break;
case 'Z':
word_bit = WORD_Z;
if (DK.State_B_P->Absolute_Mode)
Queue->Z = unit_millimeters_value;
else
Queue->Z += unit_millimeters_value;
break;
case 'I':
word_bit = WORD_I;
Queue->I = unit_millimeters_value;
break;
case 'J':
word_bit = WORD_J;
Queue->J = unit_millimeters_value;
break;
case 'K':
break;
case 'E':
break;
case 'F':
break;
case 'P':
case 'S':
break;
case 'R':
case 'G':
case 'N':
case 'M':
break;
default:
FAIL(GCSTATUS_UNSUPPORTED_PARAM);
}
if(word_bit)
{
if (GetBit(Queue->ValueWords,word_bit)) { FAIL(FAIL_WORD_REPEATED); } // [Word repeated]
SetBit(Queue->ValueWords,word_bit);
}
}
return(DK.GC_Status);
}[/mw_shl_code]
|
|