hotshotharry
Posts: 3
Joined: Sat Jul 21, 2012 8:29 am

php and uart serial output

Sat Jul 21, 2012 8:47 am

Can anyone shed some light on why this wont work on the raspbery pi? i suspect that is has something to do with the way the serial class in php is handling the serial port.

here is a snippet of code

Code: Select all

  require("php_serial_class.php"); //  /dev/ttyAMA0 ttyS0
    $serial = new phpSerial(); 
    $serial->deviceSet("/dev/ttyAMA0"); //SET THIS TO WHATEVER YOUR SERIAL DEVICE HAPPENS TO BE, YOU CAN FIND THIS UNDER THE ARDUINO SOFTWARE'S MENU
    $serial->confBaudRate(19200); //Baud rate: 19200 or 115200
    $serial->deviceOpen(); 
The following code works on a regular mac computer, i changed
$serial->deviceSet("/dev/cu.usbserial-A4009R8Z"); to the above line for the rpi

If i use this code(python 2) or minicom i can send and receive from the serial port

Code: Select all

import serial
##test=serial.Serial("/dev/ttyAMA0",19200)
test=serial.Serial("/dev/ttyAMA0",115200)
test.open()
test.write("Hello World")
test.close
here is a copy of the serial class in case someone can see a problem there?

Code: Select all

<?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 !
 *
 * Changes added by Rizwan Kassim <rizwank@uwink.com> for OSX functionality
 * default serial device for osx devices is /dev/tty.serial for machines with a built in serial device
 *
 * @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
 *
 * do not change this code unless you know what you are getting into. Leaving it as you have received it should work fine!
 */
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, 6) === "Darwin")
		{
			$this->_os = "osx";
            // We know stty is available in Darwin. 
            // stty returns 1 when run from php, because "stty: stdin isn't a
            // terminal"
            // skip this check
//			if($this->_exec("stty") === 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 osx, 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
	 * -> osx : use the device address, like /dev/tty.serial
	 * -> 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 === "osx")
			{
				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);
            }
            if ($this->_os === "darwin")
            {
                $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 <= 8)
	 * @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 > 8) $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 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->serialflush();

		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" || $this->_os === "osx")
			{
			// Behavior in OSX isn't to wait for new data to recover, but just grabs what's there!
			// Doesn't always work perfectly for me in OSX
			$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
			{
				do {
					$content .= fread($this->_dHandle, 128);
				} while (($i += 128) === strlen($content));
			}

			return $content;
		}
		elseif ($this->_os === "windows")
		{
			/* Do nothing : not implented yet */
		}

		trigger_error("Reading serial port is not implemented for Windows", E_USER_WARNING);
		return false;
	}

	/**
	 * Flushes the output buffer
	 * Renamed from flush for osx compat. issues
	 *
	 * @return bool
	 */
	function serialflush ()
	{
		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}
	//
}
?>

hotshotharry
Posts: 3
Joined: Sat Jul 21, 2012 8:29 am

Re: php and uart serial output

Sat Jul 21, 2012 6:45 pm

here is a copy of the code that uses the php serial class

Code: Select all

<?php 
session_start();
  
 
 /*
 Password <?php echo $_POST["password"]; ?>!<br />
 Value <?php echo $_POST["selection"]; ?>!<br />
 */
$passvar = $_SESSION["userpassword"];




    require("php_serial_class.php"); //  /dev/ttyAMA0 ttyS0
    $serial = new phpSerial(); 
    $serial->deviceSet("/dev/ttyAMA0"); //SET THIS TO WHATEVER YOUR SERIAL DEVICE HAPPENS TO BE, YOU CAN FIND THIS UNDER THE ARDUINO SOFTWARE'S MENU
    $serial->confBaudRate(19200); //Baud rate: 19200 
    $serial->deviceOpen(); 
    
    if ( $_POST["selection"] == 1 && $_POST["password"] == $passvar ){
    $serial->sendMessage("BF1\r"); 
    $_SESSION["valid"] = "OK";
    }
    
    if ( $_POST["selection"] == 2 && $_POST["password"] == $passvar){
    $serial->sendMessage("BF0\r"); 
    $_SESSION["valid"] = "OK";
    }
    
    if ( $_POST["selection"] == 3 && $_POST["password"] == $passvar){
    $serial->sendMessage("BS\r"); 
    $_SESSION["valid"] = "OK";
    }
    
    if ( $_POST["selection"] == 4 && $_POST["password"] == $passvar){
    $serial->sendMessage("BS\r"); 
    $_SESSION["valid"] = "OK";
    }
    
    if ( $_POST["selection"] == 5 ){
    header( "Location: hottubstatus.php" );
    }
    
    
    $serial->deviceClose(); 
    if ($_SESSION["valid"] != "OK") $_SESSION["valid"] = "Fail";	// if no option selects ok it fails
     if ($_POST["selection"] == 5) $_SESSION["valid"] = "empty";  // accounts for the status selction
    if ($_POST["selection"] != 5) header( "Location: formhtcontrol.php" ) ; 
    
    
