khanhhs
Published © GPL3+

PHPoC: Web-Based Thermometer

This project allows you to check the temperature at home from anywhere using a web browser.

BeginnerFull instructions provided3,129

Things used in this project

Hardware components

PHPoC Blue
PHPoC Blue
We can use PHPoC Black if using Ethernet instead of WiFi
×1
DS18B20 Temperature Sensor
DIYables DS18B20 Temperature Sensor
×1
Jumper Wires
DIYables Jumper Wires
×1
Starter Kit
DIYables Starter Kit
×1

Story

Read more

Schematics

Wiring between PHPoC and sensor

Wiring between PHPoC and sensor- anther way

Connect directly pin HT0 to HT1

Real Connection

Code

Main task (task0.php)

PHP
This is server side 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);
}
?>

User Interface (index.php)

PHP
<!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>

Credits

khanhhs

khanhhs

0 projects • 56 followers

Comments