Perl – Comunicação serial com Arduino

ArduinoPythonComSerialTopo

Continuando os posts sobre comunicação serial com o Arduino utilizando varias linguagens hoje vou trabalhar com Perl, muitas pessoas não conhecem principalmente quando comento com desenvolvedores Windows :), não é meu forte em desenvolver projetos longos mas com pequenos scripts e algo que irá processar uma quantidade grande de dados ele se sai/saiu muito bem, vamos lá então…

Primeiramente o ambiente utilizado será Linux :) novidade né! Bom, para este exemplo precisaremos do Device::SerialPort como não é trivial ele vir junto vamos verificar se possuímos este Modulo.

cleiton@linuxVM:~/projetos/perl/comunicao_serial$ sudo instmodsh
Available commands are:
l - List all installed modules
m <module> - Select a module
q - Quit the program
cmd? l
Installed modules are:
DateTime::Format::Mail
Perl
cmd? q

Como é a primeira vez que nessa VM eu uso algo com Perl, eu não tenho o Device::SerialPort, então vamos instalar que pode ser feito de duas maneiras:

Primeira maneira a la estilo how-to:

cleiton@linuxVM:~/projetos/perl/comunicao_serial$ sudo apt-cache search perl | grep serial
[sudo] password for cleiton:
libjson-xs-perl - module for serializing/deserializing JSON
libanyevent-serialize-perl - serializer and deserializer for AnyEvent
libbencode-perl - Perl module for BitTorrent serialisation format
libcgi-session-serialize-yaml-perl - YAML and YAML::Syck support for CGI::Session's serializers
libdata-amf-perl - Perl module for serialize / deserialize AMF data
libdata-dump-streamer-perl - module for serializing a data structure as Perl code
libdata-serializer-perl - module that serializes data structures
libdata-streamdeserializer-perl - non-blocking deserializer
libdata-streamserializer-perl - non-blocking serializer
libdevice-serialport-perl - emulation of Win32::SerialPort for Linux/POSIX
libfreezethaw-perl - module to serialize and deserialize Perl data structures
libmoosex-storage-perl - serialization framework for Moose classes
libphp-serialization-perl - Perl module to manipulate serialized PHP data structures
libthread-serialize-perl - module to serialize data-structures between threads
cleiton@linuxVM:~/projetos/perl/comunicao_serial$
cleiton@linuxVM:~/projetos/perl/comunicao_serial$
cleiton@linuxVM:~/projetos/perl/comunicao_serial$ sudo apt-get install -f libdevice-serialport-perl

Segunda maneira e a que eu prefiro :) baixar o modulo do cpan e compilar, vamos ver :)

cleiton@linuxVM:~/projetos/perl/comunicao_serial$ wget http://search.cpan.org/CPAN/authors/id/C/CO/COOK/Device-SerialPort-1.002.tar.gz
cleiton@linuxVM:~/projetos/perl/comunicao_serial$ tar -xvzf Device-SerialPort-1.002.tar.gz ; cd Device-SerialPort-1.002
cleiton@linuxVM:~/projetos/perl/comunicao_serial$ cat README
...
cleiton@linuxVM:~/projetos/perl/comunicao_serial$ perl Makefile.PL
cleiton@linuxVM:~/projetos/perl/comunicao_serial$ make
cleiton@linuxVM:~/projetos/perl/comunicao_serial$ sudo make install

O procedimento acima para construir o modulo pode ser visulizado no arquivo README, onde peguei as informações sobre compilar e instalar o modulo mas ocultei aqui a saída, sobre o make test no meu deu alguns erros porque ele usou o ttyS1 e o meu ftdi esta usando ttyS2 mas enfim, nesta etapa não importaria e atenção ao usar sudo make install ou usar permissão de super-usuário para instalar o modulo, e vamos ver novamente se o modulo esta instalado agora.

cleiton@linuxVM:~/projetos/perl/comunicao_serial$ instmodsh
Available commands are:
l - List all installed modules
m <module> - Select a module
q - Quit the program
cmd? l
Installed modules are:
DateTime::Format::Mail
Device::SerialPort
Perl
cmd? q

