极客工坊

 找回密码
 注册

QQ登录

只需一步,快速开始

楼主: oldbeginner

Arduino机械坊学习笔记04( 开始理解GRBL下位机)_2014_3_16

[复制链接]
 楼主| 发表于 2014-3-22 10:07:00 | 显示全部楼层
oldbeginner 发表于 2014-3-22 08:30
***************************
protocol.c 中

***********************
protocol.c 下1

***********************

#define EXEC_STATUS_REPORT  bit(0) // bitmask 00000001

#define EXEC_CYCLE_START    bit(1) // bitmask 00000010

#define EXEC_CYCLE_STOP     bit(2) // bitmask 00000100

#define EXEC_FEED_HOLD      bit(3) // bitmask 00001000

#define EXEC_RESET          bit(4) // bitmask 00010000

#define EXEC_ALARM          bit(5) // bitmask 00100000

#define EXEC_CRIT_EVENT     bit(6) // bitmask 01000000


Define system executor bit map. Used internally by runtime protocol as runtime command flags,  which notifies the main program to execute the specified runtime command asynchronously.
NOTE: The system executor uses an unsigned 8-bit volatile variable (8 flag limit.)
The default flags are always false, so the runtime protocol only needs to check for a non-zero value to know when there is a runtime command to execute.


内容7 ();

Executes run-time commands, when required.


This is called from various check points in the main program, primarily where there may be a while loop waiting for a buffer to clear space or any point where the execution time from the last check point may be more than a fraction of a second.
This is a way to execute runtime commands asynchronously (aka multitasking) with grbl's g-code parsing and planning functions. This function also serves as an interface for the interrupts to set the system runtime flags, where only the main program handles them, removing the need to define more computationally-expensive volatile variables. This also provides a controlled way to execute certain tasks without having two or more instances of the same task, such as the planner recalculating the buffer upon a feedhold or override.
NOTE: The sys.execute variable flags are set by any process, step or serial interrupts, pinouts, limit switches, or the main program.

void protocol_execute_runtime()
{
  if (sys.execute) { // Enter only if any bit flag is true
    uint8_t rt_exec = sys.execute; // Avoid calling volatile multiple times

        内容7A();
       }
    }
}



System alarm. Everything has shutdown by something that has gone severely wrong.
Report the source of the error to the user. If critical, Grbl disables by entering an infinite loop until system reset/abort.

内容7A();


内容7B();

内容7C();

内容7D();

内容7E();

内容7F();

内容7G();


内容7B();

Critical event. Only hard limit qualifies. Update this as new critical events surface.


    if (rt_exec & (EXEC_ALARM | EXEC_CRIT_EVENT)) {      
      sys.state = STATE_ALARM; // Set system alarm state

      if (rt_exec & EXEC_CRIT_EVENT) {
        report_alarm_message(ALARM_HARD_LIMIT);
        report_feedback_message(MESSAGE_CRITICAL_EVENT);
        bit_false(sys.execute,EXEC_RESET); // Disable any existing reset
  
      } else {

        report_alarm_message(ALARM_ABORT_CYCLE);
      }

      bit_false(sys.execute,(EXEC_ALARM | EXEC_CRIT_EVENT));
    }



内容7C();

Execute system abort.


    if (rt_exec & EXEC_RESET) {
      sys.abort = true;  // Only place this is set true.
      return; // Nothing else to do but exit.
    }



内容7D();

Execute and serial print status


    if (rt_exec & EXEC_STATUS_REPORT) {
      report_realtime_status();
      bit_false(sys.execute,EXEC_STATUS_REPORT);
    }



内容7E();

Initiate stepper feed hold


    if (rt_exec & EXEC_FEED_HOLD) {
      st_feed_hold(); // Initiate feed hold.
      bit_false(sys.execute,EXEC_FEED_HOLD);
    }



内容7F();

Reinitializes the stepper module running state and, if a feed hold, re-plans the buffer.
NOTE: EXEC_CYCLE_STOP is set by the stepper subsystem when a cycle or feed hold completes.


    if (rt_exec & EXEC_CYCLE_STOP) {
      st_cycle_reinitialize();
      bit_false(sys.execute,EXEC_CYCLE_STOP);
    }



内容7G();

    if (rt_exec & EXEC_CYCLE_START) {
      st_cycle_start(); // Issue cycle start command to stepper subsystem
      if (bit_istrue(settings.flags,BITFLAG_AUTO_START)) {
        sys.auto_start = true; // Re-enable auto start after feed hold.
      }
      bit_false(sys.execute,EXEC_CYCLE_START);
    }



信息量太大,先整理,以后慢慢看。

*********************************

内容8

Directs and executes one line of formatted input from protocol_process.
While mostly incoming streaming g-code blocks, this also executes Grbl internal commands, such as settings, initiating the homing cycle, and toggling switch states.
This differs from the runtime command module by being susceptible to when Grbl is ready to execute the next line during a cycle, so for switches like block delete, the switch only effects the lines that are processed afterward, not necessarily real-time during a cycle, since there are motions already stored in the buffer.
However, this 'lag' should not be an issue, since these commands are not typically used during a cycle.

uint8_t protocol_execute_line(char *line)
{   
  // Grbl internal command and parameter lines are of the form '$4=374.3' or '$' for help  
  if(line[0] == '$') {
   
    uint8_t char_counter = 1;
    uint8_t helper_var = 0; // Helper variable
    float parameter, value;
    switch( line[char_counter] ) {
                内容8A();
    }
    return(STATUS_OK); // If '$' command makes it to here, then everything's ok.

  } else {
    return(gc_execute_line(line));    // Everything else is gcode
  }
}



内容8A();

case 0 : 内容8B();

case '$': 内容8C();

case '#' : 内容8D();

case 'G' : 内容8E();

case 'C' : 内容8F();

case 'X' : 内容8G();

case 'H' : 内容8H();

case 'N' : 内容8I();

default : 内容8J();



内容8B();

report_grbl_help(); break;



内容8C();

Prints Grbl settings $


        if ( line[++char_counter] != 0 )
                { return(STATUS_UNSUPPORTED_STATEMENT); }
        else
                { report_grbl_settings(); }
        break;



内容8D();

Print gcode parameters #


        if ( line[++char_counter] != 0 )
                { return(STATUS_UNSUPPORTED_STATEMENT); }
        else
                { report_gcode_parameters(); }
        break;



内容8E();

Prints gcode parser state G


        if ( line[++char_counter] != 0 )
               { return(STATUS_UNSUPPORTED_STATEMENT); }
        else
               { report_gcode_modes(); }
        break;



内容8F();

Set check g-code mode C

        if ( line[++char_counter] != 0 )
               { return(STATUS_UNSUPPORTED_STATEMENT); }

        if ( sys.state == STATE_CHECK_MODE ) {
          mc_reset();
          report_feedback_message(MESSAGE_DISABLED);
        } else {
          if (sys.state)
               { return(STATUS_IDLE_ERROR); }
          sys.state = STATE_CHECK_MODE;
          report_feedback_message(MESSAGE_ENABLED);
        }
        break;


Perform reset when toggling off. Check g-code mode should only work if Grbl is idle and ready, regardless of alarm locks.
This is mainly to keep things simple and consistent.


内容8G();

Disable alarm lock X


        if ( line[++char_counter] != 0 )
                { return(STATUS_UNSUPPORTED_STATEMENT); }
        if (sys.state == STATE_ALARM) {
          report_feedback_message(MESSAGE_ALARM_UNLOCK);
          sys.state = STATE_IDLE;
          // Don't run startup script. Prevents stored moves in startup from causing accidents.
        }
        break;     



内容8H();

Perform homing cycle H


        if (bit_istrue(settings.flags,BITFLAG_HOMING_ENABLE)) {
          // Only perform homing if Grbl is idle or lost.
          if ( sys.state==STATE_IDLE || sys.state==STATE_ALARM ) {
            mc_go_home();
            if (!sys.abort)
                   { protocol_execute_startup(); } // Execute startup scripts after successful homing.
          } else
                   { return(STATUS_IDLE_ERROR); }
        } else
                 { return(STATUS_SETTING_DISABLED); }
        break;



内容8I();