?>
For some reason i can get the rpi to output any serial via php script ...

User avatar
patrikg
Posts: 168
Joined: Sun Mar 18, 2012 10:19 pm

Re: php and uart serial output

Sat Jul 21, 2012 7:21 pm

As many serial projects here, there been lot of security reson.
Do you have correct rights to write to the serial device.
Maybe have to add some groups to the user(www-data) that execute the php, like dialout and uucp.

TIP: Search on the forum for serial.

/Patrik
PS Sorry for my english DS.

hotshotharry
Posts: 3
Joined: Sat Jul 21, 2012 8:29 am

Re: php and uart serial output

Sun Jul 22, 2012 12:40 am

Thanks ! But I think my permissions are correct as I don't get an error message ... :-) and I have added pi to the dial out and the data group has been added ...

mharizanov
Posts: 19
Joined: Thu May 31, 2012 12:57 pm

Re: php and uart serial output

Tue Aug 14, 2012 6:20 am

Has there been progress on this? I have the same problem and google took me here.

User avatar
joan
Posts: 14472
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: php and uart serial output

Tue Aug 14, 2012 8:11 am

I don't know if this has anything to do with the problem but offer it as a thing to check.

1) /boot/cmdline.txt change from
dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait
to
dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 rootwait
2) /etc/inittab change the following line from
2:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
to
#2:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100

mharizanov
Posts: 19
Joined: Thu May 31, 2012 12:57 pm

Re: php and uart serial output

Tue Aug 14, 2012 3:09 pm

thanks for replying. I did that already before posting my question and am able to receive using PHP serial class, but sending won't work nicely. Connections are all fine, this is ruled out. I reduced to 9600 baud too.

it9xxs
Posts: 3
Joined: Wed Aug 22, 2012 12:31 pm

Re: php and uart serial output

Thu Aug 23, 2012 10:00 am

Hi, I'm using php_serial.class and my program is able to transmit only if I keep "cat /dev/ttyAMA0" running in another terminal, and the received string goes there (and not printed by the php program)

If I stop "cat..." the php program does not even transmit. Any idea ?

Distro on the RPI is Occidentalis v.0.1

This is the simple program:

Code: Select all

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

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

	// First we must specify the device.
	$serial->deviceSet("/dev/ttyAMA0");

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

	// To write into
	$serial->sendMessage("@AMHELLO\r");

	// And to read from
	$read = $serial->readPort(30);
	echo ($read);
	
	// The device must be closed
	$serial->deviceClose();
?>
Giovanni

it9xxs
Posts: 3
Joined: Wed Aug 22, 2012 12:31 pm

Re: php and uart serial output

Fri Aug 24, 2012 7:54 am

The program works nicely if I use an USB/serial adapter (in this case the port is /dev/ttyUSB0 instead of /dev/ttyAMA0). In either cases I replaced the string ttyS in the function deviceSet() of php_serial.class.php accordingly (see bold):

Code: Select all

if (preg_match("@^[b]ttyAMA[/b](\d+):?$@i", $device, $matches))
{
         $device = "[b]/dev/ttyAMA[/b]" . ($matches[1] - 1);
}
or, for the serial USB adapter:

Code: Select all

if (preg_match("@^[b]ttyUSB[/b](\d+):?$@i", $device, $matches))
{
         $device = "[b]/dev/ttyUSB[/b]" . ($matches[1] - 1);
}
Any help please ?
Thanks.
it9xxs wrote:Hi, I'm using php_serial.class and my program is able to transmit only if I keep "cat /dev/ttyAMA0" running in another terminal, and the received string goes there (and not printed by the php program)
...
...

psobey
Posts: 2
Joined: Sat Sep 08, 2012 7:42 am

Re: php and uart serial output

Sat Sep 08, 2012 8:09 am

Hi,

I am also having trouble getting the serial port to work with PHP. I am using the php_serial.class.php that everyone seems to be using. I have changed the device to:

Code: Select all

$device = "/dev/ttyAMA" . ($matches[1] - 1);
I have used minicom to check that the serial port works:

Code: Select all

minicom -b 9600 -o -D /dev/ttyAMA0
This works fine so I know the comms work. I say this because I have a 434MHz radio module connected to the UART and my other radio devices talk to it quite happily.
However, the php page is a problem. In order to debug it I added an error handler function to the top of my web page:

Code: Select all

// error handler function
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
    if (!(error_reporting() & $errno)) {
        // This error code is not included in error_reporting
        return;
    }

    switch ($errno) {
    case E_USER_ERROR:
        echo "<b>My ERROR</b> [$errno] $errstr<br />\n";
        echo "  Fatal error on line $errline in file $errfile";
        echo ", PHP " . PHP_VERSION . " (" . PHP_OS . ")<br />\n";
        echo "Aborting...<br />\n";
        exit(1);
        break;

    case E_USER_WARNING:
        echo "<b>My WARNING</b> [$errno] $errstr<br />\n";
        break;

    case E_USER_NOTICE:
        echo "<b>My NOTICE</b> [$errno] $errstr<br />\n";
        break;

    default:
        echo "Unknown error type: [$errno] $errstr<br />\n";
        break;
    }

    /* Don't execute PHP internal error handler */
    return true;
}
I activate this when the action is called:

Code: Select all

	// set to the user defined error handler
	$old_error_handler = set_error_handler("myErrorHandler");

	//Action required
	echo '<br />Perform GET action.<br />'; 
	//Load the serial port class
	require("php_serial.class.php");
	
	//Initialize the class
	$serial = new phpSerial();
....
I then sprinkle in some extra debug statements into the php_serial.class.php file and get the following output:
Perform GET action.
My NOTICE [1024] Using LINUX device: /dev/ttyAMA0
My NOTICE [1024] Can not set device: /dev/ttyAMA0
My WARNING [512] Specified serial port is not valid
This means that the following call fails:

Code: Select all

if ($this->_exec("stty -F " . $device) === 0)
I have set all the php files to "chmod 755" but I am not sure what the permissions of the tty should be.
Doing a "ls -l /dev/ttyAMA0" I get:
pi@raspberrypi:~$ ls -l /dev/ttyAMA0
crw-rw---T 1 root dialout 204, 64 Jan 1 1970 /dev/ttyAMA0
Why does the opening of the port fail?
Is it a permissions thing?
Has anybody been able to get reading from and writing to the serial port working via this php solution?

I should add that this is my first venture into php and my linux skills are a little rusty as well.

psobey
Posts: 2
Joined: Sat Sep 08, 2012 7:42 am

Re: php and uart serial output

Sun Sep 09, 2012 12:55 am

OK, found the solution at http://www.fritz-hut.com/tag/raspberry-pi/.

Find out what user runs PHP:

Code: Select all

<?php
echo exec('whoami');
?>
For me it was www-data. The serial connection is owned by the dialout group so we need to add www-data to the dialout group to enable the PHP script to access the serial device.

Code: Select all

sudo usermod -a -G dialout www-data
Check that the dialout has been added to the group using the command groups www-data:

Code: Select all

pi@raspberrypi:~$ groups www-data
www-data : www-data dialout
All is now good so RESTART the Raspberry Pi. Now the UART works through the PHP script. Onward and upward!

User avatar
patrikg
Posts: 168
Joined: Sun Mar 18, 2012 10:19 pm

Re: php and uart serial output

Sun Sep 09, 2012 11:32 am

Like my post little up in this thread.

http://www.raspberrypi.org/phpBB3/viewt ... ad#p129865

Great that solved your problem.

/Patrik

dosle
Posts: 1
Joined: Fri Mar 01, 2013 4:34 am

Re: php and uart serial output

Sat Mar 02, 2013 2:38 am

Thanks patrikg & psobey, this solved the issue for me as well. :D
I ran into this issue when I moved my Arduino Uno from the Mac to my Raspberry Pi board.

bufferzone
Posts: 1
Joined: Tue Mar 04, 2014 1:45 pm

Re: php and uart serial output

Thu Jul 31, 2014 4:33 am

Hello, I try to read 434MHz radio receiver but all I get are some characters. My module is http://www.wenshing.com.tw/Data_Sheet/R ... _Sheet.pdf and i used the script below:
Anyone can help me please.

Code: Select all

