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

Re: Win32 Serial Under Windows 7

by roboticus (Chancellor)
on Apr 03, 2018 at 19:18 UTC ( [id://1212283]=note: print w/replies, xml ) Need Help??


in reply to Win32 Serial Under Windows 7

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:

#!/usr/bin/perl ###################### # # 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 # ################## my $port = setup_serial_port("COM7") or die "Open Port Failed. $!\n"; ################## # # 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("STARTING RELAY SIGNAL PROGRAM", 'bold green'), "\n\n"; # Buffer used to build our command line my $command_line = ""; # Buffer for our serial data my $serial_input; # Holds incomplete command(s) my @serial_data = (); # Commands ready to process # Put console into raw mode ReadMode 4; setup_serial_interface(); my $are_we_done_yet = 0; while (!$are_we_done_yet) { # Check for console activity 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 { # NOTE: I'd try to wait here so we don't kill a CPU, but witho +ut # Time::HiRes, we can only sleep for an entire second, and tha +t # would make console I/O feel sluggish. So until we resolve t +hat, # we'll just kill a CPU #NEED SHORT DELAY HERE TO LET OTHER PROCESSES HAVE CPU } } close_serial_port(); 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; } 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"; } } ############################# # # USB/SERIAL/INTERFACE WITH # THE ARDUINO # ############################# sub setup_serial_interface { use Win32::SerialPort; my $COM = shift; $port = Win32::SerialPort->new($COM) 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; return $port; } sub close_serial_port { $port->purge_all; $port->close or die "CLOSE FAILED: $!\n"; undef $port; # FREES PORT MEMORY } sub is_serial_data_ready { # Non-blocking read: otherwise, we'll hang up here! my $c = $port->input; # Process the incoming characters for my $char (split '', $c) { if ($char eq "\n" or $char eq "\r") { # 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 return scalar @serial_data; } sub handle_serial_data { while (my $cmd = shift @serial_data) { print colored("Incoming Data:", 'bold green'), colored($cmd, 'bold yellow'), "\n"; } }

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.

Replies are listed 'Best First'.
Re^2: Win32 Serial Under Windows 7
by PilotinControl (Pilgrim) on Apr 03, 2018 at 20:10 UTC
    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.

        I added each print statement as described....the only print that comes through is the Loop.....nothing ever comes from the is_serial_data_ready print statements. I find that very weird....as stated before when I use Putty and connect to the Arduino and push the button the feedback is printed to the screen. Each computer has the same version of perl and same version of Win32::SerialPort. The laptop running Vista is fine, the laptop running Windows 7 is fine....the Tablet running Windows 10...with an attached keyboard works fine sending...doesn't receive.

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (2)
As of 2024-04-20 03:46 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found