Startup lines. N


        if ( line[++char_counter] == 0 ) { // Print startup lines
          for (helper_var=0; helper_var < N_STARTUP_LINE; helper_var++) {
            if (!(settings_read_startup_line(helper_var, line))) {
              report_status_message(STATUS_SETTING_READ_FAIL);
            } else {
              report_startup_line(helper_var,line);
            }
          }
          break;
        } else { // Store startup line
          helper_var = true;  // Set helper_var to flag storing method.
          // No break. Continues into default: to read remaining command characters.
        }



内容8J();

Storing setting methods


        if(!read_float(line, &char_counter, &parameter))
              { return(STATUS_BAD_NUMBER_FORMAT); }
        if(line[char_counter++] != '=')
              { return(STATUS_UNSUPPORTED_STATEMENT); }
        if (helper_var) { // Store startup line
          // Prepare sending gcode block to gcode parser by shifting all characters
          helper_var = char_counter; // Set helper variable as counter to start of gcode block
          do {
            line[char_counter-helper_var] = line[char_counter];
          } while (line[char_counter++] != 0);
          // Execute gcode block to ensure block is valid.
          helper_var = gc_execute_line(line); // Set helper_var to returned status code.
          if (helper_var) { return(helper_var); }
          else {
            helper_var = trunc(parameter); // Set helper_var to int value of parameter
            settings_store_startup_line(helper_var,line);
          }
        } else { // Store global setting.
          if(!read_float(line, &char_counter, &value))
                   { return(STATUS_BAD_NUMBER_FORMAT); }
          if(line[char_counter] != 0)
                   { return(STATUS_UNSUPPORTED_STATEMENT); }
          return(settings_store_global_setting(parameter, value));
        }



上面的代码解释了下面的命令
https://github.com/grbl/grbl/wiki/Configuring-Grbl-v0.8

Grbl Internal Commands:

Technically, the remaining Grbl commands are not configuration commands, but we're going to explain them here for no good reason, other than for completeness.
The three current state commands: $G, $#, ?

Grbl provides three commands to report its current state and where it is. Of the three, one of them is real-time, responding with current position. The other two are not, but respond with how incoming blocks are going to be processed depending on the states set by g-code, settings, or switches. The reason they are not realtime is that Grbl has an internal buffer that stores and plans the buffered motions. The incoming gcode blocks just tack on a new motion at the end of the buffer when it has room. The buffer basically ensures Grbl motion move at the fastest and safest rates possible, constantly re-calculating it real-time as motions finish and new ones come in.
$G - View gcode parser state

This command prints all of the active gcode modes that the parser will interpret any incoming command. These modes include G20/G21 inches/mm mode, G54-G59 active work coordinate system, G0/G1/G2/G3 active motion mode, G17/G18/G19 active plane selection, G90/G91 absolute mode, G93/G94 inverse feed rate mode, M0/M1/M2 program flow, M3/M4/M5 spindle state, M8/M9 coolant state, T tool number, and F active feed rate. It will also list any active $Sx Grbl switches, like $S1 block delete. When called, Grbl will return a line like this:

[G0 G54 G17 G21 G90 G94 M0 M5 M9 T0 F500.000]

$# - View gcode parameters

G-code parameters generally store the G54-G59 work coordinate offsets and G28/G30 home positions (must not be confused with homing and machine zero. These home positions can be set anywhere in the machine space by the G28.1/G30.1 commands). Most of these parameters are directly written to EEPROM anytime they are changed and are persistent. Meaning that they will remain the same, regardless of power-down, until they are explicitly changed.

G54-G59 work coordinates can be changed via the G10 L2 Px or G10 L20 Px command defined by the NIST gcode standard and the EMC2 (linuxcnc.org) standard. G28/G30 home positions can be changed via the G28.1 and the G30.1 commands, respectively. Please note that G92 is not persistent or held in EEPROM per g-code standards, and will reset to zero when Grbl is reset. Please read these g-code standard to understand how they are used.

When $# is called, Grbl will respond with the stored offsets from machine coordinates for each system as follows.

[G54:4.000,0.000,0.000]
[G55:4.000,6.000,7.000]
[G56:0.000,0.000,0.000]
[G57:0.000,0.000,0.000]
[G58:0.000,0.000,0.000]
[G59:0.000,0.000,0.000]
[G28:1.000,2.000,0.000]
[G30:4.000,6.000,0.000]
[G92:0.000,0.000,0.000]

For the most part, these offset are not particularly useful unless you have homing enabled. If you do have homing enabled, these are wonderfully awesome, because once you home, you can always move back to same stored position by using the work coordinate systems within the accuracy of your machine. Or if you are making multiple parts and have a tool path for just one part, all you have to do is setup your work coordinate systems to the location where the next part is going to be made and re-run that same code.
? - Current status

The ? command immediately returns Grbl's active state and the real-time current position, both in machine coordinates and work coordinates. This may be sent at any time and works asynchronously with all other processes that Grbl is doing. The $13 Grbl setting determines whether it reports millimeters or inches. When ? is pressed, Grbl will immediately reply with something like the following:

<Idle,MPos:5.529,0.560,7.000,WPos:1.529,-5.440,-0.000>

The active states Grbl can be in are: Idle, Queue, Run, Hold, Home, Alarm, Check

    Idle: All systems are go and it's ready for anything.
    Queue: Motion(s) are queued in the planner buffer waiting for a cycle start command to be issued. Certain processes like check g-code mode can't run while something is queued. Reset to clear the queue.
    Run: Indicates a cycle is running.
    Hold: A feed hold is in process of executing, or slowing down to a stop. After the hold is complete, Grbl will enter a Queue state, waiting for a cycle start to resume the program.
    Home: In the middle of a homing cycle. NOTE: Positions are not updated live during the homing cycle, but they'll be set to [0,0,0] once done.
    Alarm: This indicates something has gone wrong or Grbl doesn't know its position. This state locks out all g-code commands, but allows you to interact with Grbl's settings if you need to. '$X' kill alarm lock releases this state and puts Grbl in the Idle state, which will let you move things again. As said before, be cautious of what you are doing after an alarm.
    Check: Grbl is in check g-code mode. It will process and respond to all g-code commands, but not motion or turn on anything. Once toggled off with another '$C' command, Grbl will reset itself.

Other Commands $C $X $H ~ ! Ctrl-X


$C - Check gcode mode

This toggles the Grbl's gcode parser to take all incoming blocks process them completely, as it would in normal operation, but it does not move any of the axes, ignores dwells, and powers off the spindle and coolant. This is intended as a way to provide the user a way to check how their new g-code program fares with Grbl's parser and monitor for any errors. (And eventually this will also check for soft limit violations.)

When toggled off, Grbl will perform an automatic soft-reset (^X). This is for two purposes. It simplifies the code management a bit. But, it also prevents users from starting a job when their g-code modes are not what they think they are. A system reset always gives the user a fresh, consistent start.

NOTE: Eventually, the check gcode mode could be re-factored to allow for a "program resume" feature in Grbl. This means that Grbl could start a g-code program anywhere. It would internally go through all of the g-code program up to the desired mid-program resume point to set all of the parser states and locations, move to that start point, and begin executing/moving from that point on. For example, say you had to E-stop in the middle of a program because you forgot something or you have the wrong tool in the spindle. Your part is fine and need to restart the program. Right now, you'll have to start the program from the beginning and let it physically move and run up to the point where you e-stopped. If you have a long program, this could take a while. Instead, a "program resume" will just go through the beginning of the program internally, without moving anything, and only begin moving from the resume point on.


$X - Kill alarm lock

Grbl's alarm mode is a state when something has gone critically wrong, like a hard limit or an abort during a cycle, or if Grbl doesn't know its position. By default, if you have homing enabled and power-up the Arduino, Grbl enters the alarm state, because it does not know its position. The alarm mode will lock all g-code blocks until the '$H' homing cycle has been performed. Or if a user needs to override the alarm lock to move their axes off their limit switches, for example, '$X' kill alarm lock will override the locks and allow g-code functions to work again.

But, tread carefully!! This should only be used in emergency situations. The position has likely been lost, and Grbl may not be where you think it is. So, it's advised to use G91 incremental mode to make short moves. Then, perform a homing cycle or reset immediately afterwards.


$H - Run homing cycle

