Things used in this project

Hardware components:
Phpoc blue per 100x1000 euk22wtv9i
PHPoC Blue
×1
Micro stepper motor controller s type ifrknphfjz
PHPoC Stepper Motor Controller Ⅱ (S-type)
×2
Stepper motor SE-SM243
×2
Cocktail Machine DIY
×1

Custom parts and enclosures

lift closer
lift part
slide movement part
slider bearing side
slider motor side

Code

Server side (task0.php)PHP
This code runs in infinite loop to receives command (cocktail name) from web browser via web-socket and control step motors on the cocktail machine to make the cocktail
<?php

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

define("SID_X",				13);
define("SID_Y",				14);
define("COCKTAIL_FLOW_TIME",	3); // time for cocktail flow into cup in second
define("COCKTAIL_WAIT_TIME",	3);

function step_wait($sid)
{
	while((int)spc_request_dev($sid, "get state") > 1)
		usleep(1);
}

function spc_check_did($sid, $did)
{
	$resp = spc_request_csv($sid, 0, "get did");

	if($resp === false)
	{
		echo "spc_check_did: sid$sid - device not found\r\n";
		return false;
	}

	if($resp[1] != "40002405")
	{
		echo "spc_check_did: unknown device ", $resp[2], "\r\n";
		return false;
	}

	return true;
}

function cooktail_get_id($drink_name)
{
	global $names;
	
	for($i = 0; $i < 4; $i++)
	{
		if($names[$i] == $drink_name)
			return $i;
	}
	
	return -1;
}

function cocktail_get($recipe)
{
	global $pos;
	
	spc_request_dev(SID_X, "goto -sw1 20000 1000000");
	step_wait(SID_X);
	spc_request_dev(SID_X, "reset");
	
	for($step_motor = 0; $step_motor < 4; $step_motor++) // get component one by one
	{
		$amount = $recipe[$step_motor]; 
		if($amount > 0)
		{
			$ps = $pos[$step_motor];
			
			spc_request_dev(SID_X, "goto +$ps 20000 1000000");
			step_wait(SID_X);
			
			for($i = 1; $i <= $amount; $i++)
			{
				if($i != 1)
					sleep(COCKTAIL_WAIT_TIME);

				spc_request_dev(SID_Y, "goto -sw0 30000 1000000");
				step_wait(SID_Y);
				sleep(COCKTAIL_FLOW_TIME);
				spc_request_dev(SID_Y, "reset");
				spc_request_dev(SID_Y, "goto 90000 30000 1000000");
				step_wait(SID_Y);
			}
			
			spc_request_dev(SID_Y, "goto 140000 30000 1000000");
			step_wait(SID_Y);
		}
	}
}

function cocktail_init()
{
	spc_reset();
	spc_sync_baud(460800);

	if(!spc_check_did(SID_X, "40002405"))
		return;
	if(!spc_check_did(SID_Y, "40002405"))
		return;

	spc_request_dev(SID_X, "set vref stop 4");
	spc_request_dev(SID_X, "set vref drive 15");
	spc_request_dev(SID_X, "set mode 32");
	spc_request_dev(SID_X, "set rsnc 120 250");
	
	spc_request_dev(SID_Y, "set vref stop 4");
	spc_request_dev(SID_Y, "set vref drive 15");
	spc_request_dev(SID_Y, "set mode 32");
	spc_request_dev(SID_Y, "set rsnc 120 250");
	
	spc_request_dev(SID_X, "goto +sw0 20000 1000000");
	step_wait(SID_X);
	
	spc_request_dev(SID_Y, "goto -sw0 30000 1000000");
	step_wait(SID_Y);
	
	spc_request_dev(SID_X, "reset");
	spc_request_dev(SID_Y, "reset");
	
	spc_request_dev(SID_Y, "goto 140000 30000 1000000");
	step_wait(SID_Y);
	
	spc_request_dev(SID_X, "goto +sw0 20000 1000000");
	step_wait(SID_X);
	spc_request_dev(SID_X, "reset");
	spc_request_dev(SID_Y, "reset");
}

