Skip to: Site menu | Main content

Virtual Buttons Real Appliance

This project allows you to turn on and off physical appliances using virtual buttons inside Second Life. It includes quite a few links in a long chain, but it's a great project to get started with because the individual links themselves all make useful building blocks for your own creations.

I'll lay it out step by step, starting inside Second Life and ending at the appliance itself. There are security issues all along the way here and it's not really practical as a final system without adding access control at various points, but I'll present the bare minimum to make this work to keep it easy to understand.

Virtual Buttons


Log in to Second Life and go to a location where you have build privileges, such as land you own or a public sandbox. Right-click on an empty patch of ground and select "Create". You'll get a magic wand tool, so select a shape from the palette on the top left (I chose a sphere) and click on the ground again:



Next we need to add a script to it, so with the item still selected click the "Content" tab on the tool area. You'll see there are no scripts listed in the contents of the object so click "New Script..." to insert a default script. Then double-click the "New Script" object to open it in an editor:



Select the entire contents of the script and delete it. Then copy the following code and paste it in:

default
{
state_entry()
{
llOwnerSay("Hello, Avatar!");
}

touch_start(integer total_number)
{
string gateWay = "";
string action = "1";
gateWay = "http://1.2.3.4/webtosocket.php?command=" + action;
key http_request_id;

llOwnerSay(action);
http_request_id = llHTTPRequest(gateWay, [], "");
}
}


One thing you will need to change in this script is the IP address. The example above uses "1.2.3.4", but you'll need to replace it with the publicly accessible IP address of your machine.

After adding the script and closing the editor I then switched to the "Texture" tab in the tool area and clicked the "Color" area to select a bright green, since we'll be using this as an "on" button.

After doing all that repeat the entire process to create a second button, but this time set the line that says string action = "1" to instead say string action = "2". This will be our "off" button, so I set it to bright red. The end result should be something like this:



Clicking either of those buttons will now cause a web request to be sent to the IP address you specified, but there's nothing listening there yet so next we need to set up a script on your computer.

Web To Serial Gateway


The buttons initiate web requests, so we'll put a little PHP script in place to handle the requests and perform an action.

Create a new file called "webtosocket.php" in your web root (probably /var/www or similar) and paste this into it:

<?php
$command = $_REQUEST['command'];
if($command == "1")
{
echo "1";
send_to_arduino("1");
}
if($command == "2")
{
echo "2";
send_to_arduino("2");
}

function send_to_arduino($message)
{
$fp = fsockopen("tcp://127.0.0.1", 2000, $errno, $errstr, 30);
fputs($fp, $message);
fclose($fp);
}
?>


What this script does is look for the value "1" or "2" to be sent to it in the "command" variable, and then opens a socket connection to port 2000 on localhost and sends a value to the socket.

Socket To Serial Port


The point of the jiggery-pokery above is to allow us to use a scripting language (in this case PHP) to squirt a value out a USB port. To make that happen we need to use a utility called "ser2net", which takes serial ports and exposes them as network sockets. On Debian-ish systems you can simply apt-get install ser2net, then edit the file /etc/ser2net.conf and go to the last couple of lines. You need an entry that looks like this:

2000:telnet:600:/dev/ttyUSB0:9600 8DATABITS NONE 1STOPBIT banner


What this will do is tell ser2net that it needs to connect to /dev/ttyUSB0 at 9600bps, and expose it on port 2000 as an emulated telnet server. Then /etc/init.d/ser2net restart to apply the new configuration.

Arduino Serial To Digital


So now we need an Arduino board connected via USB to receive the messages we're about to squirt at it. Launch the Arduino IDE and create a new sketch, then paste this code into it:

int outPut1 = 11;
int outPut2 = 12;

void setup()
{
// begin the serial communication
Serial.begin(9600);
pinMode(outPut1, OUTPUT);
pinMode(outPut2, OUTPUT);
digitalWrite(outPut1, LOW);
digitalWrite(outPut2, LOW);
}

void loop()
{
byte val;

// check if data has been sent from the computer
if (Serial.available()) {
// read the most recent byte (which will be from 0 to 255)
val = Serial.read();
// If the value is "-1" there's no data on the port
if (val != -1)
{
if (val == '1')
{
// Turn output on
digitalWrite(outPut1, HIGH);
delay(500);
digitalWrite(outPut1, LOW);
}
if (val == '2')
{
// Turn output on
digitalWrite(outPut2, HIGH);
delay(500);
digitalWrite(outPut2, LOW);
}
}
}
}


This is the biggest chunk of code in the project but it's still pretty easy to follow. It starts by defining which pins we'll use for output: in this case pins 11 and 12. It then sets both those pins into "output" mode and forces them low.

The main program loop simply watches the serial port for values being sent to it, and if it sees a value of "1" it pulses pin 11 high for half a second. A value of "2" pulses pin 12 high.

Click the "verify" button in the top left of the IDE to compile it, then push the program across to the Arduino using the "Upload to I/O Board" button.

At this point you should have a system that allows you to click one of the virtual buttons inside Second Life and have one of the output pins on the Arduino pulse high in response: if you put an LED with a 220R dropper resistor in series between the output and ground you'd see the LED flash when you click the virtual button:



...more to come...

--
Last updated Friday February 8th, 2008 by Jonathan Oxer