This command is the only way to perform the homing cycle in Grbl. Previously, G28 and G30 would automatically start the homing cycle, but this is incorrect according to the g-code standards. Homing is a completely separate command handled by the controller. G28 and G30 only move to a 'home'/pre-defined position that is stored in the g-code parameters, which can be located anywhere in the machine.

TIP: After running a homing cycle, rather jogging manually all the time to a position in the middle of your workspace volume. You can set a G28 or G30 pre-defined position to be your post-homing position, closer to where you'll be machining. To set these, you'll first need to jog your machine to where you would want it to move to after homing. Type G28.1 (or G30.1) to have Grbl store that position. So then after '$H' homing, you could just enter 'G28' (or 'G30') and it'll move there auto-magically. In general, I would just move the XY axis to the center and leave the Z-axis up. This ensures that there isn't a chance the tool in the spindle doesn't catch on anything.


~ - Cycle start

This is the cycle start or resume command that can be issued at any time, as it is a real-time command. When Grbl has motions queued in its buffer and is ready to go, the ~ cycle start command will start executing the buffer and Grbl will begin moving the axes. However, by default, auto-cycle start is enabled, so new users will not need this command unless a feed hold is performed. When a feed hold is executed, cycle start will resume the program. Cycle start will only be effective when there are motions in the buffer ready to go and will not work with any other process like homing.


! - Feed hold

The feed hold command will bring the active cycle to a stop via a controlled deceleration, so not to lose position. It is also real-time and may be activated at any time. Once finished or paused, Grbl will wait until a cycle start command is issued to resume to program. Feed hold can only pause a cycle and will not affect homing or any other process.

If you need to stop a cycle mid-program and can't afford losing position, perform a feed hold to have Grbl bring everything to a controlled stop. Once finished, you can then issue a reset. Always try to execute a feed hold whenever the machine is running before hitting reset, except of course if there is some emergency situation.


Ctrl-x - Reset Grbl

This is Grbl's soft reset command. It's real-time and can be sent at any time. As the name implies, it resets Grbl, but in a controlled way, retains your machine position, and all done without powering down your Arduino. The only times a soft-reset could lose position is when problems like if the steppers were killed while they were moving. If so, it will report if Grbl's tracking of the machine position has been lost. This is because an uncontrolled deceleration can lead to lost steps, and Grbl has no feedback to how much it lost (this is the problem with steppers in general). Otherwise, Grbl will just re-initialize, run the startup lines, and continue on its merry way.

Please note that it's recommended to do a soft-reset before starting a job. This guarantees that there aren't any g-code modes active that should be from playing around or setting up your machine. So, your machine will always starts fresh and consistently, and your machine does what you expect it to.
回复 支持 反对

使用道具 举报

发表于 2014-3-22 13:12:42 | 显示全部楼层
太赞了,正需要这方面得资料呢
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-23 08:52:57 | 显示全部楼层
oldbeginner 发表于 2014-3-22 10:07
***********************
protocol.c 下1

*******************
protocol.c 下2

*******************

内容9

Process and report status one line of incoming serial data.


void protocol_process()
{
  uint8_t c;
  while((c = serial_read()) != SERIAL_NO_DATA) {
    if ((c == '\n') || (c == '\r')) {

       内容9A();

       }
    else{

        内容9B();

    }
  }
}


Performs an initial filtering by removing spaces and comments and capitalizing all letters.
Runtime command check point before executing line. Prevent any furthur line executions.
NOTE: If there is no line, this function should quickly return to the main program when the buffer empties of non-executable data.


内容9A();

      protocol_execute_runtime();

      if (sys.abort) { return; } // Bail to main program upon system abort   

      if (char_counter > 0) {// Line is complete. Then execute!
        line[char_counter] = 0; // Terminate string
        report_status_message(protocol_execute_line(line));
      }
       else {
        // Empty or comment line. Skip block.
        report_status_message(STATUS_OK); // Send status message for syncing purposes.
      }

      protocol_reset_line_buffer();



内容9B();

     if (iscomment) {
        // Throw away all comment characters
        if (c == ')') {
          // End of comment. Resume line.
          iscomment = false;
        }
      } else {
        if (c <= ' ') {
          // Throw away whitepace and control characters
        } else if (c == '/') {
          // Block delete not supported. Ignore character.
        } else if (c == '(') {
          // Enable comments flag and ignore all characters until ')' or EOL.
          iscomment = true;
        }
         else if (char_counter >= LINE_BUFFER_SIZE-1) {
          // Report line buffer overflow and reset
          report_status_message(STATUS_OVERFLOW);
          protocol_reset_line_buffer();
        } else if (c >= 'a' && c <= 'z') { // Upcase lowercase
          line[char_counter++] = c-'a'+'A';
        } else {
          line[char_counter++] = c;
        }
      }


********************************

protocol 的代码看完,还是糊里糊涂的。先继续。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-24 10:08:26 | 显示全部楼层
oldbeginner 发表于 2014-3-23 08:52
*******************
protocol.c 下2

**********************
nuts_bolts.h

Header file for shared definitions, variables, and functions
***********************************


nuts_bolts.h 被 protocol.c 文件 引用过,并且 定义了很多 重要 变量和结构。

****************

内容1

引用头文件


#include <string.h>

#include <stdint.h>

#include <stdbool.h>

#include "config.h"

#include "defaults.h"

#include "pin_map.h"



<string.h> <stdint.h> <stdbool.h> 是 标准 头文件,

网上搜一下,






config.h 已经理解过,compile time configuration
defaults.h 也理解过,defaults settings configuration file

pin_map.h - Pin mapping configuration file,端口功能定义,需要另外一篇文章理解。

********************************

内容2

利用宏定义常量


#define false 0
#define true 1

#define N_AXIS 3 // Number of axes
#define X_AXIS 0 // Axis indexing value
#define Y_AXIS 1
#define Z_AXIS 2

#define MM_PER_INCH (25.40)
#define INCH_PER_MM (0.0393701)

什么时候用 #define 什么时候用 const 定义常量,一般如下
1,对于数值和字符常量,用#define,注意添加必要注释;
2,对于其它类型常量,用 const 限定符

区别,
define宏仅仅是展开(替换),有多少地方使用,就展开多少次,不会分配内存。(宏定义不分配内存,变量定义分配内存。) const常量会在内存中分配(可以是堆中也可以是栈中)。

宏定义很简单。

************************

内容3

Useful macros


#define clear_vector(a) memset(a, 0, sizeof(a))

#define clear_vector_float(a) memset(a, 0.0, sizeof(float)*N_AXIS)

#define max(a,b) (((a) > (b)) ? (a) : (b))

#define min(a,b) (((a) < (b)) ? (a) : (b))



memset(a, 0, sizeof(a)),用 零 清空 整型数组 a;(memset 被 string.h 声明)

memset(a, 0.0, sizeof(float)*N_AXIS),用 0.0 清空 浮点型 数组 a;

max() ,min() 很简单


***********************

内容4

Bit field and masking macros


#define bit(n) (1 << n)

#define bit_true(x,mask) (x |= mask)

#define bit_false(x,mask) (x &= ~mask)

#define bit_toggle(x,mask) (x ^= mask)

#define bit_istrue(x,mask) ((x & mask) != 0)

#define bit_isfalse(x,mask) ((x & mask) == 0)


<<:左移位 http://baike.baidu.com/link?url=RbhPgdpzuUYSN4S6m7o8EFwB2Z4v8CL69WtxHXKBYeeTXIoHok1y3UNZuYot5lNVsx72S3cSwNbpmTSUmOh-jK

n = 3; //n二进制为11
例如,
[pre lang="c" line="1"]
n = 3; //n二进制为11

b = n<<1; //n向左移动一位,b二进制为110

b = n<<2; //n向左移动二位,b二进制为1100

b = 1<<n; //1像左移动n位,相当于2的n次方,b二进制为1000[/code]

这些位运算符号
&         按位与
~       按位取反
&#166;           按位或
< <     按位左移
∧         按位异或


http://blog.csdn.net/superdullwolf/article/details/4649080
位运算应用口诀
清零取反要用与,某位置一可用或
若要取反和交换,轻轻松松用异或

(1) 按位与-- &
1 清零特定位 (mask中特定位置0,其它位为1,s=s&mask)
2 取某数中指定位 (mask中特定位置1,其它位为0,s=s&mask)