#include <sys/types.h>
        #include <sys/stat.h>
        #include <fcntl.h>
        #include <termios.h>
        #include <stdio.h>

        /* baudrate settings are defined in <asm/termbits.h>, which is
        included by <termios.h> */
        #define BAUDRATE B9600            
        /* change this definition for the correct port */
        #define MODEMDEVICE "/dev/ttyAMA0"
        #define _POSIX_SOURCE 1 /* POSIX compliant source */

        #define FALSE 0
        #define TRUE 1

        volatile int STOP=FALSE; 

        main()
        {
          int fd,c, res;
          struct termios oldtio,newtio;
          char buf[255];
        /* 
          Open modem device for reading and writing and not as controlling tty
          because we don't want to get killed if linenoise sends CTRL-C.
        */
         fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
         if (fd <0) {perror(MODEMDEVICE); exit(-1); }
        
         tcgetattr(fd,&oldtio); /* save current serial port settings */
         bzero(&newtio, sizeof(newtio)); /* clear struct for new port settings */
        
        /* 
          BAUDRATE: Set bps rate. You could also use cfsetispeed and cfsetospeed.
          CRTSCTS : output hardware flow control (only used if the cable has
                    all necessary lines. See sect. 7 of Serial-HOWTO)
          CS8     : 8n1 (8bit,no parity,1 stopbit)
          CLOCAL  : local connection, no modem contol
          CREAD   : enable receiving characters
        */
         newtio.c_cflag = BAUDRATE | CRTSCTS | CS8 | CLOCAL | CREAD;
         
        /*
          IGNPAR  : ignore bytes with parity errors
          ICRNL   : map CR to NL (otherwise a CR input on the other computer
                    will not terminate input)
          otherwise make device raw (no other input processing)
        */
         newtio.c_iflag = IGNPAR | ICRNL;
         
        /*
         Raw output.
        */
         newtio.c_oflag = 0;
         
        /*
          ICANON  : enable canonical input
          disable all echo functionality, and don't send signals to calling program
        */
         newtio.c_lflag = ICANON;
         
        /* 
          initialize all control characters 
          default values can be found in /usr/include/termios.h, and are given
          in the comments, but we don't need them here
        */
         newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */ 
         newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
         newtio.c_cc[VERASE]   = 0;     /* del */
         newtio.c_cc[VKILL]    = 0;     /* @ */
         newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
         newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
         newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
         newtio.c_cc[VSWTC]    = 0;     /* '\0' */
         newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */ 
         newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
         newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
         newtio.c_cc[VEOL]     = 0;     /* '\0' */
         newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
         newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
         newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
         newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
         newtio.c_cc[VEOL2]    = 0;     /* '\0' */
        
        /* 
          now clean the modem line and activate the settings for the port
        */
         tcflush(fd, TCIFLUSH);
         tcsetattr(fd,TCSANOW,&newtio);
        
        /*
          terminal settings done, now handle input
          In this example, inputting a 'z' at the beginning of a line will 
          exit the program.
        */
         while (STOP==FALSE) {     /* loop until we have a terminating condition */
         /* read blocks program execution until a line terminating character is 
            input, even if more than 255 chars are input. If the number
            of characters read is smaller than the number of chars available,
            subsequent reads will return the remaining chars. res will be set
            to the actual number of characters actually read */
            res = read(fd,buf,8); 
            buf[res]=0;             /* set end of string, so we can printf */
            printf(":%s:%d\n", buf, res);
            if (buf[0]=='t') STOP=TRUE;
         }
         /* restore the old port settings */
         tcsetattr(fd,TCSANOW,&oldtio);
        }
Attachments
uart.png
uart.png (15.25 KiB) Viewed 20801 times

User avatar
yv1hx
Posts: 372
Joined: Sat Jul 21, 2012 10:09 pm
Location: Zulia, Venezuela
Contact: Website

Re: php and uart serial output

Thu Jul 31, 2014 2:35 pm

bufferzone wrote:Hello, I try to read 434MHz radio receiver but all I get are some characters. My module is http://www.wenshing.com.tw/Data_Sheet/R ... _Sheet.pdf and i used the script below:
Anyone can help me please.
bufferzone: I don't know about the php module that you are using, but I should recommend you the following:

Disconnect the radio module from the RaspberryPi, then loop back the Tx and Rx lines, If everything is running well, the characters that you type in should be looped back to your screen without any modifications.

In the other hand, having a look to the radio module specs, seems to be a simple remote controller, are you sure that can be used to send data (even at low speeds)?
Marco-Luis
Telecom Specialist (Now Available for Hire!)

http://www.meteoven.org
http://yv1hx.ddns.net
http://twitter.com/yv1hx

Return to “Other programming languages”