Problem communicating Arduino Mega 2560 with computer using PHP

I'm trying to send instructions from the computer to the Arduino Mega 2560 through PHP and when I open the webpage the Arduino is reseted.
This is the php code:

<?php

$fp=fopen("/dev/ttyACM0", "w");
sleep(2);
fwrite($fp, "mas");
fclose($fp);

?>

Where "mas" is the instruction.

This is the way how I configure the port where Arduino is connected:

stty -F /dev/ttyACM0 cs8 9600 ignbrk -brkint -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts

The communication between the computer and the Arduino is right because Arduino receive the instruction, but I think that when 'fopen' is executed, it reset the Arduino.
I use Ubuntu as operating system, Mozilla Firefox as navigator and Xampp as virtual server.
What is the problem? How could I solve it?
What other way could I use to communicate both systems?

When you open the serial port for communication your Arduino automatically gets reset by the DTR line changing state.
You need to disable this feature to do what you wish to do.

Look at this section to learn how to do this Arduino Playground - DisablingAutoResetOnSerialConnection

I have solved it putting a 10uF capacitor between reset and GND, but I want to solve it through software.
To configure the port I have written

stty -F /dev/ttyACM0 cs8 9600 ignbrk -brkint -imaxbel -opost -onlcr -isig -icanon -iexten -echo -echoe -echok -echoctl -echoke noflsh -ixon -crtscts -hupcl

This is the easier solution which disable auto-reset, but I continue having the same problem.
Where '-hupcl' is supossed disables auto-reset (this is the easier solution told in the link you have written which disable auto-reset). But, I am wodering if Firefox sends this signal in spite of I have disabled it.
If the communication works fine through monitor serial of Arduino IDE is because is possible to avoid auto-reset through software.
In the link you have written there is another solution using PERL, but I don't know anything about this language, so I don't know how to use it.
O maybe I should do the communication through php in another way not using fopen().

Without any doubt the reset happens when fopen() is executed because the reset happens and a little bit later the variable is increased. This delay is due to the sleep() instruction.

Without any doubt the reset happens when fopen() is executed

Yes, it does. And again then fclose() is executed.

but I want to solve it through software.

You won't solve it on the Arduino side with software alone. You might solve it on the PC side by making sure that fopen() does not do whatever explicitly causes the reset, but that would affect the entire kernel, so I don't think that's a good idea.

PaulS:

Without any doubt the reset happens when fopen() is executed

Yes, it does. And again then fclose() is executed.

but I want to solve it through software.

You won't solve it on the Arduino side with software alone. You might solve it on the PC side by making sure that fopen() does not do whatever explicitly causes the reset, but that would affect the entire kernel, so I don't think that's a good idea.

My idea is solve it with software on the pc.
What could I do to communicate the pc with Arduino? I don't mind to use other language.

What could I do to communicate the pc with Arduino? I don't mind to use other language.

Typically, you'd open the serial port, letting the Arduino reset. Then, you'd read from and write to the port. When the application on the PC ends, you'd close the serial port, letting the Arduino reset.

Opening the serial port, writing one message, and closing the serial port is what is killing you.

Why did you choose PHP? Perhaps if we knew that we could suggest alternatives.

PaulS:

What could I do to communicate the pc with Arduino? I don't mind to use other language.

Typically, you'd open the serial port, letting the Arduino reset. Then, you'd read from and write to the port. When the application on the PC ends, you'd close the serial port, letting the Arduino reset.

Opening the serial port, writing one message, and closing the serial port is what is killing you.

Why did you choose PHP? Perhaps if we knew that we could suggest alternatives.

I'll try to open the port, write and read from this and close at the end.
This communication is to control a oven (change the temperature, what resistor will be on, put on and off the oven,....)
I use PHP because is the language that I know a bit.

One work around is force serial port open forever;-

cat /dev/ttyACM0

a little better revision

cat /dev/ttyACM0 > /tmp/arduino.log

u could read serial port log by nano /tmp/arduino.log

further revision

cat /dev/ttyACM0 > /dev/null

if no log is need should pipe it to no where.

final version

cat /dev/ttyACM0 > /dev/null &

By a dding the ampersand (&) to the end of any command, you can launch it in the background and get your command prompt back right away.

put it at Ubuntu init script, make it run at start up.

If u have more than one arduino connect with box, u need add udev rule to make /dev/ttyACM0 -> /dev/arduino0 , /dev/ttyACM1-> /dev/arduino1...

