Control an Arduino With PHP
Intro: Control an Arduino With PHP
Here's how to make your Arduino do things from over the internet without an ethernet or wifi shield. This is a simple way to make your project controllable from anywhere in the world!
STEP 1: Platform Compatability
This method WILL NOT work under Windows. I can't tell you how long it took me to figure that out. The command we're using, fopen() is not implemented the same way under Windows and Linux, so you have to use Linux. Never used it before? Don't panic, it's not that bad.
STEP 2: Setting Up Your Server
You'll need to get a server running PHP for this to work. I'm going to assume you have a fresh copy of Ubuntu. There are literally thousands of tutorials on how to install Ubuntu, so I'll refer you to those if you don't.
Open a terminal and type:
sudo apt-get install php5 mysql-server apache2
It will prompt you for a root MySQL password, so give it one.
Open a browser and go to http://localhost. You should see a page that says "It works!". Next run this in a terminal:
sudo gedit /var/www/info.php
And paste in this code:
<?php
phpinfo();
?>
Save and close the file, then run
sudo service apache2 restart
Go to http://localhost/info.php
and you should see a purple table with a bunch of PHP stuff. If you do, congrats! You are now running a PHP server. Next, let's set up a page to control the Arduino.
Open a terminal and type:
sudo apt-get install php5 mysql-server apache2
It will prompt you for a root MySQL password, so give it one.
Open a browser and go to http://localhost. You should see a page that says "It works!". Next run this in a terminal:
sudo gedit /var/www/info.php
And paste in this code:
<?php
phpinfo();
?>
Save and close the file, then run
sudo service apache2 restart
Go to http://localhost/info.php
and you should see a purple table with a bunch of PHP stuff. If you do, congrats! You are now running a PHP server. Next, let's set up a page to control the Arduino.
STEP 3: Touching the Serial Port in PHP
The core of this technique is the fopen() command. This is normally used for opening a document to edit within the code (like if you wrote a script to make a text file with some information in it and save it). Instead, we're going to exploit how linux views files and use it on a port. Install Arduino from the Ubuntu Software Manager. Plug in your Arduino and open the arduino window. You should see the device name under the ports menu. It will probably be /dev/ttyUSB0 or something similar. Here's some example code that will open that port as a file and write the numbers 1 to 6 based on what button is pressed:
<?php
$verz="1.0";
$comPort = "/dev/ttyUSB0"; /*change to correct com port */
if (isset($_POST["rcmd"])) {
$rcmd = $_POST["rcmd"];
switch ($rcmd) {
case Stop:
$fp =fopen($comPort, "w");
fwrite($fp, 1); /* this is the number that it will write */
fclose($fp);
break;
case Slow:
$fp =fopen($comPort, "w");
fwrite($fp, 2); /* this is the number that it will write */
fclose($fp);
break;
case Medium:
$fp =fopen($comPort, "w");
fwrite($fp, 3); /* this is the number that it will write */
fclose($fp);
break;
case Fast:
$fp =fopen($comPort, "w");
fwrite($fp, 4); /* this is the number that it will write */
fclose($fp);
break;
case Right:
$fp =fopen($comPort, "w");
fwrite($fp, 5); /* this is the number that it will write */
fclose($fp);
break;
case Left:
$fp =fopen($comPort, "w");
fwrite($fp, 6); /* this is the number that it will write */
fclose($fp);
break;
default:
die('Crap, something went wrong. The page just puked.');
}
}
?>
<html>
<body>
<center><h1>Arduino from PHP Example</h1><b>Version <?php echo $verz; ?></b></center>
<form method="post" action="<?php echo $PHP_SELF;?>">
    
<input type="submit" value="Left" name="rcmd">
          
<input type="submit" value="Right" name="rcmd"><br/>
<br />
               
<input type="submit" value="Stop" name="rcmd"><br/>
<br />
   
<input type="submit" value="Slow" name="rcmd">
<input type="submit" value="Medium" name="rcmd">
<input type="submit" value="Fast" name="rcmd">
<br />
<br />
<br />
<br />
<br />
<br />
</form>
</body>
</html>
<?php
$verz="1.0";
$comPort = "/dev/ttyUSB0"; /*change to correct com port */
if (isset($_POST["rcmd"])) {
$rcmd = $_POST["rcmd"];
switch ($rcmd) {
case Stop:
$fp =fopen($comPort, "w");
fwrite($fp, 1); /* this is the number that it will write */
fclose($fp);
break;
case Slow:
$fp =fopen($comPort, "w");
fwrite($fp, 2); /* this is the number that it will write */
fclose($fp);
break;
case Medium:
$fp =fopen($comPort, "w");
fwrite($fp, 3); /* this is the number that it will write */
fclose($fp);
break;
case Fast:
$fp =fopen($comPort, "w");
fwrite($fp, 4); /* this is the number that it will write */
fclose($fp);
break;
case Right:
$fp =fopen($comPort, "w");
fwrite($fp, 5); /* this is the number that it will write */
fclose($fp);
break;
case Left:
$fp =fopen($comPort, "w");
fwrite($fp, 6); /* this is the number that it will write */
fclose($fp);
break;
default:
die('Crap, something went wrong. The page just puked.');
}
}
?>
<html>
<body>
<center><h1>Arduino from PHP Example</h1><b>Version <?php echo $verz; ?></b></center>
<form method="post" action="<?php echo $PHP_SELF;?>">
    
