Things Used In This Project
- 1 x PHPoC Blue
- 2 x PHPoC Stepper Motor Controller Ⅱ (S-type)
- 2 x Stepper motor SE-SM243
- Cocktail Machine DIY
- Jumper wires
How It Works
PHPoC board itself is also an embedded web server. We upload web UI on this board. When Web Browser makes an HTTP request to PHPoC Board. It returns this web UI to Web Brower.
When user chooses a cocktail from Web Browser, the cocktail name will be sent to PHPoC board via web-socket. The server side code in PHPoC board receives this cocktail name and control the cocktail machine to make that cocktail.
For detail how to wiring among PHPoC, Step motor controller and Step motor, refer to this manual: http://www.phpoc.com/support/manual/....php?id=layout
I have another project which uses Alexa to control cocktail machine here: https://www.hackster.io/56170/cockta...d-phpoc-9027c4
Source Code
User Interface <index.php>
PHP Code:
<?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">  Cancel </span>
<span id="btn_yes"> OK  </span>
</p>
</div>
</div>
</div>
</body>
</html>[/CODE]
Server Side <task0.php>
[code]<?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");
}
}
}
?>