bdurbrow / grbl-Mega

An open source, embedded, high performance g-code-parser and CNC milling controller written in optimized C that will run on an Arduino Mega2560
https://github.com/gnea/grbl/wiki
MIT License
35 stars 8 forks source link

Enhancement: Multiline fragment buffer #18

Open thawkins opened 4 years ago

thawkins commented 4 years ago

I have been working on adding "Set Zero Point" and "Return to Zero" to the system menus. but came up with a gotcha

the return to zero to be safe needs to return to X,Y first and then return to Z, so poking the command into the UILineBuffer does not work as that does not support multiple statements like "G90 X0.0 Y0.0", "G90 Z0.0". So i looked at the drilling operations menus, and discovered they rely on writing a GCode file out to the SDCard and then executing it.

We could probably do with having a memory based file that works like the SD Card, to allow short macro sequences to be written that can be executed without an SD card being present.

bdurbrow commented 4 years ago

Have a look at protocol_buffer_synchronize(). Do the first line with UILineBuffer; call protocol_buffer_synchronize(); then do the next line.

I’m in a parking lot right this second, I’ll have more information about it when I get home in about an hour.

thawkins commented 4 years ago

not urgent, dont rush

On Tue, Oct 8, 2019 at 11:17 AM Britt notifications@github.com wrote:

Have a look at protocol_buffer_synchronize(). Do the first line with UILineBuffer; call protocol_buffer_synchronize(); then do the next line.

I’m in a parking lot right this second, I’ll have more information about it when I get home in about an hour.

— You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub https://github.com/bdurbrow/grbl-Mega/issues/18?email_source=notifications&email_token=AAADRSLYNFI3L356VPPVEULQNP3VVA5CNFSM4I6L2XP2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEASQADQ#issuecomment-539295758, or mute the thread https://github.com/notifications/unsubscribe-auth/AAADRSPNLKYNMBNMMAI3PZTQNP3VVANCNFSM4I6L2XPQ .

thawkins commented 4 years ago

I defined the following, I will test and debug tonight, it should allow fragments to be sequentially executed in a menu response handler.

#define UIEXEC(s) strcpy(UILineBuffer,s); \
            UILineBuffer[strlen(s)] = 0; \
            UILineBufferState = UILineBufferState_ReadyForExecution; \
            protocol_buffer_synchronize(); \
            if (sys.abort) {  \
                UIShowError(PSTR("    Function Abort.")); \
                return; \
            }
bdurbrow commented 4 years ago

Eh... I was waiting for my dad to come out of the grocery store; and just checking stuff on my iPhone - which while great for browsing on-the-go isn't so handy for typing out responses involving source code.

Anyway... upon further thought; protocol_buffer_synchronize() isn't going to do what is desired because the main protocol loop won't see the full & ready-to-execute line buffer until you've returned from your function. To address this for you and provide this sort of functionality to the expansion interface I am going to add a function to UISupport.h.

#define UIExecuteGCode_Option_Default           (0x00)
#define UIExecuteGCode_Option_StartOfSequence   (0x01)
#define UIExecuteGCode_Option_Synchronous       (0x02)

uint8_t UIExecuteGCode(char *buffer, uint8_t options);

This will check for initial conditions if UIExecuteGCode_Option_StartOfSequence is passed in (machine is idle, etc); execute the g-code; wait for synchronization if asked for; and return a status code (if it's not STATUS_OK; you should abort the operation).

bdurbrow commented 4 years ago

This compiles, but I don't have anything in the system yet to exercise it - I think it will work, but I don't know.

// Add this to report.h
#define STATUS_USER_ABORT 50
#define STATUS_RESET 51
#define STATUS_MOTION_CANCEL 52

// Add this to UISupport.h
#define UIExecuteGCode_Option_Default           (0x00)
#define UIExecuteGCode_Option_StartOfSequence   (0x01)
#define UIExecuteGCode_Option_ResetOnUserAbort  (0x02)
#define UIExecuteGCode_Option_Synchronous       (0x04)

extern uint8_t UIExecuteGCode(char *buffer, uint8_t options);

// Add this to UISupport.cpp
uint8_t UIExecuteGCode(char *buffer, uint8_t options)
{
  if(options & UIExecuteGCode_Option_StartOfSequence)
  {
    switch (sys.state)
    {
      case STATE_IDLE:
      case STATE_CHECK_MODE:
      case STATE_JOG:
        break;
      default:
        return STATUS_IDLE_ERROR;
    }
  }

  // Check for failure conditions
    if(sys_rt_exec_state & EXEC_SAFETY_DOOR) return STATUS_CHECK_DOOR;
    if((sys_rt_exec_state & EXEC_RESET) || sys.abort) return STATUS_RESET;
    if(sys_rt_exec_state & EXEC_FEED_HOLD) return STATUS_USER_ABORT;

    // Poll UI Encoder Button 2
    #ifdef UI_ENCODER_A_PINBTN2_ACTIVE_LOW
      if(!fastDigitalRead(UI_ENCODER_A_PINBTN2))
    #else
      if(fastDigitalRead(UI_ENCODER_A_PINBTN2))
    #endif
      {
        if(options & UIExecuteGCode_Option_ResetOnUserAbort) mc_reset();
        return STATUS_USER_ABORT;
      }

  uint8_t result;

  if(buffer[0] == '$')
    result = system_execute_line(buffer);
  else
    result = gc_execute_line(buffer);

  if(result) return result;

  // If system is queued, ensure cycle resumes if the auto start flag is present.
  protocol_auto_cycle_start();

  if(options & UIExecuteGCode_Option_Synchronous)
  {
    do
    {
      protocol_execute_realtime();   // Check and execute run-time commands

      // Check for failure conditions
        if(sys_rt_exec_state & EXEC_SAFETY_DOOR) return STATUS_CHECK_DOOR;
        if((sys_rt_exec_state & EXEC_RESET) || sys.abort) return STATUS_RESET;
        if(sys_rt_exec_state & EXEC_FEED_HOLD) return STATUS_USER_ABORT;

        // Poll UI Encoder Button 2
        #ifdef UI_ENCODER_A_PINBTN2_ACTIVE_LOW
          if(!fastDigitalRead(UI_ENCODER_A_PINBTN2))
        #else
          if(fastDigitalRead(UI_ENCODER_A_PINBTN2))
        #endif
          {
            if(options & UIExecuteGCode_Option_ResetOnUserAbort) mc_reset();
            return STATUS_USER_ABORT;
          }
    } while (plan_get_current_block() || (sys.state == STATE_CYCLE));
  }
}
thawkins commented 4 years ago

I will give it a try tonight