Project tutorial

Arduino - Web-Based Keypad © GPL3+

Remotely controlling Arduino by using web-based keypad.

  • 7,721 views
  • 0 comments
  • 48 respects

Components and supplies

About this project

We can control everything with this project. In this article, I just display the pressed key on 8x8 LED matrix as an example.

Demo

Wiring

  • Stack PHPoC WiFi shield or PHPoC Shield on Arduino

Data Flow

Web browser ---> PHPoC WiFi Shield ---> Arduino

When user touches on a key, web app on web browser will send the character corresponding with the pressed key to PHPoC shield via WebSocket. When receiving the data, PHPoC shield automatically passes it to Arduino. Arduino takes action (displaying on LED matrix) according to the data received from PHPoC Shield.

Note that: PHPoC shield has a built-in program to pass data from web browser to Arduino. Therefore, we don't need to care about it.

What We Need to Do

  • Set WiFi information for PHPoC shield (SSID and password)
  • Upload new UI to PHPoC shield
  • Write Arduino code

Setting Wifi Information for PHPoC Shield

See this instruction.

Upload new Web UI to PHPoC Shield

  • Download PHPoC source code remote_keypad.php (on code section).

Write Arduino Code

  • See source code in code section.

Try it

  • Click serial button on Arduino IDE to see the IP address.
  • Open web browser, type http:// replace_ip_address/remote_keypad.php
  • Click connect button and test it.

Code

Arduino CodeArduino
#include "SPI.h"
#include "Phpoc.h"
#include <Wire.h>
#include <Adafruit_GFX.h>
#include "Adafruit_LEDBackpack.h"

PhpocServer server(80);
Adafruit_BicolorMatrix matrix = Adafruit_BicolorMatrix();

void setup() {
	Serial.begin(9600);
	while(!Serial)
		;

	Phpoc.begin(PF_LOG_SPI | PF_LOG_NET);
	//Phpoc.begin();

	server.beginWebSocket("remote_keypad");

	Serial.print("WebSocket server address : ");
	Serial.println(Phpoc.localIP());
	
	matrix.begin(0x70);	// pass in the address
	matrix.setRotation(3);
	matrix.setTextColor(LED_RED);
 
}

void loop() {
	// wait for a new client:
	PhpocClient client = server.available();

	if (client) {
		if (client.available() > 0) {
			// read the bytes incoming from the client:
			char thisChar = client.read();
			
			matrix.clear();
			matrix.setCursor(1,0);
			matrix.print(thisChar);
			matrix.writeDisplay();
		}
	}
}
User Interface (remote_keypad.php)PHP
<!DOCTYPE html>
<html>
<head>
<title>PHPoC Shield - Web Remote Control for Arduino</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7, maximum-scale=0.7">
<style>
body { text-align: center; }
h1 { font-weight: bold; font-size: 25pt; }
h2 { font-weight: bold; font-size: 15pt; }
button { font-weight: bold; font-size: 15pt; }
</style>
<script>
var BOX_WIDTH = 120;
var BOX_HEIGHT = 120;
var KEY_WIDTH = 85;
var KEY_HEIGHT = 85;
var OFFSET_X = 65;
var OFFSET_Y = 40;
var canvas_width, canvas_height;
var push_info = [];
var push_text = [ "1", "2", "3", "4", "5", "6", "7", "8", "9", "*", "0", "#" ];
var push_font = "bold 50px Arial";
var ws;