Mas no nosso script Perl também tem uma etapa que irá checar se o modulo esta OK, caso a mensagem “Device::SerialPort nao encontrado!” for exibida ao executar o script verifique os passos acima pois o modulo não foi encontrado.

Vamos ao nosso código agora:

#!/usr/bin/perl

use strict;
use warnings;

die "Device::SerialPort nao encontrado!" unless(eval{require Device::SerialPort});
use Device::SerialPort;

my ($device, $baudrate, $send_write) = @ARGV;

my $portcom = Device::SerialPort->new($device);

#9600, 8, 1, N do meu FTDI para o Arduino
$portcom->baudrate($baudrate); # you may change this value
$portcom->databits(8); # but not this and the two following
$portcom->parity("none");
$portcom->stopbits(1);

$portcom->read_const_time(1000); # 1 segundo para leitura
while (1) {
# Esse tem varias definicoes e tarefas em outras combinações mas o foco é limpar buffer
$portcom->lookclear;

# Esse acho que sem misterio, vai escrever na serial meu terceiro parametro enviado
$portcom->write($send_write);

# $count => numero de caracteres (bytes)
# $data => meu dado que chegou, ou nao
# read(10) => Quantos bytes irei ler
my ($count,$data) = $portcom->read(10);

# Se o que foi recebido é maior que 0 ou nosso dado diferente de ""
# Tem uns macete com os amigos read_interval(), read_char_time(), read_const_time(),
# read_interval(), write_char_time(), write_const_time()
if ($count > 0 or $data ne "") {
print "nTotal caracteres recebidos: $countn";
print "Dado recebido: $data";
print "Temperatura: $datan";
print "----------------------------------n";
}
else {
print "n########################################nAguardando recebimento dos dados...n########################################n";
next;
}
sleep(5);
}

Vamos testar nosso código, meu device USB é /dev/ttyS2, meu baudrate 9600 e o caractere a ser enviado é o ‘t’:

cleiton@linuxVM:~/projetos/perl/comunicao_serial$ perl perl_com_arduino.pl /dev/ttyS2 9600 t

########################################
Aguardando recebimento dos dados...
########################################

########################################
Aguardando recebimento dos dados...
########################################

Total caracteres recebidos: 7
Dado recebido: 27.86
Temperatura: 27.86

----------------------------------

Total caracteres recebidos: 7
Dado recebido: 27.37
Temperatura: 27.37

----------------------------------

A tela acima esta funcionando como previsto, caso você ver algo como abaixo:

Use of uninitialized value $nameOrConf in -f at /usr/local/lib/perl/5.12.4/Device/SerialPort.pm line 286.
Use of uninitialized value in subroutine entry at /usr/local/lib/perl/5.12.4/Device/SerialPort.pm line 312.
Can't call method "baudrate" on an undefined value at perl_com_arduino.pl line 17.
cleiton@linuxVM:~/projetos/perl/comunicao_serial$

Provavelmente o /dev/ttyS2 não é o correto, substitua pelo correto do seu device, agora caso o baudrate ou o carácter a ser enviado estiver incorreto a mensagem “Aguardando recebimento dos dados…” ficara aparecendo direto, além do mais o firmware que estou usando para o Arduino é o clássico default para todos desta serie de comunicação serial, caso precisar aqui esta o link.

Não abordei aqui a linguagem em Perl em si, o foco foi trabalhar comunicação serial com ela, então a parte de repetição, condicional, argumentos, variáveis e declarações eu abstrai, mas uma pesquisa rápida no google deve resolver, não sou um desenvolvedor Perl Expert mas sempre digo que Perl é linguagem de macho, não é tão amigável iniciar e tem umas particularidades punk.

Não se limite a apenas as funções passadas, é o básico para funcionar, mas o modulo é extenso e possui N possibilidades e recursos para ajudar.

Bom pessoal, fico por aqui espero ter ajudado com mais esta etapa e até a próxima!

Referências

http://search.cpan.org/~cook/Device-SerialPort-1.002/SerialPort.pm
http://playground.arduino.cc/Interfacing/PERL

Share Button

CC BY-NC-SA 4.0 Perl – Comunicação serial com Arduino by Cleiton Bueno is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.