Perl Interfacing

I'm trying to interface an Arduino Duemilanov with a perl script running on my Windows machine. I've sucessfully tested the functionality on the Arduino's end of things via putty, but I can't get my perl script to do anything.

When I push "R" in putty, my arduino's red lights turn on. This perl script, when run, does nothing.

COM7 is the correct port.

#!/usr/bin/perl

use strict;
use warnings;
use Win32::SerialPort qw( :STAT 0.19 );

my $port = Win32::SerialPort->new("COM7");
$port->databits(8);
$port->baudrate(9600);
$port->parity("none");
$port->stopbits(1);

my $var="R";

my $return=$port->write("$var");

print "Returned: $return\n";

Any clues would be greatly appreciated!

Ummm....do you need quotes in [my $return=$port->write("$var");]? Won't that literally print "$var" out the serial port?

I don't need quotes, but I still don't get any results when I plug the R directly in there, bypassing the variable all together..

If you use a variable in a perl double-quoted string it will give that variables value. Single quotes would be more problematic.

What are you expecting, and what are you actually getting? The write() method only returns the number of bytes sent. Does it print '1', '0', or does it hang forever, doing nothing?

!c

I get a 1, and a serial port monitor does show the R being sent. The arduino just doesn't respond like it does when I type an R in putty or the Arduino IDE.

Any way you can get the arduino to print back to serial what it receives?

I have a feeling there may some issues with the Win32API::CommPort module, as when I try it, and run it in debugging mode, it doesn't let me change the baudrate of the connection - debugging shows it to always be 2400, no matter what I set it to.

Try adding:
print "DBG: " . $port->baudrate() . "\n";

And make sure it says 9600.

!c

Good catch. I'm getting a baud rate of 1200 returned instead of the 9600 I'm setting it to. I've checked in device manager and the system has the baud rate set to 9600. Any idea how to get perl to use the right baud rate?

I got the baud rate to set by adding a line $port->write_settings();

The debug line now shows the correct baudrate. I added checks for the databits, parity, and stopbits which all are as I set them.

The arduino still isn't responding to the write() command like it should, the lights aren't turning on.

The only thing I can see that might be missing is initialize() -- the following works fine for me:

# read/write serial port win32

use strict;
use warnings;

$| = 1;

use Win32::SerialPort qw( :STAT 0.19 );

my $port = Win32::SerialPort->new('COM8');


if( ! defined($port) ) {
      die("Can't open COM8: $^E\n"); 
}


$port->initialize();

$port->baudrate(19200);
$port->parity('none');
$port->databits(8);
$port->stopbits(1);

$port->write_settings();

      # send the char "R"
print $port->write("R");

$port->close();

exit(0);

Have you checked your arduino code?

!c

I'm baffled by this.

I added in the initialize call and re-ordered my settings to match yours. Initially that yielded 0 results.

Thinking of the earlier comment to print out what the Arduino recieved, I added in a Serial.println(cmd) to my Arduino code and sent that up. Everything started work.

I then added another function to my code, triggered on the letter S, and everything stopped working :frowning:

Everything works consistently when I use Putty or the Arduino IDE. Its perl that seems to have issues. I'm debating switching to ubuntu to see if that works better...

This is the new test arduino code, it should turn the lights on when any input it received. Sending anything in putty/Arduino IDE results in the lights turning on. Sending anything via perl in Windows and Linux have no result.

#define REDLIGHTS 4

void setup() {
   Serial.begin(9600); // open serial
   pinMode(REDLIGHTS,OUTPUT);
}

void loop() {
  int cmd = 0;
  
 if (Serial.available() > 0) {
  // read the incoming byte:
  cmd = Serial.read();

  // say what you got:
  Serial.print("I received: ");
  Serial.println(cmd, DEC);
  digitalWrite(REDLIGHTS, HIGH);
  }
}

Try adding a delay(100); in your Arduino code

I believe this works on Linux :slight_smile:

#!/usr/bin/perl

use Device::SerialPort;

my $port = Device::SerialPort->new("/dev/ttyUSB0");
$port->databits(8);
$port->baudrate(9600);
$port->parity("none");
$port->stopbits(1);

my $var="testing...";

my $return=$port->write("$var");
void setup()
{
  Serial.begin(9600);
}


void loop()
{

  if (Serial.available()) {
  delay(100);
  lcd.clear();
  lcd.write(Serial.read());
 }
 }
}

Hmm, I don't see any obvious reason as to why you're having problems, as it works great for me w/ my code, however, I'm not doing a pinmode change, just sending something back and reading it in the perl code...

Take, for example:

void loop() {

 if( Serial.available() > 0 ) {
     char foo = Serial.read();
     Serial.println("Got Serial: ");
     Serial.println(foo, BYTE);
 }
}

Mated with this perl code:

# read/write serial port win32

use strict;
use warnings;

$| = 1;

use Win32::SerialPort qw( :STAT 0.19 );