<input type="submit" value="Left" name="rcmd">
          
<input type="submit" value="Right" name="rcmd"><br/>
<br />
               
<input type="submit" value="Stop" name="rcmd"><br/>
<br />
   
<input type="submit" value="Slow" name="rcmd">
<input type="submit" value="Medium" name="rcmd">
<input type="submit" value="Fast" name="rcmd">
<br />
<br />
<br />
<br />
<br />
<br />
</form>
</body>
</html>
STEP 4: How It Works & the Arduino Side
Each time a button on the page is pressed, the case statement happens and the "file" (really the port) is opened, put into write mode, a single ASCII number is written, and then it's closed. You have to close it each time or else it won't work. On the Arduino side, simply read in from the serial port using Serial.read() in the loop(). I used a big if statement to check for each ASCII number, so if 1 is sent, then do one thing, if 2 is sent, do another thing, etc. Since you're running a PHP server, you can access the page on the server from anywhere in the world and it will control the Arduino. Here's some example arduino code I used to control some motors:
#include <Servo.h>
//First, set up the servos
Servo servo1;
Servo servo2;
int debugPin = 13; // used for an led to test stuff
int motor1Pin = 9; // the first motor's port number
int motor2Pin = 10; // the second motor's port number
int usbnumber = 0; //this variable holds what we are currently reading from serial
void setup() { //call this once at the beginning
pinMode(motor1Pin, OUTPUT);
pinMode(debugPin, OUTPUT);
pinMode(motor2Pin, OUTPUT);
servo1.attach(motor1Pin,1000,2000);
servo2.attach(motor2Pin,1000,2000);
Serial.begin(9600); //start up serial port
}
void loop() { //main loop
if (Serial.available() > 0) { //if there is anything on the serial port, read it
usbnumber = Serial.read(); //store it in the usbnumber variable
}
if (usbnumber > 0) { //if we read something
if (usbnumber == 49){
servo1.write(93);
servo2.write(93);//if we read a 1, stop
analogWrite(debugPin, 0);
}
if (usbnumber == 50){
servo1.write(120);
servo2.write(120); //if we read a 2, slow
analogWrite(debugPin, 85);
}
if (usbnumber == 51){
servo1.write(150);
servo2.write(150); //if we read a 3, medium
analogWrite(debugPin, 170);
}
if (usbnumber == 52){
servo1.write(179);
servo2.write(179); //if we read a 4, fast
analogWrite(debugPin, 255);
}
if (usbnumber == 53){
servo1.write(130);
servo2.write(50); //if we read a 5, right
analogWrite(debugPin, 255);
}
if (usbnumber == 54){
servo1.write(50);
servo2.write(130); //if we read a 6, left
analogWrite(debugPin, 255);
}
}
usbnumber = 0; //reset
}
#include <Servo.h>
//First, set up the servos
Servo servo1;
Servo servo2;
int debugPin = 13; // used for an led to test stuff
int motor1Pin = 9; // the first motor's port number
int motor2Pin = 10; // the second motor's port number
int usbnumber = 0; //this variable holds what we are currently reading from serial
void setup() { //call this once at the beginning
pinMode(motor1Pin, OUTPUT);
pinMode(debugPin, OUTPUT);
pinMode(motor2Pin, OUTPUT);
servo1.attach(motor1Pin,1000,2000);
servo2.attach(motor2Pin,1000,2000);
Serial.begin(9600); //start up serial port
}
void loop() { //main loop
if (Serial.available() > 0) { //if there is anything on the serial port, read it
usbnumber = Serial.read(); //store it in the usbnumber variable
}
if (usbnumber > 0) { //if we read something
if (usbnumber == 49){
servo1.write(93);
servo2.write(93);//if we read a 1, stop
analogWrite(debugPin, 0);
}
if (usbnumber == 50){
servo1.write(120);
servo2.write(120); //if we read a 2, slow
analogWrite(debugPin, 85);
}
if (usbnumber == 51){
servo1.write(150);
servo2.write(150); //if we read a 3, medium
analogWrite(debugPin, 170);
}
if (usbnumber == 52){
servo1.write(179);
servo2.write(179); //if we read a 4, fast
analogWrite(debugPin, 255);
}
if (usbnumber == 53){
servo1.write(130);
servo2.write(50); //if we read a 5, right
analogWrite(debugPin, 255);
}
if (usbnumber == 54){
servo1.write(50);
servo2.write(130); //if we read a 6, left
analogWrite(debugPin, 255);
}
}
usbnumber = 0; //reset
}
25 Comments
francisco01 7 years ago
Thanks the post is very helpful..
albertleeabc_gmail 8 years ago
thank you for your instruction. but how can i download it?
jlester4 9 years ago
Good tutorial, but you shouldn't suggest installing services without giving proper instructions to start/stop them as well as how to prevent them from being started automatically at boot (for those who don't plan on running a dedicated HTTP service/Arduino gateway.) Also, MySQL isn't used by your tutorial. It shouldn't be included. Definitely useful for data-driven PHP sites, but that's not what your making here. Good job though!
建賴 9 years ago
Pals! My PHP code is here:
<?php
$verz="1.0";
$comPort = "/dev/ttyUSB0"; /*change to correct com port */
$led = $_POST["led"];
$fp =fopen($comPort, "w");
sleep(2);
fwrite($fp, $led); /* this is the number that it will write */
fclose($fp);
?>
<html>
<body>
<center><h1>Arduino from PHP Example</h1><b>Version <?php echo $verz; ?></b></c$
<form method="post" action="<?php echo $PHP_SELF;?>">
    
