# Issues with direct g-code transmission via serial port

Model of the printer is unknown, got it as present, probably something generic cartesian on arduino mega and ramps boards stitched together and with marlin firmware.

I've used accepted answer from here to try moving this thing from terminal. How to directly send G-code to printer from a Linux terminal?

My first attempt to get access to low-level printer interface looked like that:

./baud.py <> /dev/ttyACM0 250000
tail -f /dev/ttyACM0 &
cat > /dev/ttyACM0


First it was fine: i've entered g-code, printer executed it and returned an ok message into my terminal.

Then i've turned the printer off and on again and repeated the whole process, but now tail -f didn't output anything and printer LCD displayed garbage in the status line after I ran the command.

I've also noticed that printer controller reboots every time the serial port is accessed, not sure if it happened in the first time when everything worked well.

The output of cat /dev/ttyACM0 after baud setting is a bit weird too - and there's garbage in the status line instead of standard "%printername% ready" as well:

start
echo:Marlin1.0.0
echo: Last Updated: May 20 2017 18:12:04 | Author: (none, default config)
Compiled: May 20 2017
echo: Free Memory: 3763  PlannerBufferBytes: 1232
echo:Steps per unit:
echo:  M92 X80.00 Y80.00 Z3200.00 E97.94
echo:Maximum feedrates (mm/s):
echo:  M203 X50.00 Y50.00 Z2.50 E25.00
echo:Maximum Acceleration (mm/s2):
echo:  M201 X750 Y750 Z100 E10000
echo:Acceleration: S=acceleration, T=retract acceleration
echo:  M204 S500.00 T500.00
echo:Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s),  Z=maximum Z jerk (mm/s),  E=maximum E jerk (mm/s)
echo:  M205 S0.00 T0.00 B20000 X20.00 Z1.00 E5.00
echo:Home offset (mm):
echo:  M206 X0.00 Y0.00 Z0.00
echo:PID settings:
echo:   M301 P22.20 I1.08 D114.00
echo:SD init fail
echo:Unknown command: "starto"
ok
echo:Unknown command: "SD init failstartuthor"
ok
echo:Unknown command: " (none, default config)50.00 Z2.50 E2rBy00.00 Y0.00 Z0.00echo"
ok
echo:Unknown command: "Unknown command"
ok
echo:Unknown command: " "starto"own comm"
ok
echo:Unknown command: "aximum XY jerk (mm/s),  Z=maximum Z jerk (mm/s),  E=maximum E jerk (mm/s)echo"
ok
echo:Unknown command: "PID settings"
ok
echo:Unknown command: "okechecho"
ok


The "SD init fail" line and everything after it appears when sensor data appears on the LCD, there's a delay before that during which the LCD is empty.

If you send commands to printer using something like echo "G0 X10" > /dev/ttyACM0, it executes them only on next serial port accessing (and therefore reboot) - or doesn't execute at all.

The interesting part is that Cura "Monitor" tab can actually manipulate the caret and the Cura itself can print things in general - but i want to be able to do it manually.

Mine is a wild guess, but judging from:

echo:Unknown command: "starto"
ok
echo:Unknown command: "SD init failstartuthor"
ok
echo:Unknown command: " (none, default config)50.00 Z2.50 E2rBy00.00 Y0.00 Z0.00echo"
ok
echo:Unknown command: "Unknown command"
ok
echo:Unknown command: " "starto"own comm"
ok
echo:Unknown command: "aximum XY jerk (mm/s),  Z=maximum Z jerk (mm/s),  E=maximum E jerk (mm/s)echo"
ok
echo:Unknown command: "PID settings"
ok


It looks like you may be looping back the output of your printer as an input to itself. I am very suspicious of your line: tail -f /dev/ttyACM0 & as that seems to indicate your are trying to perform other actions in the same terminal window after you started to monitor the serial connection.

If this is the case, you should definitively open the monitor in a separate terminal (tail -f /dev/ttyACM0) and feed the input in a different one (note that yo must not use the final &).

Finally, you probably want to use cat >> /dev/ttyACM0 instead of cat > /dev/ttyACM0 as you want to append your commands without truncating the existing stream.

• It's not tail -f /dev/ttyACM0 & output, it's cat /dev/ttyACM0 output. And it was in newly opened terminal window, even baudrate was set in another one. – Karashevich B. Feb 3 '18 at 7:50
• @KarashevichB. either you misread me or you are thinking the commands do something different that what they do. :) tail - f fname will output the last bits of "fname" and keep on outputting lines when they are added to it. cat > fname will use whatever you type or get as an input on the active console as a input for "fname". Note that this is very different that cat fname!! – mac Feb 3 '18 at 9:50
• As you can see from echo:Unknown command: "Unknown command" your printer seems to have received its own response "Unknown command" as a command itself, at some point. – mac Feb 3 '18 at 9:52
• Also, if you run the tail command in it's own console, you don't want to use the final & and you want to use >> instead of > (see my last edit). – mac Feb 3 '18 at 13:52
• Whatever. The problem was actually entirely different, something with serial port parameters set wrong by default. Running set_interface_attribs from accepted answer from here stackoverflow.com/questions/6947413/… on my port solved the problem somehow. Don't know how did i get the port working in the first time but oh well. – Karashevich B. Feb 3 '18 at 14:31

That's weird but i've got some code from here: https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c , changed it a little, removed few lines, ran it - and my port started working just fine. Here's the complete code (for Linux of course).

I guess that was the c_lflag line that solved the problem.

#include <asm/termios.h>
#include <stropts.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>

int set_interface_attribs (int fd) {
struct termios2 tty;
memset (&tty, 0, sizeof tty);
ioctl(fd, TCGETS2, &tty);
tty.c_cflag&=~CBAUD;
tty.c_cflag|=BOTHER;
tty.c_ispeed=tty.c_ospeed=250000;
tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;
tty.c_iflag &= ~IGNBRK;
tty.c_lflag = 0;
tty.c_oflag = 0;
tty.c_cc[VMIN]  = 0;
tty.c_cc[VTIME] = 5;
tty.c_iflag &= ~(IXON | IXOFF | IXANY);
tty.c_cflag &= ~(PARENB | PARODD);
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CRTSCTS;
ioctl(fd, TCSETS2, &tty);
return 0;
}

int main() {
int fd=open("/dev/ttyACM0",O_RDWR|O_NOCTTY|O_SYNC);
set_interface_attribs(fd);
close(fd);
return 0;
}

• Oh, the marvels of running code without knowing what it does! ;) – mac Feb 3 '18 at 15:44