PHP serial port data return from Arduino

74,103

Solution 1

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/.

Solution 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();
?>
Share:
74,103
sisko
Author by

sisko

Professional web developer making the transition into Robotics

Updated on November 15, 2020

Comments

  • sisko
    sisko over 3 years

    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
    sisko over 11 years
    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?
  • opc0de
    opc0de over 11 years
    @sisko i have edited my answer with an example of using this library.Hope you will find it useful
  • sisko
    sisko over 11 years
    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)
  • opc0de
    opc0de over 11 years
    what operating system do you have witch apache version / php do you use ?
  • sisko
    sisko over 11 years
    The operating system is Linux Ubuntu-12, PHP is Version 5.3.10 and Apache is Apache/2.2.22
  • opc0de
    opc0de over 11 years
    @sisko can you see the serial output in Arduino IDE (SerialMon ) ?
  • opc0de
    opc0de over 11 years
    btw maybe apache hasn't rights to access the serial port. I don't think is a code issue
  • sisko
    sisko over 11 years
    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
    sisko over 11 years
    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?
  • Lukasz Kujawa
    Lukasz Kujawa over 11 years
    Could you paste your code for Arduino and PHP? Ot's hard to tell without it.
  • sisko
    sisko over 11 years
    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.
  • Lukasz Kujawa
    Lukasz Kujawa over 11 years
    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().
  • sisko
    sisko about 11 years
    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.
  • Lukasz Kujawa
    Lukasz Kujawa about 11 years
    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 (github.com/lukaszkujawa/php-multithreaded-socket-server/blo‌​b/…) handleProcess() and broadcast().
  • Lukasz Kujawa
    Lukasz Kujawa about 11 years
    ...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
    Lukasz Kujawa about 11 years
    In case you still have some problems with serial communication I created a small library for Arduino (github.com/lukaszkujawa/arduino-serial-helper). I also described idea behind it here systemsarchitect.net/…. Hopefully that will help.