(2) 按位或-- |
    常用来将源操作数某些位置1,其它位不变。 (mask中特定位置1,其它位为0 s=s|mask)

(3) 位异或-- ^
1 使特定位的值取反 (mask中特定位置1,其它位为0 s=s^mask)

这些宏定义 是双刃剑,除非 宏的名字特别清晰已记,或者很熟悉这些宏定义,否则也容易混淆。尤其对新手。

********************************

内容5

Define system executor bit map.


在 protocol.c 中简单理解过,

#define EXEC_STATUS_REPORT  bit(0) // bitmask 00000001

#define EXEC_CYCLE_START    bit(1) // bitmask 00000010

#define EXEC_CYCLE_STOP     bit(2) // bitmask 00000100

#define EXEC_FEED_HOLD      bit(3) // bitmask 00001000

#define EXEC_RESET          bit(4) // bitmask 00010000

#define EXEC_ALARM          bit(5) // bitmask 00100000

#define EXEC_CRIT_EVENT     bit(6) // bitmask 01000000

// #define                  bit(7) // bitmask 10000000



Used internally by runtime protocol as runtime command flags,  which notifies the main program to execute the specified runtime command asynchronously.
NOTE: The system executor uses an unsigned 8-bit volatile variable (8 flag limit.)
The default flags are always false, so the runtime protocol only needs to check for a non-zero value to know when there is a runtime command to execute.

上面的宏 已经在 protocol.c 被应用了,而且一般 和 system_t 结构搭配,system_t 结构如下

***********************************

内容6

Define global system variables


typedef struct {
  uint8_t abort;                 // System abort flag. Forces exit back to main loop for reset.

  uint8_t state;                 // Tracks the current state of Grbl.

  volatile uint8_t execute;      // Global system runtime executor bitflag variable. See EXEC bitmasks.

  int32_t position[N_AXIS];      // Real-time machine (aka home) position vector in steps.
                                 // NOTE: This may need to be a volatile variable, if problems arise.   
  uint8_t auto_start;            // Planner auto-start flag. Toggled off during feed hold. Defaulted by settings.
} system_t;

extern system_t sys;


用来记录 系统 状态

*********************************

内容7

Define system state bit map.


#define STATE_IDLE       0 // Must be zero.

#define STATE_INIT       1 // Initial power up state.

#define STATE_QUEUED     2 // Indicates buffered blocks, awaiting cycle start.

#define STATE_CYCLE      3 // Cycle is running

#define STATE_HOLD       4 // Executing feed hold

#define STATE_HOMING     5 // Performing homing cycle

#define STATE_ALARM      6 // In alarm state. Locks out all g-code processes. Allows settings access.

#define STATE_CHECK_MODE 7 // G-code check mode. Locks out planner and motion only.

// #define STATE_JOG     8 // Jogging mode is unique like homing.


The state variable primarily tracks the individual functions of Grbl to manage each without overlapping.
It is also used as a messaging flag for critical events.

******************************

内容8

声明 函数


int read_float(char *line, uint8_t *char_counter, float *float_ptr);

void delay_ms(uint16_t ms);

void delay_us(uint32_t us);

void sys_sync_current_position();



******************************

GRBL 的内容量 很多,只是浏览 一下 就很费力气,更别说理解要费多少精力。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-25 08:13:40 | 显示全部楼层
oldbeginner 发表于 2014-3-24 10:08
**********************
nuts_bolts.h

**********************
nuts_bolts.c

暂时只了解功能即可
***********************


不得不说,如果第一遍就把所有代码理解,对我来说是不可能完成的任务。必须要有取舍,这个文件就可以暂时不求理解其如何实现,只了解功能即可。

nuts_bolts.c - Shared functions

*********************

内容1

引用头文件


#include <util/delay.h>

#include "nuts_bolts.h"

#include "gcode.h"

#include "planner.h"


gcode.h - rs274/ngc parser. 一个重量级头文件

planner.h - buffers movement commands and manages the acceleration profile plan
  
*************************

内容2

#define MAX_INT_DIGITS 8 // Maximum number of digits in int32 (and float)
extern float __floatunsisf (unsigned long);


************************

内容3

Extracts a floating point value from a string.


The following code is based loosely on the avr-libc strtod() function by Michael Stumpf and Dmitry Xmelkov and many freely available conversion method examples, but has been highly optimized for Grbl.
For known CNC applications, the typical decimal value is expected to be in the range of E0 to E-4.
Scientific notation is officially not supported by g-code, and the 'E' character may be a g-code word on some CNC systems.
So, 'E' notation will not be recognized.
NOTE: Thanks to Radu-Eosif Mihailescu for identifying the issues with using strtod().

int read_float(char *line, uint8_t *char_counter, float *float_ptr)                  
{
  char *ptr = line + *char_counter;
  unsigned char c;
   
  // Grab first character and increment pointer. No spaces assumed in line.
  c = *ptr++;
  
  // Capture initial positive/minus character
  bool isnegative = false;
  if (c == '-') {
    isnegative = true;
    c = *ptr++;
  } else if (c == '+') {
    c = *ptr++;
  }
  
  // Extract number into fast integer. Track decimal in terms of exponent value.
  uint32_t intval = 0;
  int8_t exp = 0;
  uint8_t ndigit = 0;
  bool isdecimal = false;
  while(1) {
    c -= '0';
    if (c <= 9) {
      ndigit++;
      if (ndigit <= MAX_INT_DIGITS) {
        if (isdecimal) { exp--; }
        intval = (((intval << 2) + intval) << 1) + c; // intval*10 + c
      } else {
        if (!(isdecimal)) { exp++; }  // Drop overflow digits
      }
    } else if (c == (('.'-'0') & 0xff)  &&  !(isdecimal)) {
      isdecimal = true;
    } else {
      break;
    }
    c = *ptr++;
  }
  
  // Return if no digits have been read.
  if (!ndigit) { return(false); };
  
  // Convert integer into floating point.
  float fval;
  fval = __floatunsisf(intval);
  
  // Apply decimal. Should perform no more than two floating point multiplications for the
  // expected range of E0 to E-4.
  if (fval != 0) {
    while (exp <= -2) {
      fval *= 0.01;
      exp += 2;
    }
    if (exp < 0) {
      fval *= 0.1;
    } else if (exp > 0) {
      do {
        fval *= 10.0;
      } while (--exp > 0);
    }
  }

  // Assign floating point value with correct sign.   
  if (isnegative) {
    *float_ptr = -fval;
  } else {
    *float_ptr = fval;
  }

  *char_counter = ptr - line - 1; // Set char_counter to next statement
  
  return(true);
}


有点复杂。

***************************************

内容4

Delays variable defined milliseconds.


Compiler compatibility fix for _delay_ms(), which only accepts constants in future compiler releases.

void delay_ms(uint16_t ms)
{
  while ( ms-- ) { _delay_ms(1); }
}


**********************************

内容5

Delays variable defined microseconds.


Compiler compatibility fix for _delay_us(), which only accepts constants in future compiler releases.
Written to perform more efficiently with larger delays, as the counter adds parasitic time in each iteration.

void delay_us(uint32_t us)
{
  while (us) {
    if (us < 10) {
      _delay_us(1);
      us--;
    } else if (us < 100) {
      _delay_us(10);
      us -= 10;
    } else if (us < 1000) {
      _delay_us(100);
      us -= 100;
    } else {
      _delay_ms(1);
      us -= 1000;
    }
  }
}


*************************************

内容6

Syncs all internal position vectors to the current system position.


void sys_sync_current_position()
{
  plan_set_current_position(sys.position[X_AXIS],sys.position[Y_AXIS],sys.position[Z_AXIS]);
  gc_set_current_position(sys.position[X_AXIS],sys.position[Y_AXIS],sys.position[Z_AXIS]);
}


*************************************

大概可以看出,这个文件是起辅助作用的,不直接操作CNC 相关设置。

回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-25 09:12:44 | 显示全部楼层
oldbeginner 发表于 2014-3-25 08:13
**********************
nuts_bolts.c

************************
gcode.h

rs274/ngc parser
*************************


这里需要大量 CNC背景知识,对我来说也是一个大挑战。

内容1

