I made a similar project using Arduino here https://www.hackster.io/khanhhs/ardu...mometer-a38752
Demo
Things Used In This Project
- PHPoC Blue (We can use PHPoC Black if using Ethernet instead of WiFi)
- Waterproof DS18B20 Digital temperature sensor
- Resistor 4.7k ohm
- Jumper wires
Wiring Diagram
Or
Data Flow
PHPoC ---> Web browser
PHPoC reads temperature from sensor and send it to Web Browser via websocket. JavaScript function visualizes the temperature value on UI.
Source Code
Source code includes two files:
- index.php: This file is client side code. When receiving HTTP request from web browser, PHPoC interprets PHP script in this file, and then send the interpreted file to web browser. The interpreted file (contains html, css and JavaScript code) provides UI (User Interface), visualizing temperature received from PHPoC.
PHP Code:
<!DOCTYPE html>
<html>
<head>
<title>PHPoC - Thermometer</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7">
<meta charset="utf-8">
<style>
body { text-align: center; font-size: width/2pt; }
h1 { font-weight: bold; font-size: width/2pt; }
h2 { font-weight: bold; font-size: width/2pt; }
button { font-weight: bold; font-size: width/2pt; }
</style>
<script>
var canvas_width = 200, canvas_height = 450;
var ws;
var buffer = "";
function init()
{
var canvas = document.getElementById("remote");
//canvas.style.backgroundColor = "#999999";
canvas.width = canvas_width;
canvas.height = canvas_height;
var ctx = canvas.getContext("2d");
ctx.translate(canvas_width/2, canvas_height - 80);
update_view(0);
}
function connect_onclick()
{
if(ws == null)
{
var ws_host_addr = "<?echo _SERVER("HTTP_HOST")?>";
if((navigator.platform.indexOf("Win") != -1) && (ws_host_addr.charAt(0) == "["))
{
// network resource identifier to UNC path name conversion
ws_host_addr = ws_host_addr.replace(/[\[\]]/g, '');
ws_host_addr = ws_host_addr.replace(/:/g, "-");
ws_host_addr += ".ipv6-literal.net";
}
ws = new WebSocket("ws://" + ws_host_addr + "/thermometer", "text.phpoc");
document.getElementById("ws_state").innerHTML = "CONNECTING";
ws.onopen = ws_onopen;
ws.onclose = ws_onclose;
ws.onmessage = ws_onmessage;
//ws.binaryType = "arraybuffer";
}
else
ws.close();
}
function ws_onopen()
{
document.getElementById("ws_state").innerHTML = "<font color='blue'>CONNECTED</font>";
document.getElementById("bt_connect").innerHTML = "Disconnect";
ws.send("wsm_baud=9600\r\n");
ws.send("B\r\n");
update_view(0);
}
function ws_onclose()
{
document.getElementById("ws_state").innerHTML = "<font color='gray'>CLOSED</font>";
document.getElementById("bt_connect").innerHTML = "Connect";
ws.onopen = null;
ws.onclose = null;
ws.onmessage = null;
ws = null;
update_view(0);
}
function ws_onmessage(e_msg)
{
e_msg = e_msg || window.event; // MessageEvent
console.log(e_msg.data);
update_view(parseFloat(e_msg.data));
}
function update_view(temp)
{
var canvas = document.getElementById("remote");
var ctx = canvas.getContext("2d");
var radius = 70;
var offset = 5;
var width = 45;
var height = 330;
ctx.clearRect(-canvas_width/2, -350, canvas_width, canvas_height);
if(ws != null)
{
ctx.strokeStyle="blue";
ctx.fillStyle="blue";
}
else
{
ctx.strokeStyle="Gray";
ctx.fillStyle="Gray";
}
//5-step Degree
var x = -width/2;
ctx.lineWidth=2;
for (var i = 0; i <= 100; i+=5)
{
var y = -(height - radius)*i/100 - radius - 5;
ctx.beginPath();
ctx.lineTo(x, y);
ctx.lineTo(x - 20, y);
ctx.stroke();
}
//20-step Degree
ctx.lineWidth=5;
for (var i = 0; i <= 100; i+=20)
{
var y = -(height - radius)*i/100 - radius - 5;
ctx.beginPath();
ctx.lineTo(x, y);
ctx.lineTo(x - 25, y);
ctx.stroke();
ctx.font="20px Georgia";
ctx.textBaseline="middle";
ctx.textAlign="right";
ctx.fillText(i.toString(), x - 35, y);
}
// shape
ctx.lineWidth=16;
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.stroke();
ctx.beginPath();
ctx.rect(-width/2, -height, width, height);
ctx.stroke();
ctx.beginPath();
ctx.arc(0, -height, width/2, 0, 2 * Math.PI);
ctx.stroke();
ctx.fillStyle="#e6e6ff";
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.fill();
ctx.beginPath();
ctx.rect(-width/2, -height, width, height);
ctx.fill();
ctx.beginPath();
ctx.arc(0, -height, width/2, 0, 2 * Math.PI);
ctx.fill();
// temperature value
if(ws != null)
ctx.fillStyle="#ff1a1a";
else
ctx.fillStyle="Gray";
ctx.beginPath();
ctx.arc(0, 0, radius - offset, 0, 2 * Math.PI);
ctx.fill();
temp = Math.round(temp);
var y = (height - radius)*temp/100.0 + radius + 5;
ctx.beginPath();
ctx.rect(-width/2 + offset, -y, width - 2*offset, y);
ctx.fill();
if(ws != null)
{
ctx.fillStyle="white";
ctx.font="bold 34px Georgia";
ctx.textBaseline="middle";
ctx.textAlign="center";
ctx.fillText(temp.toString() + "°C", 0, 0);
}
}
window.onload = init;
</script>
</head>
<body>
<p>
<h1>PHPoC - Web Thermometer</h1>
</p>
<canvas id="remote"></canvas>
<h2>
<p>
WebSocket : <span id="ws_state">null</span>
</p>
<button id="bt_connect" type="button" onclick="connect_onclick();">Connect</button>
</h2>
</body>
</html>
- task0.php: This file is server side code. It is run in infinite loop to read temperature from sensor and send it to web browser via websoket
PHP Code:
<?php
include_once "/lib/sd_340.php";
include_once "/lib/sn_tcp_ws.php";
//bus reset
function begin()
{
global $pid_ht_in, $pid_ht_out;
pid_ioctl($pid_ht_in, "set repc 4");
pid_ioctl($pid_ht_in, "start");
pid_ioctl($pid_ht_out, "set count 1 600");
pid_ioctl($pid_ht_out, "set repc 2");
pid_ioctl($pid_ht_out, "start");
while(pid_ioctl($pid_ht_out, "get state"))
;
pid_ioctl($pid_ht_out, "stop");
while(pid_ioctl($pid_ht_in, "get state"))
;
pid_ioctl($pid_ht_in, "stop");
$presence_pulse = pid_ioctl($pid_ht_in, "get count 3");
if(($presence_pulse < 60) || ($presence_pulse > 240))
return false;
else
return true;
}
//1byte send
function write_byte($seq_str)
{
global $pid_ht_out;
pid_ioctl($pid_ht_out, "set count $seq_str");
pid_ioctl($pid_ht_out, "set repc 16");
pid_ioctl($pid_ht_out, "start");
while(pid_ioctl($pid_ht_out, "get state"))
;
pid_ioctl($pid_ht_out, "stop");
}
//1byte recieve
function read_byte()
{
global $pid_ht_out, $pid_ht_in;
$seq_read = "1 3 63 3 63 3 63 3 63 3 63 3 63 3 63 3";
$sum = 0;
$value = 0;
pid_ioctl($pid_ht_in, "set repc 16");
pid_ioctl($pid_ht_in, "start");
pid_ioctl($pid_ht_out, "set count $seq_read");
pid_ioctl($pid_ht_out, "set repc 16");
pid_ioctl($pid_ht_out, "start");
while(pid_ioctl($pid_ht_out, "get state"))
;
pid_ioctl($pid_ht_out, "stop");
while(pid_ioctl($pid_ht_in, "get state"))
;
pid_ioctl($pid_ht_in, "stop");
for($i = 0; $i < 8; $i++)
{
$cnt = $i * 2 + 1;
$cnt_val = pid_ioctl($pid_ht_in, "get count $cnt");
if($cnt_val < 15)
$value = 1;
else
$value = 0;
$value <<= $i;
$sum += $value;
}
return $sum;
}
//SKIP ROM command
function skip_rom()
{
global $seq_skip_rom;
write_byte($seq_skip_rom);
}
//CONVERT T command
function convert_t()
{
global $seq_convert_t;
begin();
skip_rom();
write_byte($seq_convert_t);
usleep(750000);
}
//READ SCRATCHPAD
function read_scratchpad()
{
global $seq_read_scratchpad;
$str = "";
write_byte($seq_read_scratchpad);
for($i = 0; $i < 9; $i++)
{
$data = read_byte();
$str .= int2bin($data, 1);
if($i == 8)
$crc_scratchpad = $data;
}
$crc = (int)system("crc 8 %1 00 8c lsb", substr($str, 0, -1));
if($crc != $crc_scratchpad)
{
echo "CRC Error!\r\n";
return false;
}
else
return $str;
}
//read temperature
function read_temp()
{
begin();
skip_rom();
$scratchpad_data = read_scratchpad();
if($scratchpad_data === false)
return false;
$temp = bin2int(substr($scratchpad_data, 0, 2), 0, 2);
$temp_int = $temp >> 4;
$temp_dec = 0;
$dec_flag = 0;
for($i = 0; $i < 4; $i++)
{
if($temp & 0x01)
{
$dec_flag = 1;
$temp_dec += 1.0 / pow(2, (4-$i));
}
$temp >>= 1;
}
if($dec_flag)
{
$temp_tot = $temp_int + $temp_dec;
return (float) $temp_tot;
}
else
return (float) $temp_int;
}
//timing
$seq_skip_rom = "1 65 5 65 5 10 55 10 55 65 5 65 5 10 55 10"; // 0xcc
$seq_convert_t = "1 65 5 65 5 10 55 65 5 65 5 65 5 10 55 65"; // 0x44
$seq_read_scratchpad = "1 65 5 10 55 10 55 10 55 10 55 10 55 65 5 10"; // 0xbe
//init HT1
$pid_ht_in = pid_open("/mmap/ht1");
pid_ioctl($pid_ht_in, "set div us");
pid_ioctl($pid_ht_in, "set mode capture toggle");
pid_ioctl($pid_ht_in, "set trigger from pin fall");
//init HT0
$pid_ht_out = pid_open("/mmap/ht0");
pid_ioctl($pid_ht_out, "set div us");
pid_ioctl($pid_ht_out, "set mode output toggle");
pid_ioctl($pid_ht_out, "set output od");
pid_ioctl($pid_ht_out, "set output high");
ws_setup(0, "thermometer", "text.phpoc");
while(1)
{
convert_t();
$temp = read_temp();
$temp = sprintf("%.01f", $temp);
if(ws_state(0) == TCP_CONNECTED)
{
ws_write(0, "$temp\r\n");
}
usleep(200000);
}
?>