LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Software (https://www.linuxquestions.org/questions/linux-software-2/)
-   -   Hyperterm works, minicom doesn't (https://www.linuxquestions.org/questions/linux-software-2/hyperterm-works-minicom-doesnt-4175455898/)

shanham67 03-28-2013 07:11 AM

Hyperterm works, minicom doesn't
 
I have a 1990 model cnc controller that imports/exports programs via a RS232 interface (9600,7,E,1). When I connect using a usb-serial converter, hyperterm and winxp I am able to download the text of a program from the cnc controller to my laptop with no problems.

When I connect to my linux box with the same usb-serial converter i get jibberish (foreign characters) in both minicom and from a small pySerial program that i snipped from the web.

Can anyone suggest what character translations hyperterm is automatically doing that minicom is not?

I suspect that I can mask a single bit of each character and clean it all. I also suspect that there is a setting for minicom and pySerial that will do the trick.

michaelk 03-28-2013 12:16 PM

I am not aware of any translation that hyperterm does but minicom does not. Have you verified that you have the same port settings between hyperterm and minicom?

Another alternative is cutecom which has the option to display raw data in addition to regular ASCII characters.

shanham67 03-28-2013 02:05 PM

cutecom is a no-go. running on a headless server.

michaelk 03-28-2013 02:30 PM

How do you access the server?

shanham67 03-28-2013 02:49 PM

ssh

rtmistler 03-29-2013 11:16 AM

Whatever the serial resource as it shows up on Linux, /dev/ttySx or /dev/ttyUSBx. From a shell prompt you can view the settings and change them:

Code:

stty -F/dev/ttyUSB0 115200
will change the port to be 115,200, most ports will be N81.

You can also cat the output of that port if it happens to be always talking. For instance I work with embedded sensor boards which arrive via serial USB, so I would do
Code:

cat /dev/ttyUSB0
to view the output of that port.

shanham67 04-01-2013 10:53 AM

Hyperterminal, minicom, more information...
 
2 Attachment(s)
Ok,
I think my machine is outputting binary data, perhaps some terminal protocol. Hyperterminal decodes and displays what I want to see from linux (minicom/python) (see the attached screen grab of hyperterminal). I have also posted a screen grab of the output from minicom when receiving the same RS232 stream. Addtionally, I have posted the output from my readserial.py python capture script program after piping it through xxd. Does anyone recognize this encoding scheme? If so, how do I setup something on my linux machine to perform the same translation that hyperterminal is doing automatically?

Code:

~$ sudo python readserial.py > readserial.py.out
CTRL-C (to stop the script)
~$ xxd readserial.py.out
0000000: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000010: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000020: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000030: 0000 8d0a 0a30 a042 c547 c94e a050 474d  .....0.B.G.N.PGM
0000040: a0b1 30a0 c94e c348 a08d 0a0a b1a0 d4cf  ..0..N.H........
0000050: cfcc a044 c5c6 a0b1 a0cc 2b30 a0d2 2b30  ...D......+0..+0
0000060: 2eb1 b235 a08d 0a0a b2a0 d4cf cfcc a0c3  ...5............
0000070: 41cc cca0 b1a0 5aa0 53a0 b430 3030 a08d  A.....Z.S..000..
0000080: 0a0a 33a0 c359 c3cc a044 c5c6 a035 2e30  ..3..Y...D...5.0
0000090: a0c3 c9d2 c355 cc41 d2a0 50cf c34b c5d4  .....U.A..P..K..
00000a0: a08d 0a0a b4a0 c359 c3cc a044 c5c6 a035  .......Y...D...5
00000b0: 2eb1 a053 c5d4 a055 502d 302e b2a0 8d0a  ...S...UP-0.....
00000c0: 0a35 a0c3 59c3 cca0 44c5 c6a0 352e b2a0  .5..Y...D...5...
00000d0: 44c5 50d4 48a0 2d30 2e33 a08d 0a0a 36a0  D.P.H.-0.3....6.
00000e0: c359 c3cc a044 c5c6 a035 2e33 a050 c5c3  .Y...D...5.3.P..
00000f0: 4b47 a02d 302e 3035 a0c6 b430 a08d 0a0a  KG.-0.05...0....
0000100: b7a0 c359 c3cc a044 c5c6 a035 2eb4 a0d2  ...Y...D...5....
0000110: 4144 c955 5330 2e33 35a0 8d0a 0ab8 a0c3  AD.US0.35.......
0000120: 59c3 cca0 44c5 c6a0 352e 35a0 c635 30a0  Y...D...5.5..50.
0000130: 44d2 2da0 8d0a 0a39 a0cc a0d8 2bb2 2eb2  D.-....9....+...
0000140: 35a0 592d b22e 35a0 d230 a0c6 a04d 41d8  5.Y-..5..0...MA.
0000150: a04d 3033 a08d 0a0a b130 a0cc a05a 2b30  .M03.....0...Z+0
0000160: 2eb2 a0d2 30a0 c6a0 4d41 d8a0 4d39 39a0  ....0...MA..M99.
0000170: 8d0a 0ab1 b1a0 cca0 d82b 30a0 592b 30a0  .........+0.Y+0.
0000180: 5a2b b1a0 d230 a0c6 a04d 41d8 a04d 30b2  Z+...0...MA..M0.
0000190: a08d 0a0a b1b2 a0c5 4e44 a050 474d a0b1  ........ND.PGM..
00001a0: 30a0 c94e c348 a08d 0a0a                0..N.H....
~$ file readserial.py.out
readserial.py.out: data

Code:

~$ cat readserial.py
#!/usr/bin/python

import os, serial, time

s = serial.Serial('/dev/ttyUSB0', baudrate=9600, bytesize=7, parity='E', stopbits=1, timeout=None, xonxoff=0, rtscts=0)
while True:
    line = s.readline()
    if "clear\n" == line:
        os.system('clear')
    else:
        print line


michaelk 04-01-2013 12:41 PM

Quote:

how do I setup something on my linux machine to perform the same translation that hyperterminal is doing automatically?
By using the same settings. From the hyperterm screen shot the port is configured as 8-N-1 vs 7-E-1 as posted in your python script and I assume how minicom is configured.

shanham67 04-01-2013 03:45 PM

I wish...
 
3 Attachment(s)
When I first start hyperterm the status line that you pointed out says 'Auto detect' after reading the data it changes to '9600 8-N-1'.

I don't find the status line of hyperterm very trustworthy. I can disconnect, change port settings, and reconnect and I still get good data from hyperterm.

Attached below are screen grabs of hyperterm showing both 9600-7N1 and 9600-7E1 and the same clean text output. I have also attached a screen grab of the port setup from device manager. The device manager port settings have been 9600-7E1 all along. I have a configuration parameter on the machine that I am trying to interface to that indicates that it is output 9600-7E1 data.

By the way, I have tried all of these settings (9600-8-N-1, 9600-7-N-1, 9600-7-E-1) in minicom and readserial.py.

michaelk 04-01-2013 09:06 PM

Your right... The difference between 7e1 and 8n1 is negligible and would appear like dropped bits like the output of your python script. The gibberish output from minicom is puzzling.

rtmistler 04-02-2013 08:32 AM

The original problem was to download a program to this computer via serial.

The two steps I'd do here if I could not get a specification on how to send the data would be:

1.) Write a program to run on Linux which would listen to the serial port and print out exactly what Hyperterm is sending when it sends a file the correct way in which it works. This way you'll be able to see exactly what Hyperterm is sending.