$names = array("SUMMER_RAIN", "SCREW_DRIVER", "BLACK_RUSSIAN", "BLACK_RUSSIAN_2", "SWEET_MARTINI", "MARTINI");

$recipe_list = array(//MALIBU | VODKA | OGRANGE_JUICE | KAHLUA | GIN ||
				array(   2,       1,          0,          0,      0),//||SUMMER_RAIN
				array(   0,       1,          2,          0,      0),//||SCREW_DRIVER
				array(   0,       1,          0,          2,      0),//||BLACK_RUSSIAN
				array(   0,       2,          0,          1,      0),//||BLACK_RUSSIAN_2
			);

// motor pos: //MALIBU | VODKA | OGRANGE_JUICE | KAHLUA  |  GIN  | DRY_VERMOUTH 
$pos = array(   1000,    22000,      41000,       63000,   82000,    102000);

ws_setup(0, "cocktail", "text.phpoc");
cocktail_init();

$rbuf = "";

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

		if($rlen)
		{
			$drink_name = rtrim($rbuf, "\r\n");

			$id = cooktail_get_id($drink_name);

			if($id >= 0)
			{
				$recipe = $recipe_list[$id];
				cocktail_get($recipe);
			}
			else
				echo "cocktail: The drink is not found\r\n";

			spc_request_dev(SID_X, "goto -sw1 20000 1000000");
			step_wait(SID_X);
			spc_request_dev(SID_X, "reset");
		}
	}
}
?>
User Interface (index.php)PHP
<?php
	$recipe_list = array("SUMMER_RAIN", "SCREW_DRIVER", "BLACK_RUSSIAN", "BLACK_RUSSIAN_2");
?>
<!DOCTYPE html>
<html>
<head>
<title>PHPoC - Cocktail Machine</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7">
<style>
body {
	font-family:Helvetica;
	font-size: 200%;
	text-align: center;
	background-color: #33C7F2;
}
#container {
	position: relative;
	margin-right: auto;
	margin-left: auto;
}
#frame {
	margin-right: auto;
	margin-left: auto; 
	position: absolute;
	background: url(BACKGROUND.png) no-repeat;
	background-size: contain;
}
#confirm, #img_confirm, #btn_confirm{
	margin-right: auto;
	margin-left: auto;
	position: absolute;
}
#confirm { background-color: rgba(0, 0, 255, 0.5);}
#img_confirm { background-color: red;}

div[class='item'] {
	position: absolute; 
	border: 1px solid #d9d9d9;
}
#btn_confirm {
	background-color: white;
}
p { margin:15px; }
</style>
<script>
var ws = null;
var recipe_list = [];
var selected_item = "";

<?php
$num = count($recipe_list);
for($i = 0; $i < $num; $i++) 
	echo "recipe_list.push(\"", $recipe_list[$i] , "\");";
?>

