<p>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: <a href="https://unix.stackexchange.com/questions/42964/unexpected-results-testing-serial-loopback-using-echo-and-cat">https://unix.stackexchange.com/questions/42964/unexpected-results-testing-serial-loopback-using-echo-and-cat</a></p>
<p>The key is to use a command like this to prevent certain line termination characters from repeating themselves: <code>stty 115200 -F /dev/ttyUSB0 -echo -onlcr </code>, where 115200 is your baud rate.</p>
<p>Here is what I did:</p>
<pre><code># 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 &lt; /dev/ttyUSB0 # 4. get printer output 

</code></pre>
<p>Then in a new terminal:</p>
<pre><code>   echo &quot;M119&quot; &gt;&gt; /dev/ttyUSB0

</code></pre>
<p>This will give you a real console.</p>

CC BY-SA 4.0
2020-11-09T03:39:27.053Z
Can you please share what flavour & version on linux you are using that this failed on?  (It worked on mainstream distributions - Ubuntu & Mint - at time of publishing.  Perhaps we can isolate why it wasn't successful for you.  I note your solution is for baud rate 115200, are you able to verify this works for baud rate 250000?
Mtl Dev
CC BY-SA 4.0
2020-11-09T20:14:14.543Z
Can confirm the previous answer works on Ubuntu 18.04, and IIRC Mint before that (version unknown, formatted).  Not sure why it's failing on 16.04.  Thankyou kindly for posting another answer that works for you and other people - always great to have multiple working answers to help as many people as possible, cheers!
Mtl Dev
CC BY-SA 4.0
2020-11-09T23:26:37.180Z
Actually it still repeats itself on 250000. So to get stty to stop the repeating, it seems like 115200 is needed
K Mmmm
CC BY-SA 4.0
2020-11-10T23:26:21.150Z
250000 is a non standard baud rate. In my case, 115200 works find with standard linux tools - but in order for 250000 to work, I needed that script posted in my answer. On my machines, 250000 works with that script.
Mtl Dev
CC BY-SA 4.0
2022-12-21T17:58:05.627Z
Thank you this was super helpful
user1529413
CC BY-SA 4.0
2020-11-07T16:30:44.447Z
2020-11-07T16:30:44.447Z
K Mmmm
<p>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 <code>encode()</code> and <code>decode()</code> all seemed to lead me to this thread.</p>
<p>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.</p>
<p>After a few hours scratching my head I realised that the printer reacted to input as it received each new line <code>\n</code> 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.</p>
<pre><code>self.serialPort = serial.Serial('/dev/ttyUSB0', 115200, exclusive = True)
lines = self.serialPort.read(self.serialPort.in_waiting).decode().splitlines(False)
line = line + &quot;\n&quot;
self.serialPort.write(line.encode())
</code></pre>
<p>Hopefully no one else is as stupid but to save anyone else like me time, I would like to point this out here.</p>

CC BY-SA 4.0
2020-09-05T13:29:45.477Z
This is sort of "me too" answer reacting on some other answer. Which link are you referring to? This answer could be better posted as a comment to that answer.
0scar
CC BY-SA 4.0
2020-09-09T11:10:04.833Z
i tried to move it but it said "you must have 50 rep to comment"
Jay Dee
CC BY-SA 4.0
2020-09-09T11:16:04.007Z
Please shorten the answer and indicate to which answer you'd like to respond in a comment, moderators can move it for you.
0scar
CC BY-SA 4.0
2020-09-05T11:36:02.957Z
2020-09-05T13:27:53.250Z
2020-09-05T13:27:53.250Z
Jay Dee
<p>you can use screen for that. Open a terminal window and type  <code>screen /dev/ttyUSB0 115200</code> The general form is  <code>screen serialdevice baudrate</code> You will then see everything that the printer sends. Everything you type will be send to the printer.</p>

CC BY-SA 3.0
2017-07-13T14:02:04.377Z
Thanks!  Though does that work with non standard baud rates e.g 250k?  I suspect not (at least with Ubuntu/Mint), but that it would be possible to combine the above script, with ``screen`` command as per your suggestion.
Mtl Dev
CC BY-SA 3.0
2016-12-03T01:38:04.457Z
2016-12-03T01:38:04.457Z
Lars Pötter
<p><a href="https://ubuntuforums.org/showthread.php?t=1609727" rel="nofollow noreferrer">This forum page</a>  strongly suggests you should be using <code>setserial</code> for a port, not <code>stty</code> , which is for terminals.  I'd give the code snippets there a try.
Alternatively, <a href="https://stackoverflow.com/questions/12646324/how-to-set-a-custom-baud-rate-on-linux">stackoverflow</a> has a similar discussion, with somewhat more complicated modifications.</p>

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

CC BY-SA 3.0
2016-12-01T15:23:46.357Z
You can't lower Marlin's baudrate without recompiling the firmware, I believe.
Tom van der Zanden
CC BY-SA 3.0
2016-12-01T15:24:44.207Z
@TomvanderZanden bummer :-(
Carl Witthoft
CC BY-SA 4.0
2021-09-29T06:38:04.847Z
I could not get `setserial` to work on raspberry pi zero w. But since `stty -F /dev/ttyUSB0 500000` works (and 250000 doesn't), I decided to change the baudrate on my printers. I changed the baudrate to 500000 in Marlin's Configuration.h after downloading/unzipping the printer configurations and recompiled/reuploaded. Works great now.
hellork
CC BY-SA 3.0
2016-12-01T15:21:54.483Z
2016-12-01T15:21:54.483Z
2017-05-23T12:41:54.910Z
Carl Witthoft
<p>That's work solution:
<div class="youtube-embed"><div>
                <iframe width="640px" height="395px" src="https://www.youtube.com/embed/1kcvIRhXkCo?start=0"></iframe>
            </div></div>
you need 2 terminal, one for in and another for out flows </p>

CC BY-SA 4.0
2020-02-18T06:17:29.323Z
From [help]: **Provide context for links**
Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline. *Without the video, in case of link rot, this answer has no value for the future, please describe how the video poster got access to the printer from Ubuntu, that would make a great answer!*
0scar
CC BY-SA 4.0
2020-02-12T13:39:07.767Z
2020-02-12T13:39:07.767Z
Александр Николаев
<p>For direct low-level printer control from a terminal, without specific software, I found the following solution with full credit thanks to user: <a href="http://stackexchange.com/users/6463673/meuh">http://stackexchange.com/users/6463673/meuh</a></p>

<p>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.</p>

<hr>

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

<pre><code>#!/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] &amp;= ~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]))
</code></pre>

<hr>

<p>Step 2) Run the script to set your baud rate.<br>
<code>./set_custom_baud_rate.py &lt;&gt; /dev/ttyUSB0 250000</code></p>

<hr>

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

<hr>

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

CC BY-SA 4.0
2019-07-16T17:12:21.827Z
@gipi The "<> /dev/ttyUSB0" argument defines stdin and stdout for the script.  When the script operates on stdin, it is operation on /dev/ttyUSB0.
cmm
CC BY-SA 4.0
2020-11-07T16:13:31.177Z
This didn't work for me, nor this guy: https://3dprinting.stackexchange.com/questions/10612/sending-g-code-through-usb-serial-doesnt-work-ender-3?noredirect=1&lq=1
The tail command doesn't output anything
The printer seems to thing "ok" is an unknown command, which is its response, right? So why is it receiving its own response as a command?
K Mmmm
CC BY-SA 3.0
2017-07-13T13:15:58.270Z
Can I ask you how is possible that this script works? I don't understand why you use ``<>``, at first I thought was a typo, but modifying the script and opening the serial directly doesn't modify its baudrate.
gipi
CC BY-SA 3.0
2017-07-13T13:56:24.873Z
``<>`` on unix opens a file read+write mode, without truncation, and creates the file if it doesn't already exist. i.e system call: ``open(filename, O_RDWR|O_CREAT)``
Mtl Dev
CC BY-SA 3.0
2017-07-13T13:59:09.957Z
For example, ``cat < foo.txt`` it will print the contents of foo.txt, or fail if foo.txt doesn't exist.  Whereas ``cat <> foo.txt``,will also print the contents if it exists, but will create the file if it doesn't already exist.
Mtl Dev
CC BY-SA 3.0
2017-07-13T15:42:50.083Z
I know what ``<>`` does, but I don't understand why this works for the baudrate: you are setting the baudrate of the file descriptor ``0``, i.e. ``stdin`` not for the serial port.
gipi
CC BY-SA 3.0
2017-07-13T18:25:20.267Z
My understanding is the baudrate is simply the first argument to the script, (i.e ``sys.argv[1]``).  If you were to modify the script and hardcode a baudrate, and/or open device using the python equiv. of  ``open(filename, O_RDWR|O_CREAT)``, then I, too, would be surprised if that didn't work.
Mtl Dev
CC BY-SA 3.0
2016-12-01T18:30:39.040Z
2016-12-01T20:24:40.713Z
2016-12-01T20:24:40.713Z
Mtl Dev
<p>Should it be possible to directly send G-code to the printer serial connection using pipes under Linux?</p>

<p>Example:</p>

<pre><code>echo M106 &gt; /dev/ttyUSB0
</code></pre>

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

<pre><code>stty -F /dev/ttyUSB0 250000
</code></pre>

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

<pre><code>stty: invalid argument ‘250000’
</code></pre>

<firmware><arduino-mega-2650>
How to directly send G-code to printer from a Linux terminal?
Mtl Dev
# How to directly send G-code to printer from a Linux terminal?

(Asked by: username_0 on 2016-12-01)

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’

**Tags:** firmware, arduino-mega-2650

---

## 6 answers

### Answer by username_0 on 2016-12-01. Score: 7 | Accepted answer

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

> **Comments:**
> **username_11**: Can I ask you how is possible that this script works? I don't understand why you use ``<>``, at first I thought was a typo, but modifying the script and opening the serial directly doesn't modify its baudrate.  
> **username_0**: ``<>`` on unix opens a file read+write mode, without truncation, and creates the file if it doesn't already exist. i.e system call: ``open(filename, O_RDWR|O_CREAT)``  
> **username_0**: For example, ``cat < foo.txt`` it will print the contents of foo.txt, or fail if foo.txt doesn't exist.  Whereas ``cat <> foo.txt``,will also print the contents if it exists, but will create the file if it doesn't already exist.  
> **username_11**: I know what ``<>`` does, but I don't understand why this works for the baudrate: you are setting the baudrate of the file descriptor ``0``, i.e. ``stdin`` not for the serial port.  
> **username_0**: My understanding is the baudrate is simply the first argument to the script, (i.e ``sys.argv[1]``).  If you were to modify the script and hardcode a baudrate, and/or open device using the python equiv. of  ``open(filename, O_RDWR|O_CREAT)``, then I, too, would be surprised if that didn't work.  
> **username_10**: @gipi The "<> /dev/ttyUSB0" argument defines stdin and stdout for the script.  When the script operates on stdin, it is operation on /dev/ttyUSB0.  
> **username_1**: This didn't work for me, nor this guy: https://3dprinting.stackexchange.com/questions/10612/sending-g-code-through-usb-serial-doesnt-work-ender-3?noredirect=1&lq=1 The tail command doesn't output anything The printer seems to thing "ok" is an unknown command, which is its response, right? So why is it receiving its own response as a command?  

---

### Answer by username_5 on 2016-12-03. Score: 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.

> **Comments:**
> **username_0**: Thanks!  Though does that work with non standard baud rates e.g 250k?  I suspect not (at least with Ubuntu/Mint), but that it would be possible to combine the above script, with ``screen`` command as per your suggestion.  

---

### Answer by username_1 on 2020-11-07. Score: 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.

> **Comments:**
> **username_0**: Can you please share what flavour & version on linux you are using that this failed on?  (It worked on mainstream distributions - Ubuntu & Mint - at time of publishing.  Perhaps we can isolate why it wasn't successful for you.  I note your solution is for baud rate 115200, are you able to verify this works for baud rate 250000?  
> **username_0**: Can confirm the previous answer works on Ubuntu 18.04, and IIRC Mint before that (version unknown, formatted).  Not sure why it's failing on 16.04.  Thankyou kindly for posting another answer that works for you and other people - always great to have multiple working answers to help as many people as possible, cheers!  
> **username_1**: Actually it still repeats itself on 250000. So to get stty to stop the repeating, it seems like 115200 is needed  
> **username_0**: 250000 is a non standard baud rate. In my case, 115200 works find with standard linux tools - but in order for 250000 to work, I needed that script posted in my answer. On my machines, 250000 works with that script.  
> **username_2**: Thank you this was super helpful  

---

### Answer by username_3 on 2020-09-05. Score: 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.

> **Comments:**
> **username_4**: This is sort of "me too" answer reacting on some other answer. Which link are you referring to? This answer could be better posted as a comment to that answer.  
> **username_3**: i tried to move it but it said "you must have 50 rep to comment"  
> **username_4**: Please shorten the answer and indicate to which answer you'd like to respond in a comment, moderators can move it for you.  

---

### Answer by username_6 on 2016-12-01. Score: 1

[This forum page](https://ubuntuforums.org/showthread.php?t=1609727) 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](https://stackoverflow.com/questions/12646324/how-to-set-a-custom-baud-rate-on-linux) 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?

> **Comments:**
> **username_7**: You can't lower Marlin's baudrate without recompiling the firmware, I believe.  
> **username_6**: @TomvanderZanden bummer :-(  
> **username_8**: I could not get `setserial` to work on raspberry pi zero w. But since `stty -F /dev/ttyUSB0 500000` works (and 250000 doesn't), I decided to change the baudrate on my printers. I changed the baudrate to 500000 in Marlin's Configuration.h after downloading/unzipping the printer configurations and recompiled/reuploaded. Works great now.  

---

### Answer by username_9 on 2020-02-12. Score: -2

That's work solution:you need 2 terminal, one for in and another for out flows

> **Comments:**
> **username_4**: From [help]: **Provide context for links** Links to external resources are encouraged, but please add context around the link so your fellow users will have some idea what it is and why it’s there. Always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline. *Without the video, in case of link rot, this answer has no value for the future, please describe how the video poster got access to the printer from Ubuntu, that would make a great answer!*  

---