2.) Write a program which takes your program file and sends it over the serial port to your target in the same manner which Hyperterm is sending it to you.

Also you can configure the port between 7E1 and 8N1 to see which variation makes the data look correctly when you read it as Hyperterm sends it to your Linux program. 8N1 is the most common, but I have one case of 8-bit, Odd parity in my system.

Use open(2) and read(2) to accomplish this. Here also are some examples for configuring port rates and parity via a Linux C program.

Example to configure the rate, my set port rate function uses 115,200, 230,400, or defaults to 38,400, but you can use whichever rates are appropriate for you. Note also that my log mechanism is not common, is a macro, and uses that debug argument, nothing you need to worry about. I also have many includes because it's a utilities file, so I've checked a bit and shown the includes mainly required for the library calls from termios(3).

Code:

#include <termios.h>
#include <unistd.h>

int set_port_rate(char *port, char *rate, int debug)
{
    struct termios term_ios;
    speed_t new_rate;
    int fd;

    if(!strlen(port)) {
        dae_log("set_port_rate: Invalid(NULL) port\n");
        return -1;
    }
    if((fd = open(port, O_RDWR | O_NOCTTY)) < 0) {
        l_err = errno;
        sprintf(l_err_str, "%d:%s", errno, strerror(errno));
        dae_log("set_port_rate: Error opening %s. %d(%s)\n", port, errno, strerror(errno));
        return -1;
    }
    if(!strncmp(rate, SERIAL_115200_RATE, strlen(SERIAL_115200_RATE))) {
        new_rate = B115200;
    }
    else if(!strncmp(rate, SERIAL_230400_RATE, strlen(SERIAL_230400_RATE))) {
        new_rate = B230400;
    }
    else {
        new_rate = B38400;
    }

    memset(&term_ios, 0, sizeof(term_ios));
    tcgetattr(fd, &term_ios);
    cfmakeraw(&term_ios);
    cfsetspeed(&term_ios, new_rate);
    tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &term_ios);

    return 0;
}

