Ashley Sheridan​.co.uk

Communicating Between PHP and an Arduino with Sockets

Posted on

Tags:

This article was originally posted on the TMW Tech Blog on the but I've amended the prose slightly here

Initially, I put this together as a way to quickly demonstrate to colleagues the socket capabilities of PHP, as it's a common misconception to believe it's not good at real time communications, and that it can only follow a request-response model. I decided that this would also make a good opportunity to work further on another project of mine; a multiplexed LED cube powered by an Arduino (which will come in a later code post!)

The first task for this was to run PHP as a daemon that would connect to the port the Arduino was listening on:

<?php $port = 'COM4'; while(true) { $fh = fopen($port, 'w'); fwrite($fh, 'a'); fclose($fh); sleep(1); }

The whole purpose of this block of code is to just output a letter 'a' once a second on the port COM4. This was just the port that the Arduino typically connects to on my work machine (Windows), and other operating systems will use different ports. The while loop just ensures this continues ad infinitum.

Some people have mentioned issues when attempting to open sockets up with fopen() on Windows. I was running this over XAMPP on a fairly vanilla setup and didn't run into any issues, but your mileage may vary.

The slightly more complicated part comes with the Arduino code, which is C++ with some additional Arduino built-in methods:

#include int pin = 13; int buffer_length = 10; String buffer; void setup() { Serial.begin(9600); pinMode(pin, OUTPUT); } void loop() { if (Serial.available() > 0) { char c = Serial.read(); // ignore the newline - not necessary if you set no line ending in the serial monitor or you communicate directly via sockets //if(c != 13) { buffer = buffer + c; Serial.println(buffer); if(buffer == "aaaaa") { digitalWrite(pin, HIGH); buffer = ""; delay(1000); } else digitalWrite(pin, LOW); if(buffer.length() > buffer_length) // don't let the buffer grow too large and cause an out of memory error! buffer = ""; } } }

The example here just checks if there is any data sitting in the serial buffer (set up when the Arduino is connected to the computer via USB) and if so, reads it, one byte for each iteration of the loop() function.

An output line is used if you're testing this with the serial monitor that is part of the Arduino IDE. You may note the commented out if condition above it which just ignores new lines. When I was testing this I just set the serial monitor to not append newline characters to the input, but you can uncomment this line if you prefer to keep the default settings when testing.

The if/else chunk simply checks to see if the built-up buffer string equals 5 letter 'a's (which will happen every 5 seconds when combined with the PHP script) and if so, it lights up the on-board LED for a second (because of the 1000 millisecond delay).

Finally, the very last part ensures that the string buffer is emptied out after 10 characters (as specified by buffer_length). This is important as the variable will continue to grow otherwise over time, and will eventually lead to an out of memory error on the Arduino when it grows too large.

Once you have this code on the Arduino then you can fire up the PHP daemon and watch it in action. If you run the PHP first, you will notice a lot of permission errors about opening up the port, because it is in use by the Arduino serial monitor. You can ignore these errors though, they are only warnings and when you close the serial monitor it will be able to open the port connection up again.