- Demo
- Data flow
- Things used in this project
- Source Code
1. Demo
2. Data flow
3. Things Used In This Project
- PHPoC Blue
- Color 2 click (color sensor)
- Expansion board for Click boards (optional)
- USB wireless LAN dongle
4. Source Code
Apart from library, there are two main source files in PHPoC:
- index.php: once receiving http request from a client, PHPoC executes this file (only executing source inside <?php ?> tag) and then return a html file to client. So, client side is implemented in this file.
- task0.php: this file contains the source code of server side. So you can implement the function to receive the command and control the robot here.
[Source code - index.php]
PHP Code:
<?php
$ws_host = _SERVER("HTTP_HOST");
?>
<!DOCTYPE html>
<html>
<head>
<title>PHPoC Color Sensor</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7">
<style type="text/css">
body { text-align: center; }
#color {
margin-right: auto;
margin-left: auto;
width: 500px;
height: 500px;
background: url(background.png) no-repeat;
background-size: contain;
position: relative;
margin-bottom: 10px;
border: 1px solid #000;
}
</style>
<script type="text/javascript">
var ws = null;
function init()
{
//document.body.style.backgroundColor = "red";
}
function ws_onmessage(e_msg)
{
var arr = JSON.parse(e_msg.data);
var R = Math.round(arr[0]);
var G = Math.round(arr[1]);
var B = Math.round(arr[2]);
var color = "rgb(" + R + ", " + G + ", " + B +")";
//document.body.style.backgroundColor = color;
document.getElementById("color").style.backgroundColor = color;
console.log(color);
}
function ws_onopen()
{
document.getElementById("ws_state").innerHTML = "OPEN";
document.getElementById("wc_conn").innerHTML = "Disconnect";
}
function ws_onclose()
{
document.getElementById("ws_state").innerHTML = "CLOSED";
document.getElementById("wc_conn").innerHTML = "Connect";
console.log("socket was closed");
ws.onopen = null;
ws.onclose = null;
ws.onmessage = null;
ws = null;
}
function wc_onclick()
{
if(ws == null)
{
ws = new WebSocket("ws://<?echo $ws_host?>/phpoc_color_sensor", "csv.phpoc");
document.getElementById("ws_state").innerHTML = "CONNECTING";
ws.onopen = ws_onopen;
ws.onclose = ws_onclose;
ws.onmessage = ws_onmessage;
}
else
ws.close();
}
window.onload = init;
</script>
</head>
<body>
<div id="color" class="arrow_up"></div>
<p>
WebSocket : <span id="ws_state">null</span><br>
</p>
<button id="wc_conn" type="button" onclick="wc_onclick();">Connect</button>
</body>
</html>
[Source code - task0.php]
PHP Code:
<?php
include_once "/PHPoC_ISL29125.php";
include "/lib/sn_tcp_ws.php";
// Read sensor values for each color and print them to serial monitor
function read_rgb()
{
// Read sensor values (16 bit integers)
$red = PHPoC_ISL29125_readRed();
$green = PHPoC_ISL29125_readGreen();
$blue = PHPoC_ISL29125_readBlue();
/*
// Print out readings
echo "\r\n Red: ", $red;
echo "\r\n Green: ", $green;
echo "\r\n Blue: ", $blue;
*/
if(ws_state(0) == TCP_CONNECTED)
{
$wbuf = "[$red, $green, $blue]";
ws_write(0, $wbuf);
}
}
function sensor_setup()
{
// Initialize the ISL29125 with simple configuration so it starts sampling
if (PHPoC_ISL29125_init())
{
echo "Sensor Initialization Successful\n\r";
}
read_rgb();
}
function i2c_sensor_setup()
{
global $pid ;
$pid = pid_open("/mmap/i2c0");
pid_ioctl($pid, "req reset");
pid_ioctl($pid, "set saddr 88");
pid_ioctl($pid, "set mode sm");
pid_ioctl($pid, "set role master");
//pid_close($pid);
}
$pid = 0;
i2c_sensor_setup();
ws_setup(0, "phpoc_color_sensor", "csv.phpoc");
sensor_setup();
sleep(1);
while(1)
{
read_rgb();
usleep(500000);
}
?>
[Library for color sensor - PHPoC_ISL_29125.php]
PHP Code:
<?php
include_once "/lib/sd_340.php";
// ISL29125 I2C Address
define("ISL_I2C_ADDR", 0x44);
// ISL29125 Registers
define("DEVICE_ID", 0x00);
define("CONFIG_1", 0x01);
define("CONFIG_2", 0x02);
define("CONFIG_3", 0x03);
define("THRESHOLD_LL", 0x04);
define("THRESHOLD_LH", 0x05);
define("THRESHOLD_HL", 0x06);
define("THRESHOLD_HH", 0x07);
define("STATUS", 0x08);
define("GREEN_L", 0x09);
define("GREEN_H", 0x0A);
define("RED_L", 0x0B);
define("RED_H", 0x0C);
define("BLUE_L", 0x0D);
define("BLUE_H", 0x0E);
// Configuration Settings
define("CFG_DEFAULT", 0x00);
// CONFIG1
// Pick a mode, determines what color[s] the sensor samples, if any
define("CFG1_MODE_POWERDOWN", 0x00);
define("CFG1_MODE_G", 0x01);
define("CFG1_MODE_R", 0x02);
define("CFG1_MODE_B", 0x03);
define("CFG1_MODE_STANDBY", 0x04);
define("CFG1_MODE_RGB", 0x05);
define("CFG1_MODE_RG", 0x06);
define("CFG1_MODE_GB", 0x07);
// Light intensity range
// In a dark environment 375Lux is best, otherwise 10KLux is likely the best option
define("CFG1_375LUX", 0x00);
define("CFG1_10KLUX", 0x08);
// Change this to 12 bit if you want less accuracy, but faster sensor reads
// At default 16 bit, each sensor sample for a given color is about ~100ms
define("CFG1_16BIT", 0x00);
define("CFG1_12BIT", 0x10);
// Unless you want the interrupt pin to be an input that triggers sensor sampling, leave this on normal
define("CFG1_ADC_SYNC_NORMAL", 0x00);
define("CFG1_ADC_SYNC_TO_INT", 0x20);
// CONFIG2
// Selects upper or lower range of IR filtering
define("CFG2_IR_OFFSET_OFF", 0x00);
define("CFG2_IR_OFFSET_ON", 0x80);
// Sets amount of IR filtering, can use these presets or any value between", 0x00 and", 0x3F
// Consult $datasheet for detailed IR filtering calibration
define("CFG2_IR_ADJUST_LOW", 0x00);
define("CFG2_IR_ADJUST_MID", 0x20);
define("CFG2_IR_ADJUST_HIGH", 0x3F);
// CONFIG3
// No interrupts, or interrupts based on a selected color
define("CFG3_NO_INT", 0x00);
define("CFG3_G_INT", 0x01);
define("CFG3_R_INT", 0x02);
define("CFG3_B_INT", 0x03);
// How many times a sensor sample must hit a threshold before triggering an interrupt
// More consecutive samples means more times between interrupts, but less triggers from short transients
define("CFG3_INT_PRST1", 0x00);
define("CFG3_INT_PRST2", 0x04);
define("CFG3_INT_PRST4", 0x08);
define("CFG3_INT_PRST8", 0x0C);
// If you would rather have interrupts trigger when a sensor sampling is complete, enable this
// If this is disabled, interrupts are based on comparing sensor $data to threshold settings
define("CFG3_RGB_CONV_TO_INT_DISABLE", 0x00);
define("CFG3_RGB_CONV_TO_INT_ENABLE", 0x10);
// STATUS FLAG MASKS
define("FLAG_INT", 0x01);
define("FLAG_CONV_DONE", 0x02);
define("FLAG_BROWNOUT", 0x04);
define("FLAG_CONV_G", 0x10);
define("FLAG_CONV_R", 0x20);
define("FLAG_CONV_B", 0x30);
// Generic I2C read register (single byte)
function PHPoC_ISL29125_read8($addr_reg)
{
global $pid ;
//$pid = pid_open("/mmap/i2c0"); // open I2C 0
pid_ioctl($pid, "req reset");
//pid_write($pid, "\x30\x00");
pid_ioctl($pid, "req write wait");
// register to read
pid_write($pid, $addr_reg, 1);
while(pid_ioctl($pid, "get txlen")); // check transmitted data
pid_ioctl($pid, "req stop"); // stop writing data
$data = 0;
pid_ioctl($pid, "req read 1"); // request to read 1 bytes
while(pid_ioctl($pid, "get rxlen") < 1) // check received data
;
pid_read($pid, $data, 1); // read buffer
//pid_close($pid);
return $data;
}
// Generic I2C write $data to register (single byte)
function PHPoC_ISL29125_write8($addr_reg, $data)
{
global $pid ;
//$pid = pid_open("/mmap/i2c0"); // open I2C 0
pid_ioctl($pid, "req reset");
//pid_write($pid, "\x40\x00");
pid_ioctl($pid, "req write wait");
//register to read
pid_write($pid, $addr_reg, 1);
pid_write($pid, $data, 1);
while(pid_ioctl($pid, "get txlen")); // check received data
pid_ioctl($pid, "req stop"); // stop writing data
//pid_close($pid);
}
// Generic I2C read registers (two bytes, LSB first)
function PHPoC_ISL29125_read16($addr_reg)
{
$data_lsb = 0x00;
$data_msb = 0x00;
global $pid ;
//$pid = pid_open("/mmap/i2c0"); // open I2C 0
pid_ioctl($pid, "req reset");
pid_ioctl($pid, "req write wait");
// register to read
pid_write($pid, $addr_reg, 1);
//while(pid_ioctl($pid, "get txlen")); // check transmitted data
pid_ioctl($pid, "req stop"); // stop writing data
pid_ioctl($pid, "req read 2"); // request to read 1 bytes
while(pid_ioctl($pid, "get rxlen") < 2); // check received data
pid_read($pid, $data_lsb, 1); // read buffer
pid_read($pid, $data_msb, 1); // read buffer
//pid_close($pid);
return ($data_lsb | ($data_msb << 8));
}
// Generic I2C write $data to registers (two bytes, LSB first)
function PHPoC_ISL29125_write16($addr_reg, $data)
{
$data_lsb = $data & 0xff;
$data_msb = $data >> 8;
global $pid ;
//$pid = pid_open("/mmap/i2c0"); // open I2C 0
pid_ioctl($pid, "req reset");
pid_ioctl($pid, "req write wait");
//register to read
pid_write($pid, $addr_reg, 1);
pid_write($pid, $data_lsb, 1);
pid_write($pid, $data_msb, 1);
while(pid_ioctl($pid, "get txlen")); // check received data
pid_ioctl($pid, "req stop"); // stop writing data
//pid_close($pid);
}
// Setup Configuration registers (three registers) - returns 1 if successful
// Use CONFIG1 variables from PHPoC_ISL29125.h for first parameter $config1, CONFIG2 for $config2, 3 for 3
// Use CFG_DEFAULT for default configuration for that register
function PHPoC_ISL29125_config($config1, $config2, $config3)
{
$ret = 1;
$data = 0x00;
// Set 1st configuration register
PHPoC_ISL29125_write8(CONFIG_1, $config1);
// Set 2nd configuration register
PHPoC_ISL29125_write8(CONFIG_2, $config2);
// Set 3rd configuration register
PHPoC_ISL29125_write8(CONFIG_3, $config3);
// Check if configurations were set correctly
$data = PHPoC_ISL29125_read8(CONFIG_1);
if ($data != $config1)
{
$ret &= 0;
}
$data = PHPoC_ISL29125_read8(CONFIG_2);
if ($data != $config2)
{
$ret &= 0;
}
$data = PHPoC_ISL29125_read8(CONFIG_3);
if ($data != $config3)
{
$ret &= 0;
}
return $ret;
}
// Sets upper threshold value for triggering interrupts
function PHPoC_ISL29125_setUpperThreshold($data)
{
PHPoC_ISL29125_write16(THRESHOLD_HL, $data);
}
// Sets lower threshold value for triggering interrupts
function PHPoC_ISL29125_setLowerThreshold($data)
{
PHPoC_ISL29125_write16(THRESHOLD_LL, $data);
}
// Check what the upper threshold is, 0xFFFF by default
function PHPoC_ISL29125_readUpperThreshold()
{
return PHPoC_ISL29125_read16(THRESHOLD_HL);
}
// Check what the upper threshold is, 0x0000 by default
function PHPoC_ISL29125_readLowerThreshold()
{
return PHPoC_ISL29125_read16(THRESHOLD_LL);
}
// Read the latest Sensor ADC reading for the color Red
function PHPoC_ISL29125_readRed()
{
return PHPoC_ISL29125_read16(RED_L);
/*
$data_lsb = PHPoC_ISL29125_read8(RED_L);
$data_msb = PHPoC_ISL29125_read8(RED_H);
return ($data_lsb | ($data_msb << 8));
*/
}
// Read the latest Sensor ADC reading for the color Green
function PHPoC_ISL29125_readGreen()
{
return PHPoC_ISL29125_read16(GREEN_L);
/*
$data_lsb = PHPoC_ISL29125_read8(GREEN_L);
$data_msb = PHPoC_ISL29125_read8(GREEN_H);
return ($data_lsb | ($data_msb << 8));
*/
}
// Read the latest Sensor ADC reading for the color Blue
function PHPoC_ISL29125_readBlue()
{
return PHPoC_ISL29125_read16(BLUE_L);
/*
$data_lsb = PHPoC_ISL29125_read8(BLUE_L);
$data_msb = PHPoC_ISL29125_read8(BLUE_H);
return ($data_lsb | ($data_msb << 8));
*/
}
// Check status flag register that allows for checking for interrupts, brownouts, and ADC conversion completions
function PHPoC_ISL29125_readStatus()
{
return PHPoC_ISL29125_read8(STATUS);
}
// Reset all registers - returns 1 if successful
function PHPoC_ISL29125_reset()
{
$data = 0x00;
// Reset registers
PHPoC_ISL29125_write8(DEVICE_ID, 0x46);
// Check reset
$data = PHPoC_ISL29125_read8(CONFIG_1);
$data |= PHPoC_ISL29125_read8(CONFIG_2);
$data |= PHPoC_ISL29125_read8(CONFIG_3);
$data |= PHPoC_ISL29125_read8(STATUS);
if ($data != 0x00)
{
return 0;
}
return 1;
}
// Initialize - returns 1 if successful
// Starts Wire/I2C Communication
// Verifies sensor is there by checking its device ID
// Resets all registers/configurations to factory default
// Sets configuration registers for the common use case
function PHPoC_ISL29125_init()
{
$ret = 1;
$data = 0x00;
// Check device ID
$data = PHPoC_ISL29125_read8(DEVICE_ID);
if ($data != 0x7D)
{
$ret &= 0;
}
// Reset registers
$ret &= PHPoC_ISL29125_reset();
// Set to RGB mode, 10k lux, and high IR compensation
$ret &= PHPoC_ISL29125_config(CFG1_MODE_RGB | CFG1_10KLUX, CFG2_IR_ADJUST_HIGH, CFG_DEFAULT);
return $ret;
}
Full source code here: PHPoC_Color_Sensor.zip
Thanks, and if you have any question, please don't hesitate to contact me or add comment!