Saturday, 2 May 2015

RaspberryPi, Serial Comms & PHP

I've been playing around with serial comms on 2 Raspberry Pi computers for the last couple of days.


And I now understand a little of the black-art required to get this working, including how to send serial data via a PHP web page.


So I thought I'd write up the details before I have time to forget it all again!

There are two pins available on the Pi header for simple serial comms: pin 8 (transmit data) and pin 10 (receive data). On Raspbian this port or device appears as: /dev/ttyAMA0.

Configuration


But before you can use this serial port, you may need to modify a couple of files on the Pi (modify as root user). We basically need to free-up this port for our use, and stop it being used for something else.

So type in a terminal:-

sudo pcmanfm

Now navigate to /boot/cmdline.txt and open with LeafPad. Look for any string entries containing: /dev/ttyAMA0

For example:-

console=ttyAMA0,115200

...and carefully delete them. You should end up with a series of strings/commands separated by spaces, for example:-

dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait

Save changes and navigate to: /etc/inittab

Open file and look for an entry containing /dev/ttyAMA0 which you should just comment out like this:-

#Spawn a getty on Raspberry Pi serial line
#T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100


Finally, to allow any PHP code on our web server to control this serial port we need to add the user to the dialout group. So in a terminal:-

sudo usermod -a -G dialout www-data

Note: www-data is the user running on my web server. Take a look at my earlier posts to see how my web server is configured using lighttpd and PHP.

Now re-boot.

Serial comms test


We need to test that serial comms is working, before we try and do anything clever with PHP. Open a terminal and install minicom:-

sudo apt-get install minicom

Carefully fit a jumper wire or link to connect pin 8 to pin 10.

In a terminal type:-

sudo minicom -D /dev/ttyAMA0 -b 9600

You should see a "Welcome to minicom..." message.

If you press <ctrl><a> you should get an information bar at the bottom of the terminal. Press <ESC> to clear the bar, and then type something, e.g. hello!

Your message should be displayed, which shows that your loop-back test was successful (i.e. you sent characters out via TXD and got them back via RXD.

Not convinced? Then remove the link between pins 8 and 10, and then try again. As you type, the screen does not show the result..

If you have a second Pi, you can run minicom on both systems, and connect pin 8 from one Pi to pin 10 to the other.

Two Pies are better than one


Make sure you also link the two Pi common/gnd together. Now you can test by sending a message from one Pi to the other.

Using PHP


I guess there may be several methods of using PHP with the serial port, but I found this easy code called PHP-Serial. There is a project on GitHub, but you just need to take a copy of the file. You will need to add a closing "?>" which seems to be missing from this file.

This file should be saved in your servers web root (in my case, this is the /var/www directory).

Now all you need is a php file to use this PHP-Serial class. Here is a simple example which I called LoopBack.php:-

<?php
echo exec('whoami');
error_reporting(E_ALL);
ini_set('display_errors', '1');

include "php_serial_class.php";

// create an instance of the class
$serial = new PhpSerial;

$serial->deviceSet("/dev/ttyAMA0");

// We can change the baud rate, parity, length, stop bits, flow control
$serial->confBaudRate(9600);
$serial->confParity("none");
$serial->confCharacterLength(8);
$serial->confStopBits(1);
$serial->confFlowControl("none");

$serial->deviceOpen();

// write

$serial->sendMessage("Hello!");
//Read from
usleep((int) (1000000));
$message = $serial->readPort();
echo ( "<br>Received: $message<br>" );
$serial->deviceClose();
?>



But it doesn't work!


The bad news is that I spent a few hours one evening, desperately trying to get this loop-back program to work, before giving up and going to bed tired and a little bit grumpy!

But when I woke in the morning, I had two words on my mind: "half duplex".

This code cannot work in full-duplex mode. When characters are transmitted, they are not being "instantly" read. If the Pi is buffering them, then I don't know how to point to the start of the buffer and read it.

However, by connecting a second Pi, I can show that the "write" method in this class does work and can transmit. Using minicom on the second Pi shows my message "Hello!" is received.

So we can use this PHP code in half-duplex mode.

Note that we do not need to use wiringPi to access TXD/RXD. The PHP-Serial class is simple to understand and can handle the RaspberryPi serial pins or USB.

2 comments:

  1. Well done Steve, tried it on my Pi2 and it works a treat.

    Still can't figure why the wiringPi serial library doesn't work though :-(

    ReplyDelete
    Replies
    1. I am glad this is now working for you.

      As for wiringPi, you could try sending Gordon an email: http://wiringpi.com/contact/

      I've always found him willing to offer advice.

      Delete