8

Should it be possible to directly send G-code to the printer serial connection using pipes under Linux?

Example:

echo M106 > /dev/ttyUSB0

My controller runs at 250000 baud, I have tried setting the TTY baud rate to 250 kBd with:

stty -F /dev/ttyUSB0 250000

But, unfortunately, this particular baud rate appears to be unsupported under Ubuntu, giving the error:

stty: invalid argument ‘250000’
Greenonline
  • 6,748
  • 8
  • 40
  • 68
Mtl Dev
  • 639
  • 2
  • 8
  • 20

6 Answers6

7

For direct low-level printer control from a terminal, without specific software, I found the following solution with full credit thanks to user: http://stackexchange.com/users/6463673/meuh

Sharing here as may be of use to other users in the 3d Printing community, and I was unable to source a "complete" solution to this elsewhere.


Step 1) Create a custom python script that allows you to set arbitrary baud rates (make executable with chmod u+x).

#!/usr/bin/python
# set nonstandard baudrate. Original Question: http://unix.stackexchange.com/a/327366/119298
import sys,array,fcntl

# from /usr/lib/python2.7/site-packages/serial/serialposix.py
# /usr/include/asm-generic/termbits.h for struct termios2
#  [2]c_cflag [9]c_ispeed [10]c_ospeed
def set_special_baudrate(fd, baudrate):
    TCGETS2 = 0x802C542A
    TCSETS2 = 0x402C542B
    BOTHER = 0o010000
    CBAUD = 0o010017
    buf = array.array('i', [0] * 64) # is 44 really
    fcntl.ioctl(fd, TCGETS2, buf)
    buf[2] &= ~CBAUD
    buf[2] |= BOTHER
    buf[9] = buf[10] = baudrate
    assert(fcntl.ioctl(fd, TCSETS2, buf)==0)
    fcntl.ioctl(fd, TCGETS2, buf)
    if buf[9]!=baudrate or buf[10]!=baudrate:
        print("failed. speed is %d %d" % (buf[9],buf[10]))
        sys.exit(1)

set_special_baudrate(0, int(sys.argv[1]))

Step 2) Run the script to set your baud rate.
./set_custom_baud_rate.py <> /dev/ttyUSB0 250000


Step 3) You can now monitor your printer output in a terminal window simply with:
tail -f /dev/ttyUSB0


Step 4) And finally, open up a new terminal window, and you can directly send M or Gcode to your printer; example:
echo "M115" >> /dev/ttyUSB0

Mtl Dev
  • 639
  • 2
  • 8
  • 20
6

you can use screen for that. Open a terminal window and type screen /dev/ttyUSB0 115200 The general form is screen serialdevice baudrate You will then see everything that the printer sends. Everything you type will be send to the printer.

Lars Pötter
  • 1,670
  • 2
  • 14
  • 22
4

The accepted answer didn't work for me. Everything received on the serial port was repeated back to the serial port, sending the printer into a confusing loop. There is more information about that in this answer: https://unix.stackexchange.com/questions/42964/unexpected-results-testing-serial-loopback-using-echo-and-cat

The key is to use a command like this to prevent certain line termination characters from repeating themselves: stty 115200 -F /dev/ttyUSB0 -echo -onlcr , where 115200 is your baud rate.

Here is what I did:

# 1. plug in printer
sudo chmod +777 /dev/ttyUSB0 # 2. allow access to printer USB permissions, add user to dialout or tty is better
stty 115200 -F /dev/ttyUSB0 -echo -onlcr # 3. set serial port baud rate, might be 250000 for you
cat -v < /dev/ttyUSB0 # 4. get printer output

Then in a new terminal:

   echo "M119" >> /dev/ttyUSB0

This will give you a real console.

K Mmmm
  • 1,742
  • 2
  • 17
  • 36
3

I spent a number of hours trying to work out why my Creality Ender Pro was ignoring me when I sent it serial data over USB from a Python app. Google searches trying to find a solution that were not talking about encode() and decode() all seemed to lead me to this thread.

I installed Minicom as per the video link, and all worked as it should, but I still failed to receive a reply in my Python implementation, I could connect and read the serial sent from the printer but nothing append when sending back to it.

After a few hours scratching my head I realised that the printer reacted to input as it received each new line \n character that I was failing to add to the end of each command sent so the printer was just sitting waiting for me to finish transmitting my line end that never came.

self.serialPort = serial.Serial('/dev/ttyUSB0', 115200, exclusive = True)
lines = self.serialPort.read(self.serialPort.in_waiting).decode().splitlines(False)
line = line + "\n"
self.serialPort.write(line.encode())

Hopefully no one else is as stupid but to save anyone else like me time, I would like to point this out here.

0scar
  • 37,708
  • 12
  • 68
  • 156
Jay Dee
  • 131
  • 2
1

This forum page strongly suggests you should be using setserial for a port, not stty , which is for terminals. I'd give the code snippets there a try. Alternatively, stackoverflow has a similar discussion, with somewhat more complicated modifications.

Are you sure you can't talk with your printer at a lower baud rate than the maximum capability of the printer-end?

Carl Witthoft
  • 3,073
  • 1
  • 12
  • 18
-2

That's work solution:

you need 2 terminal, one for in and another for out flows