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

UPDATED QUESTION: So basically I would like to view live input from the Arduino via Perl and send input to the Arduino via Serial. Hello Group! I can successfully send a command to the serial device and I can see the response when a button is pressed on the device however I would like to see it in real time and not when I hit the enter button again. Thanks in advanced my code is below:
use Win32::SerialPort; my $port = Win32::SerialPort->new("COM16") or die "Open Port Failed. $ +!\n"; $port->is_rs232; $port->initialize(); $port->baudrate(9600); $port->databits(8); $port->parity("none"); $port->stopbits(1); $port->write_settings || undef $port; sleep(3); print "STARTING RELAY SIGNAL PROGRAM\n\n"; while (1) { print "ENTER A SIGNAL COLOR... "; my $char = <STDIN>; $char = <STDIN> until defined $char; chomp($char); # SEND THE COMMAND TO THE ARDUINO if ($char =~ /^\d+$/) { print "\nSENDING $char ...\n\n"; $port->write("$char\r"); } $port->lookclear(); my $data = $port->lookfor; if ($data =~ /BONE/) { print "\nBUTTON PRESSED\n\n"; } $port->lookclear(); $port->purge_all; } # END WHILE LOOP

Replies are listed 'Best First'.
Re: Win32 Serial Read input from device
by roboticus (Chancellor) on Mar 26, 2018 at 22:38 UTC

    PiloinControl:

    To do that, you're going to want to find a way to not sit and wait for an input command. In other words, you want non-blocking input.

    It looks like you're headed in the right direction, since your code looks like you're trying to read a character. But by default, perl will wait until you have an entire line of data before it will return from my $char = <STDIN>;. If you use Term::ReadKey, it can let you read a character or get an undef if there isn't a character ready.

    I don't have a serial thingie set up on my computer, so here's a silly little example of how you might be able to do it:

    $ cat funky_i_o.pl use strict; use warnings; use Term::ReadKey; use Time::HiRes qw( alarm ); # Buffer used to build our command line my $command_line = ""; # Buffer for our (fake) 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 { # Don't eat *ALL* the cpu, since nothing came in from # the console or serial line, pause a brief time to let # something arrive # Here, you'd normally use a sleep or usleep. But alarm # and sleep aren't necessarily on friendly terms with each # other, and we're using alarm to fake a serial device. So # we're not actually going to delay here, but you would want # to in a real application. } } # Restore normal console mode ReadMode(0); sub handle_command { my $cmd = shift; if ($cmd =~ /^q/i) { print "Quitting!\n"; $are_we_done_yet = 1; } elsif ($cmd =~ /^d.*(\d+)/i) { print "Starting a task that takes $1 seconds!\n"; my $t = time; while ($t + $1 > time) { ; # fake process ... just wait until time expires } print "...and now we're done!\n"; } else { print "Unknown command: $cmd\n"; } } ### # Our fake serial interface ### sub setup_serial_interface { my $seconds_per_transmission = 0.567; $SIG{ALRM} = sub { push @serial_data, rand; alarm $seconds_per_transmission; }; # First packet of data should occur in a couple seconds alarm 2.5; } sub is_serial_data_ready { return scalar @serial_data; } sub handle_serial_data { print "We haz teh dataz! (", join(", ", @serial_data), ")\n"; @serial_data = (); }

    When I ran it, I got the following (with a bunch of lines snipped out, as indicated):

    $ perl funky_i_o.pl We haz teh dataz! (0.947528113451884) <<< snip! don't want output to be too long! >>> We haz teh dataz! (0.345542351805733) We haz teh dataz! (0.91829197130572) Unknown command: now is We haz teh dataz! (0.226257566965014) We haz teh dataz! (0.517020773183582) <<< snip again! >>> We haz teh dataz! (0.917061227597888) Starting a task that takes 5 seconds! ...and now we're done! We haz teh dataz! (0.214499409451559, 0.574298714543268, 0.86510970635 +5287, 0.412658576047463, 0.56280680260377, 0.488052299033619, 0.60365 +2722987906) We haz teh dataz! (0.375474185862402) We haz teh dataz! (0.382325609198627) Unknown command: now is We haz teh dataz! (0.951879935396668) <<< snip! >>> We haz teh dataz! (0.760059503593943) Quitting!

    ...roboticus

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

      Hello roboticus, I get a n Un-implemented error when I test ran your code. I am using a windows OS win32 modules etc.

        PilotinControl:

        Can you give a bit more detail about the error message and/or the changes you made to the code?

        ...roboticus

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

Re: Win32 Serial Read input from device
by stevieb (Canon) on Mar 26, 2018 at 22:21 UTC

    Hi PilotinControl,

    I have the facilities to test this (I believe), but before I dig deep into your code, it would help if you could advise what the device is at the other end, so I can grasp what it may return.

    At minimum, please post what the return is, verbatim, if the device is far from standard (still handy to say what it is however).

      The device at the other end is an Arduino Mega connected via USB and a pushbutton connected to the arduino. On the computer side is the Perl Program....I can send a command 1 or 2 and it will change LEDS on the arduino....if the button connected to the arduino is pressed it should post: Button Pressed on the serial terminal window on the computer end. It does not...it does however if the enter button is pressed it displays Button Pressed.

        Now we're talking.

        How long is the Arduino sketch? If you can narrow it down to a reasonable size, post it here. There are people familiar with that platform who can help.

        By looking at your sketch, it should be trivial enough for someone to throw together a complete hardware test platform to simulate what you're doing, and help you figure out the problem.