引入头文件


#include <avr/io.h>
#include "nuts_bolts.h"


****************************

内容2

Define modal group internal numbers for checking multiple command violations and tracking the type of command that is called in the block.


A modal group is a group of g-code commands that are mutually exclusive, or cannot exist on the same line, because they each toggle a state or execute a unique motion.
These are defined in the NIST RS274-NGC v3 g-code standard, available online, and are similar/identical to other g-code interpreters by manufacturers (Haas,Fanuc,Mazak,etc).

#define MODAL_GROUP_NONE 0

#define MODAL_GROUP_0 1 // [G4,G10,G28,G30,G53,G92,G92.1] Non-modal

#define MODAL_GROUP_1 2 // [G0,G1,G2,G3,G80] Motion

#define MODAL_GROUP_2 3 // [G17,G18,G19] Plane selection

#define MODAL_GROUP_3 4 // [G90,G91] Distance mode

#define MODAL_GROUP_4 5 // [M0,M1,M2,M30] Stopping

#define MODAL_GROUP_5 6 // [G93,G94] Feed rate mode

#define MODAL_GROUP_6 7 // [G20,G21] Units

#define MODAL_GROUP_7 8 // [M3,M4,M5] Spindle turning

#define MODAL_GROUP_12 9 // [G54,G55,G56,G57,G58,G59] Coordinate system selection


Modal commands are arranged in sets called “modal groups”, and only one member of a modal group may be in force at any given time.
In general, a modal group contains commands for which it is logically impossible for two members to be in effect at the same time — like measure in inches vs. measure in millimeters.

***************************************

内容3

Define command actions for within execution-type modal groups (motion, stopping, non-modal).
Used internally by the parser to know which command to execute.


#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 MOTION_MODE_CANCEL 4 // G80

#define PROGRAM_FLOW_RUNNING 0
#define PROGRAM_FLOW_PAUSED 1 // M0, M1
#define PROGRAM_FLOW_COMPLETED 2 // M2, M30

#define NON_MODAL_NONE 0
#define NON_MODAL_DWELL 1 // G4
#define NON_MODAL_SET_COORDINATE_DATA 2 // G10
#define NON_MODAL_GO_HOME_0 3 // G28
#define NON_MODAL_SET_HOME_0 4 // G28.1
#define NON_MODAL_GO_HOME_1 5 // G30
#define NON_MODAL_SET_HOME_1 6 // G30.1
#define NON_MODAL_SET_COORDINATE_OFFSET 7 // G92
#define NON_MODAL_RESET_COORDINATE_OFFSET 8 //G92.1


实现的命令。

****************************

内容4

g代码状态 结构体


typedef struct {
  uint8_t status_code;             // Parser status for current block

  uint8_t motion_mode;             // {G0, G1, G2, G3, G80}

  uint8_t inverse_feed_rate_mode;  // {G93, G94}

  uint8_t inches_mode;             // 0 = millimeter mode, 1 = inches mode {G20, G21}

  uint8_t absolute_mode;           // 0 = relative motion, 1 = absolute motion {G90, G91}

  uint8_t program_flow;            // {M0, M1, M2, M30}

  int8_t spindle_direction;        // 1 = CW, -1 = CCW, 0 = Stop {M3, M4, M5}

  uint8_t coolant_mode;            // 0 = Disable, 1 = Flood Enable {M8, M9}

  float feed_rate;                 // Millimeters/min
//  float seek_rate;                 // Millimeters/min. Will be used in v0.9 when axis independence is installed
  float position[3];               // Where the interpreter considers the tool to be at this point in the code

  uint8_t tool;
//  uint16_t spindle_speed;          // RPM/100

  uint8_t plane_axis_0,
          plane_axis_1,
          plane_axis_2;            // The axes of the selected plane  
  uint8_t coord_select;            // Active work coordinate system number. Default: 0=G54.
  float coord_system[N_AXIS];      // Current work coordinate system (G54+). Stores offset from absolute machine
                                   // position in mm. Loaded from EEPROM when called.
  float coord_offset[N_AXIS];      // Retains the G92 coordinate offset (work coordinates) relative to
                                   // machine zero in mm. Non-persistent. Cleared upon reset and boot.        
} parser_state_t;
extern parser_state_t gc;


应该会遇到很多应用的情况。

******************************

内容5

声明函数


// Initialize the parser
void gc_init();

// Execute one block of rs275/ngc/g-code
uint8_t gc_execute_line(char *line);

// Set g-code parser position. Input in steps.
void gc_set_current_position(int32_t x, int32_t y, int32_t z);


回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-25 10:18:52 | 显示全部楼层
本帖最后由 oldbeginner 于 2014-3-25 10:20 编辑
oldbeginner 发表于 2014-3-25 09:12
************************
gcode.h


********************
gcode.c 上

rs274/ngc parser

*********************


如果熟悉 gcode 编程,应该还好理解。我发现,GRBL 任何一个文件 对我 都是个 挑战,我以前没有接触过CNC 相关内容。

内容1

引入头文件


#include "gcode.h"

#include <string.h>

#include "nuts_bolts.h"

#include <math.h>

#include "settings.h"

#include "motion_control.h"

#include "spindle_control.h"

#include "coolant_control.h"

#include "errno.h"

#include "protocol.h"

#include "report.h"


********************************

内容2

定义变量和宏


// Declare gc extern struct
parser_state_t gc;

#define FAIL(status) gc.status_code = status;


*********************************

内容3

static int next_statement(char *letter, float *float_ptr, char *line, uint8_t *char_counter);


Parses the next statement and leaves the counter on the first character following the statement.
Returns 1 if there was a statements, 0 if end of string was reached or there was an error (check state.status_code).

static int next_statement(char *letter, float *float_ptr, char *line, uint8_t *char_counter)
{
  if (line[*char_counter] == 0) {
    return(0); // No more statements
  }
  
  *letter = line[*char_counter];
  if((*letter < 'A') || (*letter > 'Z')) {
    FAIL(STATUS_EXPECTED_COMMAND_LETTER);
    return(0);
  }
  (*char_counter)++;
  if (!read_float(line, char_counter, float_ptr)) {
    FAIL(STATUS_BAD_NUMBER_FORMAT);
    return(0);
  };
  return(1);
}


****************************

内容4

static void select_plane(uint8_t axis_0, uint8_t axis_1, uint8_t axis_2)
{
  gc.plane_axis_0 = axis_0;
  gc.plane_axis_1 = axis_1;
  gc.plane_axis_2 = axis_2;
}


*****************************

内容5

Initialize the parser


void gc_init()
{
  memset(&gc, 0, sizeof(gc));

  gc.feed_rate = settings.default_feed_rate; // Should be zero at initialization.

//  gc.seek_rate = settings.default_seek_rate;

  select_plane(X_AXIS, Y_AXIS, Z_AXIS);

  gc.absolute_mode = true;
  
  // Load default G54 coordinate system.

  if (!(settings_read_coord_data(gc.coord_select,gc.coord_system))) {
    report_status_message(STATUS_SETTING_READ_FAIL);
  }
}


***************************

内容6

Sets g-code parser position in mm. Input in steps.
Called by the system abort and hard limit pull-off routines.


void gc_set_current_position(int32_t x, int32_t y, int32_t z)
{
  gc.position[X_AXIS] = x/settings.steps_per_mm[X_AXIS];
  gc.position[Y_AXIS] = y/settings.steps_per_mm[Y_AXIS];
  gc.position[Z_AXIS] = z/settings.steps_per_mm[Z_AXIS];
}


***************************

内容7

static float to_millimeters(float value)
{
  return(gc.inches_mode ? (value * MM_PER_INCH) : value);
}


***************************

只剩下 一个 占据gcode.c  80% 内容的函数了。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-26 10:42:09 | 显示全部楼层
本帖最后由 oldbeginner 于 2014-3-26 10:43 编辑
oldbeginner 发表于 2014-3-25 10:18
********************
gcode.c 上


************************
gocde.c 下



**************************


内容8

Executes one line of 0-terminated G-Code.


The line is assumed to contain only uppercase characters and signed floating point values (no whitespace).
Comments and block delete characters have been removed.
All units and positions are converted and exported to grbl's internal functions in terms of (mm, mm/min) and absolute machine coordinates, respectively.