Hi,

Or maybe you can use php_serial.class.php class file. I used for couple project off my without any problem.

R.

rudika79:
Hi,

Or maybe you can use php_serial.class.php class file. I used for couple project off my without any problem.

R.

I am trying using this clas but I have the same problem; when i open the connection, the Arduino is reset so I am trying toopen the connection only once but I don't know how to do it. I have tried using a session, but it doesn't works.
This is the code:

 <?php
session_start();
if(isset($_GET['message'])){
	if($_GET['message'] == "iniciar")
	{
		error_reporting(E_ALL);
		ini_set('display_errors', '1');		
//		echo ($msg);
		require("php_serial.class.php");
		$_SESSION['serial'] = new phpSerial();
		$_SESSION['serial']->deviceSet("/dev/ttyACM0"); // Arduino usb-port
		$_SESSION['serial']->confBaudRate(9600);  //baud rate
		$_SESSION['serial']->confParity("none");  //Parity
		$_SESSION['serial']->confCharacterLength(8); //Character length  
		$_SESSION['serial']->confStopBits(1);  //Stop bits
		$_SESSION['serial']->confFlowControl("none");
		$_SESSION['serial']->deviceOpen(); // open connection
	}
	else if($_GET['message'] == "cerrar")
	{
		session_close();
		deviceClose();
	}
	else
	{

		$msg=$_GET['message'];

		$_SESSION['serial']->sendMessage($msg); //send the message
	}
	
}
?>
    <html><body>

    <h3>If you're running Linux: remember to give permissions to www-data to access usbport ($ sudo chmod 777 /dev/ttyACM0)</h3> 

    <a href="prueba2.php?message=mas">Send instruction "mas"</a>

    <a href="prueba2.php?message=menos">Send instruction "menos"</a>


    <a href="prueba2.php?message=iniciar">Open session</a>

    <a href="prueba2.php?message=cerrar">Close session</a>

    </body></html>

When I have oppened the session and I try to send an instruction, I get this error:

Fatal error: main(): The script tried to execute a method or access a property of an incomplete object. Please ensure that the class definition "phpSerial" of the object you are trying to operate on was loaded before unserialize() gets called or provide a __autoload() function to load the class definition in /opt/lampp/htdocs/Arduino/prueba2.php on line 28

So I think the object is destroyed when I reload the page.
I don't have any idea to solve it :(.

iceman_f5:
So I think the object is destroyed when I reload the page.
I don't have any idea to solve it :(.

You answer yourself, you need put "require("php_serial.class.php");" before you call session_start(), otherwise the object will not be deserialized correctly.

require("php_serial.class.php");
session_start();

iceman_f5:

If you're running Linux: remember to give permissions to www-data to access usbport ($ sudo chmod 777 /dev/ttyACM0)

No, No, No!!! unless you want open arduino port access for every one under the sun.

For Apache to access /dev/ttyACM0 www-data must be in the dialout or whatever group.

sudo adduser www-data dialout, restart Apache is the way to go.

BWT. did you prove your code run well without put it into session variable?

I saw your PM today, sorry and hope this answer is not too later.

sonnyyu:

iceman_f5:
So I think the object is destroyed when I reload the page.
I don't have any idea to solve it :(.

You answer yourself, you need put "require("php_serial.class.php");" before you call session_start(), otherwise the object will not be deserialized correctly.

require("php_serial.class.php");

session_start();






> iceman_f5:
> <h3>If you're running Linux: remember to give permissions to www-data to access usbport ($ sudo chmod 777 /dev/ttyACM0)</h3>



No, No, No!!! unless you want open arduino port access for every one under the sun.

For Apache to access /dev/ttyACM0 www-data must be in the dialout or whatever group.

sudo adduser www-data dialout, restart Apache is the way to go.

BWT. did you prove your code run well without put it into session variable?

I saw your PM today, sorry and hope this answer is not too later.

The way that I give permissions to access to the port, last only until I turn off the computer. So the next time that I turn on the computer, I will have to give permissions again. But that text is because was written in a example that I saw in a blog.
I don't know much about linux and PHP, so more or less I do what I see in other places or the people say here. Sometimes I don't know exactly what I am doing.
If I don't put it using session variables, I get this error:

Notice: Undefined variable: msg in /opt/lampp/htdocs/Arduino/prueba2.php on line 30

Fatal error: Call to a member function sendMessage() on a non-object in /opt/lampp/htdocs/Arduino/prueba2.php on line 30

