Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Win32::SerialPort on Win10 issue

by jmClifford (Acolyte)
on Jul 02, 2024 at 15:24 UTC ( [id://11160320]=perlquestion: print w/replies, xml ) Need Help??

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

Hi. I have had little success with actually writing and reading to/from a COMx serial port using the above. The laptop is a ASUS 64 bit machine (Win10). I can get as far as configuring the COMx port with no errors. The actual write and read of data does not work. The read I consider is a response to the write (which I cannot confirm). It difficult to trouble shoot. I do get the test unit (a USB automotive OBD2 unit) to work with RealTerm (OK) on COM5. Do people known if I should except this configuration to work ?? Regards JC......

Replies are listed 'Best First'.
Re: Win32::SerialPort on Win10 issue
by eyepopslikeamosquito (Archbishop) on Jul 03, 2024 at 00:34 UTC

    > The actual write and read of data does not work

    Not a helpful description :-) ... you'll need to show us your code that does not work, ideally in a SSCCE, along with a description of what you are trying to achieve.

    For some sample PM code that uses Win32::SerialPort see: How to read serial port with WIN32:SerialPort?

    👁️🍾👍🦟

      Not a helpful description :-)

      Actually, in this specific case it most likely is. Win32::SerialPort is strange in how it works in the Background. The Linux/Unix version (Device::SerialPort) seems to just work by setting some parameters (baud rate etc) and you can get immediately to sending/receiving data.

      But in Win32::SerialPort, you have to call write_settings() after configuration changes, otherwise the object will just sit there ignoring all your send/receive calls, most likely without showing a warning or raising an error.

Re: Win32::SerialPort on Win10 issue
by Marshall (Canon) on Jul 03, 2024 at 00:35 UTC
    People have gotten this module to work. You say: "I can get as far as configuring the COMx port with no errors." How about showing us your exact code. Some more detail about your hardware configuration would be helpful and any specs of attached USB-Serial device and target device.

    Update: You might google "rs232 breakout tester led monitor". A $20 piece of test equipment might assist debugging a lot.

Re: Win32::SerialPort on Win10 issue
by dasgar (Priest) on Jul 03, 2024 at 21:36 UTC

    It's been a while since I use Win32::SerialPort. When I first started using that module, Configuration and Capability Methods section of the documentation has information on timeouts that helped me get past my initial issues. In my case, I was trying to read too fast after sending a command. After reading that section, I made a few changes using that information helped me with my timing issue. Just sharing that in case it might help you.

    Also, you might want to take a look at Control::CLI. It's a module to let you do telnet, SSH, and serial port stuff. It uses other modules underneath (including Win32::SerialPort on Windows) and the syntax is very similar to Win32::SerialPort. The reason that I'm recommending you to check it out is that has logging (input_log(), output_log(), dump_log()), which can help you debug what is being sent by your code and what it receives from the device. Also, it provides a debug() method that might help with your troubleshooting work.

Re: Win32::SerialPort on Win10 issue
by cavac (Parson) on Jul 04, 2024 at 07:37 UTC

    We had this a while ago at work. We have a program that needs to work on bith Windows and Linux with serial ports.

    On Linux, when you change a setting like the baud rate, it works right away. When using Win32::SerialPort, you also have to call write_settings() to load the updated settings from the Perl module into the Windows kernel (or something like that). The documentation of Win32::SerialPort has this to say under "Initialization":

    The primary constructor is new with a PortName (as the Registry knows it) specified. This will create an object, and get the available options and capabilities via the Win32 API. The object is a superset of a Win32API::CommPort object, and supports all of its methods. The port is not yet ready for read/write access. First, the desired parameter settings must be established. Since these are tuning constants for an underlying hardware driver in the Operating System, they are all checked for validity by the methods that set them. The write_settings method writes a new Device Control Block to the driver. The write_settings method will return true if the port is ready for access or undef on failure. Ports are opened for binary transfers. A separate binmode is not needed. The USER must release the object if write_settings does not succeed.