function init()
{
	var remote = document.getElementById("remote");
	
	remote.width = canvas_width = BOX_WIDTH * 3 + OFFSET_X * 2;
	remote.height = canvas_height = BOX_HEIGHT * 4 + OFFSET_Y * 2;
	
	var ctx = remote.getContext("2d");
	ctx.strokeStyle = "white";
	ctx.lineJoin = "round";

	for(var push_id = 0; push_id < 12; push_id++)
	{
		if(push_id == 9 || push_id == 11)
			push_info[push_id] = {state:false, identifier:null, font:push_font, text:push_text[push_id], color_1:"Crimson", color_2:"Red"};
		else
			push_info[push_id] = {state:false, identifier:null, font:push_font, text:push_text[push_id], color_1:"#1E90FF", color_2:"Aqua"};
	}
	
	update_view();
	
	remote.addEventListener("touchstart", mouse_down);
	remote.addEventListener("touchend", mouse_up);
	remote.addEventListener("touchmove", mouse_move);

	remote.addEventListener("mousedown", mouse_down);
	remote.addEventListener("mouseup", mouse_up);
	remote.addEventListener("mousemove", mouse_move);
	remote.addEventListener("mouseout", mouse_up);
}
function connect_onclick()
{
	if(ws == null)
	{
		var ws_host_addr = "<?echo _SERVER("HTTP_HOST")?>";
		var debug = document.getElementById("debug");

		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 + "/remote_keypad", "text.phpoc");

		document.getElementById("ws_state").innerHTML = "CONNECTING";

		ws.onopen = ws_onopen;
		ws.onclose = ws_onclose;
		ws.onmessage = ws_onmessage;
	}
	else
		ws.close();
}
function ws_onopen()
{
	document.getElementById("ws_state").innerHTML = "<font color='blue'>CONNECTED</font>";
	document.getElementById("bt_connect").innerHTML = "Disconnect";

	for(var push_id = 0; push_id < 12; push_id++)
		push_info[push_id].state = false;
		
	update_view();
}
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;

	for(var push_id = 0; push_id < 12; push_id++)
		push_info[push_id].state = false;
		
	update_view();
}
function ws_onmessage(e_msg)
{
	e_msg = e_msg || window.event; // MessageEvent

	alert("msg : " + e_msg.data);
}
function update_view()
{
	var remote = document.getElementById("remote");
	var ctx = remote.getContext("2d");
	var cx, cy, x, y;
	
	ctx.clearRect(0, 0, canvas_width, canvas_height);
	ctx.lineWidth = 4;
	ctx.fillStyle = "black";
	ctx.shadowBlur = 0;
	
	var margin, radius;
	for(var i = 0; i < 3; i++)
	{
		if(i == 0)
			margin = 0;
		else if(i == 1)
			margin = 20;
		else
			margin = 28;
		
		radius = 45 - margin;
		
		ctx.beginPath(); 
		ctx.arc(margin + radius, margin + radius, radius, Math.PI, 1.5*Math.PI);
		ctx.lineTo(margin + radius, margin);
		ctx.lineTo(canvas_width - margin - radius, margin);
		ctx.arc(canvas_width - margin - radius, margin + radius, radius, 1.5*Math.PI, 0);
		ctx.lineTo(canvas_width - margin, canvas_height - margin - radius);
		ctx.arc(canvas_width - margin - radius, canvas_height - margin - radius, radius, 0, 0.5*Math.PI);
		ctx.lineTo(margin + radius, canvas_height - margin);
		ctx.arc(margin + radius, canvas_height - margin - radius, radius, 0.5*Math.PI, Math.PI);
		ctx.closePath();
		
		if(i == 0)
			ctx.fill();
		else
			ctx.stroke();
	}
	
	ctx.translate(OFFSET_X, OFFSET_Y);
	
	for(var push_id = 0; push_id < 12; push_id++)
	{
		var push = push_info[push_id];
		var state = push.state;
		
		if(state)
		{
			ctx.fillStyle = push.color_2;
			ctx.shadowBlur = 80;
			ctx.shadowColor = push.color_2;
		}
		else
		{
			ctx.shadowBlur = 0;
			ctx.fillStyle = push.color_1;
		}
		
		cx = BOX_WIDTH * (push_id % 3) + BOX_WIDTH / 2;
		cy = BOX_HEIGHT * parseInt(push_id / 3) + BOX_HEIGHT / 2;
		x = cx - KEY_WIDTH / 2;
		y = cy - KEY_HEIGHT / 2;
		
		ctx.beginPath();
		ctx.lineWidth = 7;
		ctx.rect(x, y, KEY_WIDTH, KEY_HEIGHT);
		ctx.fill();
		ctx.stroke();

		ctx.font = push.font;
		ctx.textAlign = "center";
		ctx.textBaseline = "middle";
		ctx.fillStyle = "white";
		ctx.fillText(push.text, cx, cy);

		if(!state)
			push.identifier = null;
	}
	
	ctx.translate(-OFFSET_X, -OFFSET_Y);
}

