Writing to Serial Port from Linux Command Line

Writing to the serial port from the Linux command line


echo '\x12\x02'

will not be interpreted, and will literally write the string \x12\x02 (and append a newline) to the specified serial port. Instead use

echo -n ^R^B

which you can construct on the command line by typing CtrlVCtrlR and CtrlVCtrlB. Or it is easier to use an editor to type into a script file.

The stty command should work, unless another program is interfering. A common culprit is gpsd which looks for GPS devices being plugged in.

Linux Shell, How to send a command over Serial port and return?

Here is how we fixed this issue:

  1. Config serial port with RAW setting:

    stty -F /dev/ttyS1 speed 9600 cs8 -cstopb -parenb raw
  2. Send Command using echo with \r:

    echo -ne "reboot\r" > /dev/ttyS1

I believe that the above might include a typo. If the above doesn't work, try:

 echo -ne "reboot\n\r" > /dev/ttyS1

Reading and writing to serial port in C on Linux

I've solved my problems, so I post here the correct code in case someone needs similar stuff.

Open Port

int USB = open( "/dev/ttyUSB0", O_RDWR| O_NOCTTY );

Set parameters

struct termios tty;
struct termios tty_old;
memset (&tty, 0, sizeof tty);

/* Error Handling */
if ( tcgetattr ( USB, &tty ) != 0 ) {
std::cout << "Error " << errno << " from tcgetattr: " << strerror(errno) << std::endl;
}

/* Save old tty parameters */
tty_old = tty;

/* Set Baud Rate */
cfsetospeed (&tty, (speed_t)B9600);
cfsetispeed (&tty, (speed_t)B9600);

/* Setting other Port Stuff */
tty.c_cflag &= ~PARENB; // Make 8n1
tty.c_cflag &= ~CSTOPB;
tty.c_cflag &= ~CSIZE;
tty.c_cflag |= CS8;

tty.c_cflag &= ~CRTSCTS; // no flow control
tty.c_cc[VMIN] = 1; // read doesn't block
tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout
tty.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines

/* Make raw */
cfmakeraw(&tty);

/* Flush Port, then applies attributes */
tcflush( USB, TCIFLUSH );
if ( tcsetattr ( USB, TCSANOW, &tty ) != 0) {
std::cout << "Error " << errno << " from tcsetattr" << std::endl;
}

Write

unsigned char cmd[] = "INIT \r";
int n_written = 0,
spot = 0;

do {
n_written = write( USB, &cmd[spot], 1 );
spot += n_written;
} while (cmd[spot-1] != '\r' && n_written > 0);

It was definitely not necessary to write byte per byte, also int n_written = write( USB, cmd, sizeof(cmd) -1) worked fine.

At last, read:

int n = 0,
spot = 0;
char buf = '\0';

/* Whole response*/
char response[1024];
memset(response, '\0', sizeof response);

do {
n = read( USB, &buf, 1 );
sprintf( &response[spot], "%c", buf );
spot += n;
} while( buf != '\r' && n > 0);

if (n < 0) {
std::cout << "Error reading: " << strerror(errno) << std::endl;
}
else if (n == 0) {
std::cout << "Read nothing!" << std::endl;
}
else {
std::cout << "Response: " << response << std::endl;
}

This one worked for me. Thank you all!

Reading and writing to a serial port using shell and Java

Instead of screen you may use command cu from UUCP package.
To install UUCP package sudo apt-get install uucp or sudo yum install uucp.

Then use this command:
static String command = "cu -l " + port + " -s " + baudRate;

Some explanation:

  • screen -d detaches session (it runs in background) that's why you do not see any data.
  • screen requires terminal which is not easy from java. See How to open a command terminal in Linux?


Related Topics



Leave a reply



Submit