In a previous article, I introduced internet IR solution. It has advantage and disadvantages as follows:
Advantages:
- Extend the control distance to unlimited, allowing controlling devices everywhere.
- Require to capture IR signal, analyze it to get data (devices address and command), it may be difficult for a newbie to understand.
- Specific to a kind of device, it need to capture IR signal, analyze again for new devices.
To take advantage and overcome the shortcoming of the previous solution, I introduce a new method: IR imitator. This solution allows imitating IR signal of any controller, save it in memory and then control it through internet.
There are two more advantages:
- No need to analyze IR signal.
- Work with every device.
The following image illustrates how system work.
User can use smart phone, computer or any kind devices which support web browser to access web application. This web application can switch between two modes: imitating mode (setting mode) and control mode.
Setting mode:
- Capture IR pulse chain from any remote controller,
- Assign a button to this pulse chain,
- Save this chain in FLASH memory along with a selected button.
- Buttons which were assigned to pulse chain will be activated
- If an activated button is clicked, the control command will be sent along with the button name to PHPoC. PHPoC lookup the pulse chain with respect to button name in memory. And then the pulse chain will be outputted to IR emitter. Therefore, you can control your devices.
Demo
Things Used In This Project
- One PHPoC Blue
- One Grove IR receiver
- One Grove IR emitter
- One Resistor 1kΩ
- Grove expansion board (optional)
Wiring Diagram
Working Flow
Setting mode
Controlling mode
Source Code
Client side (index.php)
PHP Code:
<!DOCTYPE html>
<html>
<head>
<title>PHPoC</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=1.0, minimum-scale=0.5, user-scalable=yes">
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
body { font-family: verdana, Helvetica, Arial, sans-serif, gulim; }
.superHeader {height: 2em; color: white; background-color: rgb(0,153,153);; z-index:5;}
.gap {height: 5px;z-index:0;}
.midHeader {color: white; background-color: rgb(6, 38, 111); z-index:3;}
.headerTitle {
font-size: 250%;
font-weight: normal;
font-family: impact;
padding: 5px;
}
.headerMenu{
width: 450px;
padding: 5px;
}
#footer{margin:0 auto; height:auto !important; height:100%; margin-bottom:-100px; }
.superFooter {
height: 2em; color: white; background-color: rgb(6, 38, 111); font-size:9pt; position:fixed; left:0; right:0; bottom:0; z-index:4;
}
#control_area {
margin-right: auto;
margin-left: auto;
width: 480px;
height: 480px;
position: relative;
}
.button1, .button2 {
background-color: LightGray;
border-width:2px;
border-style:groove;
color: white;
text-align: center;
text-decoration: none;
display: inline-block;
cursor: pointer;
position: absolute;
z-index:3;
}
.button1 {
font-size: 20px;
border-radius: 50%;
}
#setup_area {
margin-top: 10px;
margin-right: auto;
margin-left: auto;
width: 480px;
height: 100px;
position: relative;
margin-bottom: 10px;
display: none;
}
.button2 {
float: right;
margin: 5px;
margin-right:10px;
width: 80px;
height: 40px;
line-height: 40px;
font-size: 18px;
border-radius: 50%;
}
#SCAN {
float: right;
}
#SAVE {
float: right;
}
#bar {
background-color : rgb(6, 38, 111);
width: 350px; height: 5px;
z-index:3;
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script type="text/javascript">
//command sent from client to PHPoC
var CMD_GET_CONFIG = 0x01;
var CMD_CONTROL = 0x02;
var CMD_UPDATE = 0x03;
var CMD_SCAN = 0x04;
var CMD_TEST = 0x05;
var CMD_SCAN_CANCEL = 0x06;
//command sent from PHPoC to client
var _CMD_CONFIG_DATA = 0x11;
var _CMD_SCANNED = 0x12;
var _CMD_UPDATED = 0x13;
var MODE_NOMAL = 0;
var MODE_SETTING = 1;
var STATE_UNSCAN = 0x01;
var STATE_SCANNING = 0x02;
var STATE_SCANNED = 0x03;
var setup_state = STATE_UNSCAN;// state of setup mode
var btn_states = null; // an array to store button state (clickable or unclickable)
var mode = MODE_NOMAL;
var color_clickable = "DarkCyan";
var color_clicked = "Aqua";
var color_unclickable = "LightGray";
var color_setup = "OrangeRed";
var btn_array = [
["A", "B", "C"],
["D", "E", "F"],
["G", "H", "I"]
];
var setup_button_id = null;
var connected = false;
var ws = null;
function init()
{
var view = document.querySelector("#mode_option");
view.onclick = option_onclick;
var controls = document.querySelector("#control_area");
var setups = document.querySelector("#setup_area");
controls.ontouchstart = setups.ontouchstart = mouse_down;
controls.ontouchend = setups.ontouchend = mouse_up;
controls.ontouchcancel = setups.ontouchcancel = mouse_up;
controls.onmousedown = setups.onmousedown = mouse_down;
controls.onmouseup = setups.onmouseup = mouse_up;
controls.onmouseout = setups.onmouseout = mouse_up;
var btn_width = 70;
var btn_height = 70;
var gap = 30;
controls.style.width = (3*btn_width + 4*gap) + "px";
controls.style.height = (3*btn_height + 4*gap) + "px";
var y = gap;
var x = gap;
for(var j = 0; j < 3; j++)
{
for(var i = 0; i < 3; i++)
{
var button = document.getElementById(btn_array[i][j]);
button.style.width = btn_width + "px";
button.style.height = btn_height + "px";
button.style.lineHeight = btn_height + "px";
button.style.left = x + "px";
button.style.top = y + "px";
y += btn_height + gap;
}
x += btn_width + gap;
y = gap;
}
var width = (3*btn_width + 4*gap);
setups.style.width = width + "px";
setups.style.height = (100 + gap) + "px";
var button = document.getElementById("SCAN");
button.style.left = 2*gap + "px";
button.style.top = "0px";
button = document.getElementById("TEST");
button.style.left = (width-2*gap-80) + "px";
button.style.top = "0px";
button = document.getElementById("SAVE");
button.style.left = (width/2 - 40) + "px";
button.style.top = "50px";
}
function ws_onmessage(e_msg)
{
var arr = JSON.parse(e_msg.data);
switch(arr.cmd)
{
case _CMD_CONFIG_DATA:
btn_states = arr.data;
break;
case _CMD_SCANNED:
setup_state = STATE_SCANNED;
break;
case _CMD_UPDATED:
setup_state = STATE_UNSCAN;
setup_button_id = null;
btn_states = arr.data;
break;
}
update_view();
}
function ws_onopen()
{
document.getElementById("ws_state").innerHTML = "OPEN";
document.getElementById("wc_conn").innerHTML = "Disconnect";
send_command(CMD_GET_CONFIG);
connected = true;
}
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;
connected = false;
setup_state = STATE_UNSCAN;
update_view();
}
function wc_onclick()
{
if(ws == null)
{
ws = new WebSocket("ws://<?echo _SERVER("HTTP_HOST")?>/phpoc_infrared", "csv.phpoc");
document.getElementById("ws_state").innerHTML = "CONNECTING";
ws.onopen = ws_onopen;
ws.onclose = ws_onclose;
ws.onmessage = ws_onmessage;
}
else
ws.close();
}
function mouse_down(event)
{
if (connected && event.target !== event.currentTarget)
{
var id = event.target.id;
if(event.currentTarget.id == "control_area")
{
if(mode == MODE_NOMAL)
{
if (btn_states != null && btn_states[id])
{
event.target.style.backgroundColor = color_clicked;
send_command(CMD_CONTROL + " " + id);
}
}
else
{
setup_button_id = id;
update_view();
}
}
else if (event.currentTarget.id == "setup_area")
{
switch (id)
{
case "SCAN":
setup_state = STATE_SCANNING;
send_command(CMD_SCAN);
event.target.style.backgroundColor = color_clicked;
break;
case "SAVE":
if(setup_button_id != null && setup_state == STATE_SCANNED)
{
send_command(CMD_UPDATE + " " + setup_button_id);
document.getElementById("SCAN").style.backgroundColor = color_clicked;
document.getElementById("SAVE").style.backgroundColor = color_clicked;
document.getElementById("TEST").style.backgroundColor = color_unclickable;
}
break;
case "TEST":
if(setup_button_id != null && setup_state == STATE_SCANNED)
{
send_command(CMD_TEST);
event.target.style.backgroundColor = color_clicked;
}
break;
}
}
}
event.stopPropagation();
event.preventDefault();
}
function mouse_up(event)
{
if (connected && event.target !== event.currentTarget)
{
if(mode == MODE_NOMAL)
{
var id = event.target.id;
if (btn_states != null && btn_states[id])
event.target.style.backgroundColor = color_clickable;
}
else if(setup_button_id != null && setup_state == STATE_SCANNED)
document.getElementById("TEST").style.backgroundColor = color_clickable;
}
event.stopPropagation();
event.preventDefault();
}
function option_onclick(event)
{
if (event.target !== event.currentTarget)
{
var id = event.target.id;
setup_state = STATE_UNSCAN;
setup_button_id = null;
if(id == "setup")
{
mode = MODE_SETTING;
$("#setup_area").show();
}
else
{
mode = MODE_NOMAL;
send_command(CMD_SCAN_CANCEL);
$("#setup_area").hide();
}
update_view();
}
}
function send_command(cmd)
{
if(ws != null)
if(ws.readyState == 1)
ws.send(cmd + " \r\n");
console.log("send comand" + cmd);
}
function update_view()
{
if(connected)
{
if(mode == MODE_NOMAL)
{
for (btn in btn_states)
{
if (btn_states[btn])
document.getElementById(btn).style.backgroundColor = color_clickable;
else
document.getElementById(btn).style.backgroundColor = color_unclickable;
}
document.getElementById("SCAN").style.backgroundColor = color_unclickable;
document.getElementById("SAVE").style.backgroundColor = color_unclickable;
document.getElementById("TEST").style.backgroundColor = color_unclickable;
}
else
{
for (btn in btn_states)
{
if (btn_states[btn])
document.getElementById(btn).style.backgroundColor = color_clickable;
else
document.getElementById(btn).style.backgroundColor = color_unclickable;
if (setup_button_id != null && btn == setup_button_id)
document.getElementById(btn).style.backgroundColor = color_setup;
}
switch(setup_state)
{
case STATE_UNSCAN:
document.getElementById("SCAN").style.backgroundColor = color_clickable;
document.getElementById("SAVE").style.backgroundColor = color_unclickable;
document.getElementById("TEST").style.backgroundColor = color_unclickable;
break;
case STATE_SCANNING:
// SCAN button is blinking. see setInterval function
document.getElementById("SAVE").style.backgroundColor = color_unclickable;
document.getElementById("TEST").style.backgroundColor = color_unclickable;
break;
case STATE_SCANNED:
document.getElementById("SCAN").style.backgroundColor = color_clicked;
document.getElementById("SAVE").style.backgroundColor = color_clickable;
document.getElementById("TEST").style.backgroundColor = color_clickable;
break;
}
}
}
else
{
for(var j = 0; j < 3; j++)
for(var i = 0; i < 3; i++)
document.getElementById(btn_array[i][j]).style.backgroundColor = color_unclickable;
document.getElementById("SAVE").style.backgroundColor = color_unclickable;
document.getElementById("SCAN").style.backgroundColor = color_unclickable;
document.getElementById("TEST").style.backgroundColor = color_unclickable;
}
}
setInterval(function () {
$("#SCAN").css("background-color", function () {
if(setup_state == STATE_SCANNING)
{
this.switch = !this.switch
return this.switch ? color_clickable : color_clicked;
}
});
}, 500);
window.onload = init;
</script>
</head>
<body>
<center>
<div class="superHeader"></div>
<div class="gap"></div>
<div class="midHeader">
<div class="headerTitle">PHPoC Smart IR</div>
<div class="headerMenu">
<div id="mode_option" >
<input type="radio" id="normal" name="mode" value="normal" checked> REMOTE CON
<input type="radio" id="setup" name="mode" value="setup"> SETTUP
</div>
</div>
</div>
<div id="control_area">
<div id ="A" class="button1">A</div>
<div id ="B" class="button1">B</div>
<div id ="C" class="button1">C</div>
<div id ="D" class="button1">D</div>
<div id ="E" class="button1">E</div>
<div id ="F" class="button1">F</div>
<div id ="G" class="button1">G</div>
<div id ="H" class="button1">H</div>
<div id ="I" class="button1">I</div>
</div>
<div id="bar"></div>
<div id="setup_area">
<div id ="SAVE" class="button2">save</div>
<div id ="TEST" class="button2">test</div>
<div id ="SCAN" class="button2">scan</div>
</div>
<p>
WebSocket : <span id="ws_state">null</span><br>
</p>
<button id="wc_conn" type="button" onclick="wc_onclick();">Connect</button>
<div id="footer">
<div class="superFooter">
</div>
</div>
</center>
</body>
</html>
Server side (task0.php)
PHP Code:
<?php
if(_SERVER("REQUEST_METHOD"))
exit; // avoid php execution via http request
include_once "/lib/sd_340.php";
include_once "/lib/sc_envu.php";
include_once "/lib/sn_tcp_ws.php";
include_once "/lib/vd_nec_infrared.php";
define("CMD_GET_CONFIG", 0x01); // client to server
define("CMD_CONTROL", 0x02);
define("CMD_UPDATE", 0x03);
define("CMD_SCAN", 0x04);
define("CMD_TEST", 0x05);
define("CMD_SCAN_CANCEL", 0x06);
define("_CMD_CONFIG_DATA", 0x11); // server to client
define("_CMD_SCANNED", 0x12);
define("_CMD_UPDATED", 0x13);
$nvp_list = "";
/**
This function is used to load data from flash memory right after bootup.
**/
function load_data()
{
global $nvp_list;
$envu = envu_read("envu");
if( $envu === "")
{
$envu = "A=>0=>0=>0=>0\r\nB=>0=>0=>0=>0\r\nC=>0=>0=>0=>0\r\nD=>0=>0=>0=>0\r\nE=>0=>0=>0=>0\r\nF=>0=>0=>0=>0\r\nG=>0=>0=>0=>0\r\nH=>0=>0=>0=>0\r\nI=>0=>0=>0=>0";
envu_write("envu", $envu, strlen($envu), 0);
$envu = envu_read("envu");
}
$nvp_list = explode("\r\n", $envu, 9);
for($i = 0; $i < count($nvp_list); $i++)
{
$nvp = explode("=>", $nvp_list[$i], 5);
$nvp_list[$i] = $nvp;
}
}
/**
This function get button state and format it to json string.
**/
function get_config($cmd = _CMD_CONFIG_DATA)
{
global $nvp_list;
$json_str = '{"cmd":' . sprintf("%d", $cmd, 1) . ', "data":{';
for($i = 0; $i < count($nvp_list); $i++)
{
$nvp = $nvp_list[$i];
//$nvp[0] is button name, $nvp[1] is buton's state: 0->unset, 1:->set
$json_str .= ('"' . $nvp[0]. '":' .$nvp[1]. ',');
}
$json_str = rtrim($json_str, ","); // remove the last comma
$json_str .= "}}";
return $json_str;
}
function control($button)
{
global $nvp_list;
for($i = 0; $i < count($nvp_list); $i++)
{
$nvp = $nvp_list[$i];
if( ($nvp[0] == $button) && ((int)$nvp[1] == 1))
{
infrared_emit($nvp[4], (int)$nvp[2], (float)$nvp[3]);
break;
}
}
}
function update($btn_name, $btn_state, $count_buf, $count, $unit)
{
global $nvp_list;
$btn_name = ltrim(rtrim($btn_name));
$btn_state = sprintf("%d", $btn_state, 1);
$count = sprintf("%d", $count);
$unit = sprintf("%.1f", $unit);
$envu = "";
for($i = 0; $i < count($nvp_list); $i++)
{
if($nvp_list[$i][0] == $btn_name)
{
$nvp_list[$i][0] = $btn_name; // button name
$nvp_list[$i][1] = $btn_state; // button state: 0->unset, 1->set
$nvp_list[$i][2] = $count;
$nvp_list[$i][3] = $unit;
$nvp_list[$i][4] = $count_buf;
}
$envu .= ($nvp_list[$i][0] . "=>" . $nvp_list[$i][1] . "=>" . $nvp_list[$i][2] . "=>" . $nvp_list[$i][3] . "=>" . $nvp_list[$i][4]."\r\n");
}
$envu = rtrim($envu, "\r\n");
envu_write("envu", $envu, strlen($envu), 0);
envu_read("envu");
}
$rbuf = "";
$unit = 562.5 / 5;
$repc = 80;
$lower_bound = 1000;
$upper_bound = 14000;
$min_count = 15;
$count_buf = "";
$cnt_buf_len = 0;
$is_scanning = false;
ws_setup(0, "phpoc_infrared", "csv.phpoc");
load_data();
//hexdump( get_config());
while(1)
{
if(ws_state(0) == TCP_CONNECTED)
{
$rlen = ws_read_line(0, $rbuf);
if($rlen)
{
$data = explode(" ", $rbuf);
$cmd = (int)$data[0];
switch($cmd)
{
case CMD_GET_CONFIG:
ws_write(0, get_config());
break;
case CMD_CONTROL:
control($data[1]);
break;
case CMD_TEST:
infrared_emit($count_buf, $cnt_buf_len, $unit);
break;
case CMD_UPDATE:
//update
update($data[1], 1, $count_buf, $cnt_buf_len, $unit);
ws_write(0, get_config(_CMD_UPDATED));
$is_scanning = false;
break;
case CMD_SCAN:
$is_scanning = true;
break;
case CMD_SCAN_CANCEL:
$is_scanning = false;
break;
}
}
}
else
$is_scanning = false;
if($is_scanning)
{
infrared_capture_start($unit, $repc);
usleep(500000);
infrared_recv_stop();
if(infrared_available($lower_bound, $upper_bound))
{
echo "\r\n";
$count_buf = int2bin(1, 2); // first value is dummy.
$cnt_buf_len = 1;
for($i = 0; $i <= $repc; $i++)
{
//get width of pulses
$count = infrared_get_raw_count($i);
if($count > 2 && $count <100)
{
$count_buf .= int2bin($count, 2);
$cnt_buf_len++;
echo "$count, ";
}
}
if( $cnt_buf_len >= $min_count)
{
if(ws_state(0) == TCP_CONNECTED)
{
ws_write(0, '{"cmd":' . sprintf("%d", _CMD_SCANNED, 1) . '}');
}
$is_scanning = false;
}
}
}
}
?>
Library (vd_nec_infrared.php)
PHP Code:
<?php
if(_SERVER("REQUEST_METHOD"))
exit; // avoid php execution via http request
include_once "/lib/sd_340.php";
define("BASIC_CLOCK", 42000000); // basic clock of PHPoC 42MHz
$recv_ht_id = 0; // timer id which connect to an infrared receiver to capture data
$emit_control_ht_id = 1; // timer id which control an infrared emitter
$emit_carrier_ht_id = 2; // timer id which create the carier for infrared modulation
function infrared_setup($rec_ht_id, $control_ht_id, $carrier_ht_id)
{
global $recv_ht_id;
global $emit_control_ht_id;
global $emit_carrier_ht_id;
$recv_ht_id = $rec_ht_id;
$emit_control_ht_id = $control_ht_id;
$emit_carrier_ht_id = $carrier_ht_id;
}
/*
This function make timer to start capturing signal from an infrared receiver.
It is used to analyze the pulse chain, so it it set to capture toggle mode.
Paramerer:
-$unit (microsecond);
-$repc: the number of pulse need to be captured
*/
function infrared_capture_start($unit, $repc)
{
global $recv_ht_id;
$repc++; // plus one dummy pulse
$unit = $unit * BASIC_CLOCK / 1000000;
// setup capture timer
ht_ioctl($recv_ht_id, "reset");
ht_ioctl($recv_ht_id, "set div $unit");
ht_ioctl($recv_ht_id, "set mode capture toggle");
ht_ioctl($recv_ht_id, "set trigger from pin fall");
ht_ioctl($recv_ht_id, "set repc $repc");
ht_ioctl($recv_ht_id, "start"); // start trigger pulse
}
/*
This function make timer to start capturing signal from an infrared receiver.
It is used to get data, so it it set to capture fall mode.
Paramerer:
-$unit (microsecond);
-$repc: the number of pulse need to be captured
*/
function infrared_recv_start($unit, $repc)
{
global $recv_ht_id;
$repc++; // plus one dummy pulse
$unit = $unit * BASIC_CLOCK / 1000000;
// setup capture timer
ht_ioctl($recv_ht_id, "reset");
ht_ioctl($recv_ht_id, "set div $unit");
ht_ioctl($recv_ht_id, "set mode capture fall");
ht_ioctl($recv_ht_id, "set trigger from pin fall");
ht_ioctl($recv_ht_id, "set repc $repc");
ht_ioctl($recv_ht_id, "start"); // start trigger pulse
}
function infrared_recv_stop()
{
global $recv_ht_id;
ht_ioctl($recv_ht_id, "stop");
}
function infrared_carrier_start($freq)
{
global $emit_carrier_ht_id;
$div = BASIC_CLOCK / ($freq * 2);
ht_ioctl($emit_carrier_ht_id, "reset");
ht_ioctl($emit_carrier_ht_id, "set div $div"); // div 13.14us
ht_ioctl($emit_carrier_ht_id, "set mode output pwm");
ht_ioctl($emit_carrier_ht_id, "set output od");
ht_ioctl($emit_carrier_ht_id, "set count 1 1");
ht_ioctl($emit_carrier_ht_id, "start");
}
function infrared_carrier_stop()
{
global $emit_carrier_ht_id;
ht_ioctl($emit_carrier_ht_id, "stop");
ht_ioctl($emit_carrier_ht_id, "set output high");
}
/*
see nec_infrared_send($data, $bit_length) function to know how to use this function
*/
function infrared_emit($count_buf, $cnt_buf_len, $unit)
{
global $emit_control_ht_id;
$unit = $unit * BASIC_CLOCK / 1000000;
infrared_carrier_start(38000); //enable 38KHz PWM signal - carrier frequency
//ht_ioctl($emit_control_ht_id, "reset");
ht_ioctl($emit_control_ht_id, "set div $unit");
ht_ioctl($emit_control_ht_id, "set mode output toggle"); // set mode: toggle
ht_ioctl($emit_control_ht_id, "set output od");
$pid_ht = pid_open("/mmap/ht$emit_control_ht_id");
pid_write($pid_ht, $count_buf);
pid_ioctl($pid_ht, "set repc $cnt_buf_len");
pid_close($pid_ht);
ht_ioctl($emit_control_ht_id, "start"); // start HT
while(ht_ioctl($emit_control_ht_id, "get state"));
ht_ioctl($emit_control_ht_id, "stop");
infrared_carrier_stop(); // stop to save energy.
}
/*
Paramerer:
-$lower_bound: minimum value of the first captured pulse in microsecond
-$upper_bound: minimum value of the first captured pulse in microsecond
Return:
-true: value of the first captured pulse varies from $lower_bound to $upper_bound
-false: otherwise.
*/
function infrared_available($lower_bound, $upper_bound)
{
global $recv_ht_id;
$unit = ht_ioctl($recv_ht_id, "get div"); // in number clock stick
$unit = $unit * 1000000 / BASIC_CLOCK; // in microsecond
$lower_bound /= $unit;
$upper_bound /= $unit;
$count = ht_ioctl($recv_ht_id, "get count 1");
if( ($count >= $lower_bound) && ($count <= $upper_bound))
return true;
return false;
}
/*
Paramerer: $count_id start from 0.
Return: width of captured pulse in microsecond
*/
function infrared_get_count($count_id)
{
global $recv_ht_id;
$count_id++; // due to the dummy value (first value)
$unit = ht_ioctl($recv_ht_id, "get div");
$count = ht_ioctl($recv_ht_id, "get count $count_id");
$reval = $unit * $count * 1000000 / BASIC_CLOCK;
return $reval;
}
/*
Paramerer: $count_id start from 0.
Return: width of captured pulse in unit
*/
function infrared_get_raw_count($count_id)
{
global $recv_ht_id;
$count_id++; // due to the dummy value (first value)
$count = ht_ioctl($recv_ht_id, "get count $count_id");
return $count;
}
function nec_infrared_send($data, $bit_length)
{
$unit = 562.5;// 562.5¥ìs
$count_buf = int2bin(1, 2); // first value is dummy.
$count_buf .= int2bin(16, 2); // 9ms leading pulse burst (16 * 562.5us)
$count_buf .= int2bin(8, 2); // 4.5ms space (8 * 562.5us)
$cnt_buf_len = 3;
$mask = 1 << ($bit_length-1);
while($mask)
{
$count_buf .= int2bin(1, 2); // 562.5¥ìs pulse burst
$cnt_buf_len++;
if($data & $mask)
{
$count_buf .= int2bin(3, 2); // logical 1: 1.6875ms space
}
else
{
$count_buf .= int2bin(1, 2); // Logical 0 562.5¥ìs space
}
$cnt_buf_len++;
$mask = $mask >> 1;
}
$count_buf .= int2bin(1, 2); // 562.5¥ìs stop code
$cnt_buf_len++;
infrared_emit($count_buf, $cnt_buf_len, $unit);
}
function nec_infrared_recv($bit_length)
{
$data = 0;
$mask = 1 << ($bit_length -1);
for($i = 1; $i <= $bit_length; $i++)
{
$us = infrared_get_count($i);
if($us < 2500)
if($us > 1500)
{
$data |= ($mask>> ($i-1));
}
}
return $data;
}
?>
If you have any question, please feel free to give the comment
I think the problem is in $repc is 81. The valid value is from 0 to 64 by default. We can change it by"
1. Connect PHPoC board to PHPoC Debugger
2. Create phpoc.ini file on PHPoC Debugger
3. Paste the below content to the phpoc.ini file:
ht0_count_buf_size = 256
ht1_count_buf_size = 256
ht2_count_buf_size = 256
4. Click save button to save file to PHPoC.
5. Reboot PHPoC Board.
sry for the delay, I had many things to do...
It works, thank you very much, must I delete your phpoc.ini lines ?
Kind regards
Any change in phpoc.ini will take effect after device is rebooted.