Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

Re: Win32::SerialPort on Win10 issue

by jmClifford (Acolyte)
on Jul 03, 2024 at 06:19 UTC ( [id://11160333]=note: print w/replies, xml ) Need Help??


in reply to Win32::SerialPort on Win10 issue

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......

Replies are listed 'Best First'.
Re^2: Win32::SerialPort on Win10 issue
by pryrt (Abbot) on Jul 03, 2024 at 13:21 UTC
    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).)

Re^2: Win32::SerialPort on Win10 issue
by soonix (Canon) on Jul 03, 2024 at 06:45 UTC
    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"...

Re^2: Win32::SerialPort on Win10 issue
by stevieb (Canon) on Jul 03, 2024 at 08:55 UTC

    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?

Re^2: Win32::SerialPort on Win10 issue
by Marshall (Canon) on Jul 03, 2024 at 16:06 UTC
    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....

        Hi. I did eventually find out the main issue with my previous program not working. The Win32::SerialPort as presented does not work with 64 bit operation (Perl). However there is a fix provided at (as linked to by Discipulus):

        https://rt.cpan.org/Public/Bug/Display.html?id=113337#txn-1691722

        This fix basically increases the sizes of some parameters in referencing a module (the memory mapping involved with this process).

        My current working program is:

        #! C:\perl\bin\perl.exe use strict; use warnings; use Win32::SerialPort; use Time::HiRes qw(usleep); my $port_name = 'COM5'; #my $config_file = 'setup.cfg'; # use this to configure from the fi +le my $port = new Win32::SerialPort( $port_name ) || die "Unable to open +: $^E\n"; # $^E EXTENDED_OS_ERROR #my $port = new Win32::SerialPort($port_name, $config_file) || die "Un +able to open: $^E\n"; $port->handshake('none'); # none dtr rts xoff $port->baudrate(38400); # 19200 57600 1200 9600 115200 4800 600 +2400 300 38400 $port->parity('none'); # space none odd even mark #$port->parity_enable(1); # for any parity except "none" $port->databits(8); # 7 8 $port->stopbits(1); # 2 1 $port->buffers(256, 256); $port->read_interval(0); #RI $port->read_const_time(20); #RC $port->write_char_time(1); #WM $port->write_const_time(100); #WC print "Write settings \n"; $port->write_settings || undef $port; # A report out to this console 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"; # use the below to save the current configuration # if ( $port ) { $port->save('setup.cfg') ; print "Serial Port OK \n" +}; # pack: used for assembling binary stuff # my $status = pack('H2' * 6, 'ca', '00', '01', '00', '00', 'fe'); $port->write("ati"."\r"); #$port->write("ati\x0D\x0A"); # carriage return and line feed: n +o different #$port->write("ate0"."\r"); usleep 0; my $debug = 1; my $cmd = " "; while ($cmd ne "quit") { print "Input command: "; $cmd = <STDIN>; chomp $cmd; if ($cmd eq "quit") {next;} $port->write($cmd."\r"); my $loop = 1; while( $loop ) { usleep(200000); # 0.2 of a second my $response = $port->input; chomp $response; print $response; #my $responseHex = unpack ('H*', $response); #print $responseHex."\n"; my $last = substr ( $response, -1 ); # get the last charact +er if ($last eq ">") { $loop = 0; next; } print "."; } }

        Regards JC.....

        Ok. This is progress. we learn that lower case AT commands are ok and that the line ending is \x0D. Use that instead of \n.

        Did you follow my suggestion of reading the port settings (handshake, etc)? Make sure that the port is configured and "happy" - if not it won't send data. I would not introduce the complication of a config file at this early stage.

        Again, trying running outside of Eclipse. That could make a difference.

        please show the exact code that you are using for this testing.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (2)
As of 2024-09-08 16:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    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.