And this is the code:

<?php
require("php_serial.class.php");
session_start();

if(isset($_GET['message'])){
	if($_GET['message'] == "iniciar")
	{
		error_reporting(E_ALL);
		ini_set('display_errors', '1');		
//		echo ($msg);
		$msg = new phpSerial();
		$msg->deviceSet("/dev/ttyACM0"); // Arduino usb-port
		$msg->confBaudRate(9600);  //baud rate
		$msg->confParity("none");  //Parity
		$msg->confCharacterLength(8); //Character length  
		$msg->confStopBits(1);  //Stop bits
		$msg->confFlowControl("none");
		$msg->deviceOpen(); // open connection
	}
	else if($_GET['message'] == "cerrar")
	{
		session_close();
		$msg->deviceClose();
	}
	else
	{

		$mensaje=$_GET['message'];

		$msg->sendMessage($mensaje); //send the message
	}
	
}
?>
    <html><body>


    <a href="prueba2.php?message=mas">Send instruction "mas"</a>

    <a href="prueba2.php?message=menos">Send instruction "menos"</a>


    <a href="prueba2.php?message=iniciar">Open session</a>

    <a href="prueba2.php?message=cerrar">Close session</a>

    </body></html>

This is because when I click on send any instruction, the page is reloaded and the object is destroyed. That is the reason because I thought of use session variables, but I think that the session variables don't save objects.

Notice: Undefined variable: msg in /opt/lampp/htdocs/Arduino/prueba2.php on line 30
Fatal error: Call to a member function sendMessage() on a non-object in /opt/lampp/htdocs/Arduino/prueba2.php on line 30

Undefined variable: msg, the $msg = new phpSerial(); never run, since it at an other if block.
break code to one inline code, remove all the session code, html link. if, else if. then test it again.

<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');
require("php_serial.class.php");
$msg = new phpSerial();
$msg->deviceSet("/dev/ttyACM0"); // Arduino usb-port
$msg->confBaudRate(9600);  //baud rate
$msg->confParity("none");  //Parity
$msg->confCharacterLength(8); //Character length  
$msg->confStopBits(1);  //Stop bits
$msg->confFlowControl("none");
$msg->deviceOpen(); // open connection
//sleep(3);
//$mensaje='mas';
$mensaje='menos';
$msg->sendMessage($mensaje);
$msg->deviceClose();
?>

So the next time that I turn on the computer, I will have to give permissions again

U might need write udev rule to persistant device node name.

sonnyyu:

Notice: Undefined variable: msg in /opt/lampp/htdocs/Arduino/prueba2.php on line 30
Fatal error: Call to a member function sendMessage() on a non-object in /opt/lampp/htdocs/Arduino/prueba2.php on line 30

Undefined variable: msg, the $msg = new phpSerial(); never run, since it at an other if block.
break code to one inline code, remove all the session code, html link. if, else if. then test it again.

<?php

error_reporting(E_ALL);
ini_set('display_errors', '1');
require("php_serial.class.php");
$msg = new phpSerial();
$msg->deviceSet("/dev/ttyACM0"); // Arduino usb-port
$msg->confBaudRate(9600);  //baud rate
$msg->confParity("none");  //Parity
$msg->confCharacterLength(8); //Character length  
$msg->confStopBits(1);  //Stop bits
$msg->confFlowControl("none");
$msg->deviceOpen(); // open connection
//sleep(3);
//$mensaje='mas';
$mensaje='menos';
$msg->sendMessage($mensaje);
$msg->deviceClose();
?>






> So the next time that I turn on the computer, I will have to give permissions again



U might need write udev rule to persistant device node name.

Using your code (activating 'sleep(3)') the program works, but with the problem that each time that I reload the page, Arduino is reseted. I need to avoid to reset Arduino each time that I send an instruction, and due to this I tried to avoid to open the connection each time that I need to send an instruction.
I think that I won't be able to do it using PHP.

3 plans, should be more;-

plan A.
cat /dev/ttyACM0 > /dev/null &
run it every time you start machine. put in init file let it auto run.

plan B.
use Arduino Leonardo, Leonardo has no reset problem.

plan C.
hardware mod, search forum and playground.

one of plan will help.

I will try to do the communication using Processing. In fact I am doing a simple interface and later I will do the communication.
I think that this will be better than PHP. Better interface and more posibilities.
Thank you for your help. Sincerely, I think I won't be able to do the communication using PHP.