15

I wonder if there is a way to accomplish reading my serial port via PHP - that works :-)

In practising my Arduino skills, I developed a simple LED ON/OFF sketch. It works by entering on or off in the serial monitor.

Next step, I put together a webpage to act as an GUI interface to click a link and perform the on and off function above. This webbased GUI works via PHP. I am using the PHP SERIAL class to interact with the serial port my Arduino is using.

The issue is I need to find a way of getting feedback from the serial port. Using the Arduino IDE serial monitor, I can see my printed messages in response to each of my serial input and I need to retrieve the same feedback in my PHP code.

The PHP Serial class offers a readPort() function but I does not return my data.

UPDATE[2]:

ARDUINO:

const int greenPin = 2;
const int bluePin = 3;
const int redPin = 4;

int currentPin = 0; //current pin to be faded
int brightness = 0; //current brightness level

void setup(){
  Serial.begin(9600);

  pinMode(greenPin, OUTPUT);
  pinMode(bluePin, OUTPUT);
  pinMode(redPin, OUTPUT);
}

void loop(){
  //if there's any serial data in the buffer, read a byte
  if( Serial.available() > 0 ){
    int inByte = Serial.read();

      //respond only to the values 'r', 'g', 'b', or '0' through '9'
      if(inByte == 'r')
        currentPin = redPin;

      if(inByte == 'g')
        currentPin = greenPin;

      if(inByte == 'b')
        currentPin = bluePin;

      if(inByte >= '0' && inByte <= '9'){
        //map the incoming byte value to the range of the analogRead() command
        brightness = map(inByte, '0', '9', 0, 255);
        //set the current pin to the current brightness:
        analogWrite(currentPin, brightness);
      }

      Serial.print("Current Pin : ");
      Serial.println(currentPin);

      Serial.print("Brightness : ");
      Serial.println(brightness);

  }//close serial check

}

PHP/HTML:

<?php
    require("php_serial.class.php");
// include("php_serial.class.php");

    // Let's start the class
    $serial = new phpSerial();

    // First we must specify the device. This works on both Linux and Windows (if
    // your Linux serial device is /dev/ttyS0 for COM1, etc.)
    $serial->deviceSet("/dev/ttyACM0");

    // Set for 9600-8-N-1 (no flow control)
    $serial->confBaudRate(9600); //Baud rate: 9600
    $serial->confParity("none");  //Parity (this is the "N" in "8-N-1")
    $serial->confCharacterLength(8); //Character length     (this is the "8" in "8-N-1")
    $serial->confStopBits(1);  //Stop bits (this is the "1" in "8-N-1")
    $serial->confFlowControl("none");

    // Then we need to open it
    $serial->deviceOpen();

    // Read data
    $read = $serial->readPort();
print "<pre>";
print_r($read);
print "</pre>";

    // Print out the data
    echo $read;
        // print exec("echo 'r9g9b9' > /dev/ttyACM0");
    print "RESPONSE(1): {$read}<br><br>";

    // If you want to change the configuration, the device must be closed.
    $serial->deviceClose();
?>

<?php
    if( isset($_REQUEST['LED']) )
        response();
?>

<form action='index.php' method='POST'>
    <select id='led' name='LED'>
        <option id='nil'>-</option>
        <option id='red'>RED</option>
        <option id='green'>GREEN</option>
        <option id='blue'>BLUE</option>
        <option id='all'>ALL</option>
    </select>
    <input type='submit' value='SET'>
</form>

