hardy004 has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks, I am trying to use the Device::SerialPort() module from the CPAN perl library & I seem to be having some issue reading the values back for the command I send to serial port. I send some command to the Serial Port & when trying to read the value back, I see some garbage being readout. How can i really tell whether my command did go through OK. As a matter of fact, I know that the Serial Port is being opened by the perl scripts because at the same time when I tried opening up the same port using other application I cannot. Below is the piece of code that I have.

my $PortName = '/dev/ttyS16' ; my $PortObj = new Device::SerialPort($PortName) || die "Can't open $Po +rtName: $!\n"; $PortObj->databits(8); $PortObj->baudrate(19200); $PortObj->parity("none"); $PortObj->stopbits(1); #$PortObj->flowcontrol("none"); $PortObj->write('asic_rst 0'); my ($r1, $saw1) = $PortObj->read(255) ; $PortObj->write("asic_rst 1"); my ($r2, $saw2) = $PortObj->read(255) ; $PortObj->close || die "failed to close"; undef $PortObj;

The values of the return variables is as follows.

r1 = 8 $saw1 = a®k}r.\x17‚ r2 = 8 $saw1 = a®k}r.\x17Š

How do i know what is being read in $saw1/$saw2 is correct ? I know my response to the serial port is not what I am seeing here.Also note that instead of read i tried input() & lookfor() commands as well. Any input is appreciated.

Ok, so now I based on the recommendations from lot of monks, I have switched from Device::SerialPort (cygwin) to Win32::SerialPort. Below is the code. And also the output response. Basically I am still seeing the same scribbled data when trying to read. I am at all lost here.

#!/usr/bin/perl -w use strict; use warnings ; use Win32::SerialPort qw( :STAT ) ; # } my $PortName = 'COM17' ; my $serial_port = new Win32::SerialPort($PortName) || die "Can't open + $PortName: $!\n"; $serial_port->databits( 8 ); $serial_port->baudrate(19200); $serial_port->parity("none"); $serial_port->stopbits( 1 ); $serial_port->handshake("rts") ; my $response = undef ; my $complete = 0 ; my $command = "12345" ; $serial_port->write("$command\r") ; sleep 1 ; my ( $blocking_flags, $in_bytes, $out_bytes, $latch_error_flags ) = $s +erial_port->status() ; print("1: $blocking_flags\n") ; print("2: $in_bytes\n") ; print("3: $out_bytes\n") ; print("4: $latch_error_flags\n") ; $serial_port->lookclear; #clear the buffer sleep (2) ; if( $in_bytes > 0 ) { for( my $i = 0 ; $i < $in_bytes ; $i++ ) { # Get a byte at a time to process. $response .= $serial_port->read( 1 ) ; if( $response =~ /\r/ ) { $complete = 1 ; } } } print ("Response is: $response\n") ; $serial_port->close || die "failed to close"; undef $serial_port; # frees memory back
1: 0 2: 5 3: 0 4: 0 Response is: 1ªó5&#9500;

Replies are listed 'Best First'.
Re: Using Device::SerialPort
by pme (Monsignor) on Feb 11, 2015 at 02:06 UTC
Re: Using Device::SerialPort
by Anonymous Monk on Feb 11, 2015 at 00:41 UTC

    The first thing to check when receiving junk over a serial port: is the baud rate correct? (Also databits, parity and stop bits, although that's almost always 8N1 nowadays.)

    How do i know what is being read in $saw1/$saw2 is correct ?

    What do you expect to receive?

    If you want to see what's going over the wire, do you have some other way to monitor the serial port, like using a software or hardware device (even an oscilloscope)?

      Thanks for the reply. I know the baud rate is correct, since I am using other application like tera-term & Hyper terminal with the 19200 baud rate & I am getting the correct response. I expect some ACK response for the commands that I am sending. Here the response I am getting is something garbage which is nowhere what i should be seeing. What software do you recommend ?

        HyperTerminal is a Windows program, but your code seems to be for a *NIX system? Is this two different computers? Are you sure your serial device works on the *NIX system?

        If you're sure about the baud rate and the other settings (including flow control, handshake, etc.), then it's hard to guess what is going on without knowing the details of your software & hardware set-up - at least I'm at a loss at the moment, perhaps someone else has seen a similar problem. It might also help if you describe what kind of a device you're talking to, whether it is a "real" hardware serial port or a USB adapter, etc.

        some ACK response

        Could you perhaps be more specific, like show a short example session?

        To pick up on some of the things you wrote earlier:

        How can i really tell whether my command did go through OK.

        The only way to really tell what's physically going on is to look at the signal on the wires with a logic analyzer or oscilloscope. On the PC side, in my experience it's usually a matter of making sure that there's only one software trying to access the port at once, and getting all of the settings right.

        I know my response to the serial port is not what I am seeing here.

        How did you determine this?

Re: Using Device::SerialPort
by dasgar (Priest) on Feb 11, 2015 at 06:06 UTC

    I haven't tried this myself, but I'm wondering if you might be able to use something like Null-modem emulator to test your Perl code against to capture what your code is sending.

      I tryed Virtual Serial Port Emulator (http://www.eltima.com/products/serial-port-emulator/) and worked great
Re: Using Device::SerialPort
by roboticus (Chancellor) on Feb 11, 2015 at 14:40 UTC

    hardy004:

    If I had to guess, looking at your data, I'm guessing that it's 7 bits, even parity. So the characters with an odd number of bits (a, k) are coming through looking fine, and the ones with an even number of bits (c) parity are coming in with the high bit set. Setting the high bit on 'c' gives 0xe3, and I'm betting some unicode translation is occurring to give you the gibberish where the 'c' should be.

    I'd try dumping the individual bytes you get for $saw to see the actual bytes Device::SerialPort is giving you. You can also just try changing the parity and word size to see if it fixes things up for you.

    Note: It's been a good few years since I had to deal with parity & such, so I may have even/odd mixed up in my head, so I'd suggest setting data bits to 7 and try both and see if one works the way you expect.

    ...roboticus

    When your only tool is a hammer, all problems look like your thumb.

      Interesting idea - just for reference, here's what the bytes are assuming the output is Windows-1252:

      my @data = (0x61, 0xAE, 0x6B, 0x7D, 0x72, 0x2E, 0x17, 0x8A); printf "%08b\n", $_ for @data; print "---\n"; printf "%08b\n", $_ for map ord, split //, "ack"; __END__ 01100001 10101110 01101011 01111101 01110010 00101110 00010111 10001010 --- 01100001 01100011 01101011

      That's for the second example string, for the first, the last byte would be 0x2C.