Well, controlling 16x2 LCD is something we usually have in Micro-controller course 101. And here I will show you how to make it more interesting with PHPoC.

Demonstration


This is a simple project that shows how to control LCD16x2 via I2C interface, using PHPoC. It provides a web-based controller for LCD 16x2: just input any sentence, and it will be displayed on LCD after you finish typing.

Hardware components
PHPoC Blue × 1
LCD 16x2 (HD44780U) with I2C interface × 1

Schematics
Connect pin GND, VCC, and SDA and SCL of LCD16x2 to GND, PWR5V, SDA and SCL of PHPoC, respectively.

Click image for larger version

Name:	OBUrF2f.png
Views:	183
Size:	44.9 KB
ID:	414

How it works
PHPoC Blue connects with LCD16x2 via I2C interface.
PHPoC Blue and Web browser exchange data via WebSocket connection, in which PHPoC Blue acts as a WebSocket server. After receiving text data from WS client, it will control LCD 16x2 to display those texts.

Source Code
Source code includes:

init.php : It's run when system boots and specifies which file is run next
PHP Code:
<?php

system
("php task0.php");

?>

task0.php: This file contains server side code. It processes the data sent from the client and controls what to display on LCD16x2.
PHP Code:
<?php 

if(_SERVER("REQUEST_METHOD"))
   exit; 
// avoid php execution via http request


include_once "/lib/sn_tcp_ws.php";
include_once 
"lcd1602_i2c.php";

ws_setup(0"lcd""text.phpoc");
i2c_setup(0LCD_ADDRESS); 
$rbuf ="";

begin();
back_light();
set_cursor(1,0);
lcd_print("PHPoC with LCD");

while (
ws_state(0) != TCP_CONNECTED)
{   
   
sleep(1);
   
scroll_display_left();
   
sleep(1);
   
scroll_display_right();
   
sleep(1);
   
scroll_display_right();
   
sleep(1);
   
scroll_display_left();

}

while(
1)
{
   if(
ws_state(0) == TCP_CONNECTED)
   {
      
$rlen ws_read(0$rbuf);

          if(
$rlen)
        {         
         
clear();
         
home();   

         for (
$i=0;$i<$rlen;$i++)
         {
            
lcd_print($rbuf[$i]);
            if (
$i==15)
            {
               
set_cursor(0,1);
            }
         }                                       
      }                                    
   }


}

?>