function init()
{
	document.getElementById("frame").addEventListener("click", item_click);
	document.getElementById("option").addEventListener("click", option_click);

	resize();
	
	ws = new WebSocket("ws://<?echo _SERVER("HTTP_HOST")?>/cocktail", "text.phpoc");
}
function ws_onmessage(e_msg)
{
}
function ws_onclose()
{
	ws.onclose = null;
	ws.onmessage = null;
	ws = null;
}
function wc_onclick()
{
	if(ws == null)
	{
		ws = new WebSocket("ws://<?echo _SERVER("HTTP_HOST")?>/cocktail", "text.phpoc");
		document.getElementById("ws_state").innerHTML = "CONNECTING";

		ws.onclose = ws_onclose;
		ws.onmessage = ws_onmessage;  
	}
	else
		ws.close();
}
function item_click(event)
{
	if(ws == null || ws.readyState != 1)
		return;

	if (event.target !== event.currentTarget) 
	{
		selected_item = event.target.id;
		
		var confirm_item = document.getElementById("img_confirm");
		confirm_item.style.backgroundImage = "url('" + event.target.id + ".jpg')";
		confirm_item.style.backgroundRepeat = "no-repeat";
		confirm_item.style.backgroundSize = "contain";
		
		var frame = document.getElementById("frame");
		var confirm = document.getElementById("confirm");
		confirm.style.display = 'block';
	}

	event.stopPropagation();
	event.preventDefault();
}
function option_click(event)
{
	if (event.target !== event.currentTarget) 
	{
		var frame = document.getElementById("frame");
		var confirm = document.getElementById("confirm");
		confirm.style.display = 'none';
		
		if(event.target.id != "btn_yes")
			return;
		
		if(ws == null || ws.readyState != 1)
			return;

		ws.send(selected_item + "\r\n");
	}

	event.stopPropagation();
	event.preventDefault();
}
function resize()
{
	var width = window.innerWidth - 20;
	var height = window.innerHeight - 20;

	if(width > height)
		width = height;
	else
		height = width;
	
	var offset_x =  0.19 * width;
	var offset_y =  0.19 * height;
	
	var container = document.getElementById("container");
	var frame = document.getElementById("frame");
	var confirm = document.getElementById("confirm");
	container.style.width = frame.style.width = confirm.style.width = width + "px";
	container.style.height = frame.style.height = confirm.style.height = height + "px";
	
	confirm.style.display = 'none';
	
	var item_width = Math.floor(width * 0.375);
	var item_height = Math.floor(height * 0.375);
	
	
	for(var i = 0; i < recipe_list.length; i++)
	{
		//two recipe in a row
		var top = offset_y + Math.floor(i/2) * (item_height + 10);
		var left = offset_x + (i%2) * (item_width + 10);
		var item = document.getElementById(recipe_list[i]);
		item.style.width = (item_width - 12)+ "px";
		item.style.height = (item_height - 12)+ "px";
		item.style.top = top + "px";
		item.style.left = left + "px";
		item.style.backgroundImage = "url('" + recipe_list[i] + ".jpg')";
		item.style.backgroundRepeat = "no-repeat";
		item.style.backgroundSize = "contain";
	}
	
	var img_confirm = document.getElementById("img_confirm");
	var btn_confirm = document.getElementById("btn_confirm");
	
	var btn_height = 60;
	item_width = Math.floor(item_width *1.5);
	item_height = Math.floor(item_height *1.5);
	
	img_confirm.style.width = item_width + "px";
	img_confirm.style.height = item_height + "px";
	img_confirm.style.top = Math.floor((height - item_height) / 2) + "px";
	img_confirm.style.left = Math.floor((width - item_width) / 2) + "px";
	
	btn_confirm.style.width = item_width + "px";
	btn_confirm.style.top = Math.floor((height - item_height) / 2 + item_height) + "px";
	btn_confirm.style.left = Math.floor((width - item_width) / 2) + "px";
}

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

<body onresize="resize()">
<div id="container">
	<div id="frame">
		<!--<div id="SUMMER_RAIN"></div>
		<div id="SCREW_DRIVER"></div>
		<div id="BLACK_RUSSIAN"></div>
		<div id="BLACK_RUSSIAN_2"></div>-->
		<?php
		$num = count($recipe_list);
		for($i = 0; $i < $num; $i++) 
			echo "<div class=\"item\" id=\"", $recipe_list[$i] , "\"></div>";
		?>
	</div>

	<div id="confirm">
		<div id="img_confirm"></div>
		<div id="btn_confirm">
			<p style="margin:15px" id="message">Would you like to drink it?</p>
			<p id="option" style="color:blue; font-weight: bold;"> 
				<span id="btn_no">&nbsp;&nbsp;&nbspCancel&nbsp;&nbsp;&nbsp;</span>&nbsp;&nbsp;
				<span id="btn_yes">&nbsp;&nbsp;&nbsp;OK&nbsp;&nbsp;&nbsp</span>
			</p>
		</div>
	</div>
</div>
</body>
</html>

Credits

On uvdqjvxt6b
phpoc_man
3 projects • 81 followers
Contact

Replications

Did you replicate this project? Share it!

I made one

Love this project? Think it could be improved? Tell us what you think!

Give feedback

Comments

Sign up / LoginProjectsPlatformsTopicsContestsLiveAppsBetaBlog