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

just a warning up front, I think this is a perl problem, but it MAY end up being a linux problem. if so, i apologize ahead of time.

i've a device that connects via an RS232 serial cable, and I'm trying to read/write data to/from it. here's the thing, it works fine in windows using Win32::SerialPort, but in linux with Device::SerialPort, it print()s data to the device (/dev/tty0) with no problem, but it read()s nothing at all, whatever it seems to return doesnt print() to screen, isnt a blank string, and isnt undef.

here's the test script i'm using:

#!/usr/bin/perl -w use strict; use Device::SerialPort qw( :PARAM :STAT 0.07 ); use Term::ANSIColor qw(:constants); print YELLOW,"Location of device: ",RESET; my $port = <>; # prompt for device, eg: /dev/tty0 chomp $port; my $rootDir = "~"; my $config = "$rootDir/.testconf"; open(LOG,">>$rootDir/test.log"); print LOG "started\n"; # protocol-specific control chars my %IM = ( 'SOM' => chr(2), #Start of message (STX) 'EOM' => chr(3), #End of message (ETX) 'AFF' => chr(6), #Affirmative Acknowledge (ACK) 'NEG' => chr(21), #Negative Acknowledge (NAK) 'POL' => chr(5), #Poll for data (ENQ) 'SEL' => chr(7), #Alarm (BEL) 'EOR' => chr(13), #End of record (CR) 'DLE' => chr(16), #DLE 'RES' => chr(4), #Reset (EOT) 'ESOM' => chr(15), #On Error, Start of Message (SI) 'EEOM' => chr(14), #On Error, End of Message (SO) ); print "\nCreating config file...\n"; my $PortObj = new Device::SerialPort ($port) || die("Can't open $port: + $^E\n\n"); $PortObj->databits(7); $PortObj->baudrate(19200); $PortObj->parity("even"); $PortObj->stopbits(1); $PortObj->handshake("xoff"); $PortObj->buffers(4096, 4096); $PortObj->write_settings || undef $PortObj; $PortObj->save("$config"); $PortObj->close || die("failed to close\n\n"); if(defined $PortObj) { print YELLOW, "Success!\n", RESET; } else { die("PortObj is undefined!\n\n"); } undef $PortObj; print LOG "config file created and saved\n"; print "\nTie()ing to port...\n"; $PortObj = tie (*SERIAL, 'Device::SerialPort', "$config") || die("Can't open $port: $^E\n\n"); # use non-blocking read on serial port $PortObj->read_char_time(5); $PortObj->read_const_time(500); print YELLOW, "Success!\n",RESET; print LOG "tied to serial port\n"; my $EXIT = 0; $SIG{'INT'} = sub { $EXIT = 1 }; my $data; while($EXIT == 0) { print "\nPolling for data...\n"; $data = pollForData(); print YELLOW, "Success!\n",RESET; print "\nData: ",GREEN,"$data",RESET; } print LOG "stopping\n"; close(LOG); print "\n\n"; $PortObj->close || die("failed to close"); untie *SERIAL; undef $PortObj; exit; sub pollForData { my($length,$buffer,$lrc,$input); $buffer = join('',RED,"NO DATA",RESET); print SERIAL $IM{'POL'}; $length = read(SERIAL,$buffer,4096); if($buffer eq '') { return join('',RED,"BLANK STRING",RESET); } if(!defined $buffer) { return join('',RED,"UNDEFINED STRING",RESET); } if($buffer ne $IM{'RES'}) { print SERIAL $IM{'AFF'}; } # otherwise, return data return $buffer; }
when this is run, it saves and loads the config file without a problem, tie()s to a filehandle without a problem, and then prints "NO DATA" in the loop, meaning it doesnt match '' or undef...

i'm stumped, could anyone please help me?

Replies are listed 'Best First'.
Re: cant read serial data with Device::SerialPort
by GrandFather (Saint) on Aug 31, 2005 at 20:58 UTC

    As a sanity check have you tested that all the hardware works - use a loopback cable and check with a terminal program that anything you type is echoed back. Using the same loopback cable see if anything you send with your test code gets returned.


    Perl is Huffman encoded by design.
Re: cant read serial data with Device::SerialPort
by graff (Chancellor) on Sep 01, 2005 at 02:18 UTC
    I sorry I don't have the means to help directly, but I'm curious about a couple things in your "pollForData" sub, and I can suggest a few questions to consider (which you've probably covered already, but hey, no harm asking).

    Why do you not check the value of $length? (If you do check that, what do you get?) Why do you check "$buffer eq ''" before you check "!defined $buffer"?

    If $length is greater than zero (which means $buffer must be defined), what would you see if you did this before returning:

    printf( "%2.2x ", $_ ) for ( split //, $buffer ); print "\n";
    (You might want to avoid setting $buffer to the initial value of RED,"NO DATA",RESET -- just set it to undef or "" to start with.)

    Since you are doing a non-blocking read on the port, my first guess is that the device is not responding with data, so the original content of $buffer is not being replaced.

    Are you using the same host computer (i.e. dual-boot windows/linux), or different boxes? If the latter, are you using the same serial cable on both OS's? (I would always have a null-modem adapter on hand for this kind of thing, and if a device/cable doesn't work without the adapter, I put on the adapter and try again.)

Re: cant read serial data with Device::SerialPort
by zentara (Cardinal) on Sep 01, 2005 at 10:15 UTC
    I'm not sure if it's a typo, but the serial ports on linux are NOT /dev/tty0......they are /dev/ttyS0. Maybe your system has a different naming convention. I'm not surprised you can write to, but not read from /dev/tty0. Alot of devices will let you print to them, even if they don't understand it.

    Also try running the command as root, and see if it helps. If it does, then it's a port-permissions problem. On many linux's, you need to be a member of group UUCP to access the serial ports.


    I'm not really a human, but I play one on earth. flash japh
Re: cant read serial data with Device::SerialPort
by Anonymous Monk on Sep 01, 2005 at 14:58 UTC
    GrandFather: tried a loopback cable and the port keeps screaming "input/output error", so it appears it IS a linux error. ::shrug:: thanks for the advice!

    graff: you're right, sloppy programming on my part, i sort of tore apart another script to make this test script. and its different boxes entirely.

    zentara: yeah, was a typo, one that threw me for a loop too. although the serial ports arent ttyS0 on this machine, they're ttys0.

    thanks for the suggestions!