Example to set port parity. This can be extended to set bits to be 7, (term_ios.c_flag |= CS7) would be the correct action here.

Code:

int set_port_parity(char *port, tcflag_t parity, int debug)
{
    struct termios term_ios;
    int fd;

    if(!strlen(port)) {
        dae_log("set_port_parity: Invalid(NULL) port\n");
        return -1;
    }
    if((fd = open(port, O_RDWR | O_NOCTTY)) < 0) {
        l_err = errno;
        sprintf(l_err_str, "%d:%s", errno, strerror(errno));
        dae_log("set_port_parity: Error opening %s. %d(%s)\n", port, errno, strerror(errno));
        return -1;
    }

    memset(&term_ios, 0, sizeof(term_ios));
    tcgetattr(fd, &term_ios);
    term_ios.c_cflag |= (PARENB | parity);
    tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &term_ios);

    return 0;
}


shanham67 04-02-2013 10:52 AM

...making some progress
 
1 Attachment(s)
rtmistler, thanks for the time you spent replying. However, I am not sending from hyperterm. I am receiving.

I have made progress in determining that the problem seems to be with the parity bit on the linux side. In the attached screen grab you can see a hex dump of the stream I am trying to read. The back window is bray's terminal running on windows. The front window is the output of the following pyserial program running on linux.

Code:

#!/usr/bin/python

import os, serial, time, sys

s = serial.Serial('/dev/ttyUSB0', baudrate=9600, bytesize=7, parity=serial.PARITY_EVEN, stopbits=1, timeout=None, xonxoff=0, rtscts=0)
while True:
    x = s.read(1)
#    print x.encode('hex')
    sys.stdout.write(x.encode('hex')+' ')

NOTE: If I switch bray's terminal from hex mode to ascii mode it displays the correct output.

I have highlighted the differences between the output in the attached screen grab. Notice that all of the differences are for bytes which have odd parity in the lower seven bits. Next, I will mask off the MSB of each byte to see if it displays correctly. I suspect that this should not be necessary. Does anyone have any suggestions?

rtmistler 04-02-2013 11:41 AM

You're trying to use this through Linux versus Windows right?

There are other port settings besides character size, parity, and stop bits.

stty shows you that and allows you to set the port up for things like RAW mode; which is really a combination of attribute settings in a certain way. Many times when writing a serial port application in Linux I have to configure the port to be raw mode. That's why I'm referring to the termios(3) utilities: tcgetattr(), tcsetattr(), and so forth.

There either are or are not equivalents which you can use via python; however the termios utilities are based on Linux and therefore based on C, so the best recommendation I could make would be to experiment with a C program to better view and control the entire termios structure. You get that structure by tcgetattr() and then you can examine all settings, many of which will likely be meaningless, but there is one which will probably resolve this so that you can talk to this system via Linux versus Windows utilities.

theNbomr 04-02-2013 01:14 PM

You observe that the sender appears to be using ODD parity. The next thing to try, then, is to set ODD parity at the receiver, rather than masking the problem by masking the high bit.
If you need to use the serial port to do file transfers, may I suggest using one of the many serial file transfer protocols and/or applications that already exist for such purposes? Kermit or Z-modem would be good starting points.
--- rod.

shanham67 04-02-2013 01:57 PM

Solved !
 
To answer my original question, hyperterminal is apparently stripping off the high bit. Linux is not. I switched from python to perl because I know perl, was just cutting and pasting the python stuff. I still haven't gone back to see how to set 'istrip' using minicom. But the following perl script solves my problem. Here is my perl reader:

Code:

#!/usr/bin/perl

use Device::SerialPort;

my $port = Device::SerialPort->new("/dev/ttyUSB0");
$port->databits(7);
$port->baudrate(9600);
$port->parity("even");
$port->stopbits(1);

$port->read_char_time(50);
$port->read_const_time(500);
$port->stty_istrip(1);

while(1) {
  my($count,$byte)=$port->read(1);
  if($count > 0 ){
  print "$byte";
  }
}

Note: this must be sudo'd to work


All times are GMT -5. The time now is 12:31 AM.