Perl communication to Arduino over serial USB

I recently switched from using plain Atmel chips to Arduino. Arduino is a development platform that uses an Atmel Atmege168 chip. It simplifies things a lot.

The Arduino board has a USB port. It has a built in FTDI chip for USB to serial conversions.

This HOWTO shows how to communicate between Perl/Linux and the Arduino. Because of the Arduinos FTDI chip, I can use regular serial communication, I just needed to first set up the USB serial adapter drivers. Most modern linux distro should come with them installed.

The perl script will transmit a number, starting at 0, to the Arduino. The Arduino will then echo that number back to your linux/perl computer.

# Sample Perl script to transmit number
# to Arduino then listen for the Arduino
# to echo it back

use Device::SerialPort;

# Set up the serial port
# 19200, 81N on the USB ftdi driver
my $port = Device::SerialPort->new("/dev/ttyUSB0");
$port->databits(8);
$port->baudrate(19200);
$port->parity("none");
$port->stopbits(1);

my $count = 0;
while (1) {
    # Poll to see if any data is coming in
    my $char = $port->lookfor();

    # If we get data, then print it
    # Send a number to the arduino
    if ($char) {
        print "Recieved character: " . $char . " \n";
    } else {
        sleep(1);
        $count++;
        my $count_out = $port->write("$count\n");
        print "Sent     character: $count \n";
    }
}

Sample C program for Arduino. Listen for input on serial port then echos the input back out.

#include 
#include 

char incomingByte;              // for incoming serial data
char str1[50];
int count = 0;

void
setup ()
{
  beginSerial (19200);
  digitalWrite (13, HIGH);      //turn on debugging LED
}


//  MAIN CODE
void
loop ()
{
  // send data only when you receive data:
  if (Serial.available () > 0)
    {
      // read the incoming byte:
      incomingByte = Serial.read ();

      // Store it in a character array
      str1[count] = incomingByte;
      count++;

      // check if we have over 49 characaters or we recieve a return or line feed
      if (count > 49 || incomingByte == 10 || incomingByte == 13)
        {
          // Send the string back
          Serial.print (str1);
          count = 0;
        }
    }
}

Comments

neirons:

Hi,
i had tested that code snippet and result is OK.
For me, user Linux, the big good luck to find some decision in research of new ways in world AVR

Andrew:

I have uploaded the code above to both my PC and Arduino device, i am able to communicate to and from the Arduino device after uploading the code, however if i was to turn off the Arduino device and switch it back on (by unpluging the power) then attempt to send the same infomation to the Arduino device the RX light flashs however the TX light does not, and on the screen once the code has compleated reads Sent character: 0 - 10, however there are no recived characters. I have checked the board rate and it only gets set after the Arduino software uploads the program to my controller. Can anyone help me?

lennart:

Just to sure: you are communicating between the arduino and the pc over usb? You are communicating over the usb wire like it's a serial cable?

chad:

The arduino has a built in usb to serial converter. Linux, and windows, have drivers to treat usb ports as serial ports. So to Perl, it looks like you are just talking over a normal serial connection. All the conversion from USB to serial is done by the FTDI chip that is built into the arduino.

So to answer your question, yes I am connection over the usb wire like it is a serial cable.

Roland Latour:

If you load your Diecimila with Simple Message System,
available from the archives at arduino.cc, you can
communicate with the unit using my package of shell
scripts. Run 'wget http://207.14.167.161/SMS1.tgz'
to get the tarfile. Not 24/7, it only works
when my PC is booted, so keep trying. Or email
rolandl@cavenet.com and ask for a copy.

Full IO and PWM control. AD is scaled to milliVolts
and formatted for import to most spreadsheets. I have
not tried these scripts under Mac OS/X but I see no
reason why they wouldn't work there as well.

blacklocist:

This is great. I learned a couple things looking over your Ardruino C code. Thanks for putting this on the web.

sameer:

we tried to run ur first program, it gives the following error msg:

Can't locate Device/SerialPort.pm in @INC (@INC contains: c:\PROGRA~1\orient\Asia\PerlEnv C:/Perl/lib C:/Perl/site/lib .) at usb.pl line 5.
BEGIN failed--compilation aborted at usb.pl line 5.

Can you please help us

TIA

chad:

It looks like you don't have Device::SerialPort installed. It looks like you are running windows. Device::SerialPort is a linux only module. Try installed the perl module Win32::SerialPort. Then change all reference of Device::SerialPort to Win32::SerialPort. That should work.

thanks
chad

Anonymous:

You also need to change "/dev/ttyUSB0" to "COM4", or whatever COM your Arduino is hooked up to.

Anonymous:

Any way to use this as the "standard" input? I want the output from my Arduino to be treated as if it were just characters typed on a keyboard that would be entered into whatever program happens to be running? I am using Ubuntu.
But, an XP and Mac answer would be great too.

Rolad:

See my shellscript package at user.cavenet.com/rolandl for
proof of concept on this. Basics: you need a helper process
to catch the output (after the usual stty command), like this:
cat /dev/ttyUSB0 >> logfile1.raw &
When you unplug the unit, the node goes away and this process is terminated. Then 'tail -1 logfile1.raw' puts the response on stdout for further processing. My script package was developed on Kubuntu, includes GUI via xdialog and/or kdialog.
AD scaled to mV, formatted for import to most spreadsheets.
I am using reed relays connected directly to the IO pins: elexp.com 22RD5, 5v/500ohm coils. Package is SMS1.tgz, written for use with SimpleMessageSystem, from archives at arduino.cc

chad:

The arduino talks to your PC over a serial connection. So you have to have some program to catch/read that serial data. By default, a print statement in perl goes to standard out. So the program above will read in the arduino output and send it to standard out.

Post new comment

The content of this field is kept private and will not be shown publicly.
CAPTCHA
This question is used to make sure you are a human visitor and to prevent spam submissions.
Image CAPTCHA
Enter the characters shown in the image.