<?php
    print "Hi, Earthlings!";

    function response(){
        $CMDString = "";
        $execute   = false;

        if( isset($_REQUEST['LED']) ){
                switch ($_REQUEST['LED']) {
                    case 'RED':
                        $CMDString = 'r9';
                        $execute = true;

        exec("echo 'r9g0b0' > /dev/ttyACM0");

                print "<br>FOUND: {$_REQUEST['LED']}";
                        break;
                    case 'GREEN':
                        $CMDString = 'g9';
                        $execute = true;
                print "<br>FOUND: {$_REQUEST['LED']}";
                        break;
                    case 'BLUE':
                        $CMDString = 'b9';
                        $execute = true;
                print "<br>FOUND: {$_REQUEST['LED']}";
                        break;
                    case 'ALL':
                        $CMDString = 'r9g9b9';
                        $execute = true;
                print "<br>FOUND: {$_REQUEST['LED']}";
                        break;
                    default:
                        print exec("echo 'r0g0b0' > /dev/ttyACM0");
                        $execute = false;
                        break;
                }

                if($execute){
                    print exec("echo '{$CMDString}' > /dev/ttyACM0");
                    print "<br><br>executing: {$CMDString}";
                }
        }
    }
?>
sisko
  • 9,604
  • 20
  • 67
  • 139

3 Answers3

14

I assume you work on linux.

First setup your serial port:

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

Then you can use good old fashion fread/fwrite

$fp =fopen("/dev/ttyACM0", "w+");
if( !$fp) {
        echo "Error";die();
}

fwrite($fp, $_SERVER['argv'][1] . 0x00);
echo fread($fp, 10);

fclose($fp);

There is only one thing you have to remember. Arduino will restart on every connection. If you don't know that It will confuse you. For instance if you connect (fopen) and instantly send data Arduino will miss it because it's booting (which takes a sec or two). Experiment with sleep to give it some time. If you want to disable restarting use 10uF capacitor from GRD to RST.

Good luck

ps. you can troubleshoot with "screen"

screen /dev/ttyACM0 9600

Post about setting PHP with Arduino http://systemsarchitect.net/connecting-php-with-arduino-via-serial-port-on-linux/ and one more here http://systemsarchitect.net/arduino-and-php-serial-communication-with-a-protocol/.