uint8_t gc_execute_line(char *line)
{

  //If in alarm state, don't process. Immediately return with error.
  //NOTE: Might not be right place for this, but also prevents $N storing during alarm.

  if (sys.state == STATE_ALARM)
           { return(STATUS_ALARM_LOCK); }

  内容8A();

   /* Pass 1: Commands and set all modes. Check for modal group violations.
     NOTE: Modal group numbers are defined in Table 4 of NIST RS274-NGC v3, pg.20 */

  内容8B();

/* Pass 2: Parameters. All units converted according to current block commands. Position
     parameters are converted and flagged to indicate a change. These can have multiple connotations
     for different commands. Each will be converted to their proper value upon execution. */

  内容8C();

/* Execute Commands: Perform by order of execution defined in NIST RS274-NGC.v3, Table 8, pg.41.
     NOTE: Independent non-motion/settings parameters are set out of this order for code efficiency
     and simplicity purposes, but this should not affect proper g-code execution. */

  内容8D();


}


***************************

内容8A();

定义变量 和 赋值


  uint8_t char_counter = 0;  
  char letter;
  float value;
  int int_value;

  uint16_t modal_group_words = 0;  // Bitflag variable to track and check modal group words in block
  uint8_t axis_words = 0;          // Bitflag to track which XYZ(ABC) parameters exist in block

  float inverse_feed_rate = -1; // negative inverse_feed_rate means no inverse_feed_rate specified
  uint8_t absolute_override = false; // true(1) = absolute motion for this block only {G53}
  uint8_t non_modal_action = NON_MODAL_NONE; // Tracks the actions of modal group 0 (non-modal)
  
  float target[3], offset[3];  
  clear_vector(target); // XYZ(ABC) axes parameters.
  clear_vector(offset); // IJK Arc offsets are incremental. Value of zero indicates no change.
   
  gc.status_code = STATUS_OK;

  
****************************

变量涉及到 具体的 CNC 知识。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-26 11:28:19 | 显示全部楼层
oldbeginner 发表于 2014-3-26 10:42
************************
gocde.c 下

************************
gcode.c 下

内容8B

************************


内容8B();

Check for modal group violations.


  uint8_t group_number = MODAL_GROUP_NONE;

  while(next_statement(&letter, &value, line, &char_counter)) {
    int_value = trunc(value);
    switch(letter) {
      case 'G':
             内容8E();

      case 'M':
             内容8F();

    }   

    // Check for modal group multiple command violations in the current block
    if (group_number) {
      if ( bit_istrue(modal_group_words,bit(group_number)) ) {
        FAIL(STATUS_MODAL_GROUP_VIOLATION);
      } else {
        bit_true(modal_group_words,bit(group_number));
      }
      group_number = MODAL_GROUP_NONE; // Reset for next command.
    }
  }

  // If there were any errors parsing this line, we will return right away with the bad news
  if (gc.status_code)
             { return(gc.status_code); }

  
******************************************

内容8E();

Set modal group values


        switch(int_value) {
          case 4: case 10: case 28: case 30: case 53: case 92: group_number = MODAL_GROUP_0; break;
          case 0: case 1: case 2: case 3: case 80: group_number = MODAL_GROUP_1; break;
          case 17: case 18: case 19: group_number = MODAL_GROUP_2; break;
          case 90: case 91: group_number = MODAL_GROUP_3; break;
          case 93: case 94: group_number = MODAL_GROUP_5; break;
          case 20: case 21: group_number = MODAL_GROUP_6; break;
          case 54: case 55: case 56: case 57: case 58: case 59: group_number = MODAL_GROUP_12; break;
        }         

        // Set 'G' commands
        switch(int_value) {
          case 0: gc.motion_mode = MOTION_MODE_SEEK; break;
          case 1: gc.motion_mode = MOTION_MODE_LINEAR; break;
          case 2: gc.motion_mode = MOTION_MODE_CW_ARC; break;
          case 3: gc.motion_mode = MOTION_MODE_CCW_ARC; break;
          case 4: non_modal_action = NON_MODAL_DWELL; break;
          case 10: non_modal_action = NON_MODAL_SET_COORDINATE_DATA; break;
          case 17: select_plane(X_AXIS, Y_AXIS, Z_AXIS); break;
          case 18: select_plane(X_AXIS, Z_AXIS, Y_AXIS); break;
          case 19: select_plane(Y_AXIS, Z_AXIS, X_AXIS); break;
          case 20: gc.inches_mode = true; break;
          case 21: gc.inches_mode = false; break;
          case 28: case 30:
            int_value = trunc(10*value); // Multiply by 10 to pick up Gxx.1
            switch(int_value) {
              case 280: non_modal_action = NON_MODAL_GO_HOME_0; break;
              case 281: non_modal_action = NON_MODAL_SET_HOME_0; break;
              case 300: non_modal_action = NON_MODAL_GO_HOME_1; break;
              case 301: non_modal_action = NON_MODAL_SET_HOME_1; break;
              default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
            }
            break;
          case 53: absolute_override = true; break;
          case 54: case 55: case 56: case 57: case 58: case 59:
            gc.coord_select = int_value-54;
            break;
          case 80: gc.motion_mode = MOTION_MODE_CANCEL; break;
          case 90: gc.absolute_mode = true; break;
          case 91: gc.absolute_mode = false; break;
          case 92:
            int_value = trunc(10*value); // Multiply by 10 to pick up G92.1
            switch(int_value) {
              case 920: non_modal_action = NON_MODAL_SET_COORDINATE_OFFSET; break;        
              case 921: non_modal_action = NON_MODAL_RESET_COORDINATE_OFFSET; break;
              default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
            }
            break;
          case 93: gc.inverse_feed_rate_mode = true; break;
          case 94: gc.inverse_feed_rate_mode = false; break;
          default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
        }
        break;   


根据Gxx 设置相应的参数。

*******************************

内容8F();

Set modal group values


        switch(int_value) {
          case 0: case 1: case 2: case 30: group_number = MODAL_GROUP_4; break;
          case 3: case 4: case 5: group_number = MODAL_GROUP_7; break;
        }   
   
        // Set 'M' commands
        switch(int_value) {
          case 0: gc.program_flow = PROGRAM_FLOW_PAUSED; break; // Program pause
          case 1: break; // Optional stop not supported. Ignore.
          case 2: case 30: gc.program_flow = PROGRAM_FLOW_COMPLETED; break; // Program end and reset
          case 3: gc.spindle_direction = 1; break;
          case 4: gc.spindle_direction = -1; break;
          case 5: gc.spindle_direction = 0; break;
          #ifdef ENABLE_M7
            case 7: gc.coolant_mode = COOLANT_MIST_ENABLE; break;
          #endif
          case 8: gc.coolant_mode = COOLANT_FLOOD_ENABLE; break;
          case 9: gc.coolant_mode = COOLANT_DISABLE; break;
          default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
        }            
        break;


*********************

好理解,开了个好头。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-26 12:16:43 | 显示全部楼层
oldbeginner 发表于 2014-3-26 11:28
************************
gcode.c 下

*******************
gcode.c 下

内容8C();

*******************


内容8C();

Pass 2: Parameters.


All units converted according to current block commands. Position
     parameters are converted and flagged to indicate a change. These can have multiple connotations
     for different commands. Each will be converted to their proper value upon execution.

  float p = 0, r = 0;
  uint8_t l = 0;
  char_counter = 0;
  while(next_statement(&letter, &value, line, &char_counter)) {
    switch(letter) {
      
         内容8G();

  }
  
  // If there were any errors parsing this line, we will return right away with the bad news
  if (gc.status_code) { return(gc.status_code); }

  

***********************************

内容8G();

      case 'G': case 'M': case 'N': break; // Ignore command statements and line numbers
      case 'F':
        if (value <= 0) { FAIL(STATUS_INVALID_STATEMENT); } // Must be greater than zero
        if (gc.inverse_feed_rate_mode) {
          inverse_feed_rate = to_millimeters(value); // seconds per motion for this motion only
        } else {         
          gc.feed_rate = to_millimeters(value); // millimeters per minute
        }
        break;
      case 'I': case 'J': case 'K': offset[letter-'I'] = to_millimeters(value); break;
      case 'L': l = trunc(value); break;
      case 'P': p = value; break;                    
      case 'R': r = to_millimeters(value); break;
      case 'S':
        if (value < 0) { FAIL(STATUS_INVALID_STATEMENT); } // Cannot be negative
        // TBD: Spindle speed not supported due to PWM issues, but may come back once resolved.
        // gc.spindle_speed = value;
        break;
      case 'T':
        if (value < 0) { FAIL(STATUS_INVALID_STATEMENT); } // Cannot be negative
        gc.tool = trunc(value);
        break;
      case 'X': target[X_AXIS] = to_millimeters(value); bit_true(axis_words,bit(X_AXIS)); break;
      case 'Y': target[Y_AXIS] = to_millimeters(value); bit_true(axis_words,bit(Y_AXIS)); break;
      case 'Z': target[Z_AXIS] = to_millimeters(value); bit_true(axis_words,bit(Z_AXIS)); break;
      default: FAIL(STATUS_UNSUPPORTED_STATEMENT);
    }


