User avatar
emgi
Posts: 357
Joined: Thu Nov 07, 2013 4:08 pm
Location: NL

Arduino Serial with Perl

Sat May 13, 2017 8:46 am

Whenever you search for serial comms between the raspberry pi and Arduino, you are inescapably confronted with python
As a longtime Perl-adept I was not satisfied with this. There is a serial port module for Perl but I found it difficult to work with.
Nevertheless I managed to make something that works for my scenario and I'm happy to share it, also in the hope that there is someone who can pinpoint the mistake(s) I may have made.

The perl code sends out a one letter starting code to the Arduino ('Q') and the Arduino responds with the value of analog inputs A0 and A1. Reading was a fairly easy task, I got that working quickly with a script called 'getArduino.pl'. URL http://tardus.net/readNano.html
However, this script implements reading a continuous stream of data. I wanted the Pi to trigger the transfer by sending a string.
Initially I had no success at all but eventually it turned out that you need to build in some delay in order for the program to work properly. That's not really my way of programming, I'd rather have the code in a wait-loop for something to happen but in this case it appeared to work only with the delay. This is the code:

Code: Select all

#!/usr/bin/perl -w

# readUNO.pl
# v1.1 emgi May2017

use strict;
use Device::SerialPort;
use Time::HiRes qw( usleep);

my $PT = "/dev/ttyUSB0";
my $port = new Device::SerialPort ($PT) || die "Can't open $PT: $!\n";

$port->baudrate(9600);
$port->databits(8);
$port->parity("none");
$port->stopbits(1);
$port->handshake("none");
$port->write_settings;

my $count;
my $outstring='Q';
my $reply='';
my $blockingflags = 0;
my $inbytes = 0;
my $outbytes = 0;
my $errflags = 0;
my $sent=0;

do {
$outbytes = $port->write($outstring); $sent++;
($blockingflags, $inbytes, $outbytes, $errflags) = $port->status;
#print "in: $inbytes, out: $outbytes\n";
($count,$reply) = $port->read($inbytes);
usleep (60000);
} until ($count);

my $total=$sent*60;
print "Time: $total ms\n";

my $dummy;
my $A0;
my $A1;

my ($line1,$line2)=split /\n/, $reply;
($dummy, $A0)=split / /,$line1;
($dummy, $A1)=split / /,$line2;

print "A0: $A0\n";
print "A1: $A1\n";
The biggest issue is that the serial write appears to be unreliable; the code I have now keeps sending the starting code every 60ms but it takes a many attempts before the Arduino actually receives it. When used without delay, it doesn't even work at all.
Another essential line is the call to $port->status. It doesn't accomplish anything but when I leave it out the code stops working.

As it is, it works and a call typically takes 660ms. I'm sure you can adapt this to read any port from the Arduino and as such it can be a useful piece of software. Anybody who knows how to fix the ureliable write is welcome to let me know!
I have attached the Arduino script in a file.
Attachments
sertopi01.zip
(423 Bytes) Downloaded 65 times

Return to “Other programming languages”