Using PHP to control the Arduino over USB (serial connection)

Hi.

I'm trying to control my Arduino via PHP but ran into a few problems.
My setup is XAMPP on Mountain Lion, the Arduino is connected via USB.

I've stripped the code down because it already fails at opening the stream.

<?php
$f = fopen("/dev/tty.usbmodem621", "w");
fclose($f);
?>

When I open that page the Arduino restarts, so there seems to be some kind of access. But the PHP page hangs until I unplug the Arduino. Then I get this error message:

Warning: fopen(/dev/tty.usbmodem621) [function.fopen]: failed to open stream: 
Device not configured in /Applications/XAMPP/xamppfiles/htdocs/index.php on line 2

While the PHP page hangs I can't connect to the Arduino with screen or the serial monitor because it is in use, so there seems to be a connection.

This is what the Arduino is running. I can connect via the serial monitor and and screen. Turning the LED on/off works, so does the echoing of unknown commands.

char incomingByte;
int led = 13;

void setup() 
{
  pinMode(led, OUTPUT);
  Serial.begin(9600);
}

void loop() 
{
  if (Serial.available() > 0) 
  {
    incomingByte = Serial.read();
    switch ( incomingByte )
    {
      case '0':
      digitalWrite(led, LOW);
      break;

      case '1':
      digitalWrite(led, HIGH);
      break;

      default:
      Serial.print(incomingByte);
    }
  }
}

Baud are fine, permissions allow reading:

~:$ stty -f /dev/tty.usbmodem621 
speed 9600 baud;
lflags: -icanon -isig -iexten -echo
iflags: -icrnl -ixon -ixany -imaxbel -brkint
oflags: -opost -onlcr -oxtabs
cflags: cs8 -parenb crtscts
~:$ ls -la /dev/tty.usbmodem621 
crw-rw-rw-  1 root  wheel   18,  68 Dec 16 14:09 /dev/tty.usbmodem621

The second problem is that I can't use stty to disable hupcl. The command runs without error but checking the flags shows me that it did not stick.

~:$ stty -f /dev/tty.usbmodem621 
speed 9600 baud;
lflags: -icanon -isig -iexten -echo
iflags: -icrnl -ixon -ixany -imaxbel -brkint
oflags: -opost -onlcr -oxtabs
cflags: cs8 -parenb crtscts
~:$ stty -f /dev/tty.usbmodem621 -hup
~:$ stty -f /dev/tty.usbmodem621 
speed 9600 baud;
lflags: -icanon -isig -iexten -echo
iflags: -icrnl -ixon -ixany -imaxbel -brkint
oflags: -opost -onlcr -oxtabs
cflags: cs8 -parenb crtscts

When I open that page the Arduino restarts, so there seems to be some kind of access.

That is the normal behavior when opening the serial port.

It resets on close, too.

PaulS:

When I open that page the Arduino restarts, so there seems to be some kind of access.

That is the normal behavior when opening the serial port.

It resets on close, too.

I'm aware of that, that's what I was trying to stop by disabling hupcl. Sorry, if I did not make myself entirely clear. I was just pointing out that the initial access works and that the problem seems to occur at a later stage.

I've stripped the code down because it already fails at opening the stream.

All that that code does is reset the Arduino twice.

There are a couple of ways to prevent the Arduino from being reset. It's more normal, though, to simply plan for that happening. Don't open and close the port every time you want to talk to the Arduino. Wait, after opening the serial port for the Arduino to reset before trying to talk to it.

That's all that I wan't the code to do for now. My problem is that it does not do that. :slight_smile:

The page does not render until I disconnect the Arduino. At that point I get the error.

If the code would work it would connect, disconnect and load the page. I would be able to connect to the Arduino again (by using screen or refreshing the page) but it won't let me do that.

That's all that I wan't the code to do for now.

You want the code to just reset the Arduino twice? I'm at a loss to understand why.

Try separating the php stuff into two separate blocks - one to open the serial port and the other to close it.

Do you have debug mode turned on in PHP?

PaulS:
You want the code to just reset the Arduino twice? I'm at a loss to understand why.

There's no point in coding read/write operations as long as I can't open the file.

<?php
$f = fopen("/dev/tty.usbmodem621", "r");
sleep(2);
if (!$f) echo 'error opening stream';
fclose($f);
?>

I have waited over a minute for the result to show up but the page does not load. When I pull the usb plug I get this:

The output:

Warning: fopen(/dev/tty.usbmodem621) [function.fopen]: failed to open stream: Device not configured in /Applications/XAMPP/xamppfiles/htdocs/index.php on line 2
error opening stream
Warning: fclose() expects parameter 1 to be resource, boolean given in /Applications/XAMPP/xamppfiles/htdocs/index.php on line 5

PaulS:
Do you have debug mode turned on in PHP?

Yes, but the two warnings and my echo is all I get.

error_reporting  =  E_ALL
display_errors = On

Maybe I'm just being really stupid here, but I would kind of expect the Arduino to reset, wait two seconds and reset again. Which should free up the connection and allow me to connect again. Something goes wrong while executing fopen.

Where do things like baud rate, parity, stop bits, etc. get set?

What happens if you remove the fclose() call? Just open the connection. Don't send anything. Don't try to close the connection.

Removing the fclose() does not change anything. Except that I get 1 less warning when I finally pull the plug.

But you are on to something with the parameters. I tried setting them just before fopen() with:

exec("stty -f /dev/tty.usbmodem621 cs8 9600 -hup ignbrk -brkint -icrnl -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts");

but that did not work. (The parameters are from: Arduino Playground - HomePage)

Opening the Arduino serial-monitor first (and keeping it open) and then calling the PHP script causes the it to terminate without errors though.

So I tried this next script with the serial-monitor open and it did turn the LED on after 2 seconds. Using the serial monitor to send and receive commands worked as well.

<?php
$f = fopen("/dev/tty.usbmodem621", "w");
sleep(2);
fwrite($f, '1');
fclose($f);
?>

The problem is that I can't get stty to change any values for me, because keeping the serial-monitor open is kind of inconvenient.