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

Hello, Am trying to use Win32::SerialPort on a portable strawberry perl implementation, version 5-32-1. (32 bit). Using it to try and set up a datalogger on a Win10 machine, for an instrument that reports through a RS232 output. Also have a general test bed which is two windows PCs connected by a serial cable, and one sending messages (from Powershell) to the other - which testing has shown acts in the same way as the end use. Have come across a variety of scripts online. For some reason though, I can't get any Perl script to output the RS232 input on its own. However, if I open and close the port in powershell, suddenly the exact same Perl script DOES work! The perl script continues to work as expected until the PC is rebooted. So I'm wondering if there's a key parameter needing to be set, which is sorted by Powershell but not by Perl? Couldn't see anything obvious in the SerialPort documentation. An example script that only works when powershell has "activated" the port is:
use Win32::SerialPort; # Use instead for Windows my $port=Win32::SerialPort->new("COM1") || die "couldn't open COM1"; $port->baudrate(9600); # Configure this to match your device $port->databits(8); $port->parity("none"); $port->stopbits(1); #$port->handshake("none"); $port->user_msg(ON); print "Port COM1 successfully opened\n"; $count = 0; my $chars=0; my $buffer=""; print "1\n"; do { print "2\n"; my ($count,$saw)=$port->read(255); # will read _up to_ 255 char +s print "3\n"; if ($count > 0) { $chars+=$count; $buffer.=$saw; print $saw; } print "4\n"; $port->lookclear; print "5\n"; } while 1; $port->close;
This code stops after printing "2" if I've not opened/closed the port in Powershell yet - it's the reading of RS232 input where the script seems to get blocked quite consistently across different scripts. Powershell code to open and close is:
$port = new-Object System.IO.Ports.SerialPort COM1,9600,None,8,one $port.open() $port.close()
Powershell to send RS232 on test bed is: $port.WriteLine("test") Unfortunately access permissions do not let me run a powershell script, and I'd rather not have the end user have to manually type in powershell code each time the PC is turned on... Many thanks for any advice provided.

Replies are listed 'Best First'.
Re: SerialPort issues under Windows 10
by haukex (Archbishop) on Apr 15, 2021 at 19:08 UTC

    Based on my testing, the issue is that you need to do $port->write_settings or die "write_settings: $^E"; after setting the parameters.

    The next issue I had was that Win32::SerialPort's ->read appears to be behaving non-blocking (I unfortunately don't have enough time to investigate further at the moment see reply). See its documentation for a few blocking methods you can try, or you can use the tied filehandle interface to be able to use Perl's readline and read - if I wanted blocking I/O, the latter is what I would do as I find the filehandle interface more familiar.

    Note you should Use strict and warnings!

      The next issue I had was that Win32::SerialPort's ->read appears to be behaving non-blocking

      It's actually just timing out immediately - adding the minimum of e.g. $port->read_const_time(1000); sets the read timeout to 1s.

      Aha! write_settings was the key step I think - I naively thought that was just to write settings to a file, rather than initiate the settings described!

      Many thanks all.

      Will try and remember strict and warnings... Have had a bug in the last several years of occasional scripting where that might have been useful, in retrospect. Old habits etc...

Re: SerialPort issues under Windows 10
by Discipulus (Canon) on Apr 15, 2021 at 13:05 UTC
    Hello clinicalAD and welcome to the monastery and to the wonderful worldo of perl!

    waiting for others answers, just shooting in the dark: try to print also the OS error in your die clause: || die "couldn't open COM1 $^E";

    Then you can imports some useful constants (see also Operating methods) from the module, which inherit from Win32API::CommPort

    Search here at the monastery for other useful examples, some one very recent as How to read serial port with WIN32:SerialPort?

    L*

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.
Re: SerialPort issues under Windows 10
by jcb (Parson) on Apr 16, 2021 at 02:58 UTC

    I have yet to use serial ports with Perl, and I am happy to say that I have not used Windows in some time, but I will guess that your device does not assert DCD and the system is waiting for DCD before reading data. There may be some other setting to ignore DCD that PowerShell quietly sets and that persists in the serial driver, or your commented-out line 7 may be part of the problem. Another monk (haukex) mentioned that apparently the Win32::SerialPort module has a special write_settings method for making configuration changes effective; you may need that too or a missing call to it may be your problem.