Lukasz Kujawa
  • 3,026
  • 1
  • 28
  • 43
  • Thank you for your very helpful comments. I have successfully applied a 10uF capacitor to my setup. So I no longer need to have the Arduino serial monitor open. I can now just use a web interface to control my RGB-LED experiment. The only issue is I still do not get any return statements from my Aduino code I:E in the serial monitor I have confirmation statements like "RED ON". In my web interface I an not getting this very important data. I executed your stty command successfully but it made no difference. Can you please give me some more help? – sisko Jan 30 '13 at 23:07
  • Could you paste your code for Arduino and PHP? Ot's hard to tell without it. – Lukasz Kujawa Jan 31 '13 at 16:17
  • Hi Lukasz, I have updated my question with the latest PHP/HTML code and included my Arduino sketch. The PHP includes the PHP_Serial class downloadable from the link in my question. – sisko Jan 31 '13 at 22:16
  • I see you only ready Arduino output on the beginning of your script. Is there anything in $read variable? From Arduino code I can understand you have to send 2 bytes first to get any output. I don't know the library you are using. You can use simple fopen(), read() and wrtie(). – Lukasz Kujawa Jan 31 '13 at 23:19
  • Hi Lukasz, your ongoing help has been invaluable and is very appreciated. I am marking your answer correct but I will appreciate more help with yet more complications I am experiencing. Your strategy of opening and reading the port works but only intermittently i.e : it works sometimes but the majority of the time, I get no output. When I do get output, it's everything in the serial port rather than the most recent. Can you offer more advise on this, please? PLUS, can you explain what the "stty ..." command code does? It doesn't seem to help my situation. – sisko Feb 07 '13 at 11:03
  • The stty command just makes sure the device will be Arduino friendly (for example it sets transition speed to 9600bps). /dev/ttyACM0 is just a pipe. It doesn't have any intelligence to serve you data in convenient packages. You read N amount of bytes and if something is there then you get it. It's good to know how much data you want to read. Look at this example I created for inter process communication (https://github.com/lukaszkujawa/php-multithreaded-socket-server/blob/master/sock/SocketServerBroadcast.php) handleProcess() and broadcast(). – Lukasz Kujawa Feb 07 '13 at 15:10
  • ...First 4 bytes of data I send to pipe is an integer so later when I read from the pipe I read only 4 bytes to find out how many bytes I have to read. Experiment with pipes outside from the Arduino to get a good understanding of what are you doing. – Lukasz Kujawa Feb 07 '13 at 15:11
  • In case you still have some problems with serial communication I created a small library for Arduino (https://github.com/lukaszkujawa/arduino-serial-helper). I also described idea behind it here http://systemsarchitect.net/arduino-and-php-serial-communication-with-a-protocol/. Hopefully that will help. – Lukasz Kujawa Feb 21 '13 at 10:05
3

/dev/ttyUSB0 running with user root, if your using apache try chown /dev/ttyUSB0 to apache or user is logged in.

$ sudo chown apache2:apache2 /dev/ttyACM0
OR
$ sudo chown yourusername:yourusername /dev/ttyACM0

and then try again, or try logout from ubuntu and login as root user.

  • https://symfony.com/doc/current/reference/constraints/LessThanOrEqual.html#basic-usage – mblaettermann Sep 21 '18 at 11:38
  • You should probably add the Apache user to `dialout` group instead of changing the owner or permissions of the device. – jww Jul 02 '19 at 02:17
2

You are probably trying to read when is no data on the serial port. You need to implement JavaScript code to call PHP code that can read at regular intervals.

When you have got data, you should process it.

readPort() has worked fine for me. If the baud rate, parity, etc. is adjusted properly, then you should not have any problem reading the serial port.

Here is a sample of using the library for Arduino. It worked for me some time ago:

<?php
    include "php_serial.class.php";

    // Let's start the class
    $serial = new phpSerial();

    // First we must specify the device. This works on both Linux and Windows (if
    // your Linux serial device is /dev/ttyS0 for COM1, etc.)
    $serial->deviceSet("/dev/ttyUSB0");

    // Set for 9600-8-N-1 (no flow control)
    $serial->confBaudRate(9600); //Baud rate: 9600
    $serial->confParity("none");  //Parity (this is the "N" in "8-N-1")
    $serial->confCharacterLength(8); //Character length     (this is the "8" in "8-N-1")
    $serial->confStopBits(1);  //Stop bits (this is the "1" in "8-N-1")
    $serial->confFlowControl("none");

    // Then we need to open it
    $serial->deviceOpen();

    // Read data
    $read = $serial->readPort();

    // Print out the data
    echo $read;

    // If you want to change the configuration, the device must be closed.
    $serial->deviceClose();
?>
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
opc0de
  • 11,557
  • 14
  • 94
  • 187
  • I know what the baud rate is but do you mind telling me what parity is and how to correctly configure it in this context? – sisko Oct 29 '12 at 09:57
  • @sisko i have edited my answer with an example of using this library.Hope you will find it useful – opc0de Oct 29 '12 at 09:59
  • thanks for your answers and code example. I updated my code with extracts of your but I still have no feedback. I updated my original question with my PHP/HTML script. I should be getting some feedback in 3 places but nothing is coming through. I should point out that my port (/dev/ttyACM0) is set to chmod 777 and I am actually calling Serial.println in my Arduino sketch which is why I am expecting some data to be returned in PHP. Infact, each time I use my web interface my LEDs successfully respond and my Arduino serial monitor prints my message(s) – sisko Oct 29 '12 at 19:57
  • what operating system do you have witch apache version / php do you use ? – opc0de Oct 30 '12 at 07:28
  • The operating system is Linux Ubuntu-12, PHP is Version 5.3.10 and Apache is Apache/2.2.22 – sisko Oct 30 '12 at 11:09
  • @sisko can you see the serial output in Arduino IDE (SerialMon ) ? – opc0de Oct 30 '12 at 11:10
  • btw maybe apache hasn't rights to access the serial port. I don't think is a code issue – opc0de Oct 30 '12 at 11:11
  • Yes, I can see serial output in the Arduino IDE. Even when I use my PHP web interface output occurs in the IDE. I don't know how Apache might be interfering with PHP return data from my port but I will start googling. Can you offer any suggestions? – sisko Oct 30 '12 at 18:42