strydom Posted November 14, 2012 Share Posted November 14, 2012 Hey im new to this forum and to php. im look for some help as i cant seem to get my lights to light up on my Arduino Uno board using 'Serial Comunication' This is my code on the server... $serial->deviceOpen(); if ($_GET['action'] == "on") { $serial->sendMessage("N\r\n"); $file = fopen("testFile.txt","w"); fwrite($file, "1"); fclose($file); } else if ($_GET['action'] == "off") { $serial->sendMessage("0\r\n"); $file = fopen("testFile.txt","w"); fwrite($file, "0"); fclose($file); } And my code on the Arduino is listening to the serial port and is waiting for N. I know this is correct as i can test it by manually sending it an N... If you know what is wrong with my code please help me and if you need more code snippets then i will gladly post them. Thanks! Chris Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/ Share on other sites More sharing options...
requinix Posted November 14, 2012 Share Posted November 14, 2012 I assume you're using this? How about showing us more code? Specifically stuff dealing with $serial. Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1392461 Share on other sites More sharing options...
strydom Posted November 15, 2012 Author Share Posted November 15, 2012 yea something similar... Here is the full code... <html><head> <style type="text/css"> body {background:white; color:black;} a:link {color:black;} /* unvisited link */ a:visited {color:black;} /* visited link */ a:hover {color:#00FF00;} /* mouse over link */ a:active {color:#FF0000;} /* selected link */ table.center { margin-left:auto; margin-right:auto; font-size:28 pt; } </style> </head> <body> <?php //check the GET action var to see if an action is to be performed if (isset($_GET['action'])) { //Action required //Load the serial port class require("php_serial.class.php"); //Initialize the class $serial = new phpSerial(); //Specify the serial port to use... in this case COM1 $serial->deviceSet("COM7"); //Set the serial port parameters. The documentation says 9600 8-N-1, so $serial->confBaudRate(9600); //Baud rate: 9600 $serial->confParity("none"); //Parity (this is the "N" in "8-N-1") $serial->confCharacterLength(; //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"); //Device does not support flow control of any kind, so set it to none. //Now we "open" the serial port so we can write to it $serial->deviceOpen(); //Issue the appropriate command according to the serial relay board documentation if ($_GET['action'] == "on") { //to turn relay number 1 on, we issue the command $serial->sendMessage("N\r\n"); //$serial->sendMessage("N1\r"); $file = fopen("testFile.txt","w"); fwrite($file, "1"); fclose($file); } else if ($_GET['action'] == "off") { //to turn relay number 1 off, we issue this command $serial->sendMessage("0\r\n"); //$serial->sendMessage("F1\r"); $file = fopen("testFile.txt","w"); fwrite($file, "0"); fclose($file); } //We're done, so close the serial port again $serial->deviceClose(); } ?> <table border="1" class="center"> <tr> <th>Lights</th> <tr> <td> <pre> <a href="<?php echo $_SERVER['PHP_SELF'] . '?action=on' ?>">ON</a> <?php $file = fopen("testFile.txt", "r") or exit("Unable to open file!"); if (fgetc($file)==1) echo "<img src=\"Light On.gif\" />"; else echo "<img src=\"Light Off.gif\" />"; fclose($file); ?> <a href="<?php echo $_SERVER['PHP_SELF'] . '?action=off' ?>">OFF</a> </pre> </td> </tr> </table> </body> </html> And here is the Serial Code...i think its the same as the one you showed... <?php define ("SERIAL_DEVICE_NOTSET", 0); define ("SERIAL_DEVICE_SET", 1); define ("SERIAL_DEVICE_OPENED", 2); /** * Serial port control class * * THIS PROGRAM COMES WITH ABSOLUTELY NO WARANTIES ! * USE IT AT YOUR OWN RISKS ! * * @author Rémy Sanchez <thenux@gmail.com> * @thanks Aurélien Derouineau for finding how to open serial ports with windows * @thanks Alec Avedisyan for help and testing with reading * @copyright under GPL 2 licence */ class phpSerial { var $_device = null; var $_windevice = null; var $_dHandle = null; var $_dState = SERIAL_DEVICE_NOTSET; var $_buffer = ""; var $_os = ""; /** * This var says if buffer should be flushed by sendMessage (true) or manualy (false) * * @var bool */ var $autoflush = true; /** * Constructor. Perform some checks about the OS and setserial * * @return phpSerial */ function phpSerial () { setlocale(LC_ALL, "en_US"); $sysname = php_uname(); if (substr($sysname, 0, 5) === "Linux") { $this->_os = "linux"; if($this->_exec("stty --version") === 0) { register_shutdown_function(array($this, "deviceClose")); } else { trigger_error("No stty availible, unable to run.", E_USER_ERROR); } } elseif(substr($sysname, 0, 7) === "Windows") { $this->_os = "windows"; register_shutdown_function(array($this, "deviceClose")); } else { trigger_error("Host OS is neither linux nor windows, unable tu run.", E_USER_ERROR); exit(); } } // // OPEN/CLOSE DEVICE SECTION -- {START} // /** * Device set function : used to set the device name/address. * -> linux : use the device address, like /dev/ttyS0 * -> windows : use the COMxx device name, like COM1 (can also be used * with linux) * * @param string $device the name of the device to be used * @return bool */ function deviceSet ($device) { if ($this->_dState !== SERIAL_DEVICE_OPENED) { if ($this->_os === "linux") { if (preg_match("@^COM(\d+):?$@i", $device, $matches)) { $device = "/dev/ttyS" . ($matches[1] - 1); } if ($this->_exec("stty -F " . $device) === 0) { $this->_device = $device; $this->_dState = SERIAL_DEVICE_SET; return true; } } elseif ($this->_os === "windows") { if (preg_match("@^COM(\d+):?$@i", $device, $matches) and $this->_exec(exec("mode " . $device)) === 0) { $this->_windevice = "COM" . $matches[1]; $this->_device = "\\.\com" . $matches[1]; $this->_dState = SERIAL_DEVICE_SET; return true; } } trigger_error("Specified serial port is not valid", E_USER_WARNING); return false; } else { trigger_error("You must close your device before to set an other one", E_USER_WARNING); return false; } } /** * Opens the device for reading and/or writing. * * @param string $mode Opening mode : same parameter as fopen() * @return bool */ function deviceOpen ($mode = "r+b") { if ($this->_dState === SERIAL_DEVICE_OPENED) { trigger_error("The device is already opened", E_USER_NOTICE); return true; } if ($this->_dState === SERIAL_DEVICE_NOTSET) { trigger_error("The device must be set before to be open", E_USER_WARNING); return false; } if (!preg_match("@^[raw]\+?b?$@", $mode)) { trigger_error("Invalid opening mode : ".$mode.". Use fopen() modes.", E_USER_WARNING); return false; } $this->_dHandle = @fopen($this->_device, $mode); if ($this->_dHandle !== false) { stream_set_blocking($this->_dHandle, 0); $this->_dState = SERIAL_DEVICE_OPENED; return true; } $this->_dHandle = null; trigger_error("Unable to open the device", E_USER_WARNING); return false; } /** * Closes the device * * @return bool */ function deviceClose () { if ($this->_dState !== SERIAL_DEVICE_OPENED) { return true; } if (fclose($this->_dHandle)) { $this->_dHandle = null; $this->_dState = SERIAL_DEVICE_SET; return true; } trigger_error("Unable to close the device", E_USER_ERROR); return false; } // // OPEN/CLOSE DEVICE SECTION -- {STOP} // // // CONFIGURE SECTION -- {START} // /** * Configure the Baud Rate * Possible rates : 110, 150, 300, 600, 1200, 2400, 4800, 9600, 38400, * 57600 and 115200. * * @param int $rate the rate to set the port in * @return bool */ function confBaudRate ($rate) { if ($this->_dState !== SERIAL_DEVICE_SET) { trigger_error("Unable to set the baud rate : the device is either not set or opened", E_USER_WARNING); return false; } $validBauds = array ( 110 => 11, 150 => 15, 300 => 30, 600 => 60, 1200 => 12, 2400 => 24, 4800 => 48, 9600 => 96, 19200 => 19, 38400 => 38400, 57600 => 57600, 115200 => 115200 ); if (isset($validBauds[$rate])) { if ($this->_os === "linux") { $ret = $this->_exec("stty -F " . $this->_device . " " . (int) $rate, $out); } elseif ($this->_os === "windows") { $ret = $this->_exec("mode " . $this->_windevice . " BAUD=" . $validBauds[$rate], $out); } else return false; if ($ret !== 0) { trigger_error ("Unable to set baud rate: " . $out[1], E_USER_WARNING); return false; } } } /** * Configure parity. * Modes : odd, even, none * * @param string $parity one of the modes * @return bool */ function confParity ($parity) { if ($this->_dState !== SERIAL_DEVICE_SET) { trigger_error("Unable to set parity : the device is either not set or opened", E_USER_WARNING); return false; } $args = array( "none" => "-parenb", "odd" => "parenb parodd", "even" => "parenb -parodd", ); if (!isset($args[$parity])) { trigger_error("Parity mode not supported", E_USER_WARNING); return false; } if ($this->_os === "linux") { $ret = $this->_exec("stty -F " . $this->_device . " " . $args[$parity], $out); } else { $ret = $this->_exec("mode " . $this->_windevice . " PARITY=" . $parity{0}, $out); } if ($ret === 0) { return true; } trigger_error("Unable to set parity : " . $out[1], E_USER_WARNING); return false; } /** * Sets the length of a character. * * @param int $int length of a character (5 <= length <= * @return bool */ function confCharacterLength ($int) { if ($this->_dState !== SERIAL_DEVICE_SET) { trigger_error("Unable to set length of a character : the device is either not set or opened", E_USER_WARNING); return false; } $int = (int) $int; if ($int < 5) $int = 5; elseif ($int > $int = 8; if ($this->_os === "linux") { $ret = $this->_exec("stty -F " . $this->_device . " cs" . $int, $out); } else { $ret = $this->_exec("mode " . $this->_windevice . " DATA=" . $int, $out); } if ($ret === 0) { return true; } trigger_error("Unable to set character length : " .$out[1], E_USER_WARNING); return false; } /** * Sets the length of stop bits. * * @param float $length the length of a stop bit. It must be either 1, * 1.5 or 2. 1.5 is not supported under linux and on some computers. * @return bool */ function confStopBits ($length) { if ($this->_dState !== SERIAL_DEVICE_SET) { trigger_error("Unable to set the length of a stop bit : the device is either not set or opened", E_USER_WARNING); return false; } if ($length != 1 and $length != 2 and $length != 1.5 and !($length == 1.5 and $this->_os === "linux")) { trigger_error("Specified stop bit length is invalid", E_USER_WARNING); return false; } if ($this->_os === "linux") { $ret = $this->_exec("stty -F " . $this->_device . " " . (($length == 1) ? "-" : "") . "cstopb", $out); } else { $ret = $this->_exec("mode " . $this->_windevice . " STOP=" . $length, $out); } if ($ret === 0) { return true; } trigger_error("Unable to set stop bit length : " . $out[1], E_USER_WARNING); return false; } /** * Configures the flow control * * @param string $mode Set the flow control mode. Availible modes : * -> "none" : no flow control * -> "rts/cts" : use RTS/CTS handshaking * -> "xon/xoff" : use XON/XOFF protocol * @return bool */ function confFlowControl ($mode) { if ($this->_dState !== SERIAL_DEVICE_SET) { trigger_error("Unable to set flow control mode : the device is either not set or opened", E_USER_WARNING); return false; } $linuxModes = array( "none" => "clocal -crtscts -ixon -ixoff", "rts/cts" => "-clocal crtscts -ixon -ixoff", "xon/xoff" => "-clocal -crtscts ixon ixoff" ); $windowsModes = array( "none" => "xon=off octs=off rts=on", "rts/cts" => "xon=off octs=on rts=hs", "xon/xoff" => "xon=on octs=off rts=on", ); if ($mode !== "none" and $mode !== "rts/cts" and $mode !== "xon/xoff") { trigger_error("Invalid flow control mode specified", E_USER_ERROR); return false; } if ($this->_os === "linux") $ret = $this->_exec("stty -F " . $this->_device . " " . $linuxModes[$mode], $out); else $ret = $this->_exec("mode " . $this->_windevice . " " . $windowsModes[$mode], $out); if ($ret === 0) return true; else { trigger_error("Unable to set flow control : " . $out[1], E_USER_ERROR); return false; } } /** * Sets all appropriate parameters for communicating with Relay board in one fell swoop * (9600 8-N-1 no flow control) */ function initRlyBoard() { if ($this->_os === "linux") { $ret = $this->_exec("stty -F " . $this->_device . " 9600 -parenb cs8 -cstopb clocal -crtscts -ixon -ixoff" , $out); } elseif ($this->_os === "windows") { $ret = $this->_exec("mode " . $this->_windevice . " BAUD=9600 PARITY=n DATA=8 STOP=1 xon=off octs=off rts=on" , $out); } else return false; if ($ret !== 0) { trigger_error ("Unable to setup port for serial board: " . $out[1], E_USER_WARNING); return false; } } /** * Sets a setserial parameter (cf man setserial) * NO MORE USEFUL ! * -> No longer supported * -> Only use it if you need it * * @param string $param parameter name * @param string $arg parameter value * @return bool */ function setSetserialFlag ($param, $arg = "") { if (!$this->_ckOpened()) return false; $return = exec ("setserial " . $this->_device . " " . $param . " " . $arg . " 2>&1"); if ($return{0} === "I") { trigger_error("setserial: Invalid flag", E_USER_WARNING); return false; } elseif ($return{0} === "/") { trigger_error("setserial: Error with device file", E_USER_WARNING); return false; } else { return true; } } // // CONFIGURE SECTION -- {STOP} // // // I/O SECTION -- {START} // /** * Sends a string to the device * * @param string $str string to be sent to the device * @param float $waitForReply time to wait for the reply (in seconds) */ function sendMessage ($str, $waitForReply = 0.1) { $this->_buffer .= $str; if ($this->autoflush === true) $this->flush(); usleep((int) ($waitForReply * 1000000)); } /** * Reads the port until no new datas are availible, then return the content. * * @pararm int $count number of characters to be read (will stop before * if less characters are in the buffer) * @return string */ function readPort ($count = 0) { if ($this->_dState !== SERIAL_DEVICE_OPENED) { trigger_error("Device must be opened to read it", E_USER_WARNING); return false; } if ($this->_os === "linux") { $content = ""; $i = 0; if ($count !== 0) { do { if ($i > $count) $content .= fread($this->_dHandle, ($count - $i)); else $content .= fread($this->_dHandle, 128); } while (($i += 128) === strlen($content)); } else { //test do { $content .= fread($this->_dHandle, 128); } while (($i += 128) === strlen($content)); } return $content; } elseif ($this->_os === "windows") { /* Do nohting : not implented yet */ } trigger_error("Reading serial port is not implemented for Windows", E_USER_WARNING); return false; } /** * Flushes the output buffer * * @return bool */ function flush () { if (!$this->_ckOpened()) return false; if (fwrite($this->_dHandle, $this->_buffer) !== false) { $this->_buffer = ""; return true; } else { $this->_buffer = ""; trigger_error("Error while sending message", E_USER_WARNING); return false; } } // // I/O SECTION -- {STOP} // // // INTERNAL TOOLKIT -- {START} // function _ckOpened() { if ($this->_dState !== SERIAL_DEVICE_OPENED) { trigger_error("Device must be opened", E_USER_WARNING); return false; } return true; } function _ckClosed() { if ($this->_dState !== SERIAL_DEVICE_CLOSED) { trigger_error("Device must be closed", E_USER_WARNING); return false; } return true; } function _exec($cmd, &$out = null) { $desc = array( 1 => array("pipe", "w"), 2 => array("pipe", "w") ); $proc = proc_open($cmd, $desc, $pipes); $ret = stream_get_contents($pipes[1]); $err = stream_get_contents($pipes[2]); fclose($pipes[1]); fclose($pipes[2]); $retVal = proc_close($proc); if (func_num_args() == 2) $out = array($ret, $err); return $retVal; } // // INTERNAL TOOLKIT -- {STOP} // } ?> Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1392537 Share on other sites More sharing options...
requinix Posted November 15, 2012 Share Posted November 15, 2012 You sure it's COM7 and with those settings? If you don't have a better tool installed, I think you can test COM7 by running C:\>copy con com7 ^Z from cmd. (The ^Z is Ctrl+Z.) That probably won't do exactly what you need but it should tell you whether COM7 works. Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1392539 Share on other sites More sharing options...
strydom Posted November 15, 2012 Author Share Posted November 15, 2012 yea it definitly works :/ when i click to turn the light on the arduino responds and the lights blink on and then off but they are supposed to stay on :/ could it be something to do with the flush or something? Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1392701 Share on other sites More sharing options...
requinix Posted November 15, 2012 Share Posted November 15, 2012 "Click"? What are you clicking? As for flushing, sendMessage() will do that unless you specifically turn off autoflush (which you don't). Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1392720 Share on other sites More sharing options...
strydom Posted November 15, 2012 Author Share Posted November 15, 2012 The linked 'ON' button from... <a href="<?php echo $_SERVER['PHP_SELF'] . '?action=on' ?>">ON</a> Do you see anything wrong with any of the code? I am using all of the code to communicate through my COM7 port to my Arduino. The bud rate and everything is correct and my Arduino 'RX' Light flashes when i Click 'ON' which means that it is receiving some kind of response. I am 100% sure that the code on the Arduino is correct so it must be to do with the PHP somewhere... Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1392756 Share on other sites More sharing options...
requinix Posted November 15, 2012 Share Posted November 15, 2012 What does var_dump($serial->flush()); after you sendMessage() output? Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1392767 Share on other sites More sharing options...
kicken Posted November 15, 2012 Share Posted November 15, 2012 (edited) What is the code you're using on the arduino? You said the light turn on, but then turns off again right away so it sounds like PHP is sending the data properly. The Arduino is just not interpreting it properly or the PHP code is not sending the correct data. Without both pieces of the puzzle it's hard to say which. Edited November 15, 2012 by kicken Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1392787 Share on other sites More sharing options...
strydom Posted November 16, 2012 Author Share Posted November 16, 2012 Im not sure requinix :/ And kicken i think it is the PHP code not sending it corectly but here is the arduino code... int ldr = 0; int led = 11; int in = 0; void setup() { pinMode(led, OUTPUT); pinMode(ldr, INPUT); Serial.begin(9600); } void loop() { if (Serial.available() > 0) { in = Serial.read(); } if (in == 'L') { int val = (analogRead(ldr)); val = constrain(val, 150, 500); int LightLvl = map(val, 150, 500, 255, 0); analogWrite(led, LightLvl); } else (analogWrite(led, LOW)); I think i might have changed the if (in == 'L') part from the code i sent before but it matches on the PHP and Arduino code still. Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1392872 Share on other sites More sharing options...
strydom Posted November 16, 2012 Author Share Posted November 16, 2012 (edited) Yea just checked and in the PHP code i sent before it says its sending an 'N' but i have changed that to an 'L'. So the Codes both match. Just to clear that up they were matching in the start so nothing has changed. Its still not working properly... Edited November 16, 2012 by strydom Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1392873 Share on other sites More sharing options...
kicken Posted November 16, 2012 Share Posted November 16, 2012 Your Arduino code does not account for the \r\n characters you are sending. When your PHP code sends "L\r\n" you're sending three separate characters that the arduino will then read. On the first loop it will read 'L' and set the light because in == 'L'. On the second loop it will read the \r and hit the else part, turning the light off again. The third loop will read a \n and hit the else again then the rest of the loops will just keep hitting the else branch because in=='\n'. You'll need to either change the arduino code to allow for the new lines or change the PHP to not send them. I haven't looked through the PHP serial class to know if they are necessary to flush the data or not. Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1392874 Share on other sites More sharing options...
strydom Posted November 16, 2012 Author Share Posted November 16, 2012 I don’t believe that the /r/n will change anything... i tried it and had no results. I also do think that they have something to do with the flush and line breaks or something along those lines. Thanks for the suggestion though Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1393034 Share on other sites More sharing options...
kicken Posted November 16, 2012 Share Posted November 16, 2012 So I did some playing around (I have an arduino) and aside from the previously mentioned problem with \r\n, the phpSerial class is not properly setting up the connection parameters. If you add a system('mode') after the deviceOpen call and find the port # the parameters are incorrect. In my case they were set to: Status for device COM3: ----------------------- Baud: 9600 Parity: Even Data Bits: 7 Stop Bits: 1 Timeout: ON XON/XOFF: OFF CTS handshaking: OFF DSR handshaking: OFF DSR sensitivity: OFF DTR circuit: OFF RTS circuit: ON Which ended up causing the character 'L' to be ready by the arduino as byte 207 rather than byte 76 like it should have been meaning the if statement never triggered to turn the light on. Setting the parameters myself rather than through the class, and removing the \r\n, corrected the issue: exec('mode COM3 BAUD=96 PARITY=n DATA=8 STOP=1 xon=off octs=off rts=on'); $serial->deviceOpen(); Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1393098 Share on other sites More sharing options...
strydom Posted November 16, 2012 Author Share Posted November 16, 2012 Right i think i got what you meant... My code now looks like this... <?php //check the GET action var to see if an action is to be performed if (isset($_GET['action'])) { //Action required //Load the serial port class require("php_serial.class.php"); //Initialize the class $serial = new phpSerial(); //Specify the serial port to use... in this case COM1 $serial->deviceSet("COM3"); exec('mode COM3 BAUD=96 PARITY=n DATA=8 STOP=1 xon=off octs=off rts=on'); //Now we "open" the serial port so we can write to it $serial->deviceOpen(); //Issue the appropriate command according to the serial relay board documentation if ($_GET['action'] == "on") { $serial->sendMessage("L"); $file = fopen("lights.txt","w"); fwrite($file, "1"); fclose($file); } else if ($_GET['action'] == "off") { $serial->sendMessage("l"); $file = fopen("lights.txt","w"); fwrite($file, "0"); fclose($file); But im still not getting anything. My arduino keeps resetting when i click the button to turn the LED on Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1393107 Share on other sites More sharing options...
kicken Posted November 17, 2012 Share Posted November 17, 2012 Connecting to the serial port on the arduino causes a reset. There are various ways to disable it if you do some google searching about it. Which one works best for you would depend on what your needs are. Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1393123 Share on other sites More sharing options...
strydom Posted November 17, 2012 Author Share Posted November 17, 2012 Ah i have found the culprit... i forgot that my front ports messed up a while back and won’t play sound or anything... so i plugged the Arduino in the back main motherboard ports and now it’s all working!!! I done this before but it didn’t work so obviously it had something to do with the code as well Thanks for all the help and suggestions though! They were much appreciated Thanks a Bunch, Chris Quote Link to comment https://forums.phpfreaks.com/topic/270698-help-with-serial-port-script/#findComment-1393224 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.