my $port = Win32::SerialPort->new('COM8');


if( ! defined($port) ) {
      die("Can't open COM8: $^E\n"); 
}


$port->initialize();

$port->baudrate(19200);
$port->parity('none');
$port->databits(8);
$port->stopbits(1);

$port->write_settings();

      # send the char "R"
print $port->write("R") . "\n";


      # read data coming from it

my $total_lines = 0;

while($total_lines < 1) {

  my $gotit = "";
  my $match1 = "";

  while ( $gotit eq '' ) {
      $gotit = $port->lookfor();

      if( ! defined($gotit) ) {
            die("No data result\n");
      }

       print "$gotit";

  }

  print "\n";
  $total_lines++;
}

$port->close();

Results in:

J:\>perl qwk.pl
1
Got Serial: R

Do you have putty/whatever open at the same time you run the script? Windows may be having issues with having two things attached to the serial port, I know that the buggy Win32API::CommPort code keeps crashing like crazy on my XP box, and while it's in 'crash mode', no other perl script can access the port, but hyperterminal and such can.

!c

Like drone I don't see anything wrong either, but who knows

I must say I like Device::SerialPort on Linux better :slight_smile:

I've used it to write to my LCDs, controlled my servos with it and used it to read and write to and from various MCUs, so far it has worked perfectly :slight_smile:

I think Ubuntu with Device::SerialPort should work better for you :slight_smile:

I'll give those both a try later today when I get back to my desktop.

Cool :slight_smile:

Fedora + Device::SerialPort and CentOS + Device::SerialPort work great too :slight_smile:

Keep us posted :slight_smile:

Well, I'm still stuck here. I've tried Win32 and Ubuntu (VMWare'ed, the USB is disconnected from Windows but attached in Ubuntu). Here's what I'm using for code:

Arduino:

void setup() {
   Serial.begin(9600); // open serial
   pinMode(4, OUTPUT);
}

void loop() {

 if( Serial.available()) {
     delay(100);
     char foo = Serial.read();
     Serial.println("Got Serial: ");
     Serial.println(foo, BYTE);
     digitalWrite(4, HIGH);
 }
}

And the Perl:

# read/write serial port win32

use strict;
use warnings;

$| = 1;

use Win32::SerialPort qw( :STAT 0.19 );

my $port = Win32::SerialPort->new('COM7');


if( ! defined($port) ) {
      die("Can't open COM7: $^E\n");
}


$port->initialize();

$port->baudrate(9600);
$port->parity('none');
$port->databits(8);
$port->stopbits(1);

$port->write_settings();

      # send the char "R"
print $port->write("R");

$port->close();

exit(0);

Of course in Ubuntu I change the Win32 to Device, and the COM7 to /dev/ttyUSB0

I think I'm going to start looking at the network serial port, maybe I can have more luck with that.

Windows may still be screwing with your serial ports in a VM

Power windows down

Change your BIOS to boot from CD

Boot from the Ubuntu live CD

Applications => Accessories => Terminal

sudo su -

perl -MCPAN -e shell

cpan> install Device::SerialPort

and give it a try :slight_smile:

Hello,

If you got problems by using your comport, chance your com to a lower port. By installing the arduino the port that was installed was com15 i change that to com2. Next i tried again and the interfacing with perl worked perfect under win32!!

Greetings,

Christian

C:\htdocs\public_html>perl arduino.cgi
SEND --! UTOH5UAZJD
RECV !-- UTOH5UAZJD (Time: 0.021213 Seconds)
SEND --! 9PNPSTNI2B
RECV !-- 9PNPSTNI2B (Time: 0.027334 Seconds)
SEND --! 4FXYNIJHCV
RECV !-- 4FXYNIJHCV (Time: 0.021914 Seconds)
SEND --! SJA7IBBPXQ
RECV !-- SJA7IBBPXQ (Time: 0.026025 Seconds)
SEND --! 227UOIQ3ZB
RECV !-- 227UOIQ3ZB (Time: 0.025867 Seconds)
SEND --! CROG7LBHBZ
RECV !-- CROG7LBHBZ (Time: 0.02321 Seconds)
SEND --! SWMCJOIDVC
RECV !-- SWMCJOIDVC (Time: 0.015827 Seconds)
SEND --! JYBDRN71QE
RECV !-- JYBDRN71QE (Time: 0.022437 Seconds)
SEND --! SUZFSBBOUF
RECV !-- SUZFSBBOUF (Time: 0.0127 Seconds)
Terminating on signal SIGINT(2)

C:\htdocs\public_html>

I think I figured it out.

I needed a sleep(5) in my perl code to give the Arduino time to initialize or something. I would have never noticed this in Putty because there was always a very short delay from when I open the connection and then start sending data

Using Win32::SerialPort, after I do my port->write_settings() I sleep() the script for a few seconds and they continue on.

I don't know why I need to do this, but it works!