perlquestion
dburke
<p>Hi guys! This is my first post, but don't spare me. :) <b>Any suggestions/comments are appreciated; the negative ones tend to be the most enlightening!</b>
I'm currently trying to make a perl script to help me handle the cycling of my aquaponics system. I have the script connect to my Arduino Uno and then issue very simple commands to have the arduino control a pump.</p>
<p>Currently, I've found I get the best results by having my script fork a process that deals with listening for incoming signals (from the arduino) over the serial connection while the main process deals with handling user input and issuing the commands to the arduino over the serial connection. I did this because the script couldn't finish what it was doing fast enough to catch the incoming data from the arduino (I think).</p>
<p>The problem that I'm having is that the output of this script has formatting issues that sometimes cut the first few characters off of a <code>print</code> function; I also occasionally get undesired non-alphabetical characters in the messages sometimes (only coming from the arduino). At first, I thought this was due to something related to the serial connection because every message from the Arduino seems to get cut, but as I've changed my script prints from the script that have nothing to do with info coming from the arduino are also getting cut. I've temporarily added a space or line break at the beginning of these messages to avoid having a bit of the messages cut off. </p>
<p> Another related issue is that the prints from the child process (that prints the incoming arduino messages) tend to alternate coming in before and after the prints from the parent. The end result of this is a bunch of confusing output like this:</p>
<code> Listening...
Please pick an option you'd like to use:
[1] Cycle [2] Relay OFF [3] Relay ON [4] Config [ ]: 1
Sent cmd: 1
Waiting for plant bed to fill...
[1] Cycle [2] Relay OFF [3] Relay ON [4] Config [1]:
From arduino: �Relay on
1
Sent cmd: 1
Waiting for plant bed to fill...
[1] Cycle [2] Relay OFF [3] Relay ON [4] Config [1]: 3
</code>
<p> OR</p>
<code>Listening...
Please pick an option you'd like to use:
[1] Cycle [2] Relay OFF [3] Relay ON [4] Config [ ]: 1
Sent cmd: 1
Waiting for plant bed to fill...
[1] Cycle [2] Relay OFF [3] Relay ON [4] Config [1]:
From arduino: Relay on
</code>
<p>So far, I'm thinking some sort of "buffer" needs to be made to deal with the order in which the messages come in or perhaps somehow make these messages print in the same spot every time to create some sort of consistency.</p>
<b>TL;DR</b>
<p>I need to figure out a way to make the "interface" or output that's created more consistent. And I'm open to exploring new ways of handling the connection to my arduino. Perhaps forking was a bad idea? I know this question is a little vague, but I'm not sure where to look for answers. Any help is greatly appreciated.</p>
<p> Below is my code and..</p>
<p><b>Thank you!</b></p>
<p> My perl script (I apologize for the poor formatting):
<code>#!/usr/bin/perl -w
# Sample Perl script to transmit number
# to Arduino then listen for the Arduino
# to echo it back
use strict;
use Device::SerialPort;
use Switch;
use Time::HiRes qw ( alarm );
# Set up the serial port
# 19200, 81N on the USB ftdi driver
my $device = '/dev/ttyACM0';
# Tomoc has to use a different tty for testing
#$device = '/dev/ttyS0';
my $port = new Device::SerialPort ($device)
or die('Unable to open connection to device');;
$port->databits(8);
$port->baudrate(19200);
$port->parity("none");
$port->stopbits(1);
my $lastChoice = ' ';
my $pid = fork();
my $signalOut;
my $args = shift(@ARGV);
# Parent must wait for child to exit before exiting itself on CTRL+C
$SIG{'INT'} = sub {
waitpid($pid,0) if $pid != 0; exit(0);
};
# What child process should do
if($pid == 0) {
# Poll to see if any data is coming in
print "\nListening...\n\n";
while (1) {
my $char = $port->lookfor();
# If we get data, then print it
if ($char) {
print "\nFrom arduino: " . $char . "\n\n";
}
}
}
# What parent process should do
else {
if ($args eq "cycle") {
$SIG{ALRM} = sub {
print "Expecting plant bed to be full; please check.\n";
$signalOut = $port->write('2'); # Signal to set pin 3 low
print "Sent cmd: 2\n";
};
$signalOut = $port->write('1'); # Signal to arduino to set pin 3 High
print "Sent cmd: 1\n";
print "Waiting for plant bed to fill...\n";
alarm (420);
die "Done.";
}
else {
sleep(1);
my $choice = ' ';
print "Please pick an option you'd like to use:\n";
while(1) {
print " [1] Cycle [2] Relay OFF [3] Relay ON [4] Config [$lastChoice]: ";
chomp($choice = <STDIN>);
switch ($choice) {
case /1/ {
$SIG{ALRM} = sub {
print "Expecting plant bed to be full; please check.\n";
$signalOut = $port->write('2'); # Signal to set pin 3 low
print "Sent cmd: 2\n";
};
$signalOut = $port->write('1'); # Signal to arduino to set pin 3 High
print "Sent cmd: 1\n";
print "Waiting for plant bed to fill...\n";
alarm (300);
$lastChoice = $choice;
}
case /2/ {
$signalOut = $port->write('2'); # Signal to set pin 3 low
print "Sent cmd: 2";
$lastChoice = $choice;
}
case /3/ {
$signalOut = $port->write('1'); # Signal to arduino to set pin 3 High
print "Sent cmd: 1";
$lastChoice = $choice;
}
case /4/ {
print "There is no configuration available yet. Please stab the developer.";
}
else { print "Please select a valid option.\n\n";}
}
}
}
}
</code></p>