Problem with streaming Gcode via tx/rx from device to GRBL running on Nano

Hi,
I have being writing a code for my device and the end output is a g-code generated after an interpolated array.
The device running my code is a Teensy 4.1 and the one running GRBL is an Arduino NANO.

A command key sends the Teensy's Gcode output via serial, adding a header and footer to it.

Both devices are connected by their tx1/rx1 pins amd grounded together. Baud is 115200.

The output polyline g-code is simple, and seems correct, also communication with GRBL is there.

Problem arise when streaming. Somehow the stream stops (which I understand my be buffer full and waiting to ok response), and when it starts to get codes again, the machine gives error 24 and motors come to a halt.

It does not seem to happen when generating just a short code, but if the file has more than 10 or so lines the error will appear.

Also if I force a delay if about 1 sec between each line is sent, there are no errors, but the machine will work faster than it will receive lines making it stop between each next point (as it waits for next line)

I tried copying the generated output to notepad, save as .gcode and run from PC using UGS. No problems at all, even with larger files.

I wonder if there is any thing that may indicate this is an issue with grbl sending OK's when it's not fully ready yet. Is this possible?

I am quite puzzled and wonder if that can also be caused by arduino code being in loop / blocking.

I am thinking to try out the esp32 grbl fork and see if it's any improvement but I am almost out of ideas.

My code does lots of other things before and is huge but I can post the communication bits if it can be anything related to my side of the streaming.

I hope someone has any idea if what may be going on and could shed some light in these dark debugging days :slight_smile:

Without code, only speculation will happen :slight_smile:

If UGS (a program?) running on a PC works, does it do any sort of handshaking besides just streaming the data? Things like XON/XOFF or using RTS/DSR

Hi I will try to copy where I did the communicating int.
I am just using a simple send/received protocol and sending a new line after an ok is received from grbl.
No handshaking or xon/xoff, but I saw that the character counting code used that method on the repository.

That is not "streaming".
Paul

Seems the people behind grbl will disagree...

" Streaming Protocol: Simple Send-Response [Recommended for Grbl v0.9+]

The send-response streaming protocol is the most fool-proof and simplest method to stream a G-code program to Grbl. The host PC interface simply sends a line of G-code to Grbl and waits for an ok or error: response before sending the next line of G-code. So, no matter if Grbl needs to wait for room in the look-ahead planner buffer to finish parsing and executing the last line of G-code or if the the host computer is busy doing something, this guarantees both to the host PC and Grbl, the programmed G-code has been sent and received properly. An example of this protocol is published in our simple_stream.py script in our repository."

Streaming is what over-the -air TV uses. AKA "shoot and forget". IF there is an error, the next block of data will fix it.
Paul

It may be. I just referred to the terminology used on their wiki.

Here is the part of my code which is handling the communication with GRBL. Waits for ok to send new line and stops when reports on error.


      if (grbl_reply.indexOf("error:") >= 0) {
           while (Serial1.available()) {
            grbl_error += Serial1.read();
           }
        Serial.println(grbl_error);   
        grblReportError();
        return -1;
      }
    }
  }
  grblReportError();    
  return -1;
}

That function unilaterally returns after sending "G30" so you never transmit "M2" or "%"

In your getReplyFromGRBL() function, you should initialize your grbl_error to an empty string since you just start concatenating to it in your error code. Or better yet, there is no need to build up a String just to print it out. Just do it char by char.

    if (grbl_reply.indexOf("error:") >= 0) {
      while (Serial1.available()) {
        Serial.write(Serial1.read());
      }
      // Serial.println(grbl_error);
      grblReportError();
      return -1;
...

Tried these changes but wasn't any difference.
My output is something like this

I don't think is a cable/EMI issue as I can send fine if forcing a delay between each line.

pictures of text are rarely useful. Cutting and Pasting inside code tags is always better. (and this gets more true are the eyes get older :slight_smile: )

Basically it replies all ok and suddenly prints the error 24 as a reply.

On start, and while the machine is moving/hovering the Y and Y axis above the surface, and on its way to the first working height point, the buffer is filled up very fast and the serial activity stays stalled until the first movement is completed, when the sending recovers activity and usually outputs the error after a few seconds.

This behavior leads to believe that the buffer is overflowed, It may be a way to read the available buffer space and throttle the data accordingly, but I have no idea how.

Edit: I see that a Python script from GRBL repo can keep track of the characters sent and ok's received and will control the output in such a way to never let the buffer get full.

I will give a try in implementing this part in C..

# Send g-code program via a more agressive streaming protocol that forces characters into
    # Grbl's serial read buffer to ensure Grbl has immediate access to the next g-code command
    # rather than wait for the call-response serial protocol to finish. This is done by careful
    # counting of the number of characters sent by the streamer to Grbl and tracking Grbl's 
    # responses, such that we never overflow Grbl's serial read buffer. 
    g_count = 0
    c_line = []
    # periodic() # Start status report periodic timer
    for line in f:
        l_count += 1 # Iterate line counter
        # l_block = re.sub('\s|\(.*?\)','',line).upper() # Strip comments/spaces/new line and capitalize
        l_block = line.strip()
        c_line.append(len(l_block)+1) # Track number of characters in grbl serial read buffer
        grbl_out = '' 
        while sum(c_line) >= RX_BUFFER_SIZE-1 | s.inWaiting() :
            out_temp = s.readline().strip() # Wait for grbl response
            if out_temp.find('ok') < 0 and out_temp.find('error') < 0 :
                print "  Debug: ",out_temp # Debug response
            else :
                grbl_out += out_temp;
                g_count += 1 # Iterate g-code counter
                grbl_out += str(g_count); # Add line finished indicator
                del c_line[0] # Delete the block character count corresponding to the last 'ok'
        if verbose: print "SND: " + str(l_count) + " : " + l_block,
        s.write(l_block + '\n') # Send g-code block to grbl
        if verbose : print "BUF:",str(sum(c_line)),"REC:",grbl_out

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.