function find_push_id(x, y)
{
	var cx, cy, push_id;
	
	x -= OFFSET_X;
	y -= OFFSET_Y;
	
	if((x < 0) || (x >= BOX_WIDTH * 3))
		return 12;

	if((y < 0) || (y >= BOX_HEIGHT * 4))
		return 12;

	push_id = parseInt(x / BOX_WIDTH);
	push_id += 3 * parseInt(y / BOX_WIDTH);

	cx = BOX_WIDTH * (push_id % 3) + BOX_WIDTH / 2;
	cy = BOX_HEIGHT * parseInt(push_id / 3) + BOX_HEIGHT / 2;

	if( Math.abs(x - cx) < KEY_WIDTH && Math.abs(y - cy) < KEY_HEIGHT)
		return push_id;
	else
		return 12;
}
function mouse_down(event)
{
	var debug = document.getElementById("debug");
	var x, y, push_id;

	if(event.changedTouches)
	{
		for(var touch_id = 0; touch_id < event.changedTouches.length; touch_id++)
		{
			var touch = event.changedTouches[touch_id];

			x = touch.pageX - touch.target.offsetLeft;
			y = touch.pageY - touch.target.offsetTop;

			push_id = find_push_id(x, y);

			if(push_id < 12)
			{
				var push = push_info[push_id];

				if(push.state == false)
				{
					var key = push_info[push_id].text;
					send_key(key);
					push_info[push_id].state = true;
					update_view();
					push.identifier = touch.identifier;
				}
			}
		}
	}
	else
	{
		x = event.offsetX;
		y = event.offsetY;

		push_id = find_push_id(x, y);

		if(push_id < 12)
		{
			var key = push_info[push_id].text;
			send_key(key);
			push_info[push_id].state = true;
			update_view();
		}
	}

	event.preventDefault();
}
function mouse_up(event)
{
	var debug = document.getElementById("debug");
	var push_id;

	if(event.changedTouches)
	{
		for(var touch_id = 0; touch_id < event.changedTouches.length; touch_id++)
		{
			var touch = event.changedTouches[touch_id];

			for(var push_id = 0; push_id < 12; push_id++)
			{
				if(touch.identifier == push_info[push_id].identifier)
					break;
			}

			if(push_id < 12)
			{
				push_info[push_id].state = false;
				update_view();
			}
		}
	}
	else
	{
		for(var push_id = 0; push_id < 12; push_id++)
		{
			if(push_info[push_id].state)
			{
				push_info[push_id].state = false;
				update_view();
				break;
			}
		}
	}

	event.preventDefault();
}
function mouse_move(event)
{
	event.preventDefault();
}
function send_key(key)
{
	if(ws && (ws.readyState == 1))
		ws.send(key);
}
window.onload = init;
</script>
</head>

<body>

<p>
<h1>Web-based Remote Keypad</h1>
</p>

<canvas id="remote"></canvas><br>

<h2>WebSocket <font id="ws_state" color="gray">CLOSED</font></h2>
<button id="bt_connect" type="button" onclick="connect_onclick();">Connect</button>
<span id="debug"></span>

</body>
</html>

Schematics

wiring_SLhmifR38E.png
Wiring slhmifr38e

Comments

Similar projects you might like

Arduino - Web-Based Joystick

Project tutorial by IoT_lover

  • 12,087 views
  • 13 comments
  • 73 respects

Arduino - Web-Based Thermometer

Project tutorial by khanhhs

  • 10,021 views
  • 12 comments
  • 37 respects

Arduino - Web-Based Gauge

Project tutorial by IoT_lover

  • 4,040 views
  • 0 comments
  • 21 respects

Arduino - Web-Based Two-Player Game

Project tutorial by khanhhs

  • 9,354 views
  • 38 comments
  • 53 respects

Arduino - Web-Based MP3 Player

Project tutorial by khanhhs

  • 7,748 views
  • 4 comments
  • 27 respects

Arduino Dynamic Web Control

Project tutorial by phpoc_man

  • 34,771 views
  • 15 comments
  • 117 respects
Add projectSign up / Login