*******************************

暂时可以这样理解, 这个执行的命令类似 X10 之类的。(前面的 G01 类似命令在 PASS 1中)
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-27 09:49:38 | 显示全部楼层
本帖最后由 oldbeginner 于 2014-3-27 10:10 编辑
oldbeginner 发表于 2014-3-26 12:16
*******************
gcode.c 下

*************************
gcode.c 下

内容8D()
*************************


内容8D();                                                                                       

Execute Commands: Perform by order of execution defined in NIST RS274-NGC.v3, Table 8, pg.41.


NOTE: Independent non-motion/settings parameters are set out of this order for code efficiency
     and simplicity purposes, but this should not affect proper g-code execution.
  
  // ([F]: Set feed and seek rates.)
  // TODO: Seek rates can change depending on the direction and maximum speeds of each axes. When
  // max axis speed is installed, the calculation can be performed here, or maybe in the planner.

内容8H();

    // [G54,G55,...,G59]: Coordinate system selection

  内容8I();

  // [G4,G10,G28,G30,G92,G92.1]: Perform dwell, set coordinate system data, homing, or set axis offsets.
  // NOTE: These commands are in the same modal group, hence are mutually exclusive. G53 is in this
  // modal group and do not effect these actions.

  内容8J();

  // [G0,G1,G2,G3,G80]: Perform motion modes.
  // NOTE: Commands G10,G28,G30,G92 lock out and prevent axis words from use in motion modes.
  // Enter motion modes only if there are axis words or a motion mode command word in the block.

   if ( bit_istrue(modal_group_words,bit(MODAL_GROUP_1)) || axis_words ) {
  内容8K();

    // Convert all target position data to machine coordinates for executing motion. Apply
    // absolute mode coordinate offsets or incremental mode offsets.
    // NOTE: Tool offsets may be appended to these conversions when/if this feature is added.

  内容8L();

    switch (gc.motion_mode) {

          内容8M();
     }

    // Report any errors.

   内容8N();

    // As far as the parser is concerned, the position is now == target. In reality the
    // motion control system might still be processing the action and the real tool position
    // in any intermediate location.

    内容8O();
}  // if ( bit_istrue(modal_group_words,bit(MODAL_GROUP_1)) || axis_words )

  // M0,M1,M2,M30: Perform non-running program flow actions. During a program pause, the buffer may
  // refill and can only be resumed by the cycle start run-time command.
   
    内容8P();                                                                          

  return(gc.status_code);
}


*****************************************

内容8H();                                                                             

  if (sys.state != STATE_CHECK_MODE) {
    //  ([M6]: Tool change should be executed here.)

    // [M3,M4,M5]: Update spindle state
    spindle_run(gc.spindle_direction);
  
    // [*M7,M8,M9]: Update coolant state
    coolant_run(gc.coolant_mode);
  }


只要不是 check mode,就执行 主轴功能,冷却功能。

*****************************************

内容8I();                                                                                    

// [G54,G55,...,G59]: Coordinate system selection


  if ( bit_istrue(modal_group_words,bit(MODAL_GROUP_12)) ) { // Check if called in block

    float coord_data[N_AXIS];

    if (!(settings_read_coord_data(gc.coord_select,coord_data))) { return(STATUS_SETTING_READ_FAIL); }

    memcpy(gc.coord_system,coord_data,sizeof(coord_data));
  }


Read selected coordinate data from EEPROM. Updates pointed coord_data value. settings_read_coord_data 函数定义在setting.c中。

*********************

内容8J();                                                                                                                                                        

  // [G4,G10,G28,G30,G92,G92.1]: Perform dwell, set coordinate system data, homing, or set axis offsets.
  // NOTE: These commands are in the same modal group, hence are mutually exclusive. G53 is in this
  // modal group and do not effect these actions.




  switch (non_modal_action) {
    case NON_MODAL_DWELL:
         
               内容8X();
      break;
    case NON_MODAL_SET_COORDINATE_DATA:

               内容8Y();
      break;
    case NON_MODAL_GO_HOME_0: case NON_MODAL_GO_HOME_1:

               内容8Z();
      break;
    case NON_MODAL_SET_HOME_0: case NON_MODAL_SET_HOME_1:

              内容8AA();
      break;   
    case NON_MODAL_SET_COORDINATE_OFFSET:

             内容8AB();
      break;
    case NON_MODAL_RESET_COORDINATE_OFFSET:

             内容8AC();
      break;
  }



内容8X();                                                                                          


      if (p < 0) { // Time cannot be negative.
        FAIL(STATUS_INVALID_STATEMENT);
      } else {
        // Ignore dwell in check gcode modes
        if (sys.state != STATE_CHECK_MODE) { mc_dwell(p); }
      }


内容8Y();                                                                                          

      int_value = trunc(p); // Convert p value to int.
      if ((l != 2 && l != 20) || (int_value < 0 || int_value > N_COORDINATE_SYSTEM)) { // L2 and L20. P1=G54, P2=G55, ...
        FAIL(STATUS_UNSUPPORTED_STATEMENT);
      } else if (!axis_words && l==2) { // No axis words.
        FAIL(STATUS_INVALID_STATEMENT);
      } else {
        if (int_value > 0) { int_value--; } // Adjust P1-P6 index to EEPROM coordinate data indexing.
        else { int_value = gc.coord_select; } // Index P0 as the active coordinate system
        float coord_data[N_AXIS];
        if (!settings_read_coord_data(int_value,coord_data)) { return(STATUS_SETTING_READ_FAIL); }
        uint8_t i;
        // Update axes defined only in block. Always in machine coordinates. Can change non-active system.
        for (i=0; i<N_AXIS; i++) { // Axes indices are consistent, so loop may be used.
          if (bit_istrue(axis_words,bit(i)) ) {
            if (l == 20) {
              coord_data = gc.position-target; // L20: Update axis current position to target
            } else {
              coord_data = target; // L2: Update coordinate system axis
            }
          }
        }
        settings_write_coord_data(int_value,coord_data);
        // Update system coordinate system if currently active.
        if (gc.coord_select == int_value) { memcpy(gc.coord_system,coord_data,sizeof(coord_data)); }
      }
      axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags.


内容8Z();                                                                                         

      // Move to intermediate position before going home. Obeys current coordinate system and offsets
      // and absolute and incremental modes.
      if (axis_words) {
        // Apply absolute mode coordinate offsets or incremental mode offsets.
        uint8_t i;
        for (i=0; i<N_AXIS; i++) { // Axes indices are consistent, so loop may be used.
          if ( bit_istrue(axis_words,bit(i)) ) {
            if (gc.absolute_mode) {
              target += gc.coord_system + gc.coord_offset;
            } else {
              target += gc.position;
            }
          } else {
            target = gc.position;
          }
        }
        mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], settings.default_seek_rate, false);
      }
      // Retreive G28/30 go-home position data (in machine coordinates) from EEPROM
      float coord_data[N_AXIS];
      if (non_modal_action == NON_MODAL_GO_HOME_1) {
        if (!settings_read_coord_data(SETTING_INDEX_G30 ,coord_data)) { return(STATUS_SETTING_READ_FAIL); }     
      } else {
        if (!settings_read_coord_data(SETTING_INDEX_G28 ,coord_data)) { return(STATUS_SETTING_READ_FAIL); }     
      }      
      mc_line(coord_data[X_AXIS], coord_data[Y_AXIS], coord_data[Z_AXIS], settings.default_seek_rate, false);
      memcpy(gc.position, coord_data, sizeof(coord_data)); // gc.position[] = coord_data[];
      axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags.