<input type="text" name="led">
<input type="submit" value="OK">
<br />
</form>
</body>
</html>
And the Arduino code is here, it lights up the LED on Pin 9 when Arduino Nano received ASCII '1' :
int motor1Pin = 9; // the first motor's port number
int usbnumber = 0; //this variable holds what we are currently reading from serial
void setup() { //call this once at the beginning
pinMode(motor1Pin, OUTPUT);
Serial.begin(9600); //start up serial port
}
void loop() { //main loop
if (Serial.available() > 0) { //if there is anything on the serial port, read it
usbnumber = Serial.read(); //store it in the usbnumber variable
}
if(usbnumber == '1')
digitalWrite(motor1Pin, HIGH);
else
digitalWrite(motor1Pin, LOW);
}
DavidR23 10 years ago
i get stack errors when I press any button
brianfit 10 years ago
Nice one. Was looking for help in writing to the serial port from a php sequence to trigger output on the Arduino, this was just the ticket. No Servos, I just needed buttons and LED response. Thanks, aloishis89!
DavidR23 10 years ago
any luck?
Ella Jameson 10 years ago
Everytime you open the serial port with $fp =fopen($comPort, "w");, you have to sleep(2); in order to allow the arduino time to boot up. It's pretty annoying, because you have to wait 2 seconds every time you send a command, but unless you can sustain the connection, you have to do that.
jelimoore 10 years ago
So I'd (like) to assume this also works under OSX, too?
SorinMS 11 years ago
I've fixed the problem.
I give Apache permission to use the serial port. I did this in terminal
with the following command:
sudo adduser www-data dialout
Once this is done, I restart Apache with the following terminal command:
sudo /etc/init.d/apache2 restart
SorinMS 11 years ago
It doesn't work for me.
marcovanbostin 11 years ago
marcovanbostin 11 years ago
Beekoz 11 years ago
And even THAT isn't working with me, I'm on Mac as well.
Mr Kokoszka 11 years ago
Apparently when there is no serial connection happening, the arduino goes to sleep and takes a while to reboot. Go here http://playground.arduino.cc/Main/DisablingAutoRes... for some solutions. I just used the capacitor going to ground.
Mr Kokoszka 11 years ago
Do I have to allow PHP permissions to do anything special? I have been working over many a code and still nothing comes out of php other than ls and simple commands.
wdipa 11 years ago
put this code-> $PHP_SELF="your file php name";
after this code
$verz="1.0";
$comPort = "com4"; /*change to correct com port */
example:
$verz="1.0";
$comPort = "com4"; /*change to correct com port */
$PHP_SELF="control.php";
Mr Kokoszka 11 years ago
Thanks for your help. I forgot I inquired about this issue. I actually got my code to work after changing some permissions on the usb device (making the specific USB port world writable). Probably not the most secure thing to do, but will also be ignoring escape characters or what not.
dmanovski 11 years ago
sss 11 years ago
thanks so much