index.php: This is client side code. When you input any sentence, the Web client (Web browser) will send it to Web server (PHPoC Blue) via WebSocket connection.
PHP Code:
<!DOCTYPE html>
<html>
<head>
<title>PHPoC - LCD 1602</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7">
<style>
body { text-align: center; font-size: 15pt; font-family: Arial, Helvetica, sans-serif;}
h1 { font-weight: bold; font-size: 25pt; }
h2 { font-weight: bold; font-size: 15pt; }
button { font-weight: bold; font-size: 15pt; }
textarea { width:500px; height:100px; padding:20px; font-family:courier; font-size:50px; background-color: #ccff66;overflow:hidden;word-wrap:break-word;}

</style>
<script>

var ws = null;
var last_sent = null;
var timer = null;

function init()
{
   var lcd_display = document.getElementById("wc_text");
   lcd_display.addEventListener("keydown", key_down);
}


function connect_onclick()
{
   if(ws == null)
   {
      var ws_host_addr = "<?echo _SERVER("HTTP_HOST")?>";
      ws = new WebSocket("ws://" + ws_host_addr + "/lcd", "text.phpoc");
      document.getElementById("ws_state").innerHTML = "CONNECTING";
      ws.onopen = ws_onopen;
      ws.onclose = ws_onclose;
      ws.onmessage = ws_onmessage;
   }
   else
      ws.close();
}


function ws_onopen()
{
   document.getElementById("ws_state").innerHTML = "<font color='blue'>CONNECTED</font>";
   document.getElementById("bt_connect").innerHTML = "DISCONNECT";

}


function key_down()
{
   clearTimeout(timer); 
    timer = setTimeout(send_to_lcd, 2000);
}


function ws_onclose()
{
   document.getElementById("ws_state").innerHTML = "<font color='gray'>NOT CONNECTED</font>";
   document.getElementById("bt_connect").innerHTML = "START";
   ws.onopen = null;
   ws.onclose = null;
   ws.onmessage = null;
   ws = null;

}


function ws_onmessage(e_msg)
{
   e_msg = e_msg || window.event;    
   alert("msg : " + e_msg.data);
}


function send_to_lcd()
{
   var val = document.getElementById("wc_text").value;

   if(ws != null)
   {
      if (val != last_sent)
      {
         last_sent = val;         
         ws.send(val);
      }
   }
}

window.onload = init;
</script>
</head>

<body>
<center>
<p>
<h1>PHPoC - LCD 1602</h1>
</p>

<h2>

<p>
<textarea id="wc_text" class="input" type="text" cols="20" rows="2" maxlength="32" font="Courier" ></textarea><br>
</p>

<p>
WebSocket : <span id="ws_state">null</span>
</p>

<button id="bt_connect" type="button" onclick="connect_onclick();">START</button>
</h2>
</center>
</body>
</html>

lcd1602_i2c.php : LCD16x2 library with I2C interface for PHPoC.
PHP Code:
<?php
include_once "/lib/sd_340.php";

// Device I2C Adrress
define ("LCD_ADDRESS",      0x3F);

// LCD commands
define ("LCD_CLEARDISPLAY",      0x01);
define ("LCD_RETURNHOME",      0x02);
define ("LCD_ENTRYMODESET",    0x04);
define ("LCD_DISPLAY_CONTROL",   0x08);
define ("LCD_CURSORSHIFT",      0x10);
define ("LCD_FUNCTIONSET",      0x20);
define ("LCD_SETCGRAMADDR",      0x40);
define ("LCD_SETDDRAMADDR",      0x80);

// Flags for display entry mode
define ("LCD_ENTRYRIGHT",         0x00);
define ("LCD_ENTRYLEFT",         0x02);
define ("LCD_ENTRYSHIFTINCREMENT",   0x01);
define ("LCD_ENTRYSHIFTDECREMENT",    0x00);

// Flags for display on/off control
define ("LCD_DISPLAYON",      0x04);
define ("LCD_DISPLAYOFF",      0x00);
define ("LCD_CURSORON",         0x02);
define ("LCD_CURSOROFF",      0x00);
define ("LCD_BLINKON",         0x01);
define ("LCD_BLINKOFF",         0x00);

// Flags for display/cursor shift
define ("LCD_DISPLAYMOVE",   0x08);
define ("LCD_CURSORMOVE",   0x00);
define ("LCD_MOVERIGHT",   0x04);
define ("LCD_MOVELEFT",      0x00);

// Flags for function set
define ("LCD_8BITMODE",      0x10);
define ("LCD_4BITMODE",      0x00);
define ("LCD_2LINE",      0x08);
define ("LCD_1LINE",      0x00);
define ("LCD_5x10DOTS",      0x04);
define ("LCD_5x8DOTS",      0x00);
define ("LCD_BACKLIGHT",    0x08);
define ("LCD_NOBACKLIGHT",    0x00);

// Bit control
define ("EN",    0x04); //Enable bit
define ("RS",   0x01); //Register select

$display_control 0;
$display_function 0;
$backlight_val 0;
$display_mode 0;

function 
expander_write($data)
{
   global 
$backlight_val;
   
i2c_write(0, ($data $backlight_val) , 1);      
}

function 
pulse_enable($data)
{
   
expander_write($data EN);
   
usleep(1);
   
expander_write($data & (~EN));
   
usleep(50);
}

function 
write_nibble($data)
{
   
expander_write($data);
   
pulse_enable($data);   
}

function 
send_data($value$mode)
{
   
$high_nib$value&0xf0;
   
$low_nib=($value<<4)&0xf0;
    
write_nibble(($high_nib)|$mode);
   
write_nibble(($low_nib)|$mode);    
}

function 
command($cmd)
{
   
send_data($cmd0);
}

function 
display() 
{
   global 
$display_control;
    
$display_control |= LCD_DISPLAYON;
    
command(LCD_DISPLAY_CONTROL $display_control);
}

function 
clear()
{
    
command(LCD_CLEARDISPLAY);           
    
usleep(2000);                      
}

function 
home()
{
    
command(LCD_RETURNHOME);        
    
usleep(2000);                   
}

function 
back_light() {
   global 
$backlight_val;
   
$backlight_val LCD_BACKLIGHT;
   
expander_write(0);
}

function 
no_back_light() {
   global 
$backlight_val;
   
$backlight_val LCD_NOBACKLIGHT;
   
expander_write(0);
}

function 
print_ascii($data)
{
   
send_data($dataRS);      
}

function 
lcd_print($str) {
   
$len strlen($str);
   for (
$i=0$i $len$i++)
   {
      
$cur_char bin2int($str$i1);
      
print_ascii($cur_char);
   }
}

function 
scroll_display_left() {
   
command(LCD_CURSORSHIFT LCD_DISPLAYMOVE LCD_MOVELEFT);
}

function 
scroll_display_right() {
   
command(LCD_CURSORSHIFT LCD_DISPLAYMOVE LCD_MOVERIGHT);
}

function 
set_cursor($col$row){
   
$row_offsets = array(0x000x40);
   if ((
$row==0)||($row==1))
   {
      
command(LCD_SETDDRAMADDR | ($col $row_offsets[$row]));
   }
   else
   {
      echo 
"Please select row value again";
      return;
   }   
}

function 
begin()
{
   global 
$display_control$backlight_val$display_mode;

   
$display_function LCD_4BITMODE LCD_2LINE LCD_5x8DOTS;   

   
// Wait for more than 40ms after Vcc rises to 2.7V
   
usleep(50000); 

   
// Turn backlight off
   
$backlight_val LCD_NOBACKLIGHT;
   
expander_write($backlight_val);
   
usleep(1000);

    
write_nibble(0x03 << 4);
   
// Wait for more than 4.1ms
    
usleep(4500); 

   
write_nibble(0x03 << 4);
   
// Wait for more than 4.1ms
   
usleep(4500);

   
write_nibble(0x03 << 4); 
   
// Wait for more than 100us
   
usleep(150);

      
// Set to 4-bit interface
   
write_nibble(0x02 << 4); 

   
// Set number of lines, font size
   
command(LCD_FUNCTIONSET $display_function);  

   
// Turn the display on with no cursor or blinking default
   
$display_control LCD_DISPLAYON LCD_CURSOROFF LCD_BLINKOFF;
   
display();

   
// Clear LCD
   
clear();

   
// Initialize to default text direction 
   
$display_mode LCD_ENTRYLEFT LCD_ENTRYSHIFTDECREMENT;

   
// Set the entry mode
   
command(LCD_ENTRYMODESET $display_mode);

   
home();

}

?>