内容8AA();                                                                                       

      if (non_modal_action == NON_MODAL_SET_HOME_1) {
        settings_write_coord_data(SETTING_INDEX_G30,gc.position);
      } else {
        settings_write_coord_data(SETTING_INDEX_G28,gc.position);
      }


内容8AB();                                                                                      

      if (!axis_words) { // No axis words
        FAIL(STATUS_INVALID_STATEMENT);
      } else {
        // Update axes defined only in block. Offsets current system to defined value. Does not update when
        // active coordinate system is selected, but is still active unless G92.1 disables it.
        uint8_t i;
        for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used.
          if (bit_istrue(axis_words,bit(i)) ) {
            gc.coord_offset = gc.position-gc.coord_system-target;
          }
        }
      }
      axis_words = 0; // Axis words used. Lock out from motion modes by clearing flags.


内容8AC();                                                                                    

      clear_vector(gc.coord_offset); // Disable G92 offsets by zeroing offset vector.


****************************************
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-27 10:14:37 | 显示全部楼层
oldbeginner 发表于 2014-3-27 09:49
*************************
gcode.c 下

**********************
gcode.c 下

**********************

内容8K();                                                   

    // G1,G2,G3 require F word in inverse time mode.  

    if ( gc.inverse_feed_rate_mode ) {
      if (inverse_feed_rate < 0 && gc.motion_mode != MOTION_MODE_CANCEL) {
        FAIL(STATUS_INVALID_STATEMENT);
      }
    }

    // Absolute override G53 only valid with G0 and G1 active.

    if ( absolute_override && !(gc.motion_mode == MOTION_MODE_SEEK || gc.motion_mode == MOTION_MODE_LINEAR)) {
      FAIL(STATUS_INVALID_STATEMENT);
    }

    // Report any errors.  
    if (gc.status_code) { return(gc.status_code); }



内容8L();                                                   

    uint8_t i;
    for (i=0; i<=2; i++) { // Axes indices are consistent, so loop may be used to save flash space.
      if ( bit_istrue(axis_words,bit(i)) ) {
        if (!absolute_override) { // Do not update target in absolute override mode
          if (gc.absolute_mode) {
            target += gc.coord_system + gc.coord_offset; // Absolute mode
          } else {
            target += gc.position; // Incremental mode
          }
        }
      } else {
        target = gc.position; // No axis word in block. Keep same axis position.
      }
    }


*********************
头疼。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-27 11:53:33 | 显示全部楼层
oldbeginner 发表于 2014-3-27 10:14
**********************
gcode.c 下

*****************************
gcode.c 下

****************************


内容8M();                                                              


      case MOTION_MODE_CANCEL:
               
               内容G80();
        break;
      case MOTION_MODE_SEEK:

               内容G00();
        break;
      case MOTION_MODE_LINEAR:
               
              内容G01();
        break;
      case MOTION_MODE_CW_ARC: case MOTION_MODE_CCW_ARC:

              内容G02G03();
       break;


可以看出,执行的是 GROUP1 中的命令

内容G80();                                                            

        if (axis_words) { FAIL(STATUS_INVALID_STATEMENT); } // No axis words allowed while active.

内容G00();                                                           

        if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);}
        else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], settings.default_seek_rate, false); }

mc_line 定义在 motion_control.c 文件中

内容G01();                                                         

        // TODO: Inverse time requires F-word with each statement. Need to do a check. Also need
        // to check for initial F-word upon startup. Maybe just set to zero upon initialization
        // and after an inverse time move and then check for non-zero feed rate each time. This
        // should be efficient and effective.
        if (!axis_words) { FAIL(STATUS_INVALID_STATEMENT);}
        else { mc_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS],
          (gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode); }

内容G02G03();                                                         

        // Check if at least one of the axes of the selected plane has been specified. If in center
        // format arc mode, also check for at least one of the IJK axes of the selected plane was sent.
        if ( !( bit_false(axis_words,bit(gc.plane_axis_2)) ) ||
             ( !r && !offset[gc.plane_axis_0] && !offset[gc.plane_axis_1] ) ) {
          FAIL(STATUS_INVALID_STATEMENT);
        } else {
          if (r != 0) { // Arc Radius Mode

            // Calculate the change in position along each selected axis
            float x = target[gc.plane_axis_0]-gc.position[gc.plane_axis_0];
            float y = target[gc.plane_axis_1]-gc.position[gc.plane_axis_1];
            
            clear_vector(offset);
            // First, use h_x2_div_d to compute 4*h^2 to check if it is negative or r is smaller
            // than d. If so, the sqrt of a negative number is complex and error out.
            float h_x2_div_d = 4 * r*r - x*x - y*y;
            if (h_x2_div_d < 0) { FAIL(STATUS_ARC_RADIUS_ERROR); return(gc.status_code); }
            // Finish computing h_x2_div_d.
            h_x2_div_d = -sqrt(h_x2_div_d)/hypot(x,y); // == -(h * 2 / d)
            // Invert the sign of h_x2_div_d if the circle is counter clockwise (see sketch below)
            if (gc.motion_mode == MOTION_MODE_CCW_ARC) { h_x2_div_d = -h_x2_div_d; }

            if (r < 0) {
                h_x2_div_d = -h_x2_div_d;
                r = -r; // Finished with r. Set to positive for mc_arc
            }        
            // Complete the operation by calculating the actual center of the arc
            offset[gc.plane_axis_0] = 0.5*(x-(y*h_x2_div_d));
            offset[gc.plane_axis_1] = 0.5*(y+(x*h_x2_div_d));

          } else { // Arc Center Format Offset Mode            
            r = hypot(offset[gc.plane_axis_0], offset[gc.plane_axis_1]); // Compute arc radius for mc_arc
          }
         
          // Set clockwise/counter-clockwise sign for mc_arc computations
          uint8_t isclockwise = false;
          if (gc.motion_mode == MOTION_MODE_CW_ARC) { isclockwise = true; }
   
          // Trace the arc
          mc_arc(gc.position, target, offset, gc.plane_axis_0, gc.plane_axis_1, gc.plane_axis_2,
            (gc.inverse_feed_rate_mode) ? inverse_feed_rate : gc.feed_rate, gc.inverse_feed_rate_mode,
            r, isclockwise);

**************************************

圆弧插补 的方法看起来有些复杂,需要其它资料来辅助理解。
回复 支持 反对

使用道具 举报

发表于 2014-3-27 17:18:26 | 显示全部楼层
英语太差啊!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2014-3-28 10:03:04 | 显示全部楼层
oldbeginner 发表于 2014-3-27 11:53
*****************************
gcode.c 下

******************************
gcode.c 下

******************************

内容8N();                                                            

Report any errors


    if (gc.status_code) { return(gc.status_code); }   

    // As far as the parser is concerned, the position is now == target. In reality the
    // motion control system might still be processing the action and the real tool position
    // in any intermediate location.

memcpy(gc.position, target, sizeof(target)); // gc.position[] = target[];

内容8O();                                                            

M0,M1,M2,M30: Perform non-running program flow actions.

  if (gc.program_flow) {
    plan_synchronize(); // Finish all remaining buffered motions. Program paused when complete.
    sys.auto_start = false; // Disable auto cycle start. Forces pause until cycle start issued.


内容8P();                                                            

If complete, reset to reload defaults (G92.2,G54,G17,G90,G94,M48,G40,M5,M9).

    if (gc.program_flow == PROGRAM_FLOW_COMPLETED) { mc_reset(); }
    else { gc.program_flow = PROGRAM_FLOW_RUNNING; }
  }

******************************

gcode.c 应该是目前最重要的一个文件,遗憾的是,它同时也是最复杂和最难理解的。
回复 支持 反对

使用道具 举报

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

本版积分规则 需要先绑定手机号

Archiver|联系我们|极客工坊

GMT+8, 2024-5-24 14:26 , Processed in 0.046657 second(s), 17 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2021, Tencent Cloud.

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