Project Communications Object

Introduction

A communication object is used by the control program to communicate with the Arduino.

Create the file communications.pm with the code in it.

Note: See the test programs for an example of using a communication object.

Perl Code

package communications;
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Object methods:
# new           create a new object
# toString      return a string version of the object data   
# open          open a connection to a port 
# close         close a connection to a port
#               object is not destroyed and may be re-used
# sentMessage   send a message (string)
# receiveReply  receive reply messages (strings)
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

use strict;
use warnings;

require Win32::SerialPort;

# -------------------------------------------------------------------
# constructor
# ------------------------------------------------------------------- 

sub new
{
   my ($class) = @_;
   my ($self) = { _port     => undef,
                  _portname => undef,
                  _baudrate => undef };
   bless($self,$class);
   return $self;
}

# -------------------------------------------------------------------
# convert object to string
# ------------------------------------------------------------------- 

sub toString
{
   my ($self) = @_;

   my $str = "";

   if (!defined($self->{_port}))
   {
      $str="Port not defined";
      return $str;
   }

   $str = "Port is open\n" . 
          "Port name " . $self->{_portname} . "\n" .
          "Baudrate " . $self->{_baudrate};

   return $str;
}

# -------------------------------------------------------------------
# open port connection
# ------------------------------------------------------------------- 

sub open
{
   my ($self,$portname,$baudrate) = @_;

   # is the port already open?

   my @reply = ();

   if (defined($self->{_port}))
   {
      $reply[0] = "Connection already open";
      return (0,\@reply);
   }

   # open port connection

   my $port;
   my $quite = 1;

   if (!($port = Win32::SerialPort->new($portname,$quite)))
   {
      $reply[0] = "Can not open port ($portname)";
      $reply[1] = $^E;
      return (0,\@reply); 
   }

   # save the port information

   $self->{_port}     = $port;
   $self->{_portname} = $portname;
   $self->{_baudrate} = $baudrate;


   # -- for debugging --------------------------------------------------
   # prints hardware messages like "Framing Error"
   # $self->{_port}->error_msg(1);
   # prints function messages like "Waiting for CTS"
   # $self->{_port}->user_msg(1);   
   # ------------------------------------------------------------------- 

   $self->{_port}->initialize();
   $self->{_port}->databits(8);
   $self->{_port}->baudrate($self->{_baudrate});
   $self->{_port}->parity("none");
   $self->{_port}->stopbits(1);
   $self->{_port}->debug(0);
   $self->{_port}->are_match("\r\n");

   $reply[0] = "Connected to port ($portname)";
   return (1,\@reply);
}

# ----------------------------------------------------------------
# close port connection
# ----------------------------------------------------------------

sub close
{
  my ($self) = @_;
  if (!defined($self->{_port})) { return 1; }
  $self->{_port}->close();
  $self->{_port}     = undef;
  $self->{_portname} = undef;
  $self->{_baudrate} = undef;
  my @reply = ("Connection closed");
  return (1,\@reply);
}

# ----------------------------------------------------------------
# send message
# ----------------------------------------------------------------

sub sendMessage
{
   my ($self,$msg) = @_;

   if (! defined($self->{_port}))
   {
      my @reply = ("Connection not open");
      return (0,\@reply);
   }

   my $l = length($msg);       # length of message 

   $self->{_port}->lookclear;  # empty buffer

   my $c = $self->{_port}->write($msg); # write message,
                                        # get characters sent count

   if ($c == 0)
   {
      my @reply = ("write failed - no characters sent");
      return (0,\@reply);
   }
   elsif ($c != $l)
   {
      my @reply = ("Write incomplete (sent=$c) (msglength=$l)");
      return (0,\@reply);
   }

   my @reply = ("Write complete (sent=$c)");
   return (1,\@reply);
}

# ----------------------------------------------------------------
# receive reply messages
# ----------------------------------------------------------------

sub receiveReply
{
   my ($self) = @_;

   my @reply = ();             # array to collect reply messages

   if (! defined($self->{_port}))
   {
      $reply[0] = "Connection not open";
      return (0,\@reply);
   }

   $self->{_port}->lookclear;  # empty buffer

   my $msg;                    # reply message

   while(1)
   {
      # poll looking for data

      $msg = $self->{_port}->lookfor();

      # if we get data, save it

      if ($msg) { push(@reply,$msg); }

      # last reply messages?

      if ($msg =~ /^x/) { return (1,\@reply); }
   }     

   unshift(@reply,'Received reply terminated early. ' .
                  'Did not receive "x" message.');

   return (0,\@reply);
}

1;