Forum

SerialPort send GCODE to 3D Printer

I am trying to use V4 gamma to send GCODE instructions to an Ender 3 Pro using the SerialPort node.

I can use the RS232 node in V4 beta to do this successfully but there appears to be a problem with the way ToBytes (gamma) encodes the data compared with AsRaw (beta) - when both using the UTF8 encoding.

Using V4 beta, the test GCODE of G28 is converted with the AsRaw node to the byte string [47 32 38 0A 0D 0A] which is sent through the RS232 node and executed by the printer.

In V4 gamma however, the input node only allows data formatted as Spread, which using the FromSequence node converts the G28 command to the Spread:

71 (0x47)
50 (0x32)
56 (0x38)

Please see attached screenshot for reference.

I’d be grateful for any advice on how to make ToBytes behave the same way as the AsRaw node, and then how to successfully pass that through the SerialPort node.

Many thanks

In the beta patch, there is a cons and a plus node, maybe they add the additional bytes? Otherwise, looks correct… Also make sure that the com port isn’t opened by another software.

Edit: this is wrong!

ahoi, it looks like you need to send the byte encoded as Hex

We did rebuild the Patch and figured out that you added some LF + CR LF in the Beta version - thats the 0A 0D 0A part.

In gamma the tobytes gives you the decimal representation of the supplied char as byte.
The easy solution is to convert your String into a CharArray and format each char as Hex Byte String. (I hope this makes sense :) )

Edit:

There is also a solution without low level nodes:

Convert the String in Chars in a ForEach, then use ToString (HEX)

image

i’m afraid that doesn’t sound right.

the confusion here seems to be only regarding the different displays of raw/byte data between beta and gamma. while beta displays hex values only, gamma shows the actual byte values (+ hex values in tooltips). so really both are the same. the only difference seems to be, as tonfilm pointed out, the additional bytes that there are added in the beta patch.

Well, that makes sense :)

You can add the additional Bytes with a + Node and LF / CR

image

1 Like

Many thanks all!

The trick with the LR and CR nodes fixed it. I had based the beta script on a previous example and hadn’t realised what those nodes were for.

Do you have any advice how I could serialise a list of GCODE commands and execute them line by line?

Thanks again!

gcodereader.vl (27.3 KB)

something like this maybe? i bet it can be simplified :) used a prusa slicer generated gcode file

edit: apologies I have just realised that the Message Sent node in your example does this job!

thanks @bildwerk this is just what I needed!

Although I’m having one problem - do you know how I could buffer sending the commands based on the SerialPort OnData counter node - without avoiding a circular error? (V4 won’t let me plug it diretly in)

Please see the image where the counter has reached 60 but only 20 lines have been successfully sent. I’d like to use that value of 20 to buffer the commands.

I think it is being done here in beta: https://www.youtube.com/watch?v=NRgh7w-VN9k&ab_channel=HarukiTakahashi

Many thanks

now i’m curious now what you are printing

@bildwerk at the minute I’m using the printer as a drawing machine where the gcode can be edited as it is printing using Grasshopper.

This example is repeatedly drawing a circle where the radius is determined by the pressure of a wacom tablet. So the circle grows and shrinks as it is being drawn.

But will progress into more sophisticated prints that can be modified in realtime as they are being printed.

Cheers for your help

4 Likes

@bildwerk I have been using this set up for a while and it is working well!

But I’ve run into a speed limitation of how fast I can issue GCODE commands - resulting in stuttering print behaviour. Is this a limitation of the Counter node?

I don’t think this is due to the data rate of the Serial Port as I have tried multiple methods to create a fast counting list of numbers (etc. Trigger, Oscillator) but cannot seem to increase the speed of Counter without dropping values.

What is the best method to write a list of rapidly increasing integers? I’ve searched the forums but can’t find a solution

Many thanks

@lewisbrown10 please share the patch you’re currently using so we can see if there is a way to optimize it.

GCODE.vl (163.2 KB)

Please find attached, thanks!

ouright, so it seems your problem is that the patch is mainloop-bound. the counter can only update once per frame.

one of the big new features with VL though is that this doesn’t have to be the case. you can send/receive things without being bound to the mainloop!

if i understand your patch correctly, see this outline how this should basically work using Reactive nodes:
GCODE-Sender-Outline.vl (19.1 KB)
note, this is a non-functional, non-complete sketch to only give you the basic idea.

what happens between the Receiver and the Sender is not bound to the mainloop but instead triggered by the receive or init events: you press the init bang to start the whole thing. this sends an event and foreach event the counter is advanced and the according GCode line is passed down to the sender. this in turn triggers a message being sent back to the receiver which again passes an even down, further advancing the counter.

like this the patchs mainloop can be anything and still the communication to the printer will be as fast as possible.

Thanks a lot for this!

I’ve tried to integrate it into my existing workflow but have a couple of questions/ problems:

  1. Previously I was using IsMatch and Message Sent to buffer the commands so that the counter was only advanced when an ‘ok’ is received through the SerialPort. Is it possible to integrate this into the new method? Now it just sends all commands rapidly without knowing the state of the printer.

  2. Often the data received from the SerialPort is a fragment of the full string eg. ‘o’ or ‘k□’, and so the IsMatch method fails in these cases. I think this might be to do Parity and Stop Bits (I currently have set as None and One respectively but have tried all the different settings)

  3. What is the best method to add a pause function with the init?

I’ve attached my working file and would appreciate any further help.

Thanks!

GCODE_FAST.vl (187.9 KB)

My bad. The most important info was missing. As you remarked in 2) when receiving data via the SerialPort, messages can be fragmented. That’s why you have to use a Tokenizer to receive them! I recommend reading this article about message framing for a general understanding of the issue.

Note how i assumed that the message sent by the printer is “OK\r\n”. ie. the framing used would be a postfix of “\r\n”, (carriage return, line feed). If my assumption is not correct, you’ll have to adapt this, otherwise it will not work!

I stuck to my outline and adapted it, adding also a pause:
GCODE-Sender-Outline2.vl (28.2 KB)

this works great thanks!
although I am still having a couple of issues:

  1. the TopEdge node doesn’t appear to ‘bang’ when pause is unpressed (even in the unedited file you sent) - this then means that I have to reset the Init which restarts the list of GCODE - rather than continuing from the last line sent (this is a problem I seem to have often where nodes like TogEdge and Changed don’t react to changing inputs)

  2. I’d like the ability to send commands line by line at the beginning of the print (which I was able to with the old method), and have tried to implement this but can’t seem to get it to work properly. when I have managed to get it to work - by sending a single ‘bang’ to un-pause the process - the ForEach loop sends multiple lines instead of just one, and resets from the first line each time

do you have any ideas on how I could fix these?
I’ve attached my edited file for reference if useful

many thanks!

GCODE_FAST_V2.vl (167.2 KB)

hmm I’m afraid 1) doesn’t make much sense. attach a counter to the togedge output and you should see it work

ad 2) for this it should be enough to go into pause and then bang the ToObservable to which the togedge is connect. use an OR there to have both

  1. is working now after a restart
  2. I have implemented the OR but have not been successful in getting it to send only one command

I have also added a graphic interface using the skia renderer - of the current 3d printer state based on GCODE progress - but is it possible to use the counter value within the ForEach(Keep)? I am unable to add an additional output.

As the counters outside the ForEach loop always lag significantly behind - as per the attached screenshot. I’ve also attached the file for reference

Thanks


GCODE_FAST.vl (266.3 KB)

just use a ValueTuple with the amount of elements you want to pass out.