Re: Win32::SerialPort on Win10 issue
by jmClifford (Acolyte) on Jul 03, 2024 at 06:19 UTC

    Hi. I was hoping for a recognizable known fault. I trust that I provide the additional data with a comment (like this) to the Issue trail.

    I can establish the correctness on the USB unit (OBD2 LM327) connected to COM5 with RealTerm SW (on Laptop Win 10 system). I did have some screen dumps to demonstrate this. But I am unsure if this is possible with this interface. These RealTerm dumps do demonstrate connection of 38,400 baud and 8N1. Also transmitting the command "ati\n" (\n carriage return) gives a response of "ELM327 v1.5 carriage return". Note I have ensured the echoing is off ("ate0\n"), prior to this. This USB unit's operation copies modem AT commands.

    The next part of this involves running the same COM5 port setup with not RealTerm but with Perl. The manipulation of the configuration can be achieved with a program like (and the response just below it) ;

    #! perl -w use strict; use Win32::SerialPort; my $ob = Win32::SerialPort->new ('COM5') || die; my $baud = $ob->baudrate; my $parity = $ob->parity; my $data = $ob->databits; my $stop = $ob->stopbits; my $hshake = $ob->handshake; print "B = $baud, D = $data, S = $stop, P = $parity, H = $hshake\n"; my @data_opt = $ob->databits; # list context print "\nData Bit Options: "; foreach $a (@data_opt) { print " $a"; } @data_opt = $ob->stopbits; # list context print "\nData Bit Options: "; foreach $a (@data_opt) { print " $a"; } @data_opt = $ob->handshake; # list context print "\nData Bit Options: "; foreach $a (@data_opt) { print " $a"; } @data_opt = $ob->parity; # list context print "\nData Bit Options: "; foreach $a (@data_opt) { print " $a"; } @data_opt = $ob->baudrate; # list context print "\nData Bit Options: "; foreach $a (@data_opt) { print " $a"; } undef $ob; ======================= Response ================== B = 38400, D = 8, S = 1, P = none, H = none Data Bit Options: 7 8 Data Bit Options: 2 1 Data Bit Options: rts none dtr xoff Data Bit Options: odd space even none mark Data Bit Options: 300 115200 57600 19200 1200 4800 9600 38400 2400 60 +0

    I seem to have no issues with the manupilation of the configuration of COM5.

    However, if I cross to a write then read program, coping the above RealTerm success of outputting "ati\n", I get no success. The code used and the response is;

    #! C:\perl\bin\perl.exe use strict; use warnings; use Win32::SerialPort; my $port_name = 'COM5'; my $config_file = 'setup.cfg'; my $port = new Win32::SerialPort($port_name, $config_file) || die "Una +ble to open: $^E\n"; # my $status = pack('HHHHHH', 'ca', '00', '01', '00', '00', 'fe'); $port->write("ati"."\n"); sleep 0; my $debug = 1; while(1) { my $line = $port->lookfor(); if( $line ) { { local $/ = "\r"; chomp $line; } if ($debug) { print "[$line]" ;} # Some data processing takes place } else { sleep(1); # Allocate time for other processes to run print "."; } } ======================= Response ================== .......

    As you can see from the above I get to the endless loop without any information presented.

    My IDE is Eclipse.

    Regards JC......

      You say, using RealTerm,
      Also transmitting the command "ati\n"

      ... this implies that your communication protocol expects just LF, not CRLF, assuming that RealTerm doesn't do any EOL translation.

      In your code, you say,

      $port->write("ati"."\n");

      At least in Strawberry Perl (and I think in homebuilt or ActiveState Perl, too, but I am not sure), on a Windows machine, it defaults the STDOUT output layer to translate \n in Perl to \r\n when it prints to STDOUT (effectively, an implied binmode STDOUT, ':crlf'). I don't know whether Win32::SerialPort follows that convention, too, or whether ->stty_eol(...) defines what \n is translated into, or whether ->write(...) automatically appends the ->stty_eol(...) sequence.

      The docs say, "The read, input, read_done, write methods all treat data as "raw"." -- That somewhat indicates that they won't apply the CRLF transformation.

      But if write automatically appends the stty_eol sequence, then you might be getting ati followed by two LF rather than the one you intended. And, though they don't have a lot of ->write(...) examples in their POD, none of them show them manually appending the newline, so you might want to at least try to not have the ."\n" in your code.

      (Debugging communication-protocol on physical wires is so much easier when you've got a way to watch the signals, with the "rs232 breakout tester led monitor" that Marshall suggested, or an oscilloscope or professional-quality logic analyzer, or a hobbiest logic analyzer (like the SparkFun, or Amazon lists a < US$15 "USB Logic Analyzer" which goes up to 24Mbps, which is plenty for your 38.4k signal).)

      long time no see serial ports 🤔

      Although the Win32::SerialPort doc says "The handshake setting is recommended but no longer required.", I'd try out the different settings, starting with "none"...

      I only use Windows to develop a single application and for no other reason, so this is a wild guess. I've written a lot of RS232 along with other serial communication software, but not for this platform...

      However, if I cross to a write then read program, coping the above RealTerm success of outputting "ati\n", I get no success.

      What if you try ati\r\n?

      Maybe on Windows the carriage return makes a difference?

      Looks like you are well on the way. Yes, Win32:SerialPort should work fine for this application.

      I would print the configuration to make sure you know what it is. 38400 8N1 is common for these types of devices - looks plausible. You can just put explicit <CR> <LF> characters into the write string to prevent any ambiguities with "what does \n mean?". A single <CR> character should be enough for the modem to recognize end of command. But, you could try some permutations. Power on/off box between trials (make sure its brain is starting from zero). I would wait 1 second for ATI command to be sent before trying to read the response - the answer should be waiting when you get there.

      It could be that your IDE is affecting things somehow. Try running your test program from the command line.

      my $baud = $port->baudrate; my $parity = $port->parity; my $data = $port->databits; my $stop = $port->stopbits; my $hshake = $port->handshake; print "B = $baud, D = $data, S = $stop, P = $parity, H = $hshake\n"; $port->write("ati\x0D"); #keep simple for now single <CR> #also try \x0D\x0A <CR><LF> #try ATI\x0D (AT spec says upper case) sleep 1; #should allow for whole string to be sent #reply should be waiting #not clear how much buffering #goal is get a character, any character at first while(1) { my $line = $port->lookfor(); #can be multi-character response if( $line ) { print "[$line]"; # Some data processing takes place } else { sleep(1); # Allocate time for other processes to run print "."; } }
      Update: perhaps try the streamline method, but the above should work.

      update2: I think I understand what you have now. A USB gizmo that has 16 pin connector to the car on the other side. You don't actually have a serial cable so, serial cable breakout box won't help. However, Wireshark freeware for Windows can capture USB traffic CaptureSetup/USB. I would setup with your terminal emulator and capture USB traffic and then do the same with the Perl program.

        Hi. Thanks to all for the help.

        I did try Serial Port Monitor (2 weeks trail). Wireshark looks too involved (and I previously have used on TCP/IP only). The Serial Port Monitor gives the response below, when I used the Realterm connection;

        [05/07/2024 13:43:32] - Open port COM5 (C:\Program Files (x86)\BEL\Rea +lterm\realterm.exe) # this occurs on connection with SW [05/07/2024 13:04:58] Written data (COM5) 61 74 69 0d ati. + [05/07/2024 13:04:58] Read data (COM5) 45 4c 4d 33 32 37 20 76 31 2e 35 0d 0d 3e ELM327 v1.5..> + [05/07/2024 13:05:05] - Close port COM5 # this occurs on Realterm shutdown

        While when I use the PERL connection;

        [05/07/2024 13:05:12] - Open port COM5 (C:\Strawberry\perl\bin\perl.ex +e) # occurs with the creation of the object [05/07/2024 13:05:28] - Close port COM5 # occurs with Eclipse shutting down the running Perl

        My only conclusion (at this stage) is that I am failing to connect to COM5 while there is nothing suspicious about the USB unit (yes it is a On Board Diagnostic unit used with automobiles with ~16 pin connector and no access to RS232).

        Regards JC....

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11160320]
Approved by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others pondering the Monastery: (6)
As of 2024-09-15 22:17 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    The PerlMonks site front end has:





    Results (21 votes). Check out past polls.

    Notices?
    erzuuli‥ 🛈The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.