Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Win32 Serial Under Windows 7

by PilotinControl (Pilgrim)
on Mar 31, 2018 at 22:31 UTC ( [id://1212087]=perlquestion: print w/replies, xml ) Need Help??

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

Hello Esteemed monks! The below code works fine under windows vista....however it does not work fine under windows 7. Now I can send the commands just fine and it works connecting to the Arduino.....the issue is the messages from the Incoming Data are not being received... I disabled ALL network blocks so its sending the info just not receiving. Thanks in advanced and thanks to roboticus for helping so far.
#!/usr/bin/perl -w ###################### # # VARIABLES, # PACKAGES, & DEFINES # ###################### use strict; use warnings; use diagnostics; use Term::ReadKey; use Win32::Console::ANSI qw/ Title SetCloseButton Cursor :SW_ /; use Win32::Console::ANSI; use Win32::Console; use Term::ANSIColor; use Term::ANSIScreen qw/:cursor :screen/; ########################## # # SET TERMINAL ATTRIBUTES # ########################## $SIG{INT}= 'IGNORE'; SetCloseButton(0); ShowConsoleWindow(SW_SHOWMAXIMIZED); #################################### # # LOGGING KEY STROKE TIME STAMP SUB # #################################### my $time = localtime(time); # ADD TIME STAMP TO LOGFILE ################## # # SET SERIAL PORT # ################## use Win32::SerialPort; my $port = Win32::SerialPort->new("COM7") or die "Open Port Failed. $! +\n"; $port->is_rs232; # SET UP THE SERIAL PORT # 9600 OR 19200, 81N ON THE USB FTDI DRIVER $port->initialize(); $port->baudrate(9600); $port->databits(8); $port->parity("none"); $port->stopbits(1); $port->write_settings || undef $port; ################## # # MAIN SCREEN SUB # ################## no warnings 'numeric'; Title "Simple Signals Driver"; print colored("CONNECTING TO SIGNAL SYSTEM...", 'bold green'), "\n"; sleep(15); print "\n", colored("CONNECTED...",'bold green'), "\n", colored("START +ING RELAY SIGNAL PROGRAM", 'bold green'), "\n\n"; # Buffer used to build our command line my $command_line = ""; # Buffer for our serial data my @serial_data = (); # Put console into raw mode ReadMode 4; setup_serial_interface(); my $are_we_done_yet = 0; while (!$are_we_done_yet) { my $con_key = ReadKey(-1); if (defined $con_key) { if ($con_key eq "\r" or $con_key eq "\n") { # user finished entering the command handle_command($command_line); $command_line = ""; } else { # Not end of line, so add to command line. # NOTE: you'll want to handle backspace and/or # other line editing commands. But that's too # much work for a quick demo... $command_line .= $con_key; } } elsif (is_serial_data_ready()) { # Serial device gave us something to do handle_serial_data(); } else { } } ReadMode(0); # RESTORE CONSOLE MODE ################# # # HANDLE COMMAND # ################# sub handle_command { my $cmd = shift; if ($cmd =~ /^q/i) { print "\n", colored("QUIT PROGRAM!", 'bold yellow'), "\n"; $are_we_done_yet = 1; $port->purge_all; $port->close or die "CLOSE FAILED: $!\n"; undef $port; # CLOSES PORT FREES MEMORY sleep(3); } elsif ($cmd =~ /^\d+$/i) { print colored("\nSENDING COMMAND $cmd $time...", 'bold yellow'), "\n\n +"; $port->write("$cmd\r"); $port->lookclear(); print colored("DONE!", 'bold yellow'), "\n\n"; } else { print colored("UNKNOWN COMMAND: $cmd", 'bold red'), "\n"; } # END ELSE } # END HANDLE COMMAND ############################# # # USB/SERIAL/INTERFACE WITH # THE ARDUINO # ############################# sub setup_serial_interface { my $seconds_per_transmission = 1.5; $SIG{ALRM} = sub { push @serial_data, rand; alarm $seconds_per_transmission; }; # ALARM SUB alarm(3); # LOOK FOR PACKET DATA } # END SUB sub is_serial_data_ready { return scalar @serial_data; } # END SUB sub handle_serial_data { my $c = $port->input; # non-blocking read #$c =~ s/r/\n/; print colored("Incoming Data:", 'bold green'), colored("$c", 'bold yel +low'), "\n"; #print "Incoming Data: $c(", join(", ", @serial_data), ")\n"; @serial_data = (); } # END SUB

Replies are listed 'Best First'.
Re: Win32 Serial Under Windows 7
by roboticus (Chancellor) on Apr 03, 2018 at 19:18 UTC

    PilotinControl:

    Sorry I've not gotten back to you earlier. Anyway, let's take a look at a few things:

    • You don't need the "-w" since we're doing "use warnings":
      #!/usr/bin/perl -w
    • If you'd keep your code nicely indented, you wouldn't need lines like:
      } # END SUB
      because everything would be nicely aligned so you can see it.
      I typically don't add comments to the end of blocks like this. When I do, it's because the block is too long to see both the top and the bottom on the screen. Keeping your functions short and nicely indented is better.
    • I put the setup_serial_interface(), is_serial_data_ready() and handle_serial_data() routines there to give you nice places to hook in your code. The code in those routines that I provided was just faked to give you an idea of how it works.
      In any case, it looks like your problem is how you're using these routines:
      • is_serial_data_ready() - should return a true value if there's some serial data that's ready for you to handle. Since you're not using the @serial_data array to hold incoming commands, it's never ready, so it'll never call the handle_serial_data() function.
        It looks like you only want to process completed lines from the serial port, so I rearranged some of your code and tried to build an appropriate function for you: It stores partial command lines in $serial_input, and when it finds an end-of-line character, it moves the completed command to @serial_data.
      • handle_serial_data() - should process the completed commands that are ready (in @serial_data).

    So, when I made appropriate edits, I get something as shown below in the "read more" tag. Note: I don't have many of the packages installed, so I can't actually test the code, so there may be a few bits you'll need to look over:

    Update: I see after I posted the node that dasgar has already suggested the notion that you have a buffering problem.

    ...roboticus

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

      Ok the good news is your revised code works the same...however the data coming from the arduino isnt getting displayed....and normally the: Incoming Data: line gets displayed when its polling for data...that doesnt happen...I must point out this is Windows 10 on an Asus Touchscreen tablet with Keyboard....I am not sure if that makes a difference...I do get the incoming data when I connect Putty to the arduino and I push the button.

        PilotinControl:

        I don't know anything about Win32::Serial, nor how it may interact with Windows 10. I'd suggest sprinkling a few print statements in locations to see what the code is doing.

        The first one I'd suggest is to put a print statement immediately inside the while loop:

        my $are_we_done_yet = 0; while (!$are_we_done_yet) { print "loop\n"; # Check for console activity my $con_key = ReadKey(-1);

        This way, we can see if the loop is operating correctly. However, it'll quickly fill your screen up. So if that's working OK, you'll want to take it out again after checking.

        Next, we can add a couple print statements to is_serial_data_ready, to see what it's doing:

        sub is_serial_data_ready { print "is_serial_data_ready: enter\n"; # Non-blocking read: otherwise, we'll hang up here! my $c = $port->input; print "is_serial_data_ready: got <$c>\n"; # Process the incoming characters for my $char (split '', $c) { print "is_serial_data_ready: char '$char'\n"; if ($char eq "\n" or $char eq "\r") { print "is_serial_data_ready: end-of-line found\n"; # End of line found, add current line to buffer # (unless it's empty) if ($serial_input ne '') { push @serial_data, $serial_input; # start a new blank line $serial_input = ""; } } else { # Just a normal character, add to the input $serial_input .= $char; } } # Returns true if there are any completed lines to handle print "is_serial_data_ready: ", join(" // ", @serial_data), ".\n"; return scalar @serial_data; }

        This way, you can see if it's actually entering the is_serial_data_ready function. If so, you can see if there's any time lag on the input statement, and whether anything ever shows up in $c. It'll also show if the characters are building up into statements or not.

        The idea is to put some print statements in various locations to verify that the program is operating as you expect it to. Normally, I'd suggest using the perl debugger, but this trick should help you get started along finding the problem.

        Since you say it operates differently between Windows 10 and Windows 7, I'd try to first concentrate on finding out just what the difference is. From there, it may give a clue on what to research to find the problem.

        ...roboticus

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

Re: Win32 Serial Under Windows 7
by huck (Prior) on Apr 02, 2018 at 23:36 UTC
      Windows 7 and 10 are 32-bit OS operating on a x64 system.
Re: Win32 Serial Under Windows 7
by dasgar (Priest) on Apr 03, 2018 at 03:53 UTC

    My first thought on debugging would be to log all of the incoming/outcoming communication and check the logs as a way to verify what is actually being sent and received. I didn't see anything in Win32::SerialPort's documentation or the documentation for Win32API::CommPort (which Win32::SerialPort is based on). The logging options are clearly documented for Control::CLI, which uses Win32::SerialPort on Windows for serial port communications. If you don't want to switch over to use Control::CLI, you can check out its source code to see how its doing the logging.

    My next thought would be to look at timeouts and buffering. For the timeouts aspect, check out the last portion of the Configuration and Capability Methods section of the Win32::SerialPort documentation. It's been a long time since I worked on code using Win32::SerialPort, but I remember having issues related to timeouts.

      I downloaded a serial monitoring program and I can see the packets coming and going to the Arduino when I run my script....the sending is fine....the receiving is not being acknowledged...I tried changing the timing to read the data coming it...that did not help any.
        I downloaded a serial monitoring program and I can see the packets coming and going to the Arduino when I run my script

        Based on that description, you have confirmed that "something" is being sent from both sides. If you can get logging going from your Perl code, that would help you to verify that your code is actually sending what you think it is sending and verify exactly what it is receiving. This will help you to catch issues such as extra/missing white space characters (like carriage returns and line feeds) in what you send. By verifying what your code actually receives, you can debug the portions of your code that is reading the data sent from the device by seeing if it is processing the incoming data properly.

        Another debugging method would be to use something like putty to manually connect to the device to try to interact with it manually. If that's not working, then there might be other issues that need to be addressed first.

        I tried changing the timing to read the data coming it

        Have you looked into the buffering aspect of things?

        Another thing you can check is to see if you're using the same versions of Perl and the Win32::SerialPort module on both systems.

Re: Win32 Serial Under Windows 7
by haukex (Archbishop) on Apr 04, 2018 at 10:27 UTC

    Crossposted to StackOverflow. Crossposting is acceptable, but it is considered polite to inform about it so that efforts are not duplicated.

Re: Win32 Serial Under Windows 7
by PilotinControl (Pilgrim) on Apr 02, 2018 at 16:34 UTC
    Anyone have a clue? I've tried several things and I am still stumped. Thanks.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2024-04-25 23:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found