As part of the all-remote 'Good Things Fest', organised by the folks who usually organise the Thingscon conference, in December 2020 we ran a workshop using Smartibot robots and the Smartipresence telepresence system to build physical games that could be played over the internet.
Remote cardboard robot making
Participants received a Smartibot kit and two 9G servo motors in the post. We started the workshop using the cardboard modelling techniques covered in detail in our tutorial on how to make Battlebots from cardboard to build a basic robot chassis that can carry a smartphone in portrait orientation. We used this A4 template for all the cardboard parts.
Telepresence Firmware
Some participants added mechanisms to their robots that were worked by servo motors (and triggered by the look up and look down buttons in the pilot app). To do so they loaded the custom firmware at the bottom of this post onto their Smartibots and then edited it to set the position of the servos when the user would press the 'look up' and 'look down' buttons. (Instructions for how to program your Smartibot are here and the web-based tool you use to do it is the Espruino IDE)
To prevent the app using the standard telepresence firmware participants also switched it into 'Custom Firmware' in settings before connecting to the Smartibot.
Telepresence Games
With everyone knowing how to build and program their robots we broke up for a break and everyone worked on their game experiences. We met up again later in the day and we took it in turns to play one another's games whilst the rest of us watched. You can see footage of all of these in the video at the top of this page but here is a quick overview.
As an example we put a cardboard grabber on the front of our robot, actuated by two servo motors, and made a game where you had to rescue office workers from zombies which were made from carrots.
One participant made a game where you have to knock over different items (worth different amounts of points) whilst avoiding driving in areas of lava (which lose you points).
Another made a very simple experience where you drove around under her desk meeting a series of delightful robot Christmas decorations.
Another made game where the robot had a cardboard fishing rod which could be raised and lowered using the look up and look down buttons. The rod had a magnet on the end and there were cardboard fish (also with magnets on them) arrayed on the floor which could be caught.
One participant put a motorised rattle on his robot so that the grandparents of his new baby (who could not be physically with them) could play with them over the internet.
Custom smartibot telepresence firmware
var smarti = require("Smartibot"); var counting = false; var lookUp = false; var lookDw = false; var lookSt = false; var stopping = false; var stopping2 = false; var count = 0; var step = 2; Modules.addCached("Smartibot",`function e(){a.writeTo(88,[0,0]);a.writeTo(88,[0,16]);a.writeTo(88,[254,112]);a.writeTo(88,[0,0]);a.writeTo(88,[0,161])}exports.M1=[D4,D6];exports.M2=[D10,D11];var a=new I2C;a.setup({sda:D27,scl:D28});exports.E1={i2c:a,ad:D0,"int":D1};exports.E2={i2c:a,ad:D30,"int":D26};exports.setLEDs=function(a,b){var d=new Uint8Array(16);d[4]=255;d[8]=255;d.fill(255,12);d.set(a,5);d.set(b,9);var c=new SPI;c.setup({mosi:D8,sck:D7});c.write(d)};exports.setMotor=function(a,b){var d=[void 0,D4,D10,D2,D9][a], c=[void 0,D6,D11,D3,D12][a];0===b&&(digitalWrite(d,0),digitalWrite(c,0));0<b?(digitalwrite(d,0),analogwrite(c,b)):(digitalwrite(c,0),analogwrite(d,-b))};e();e.on("init",e);exports.setservo=function(c,b){if(1>c||10<c)throw"num out="" of="" range";b="130+4*b;if(1">b||4095<b)throw"val out="" of="" range";a.writeto(88,[6+4*(c-1),0,0,b,b="">>8])}`); (function(){var s=require("Smartibot"),m=s.setMotor.bind(s); if("undefined"==typeof aiReset)aiReset=_=>s.setLEDs([90,24,77],[90,24,77]); if("undefined"==typeof aiDetect)aiDetect=(a,x,y)=>{ s.setLEDs([11,82,42],[11,82,42]); var d=50; if (x < -5) {m(1,0.7);m(2,0.7); } else if (x > 5) {m(1,-0.7);m(2,-0.7); } else {d=100;m(1,0.7);m(2,-0.7);} setTimeout(_=>{m(1,0);m(2,0);}, d); };})(); smarti.setServo(1,80); smarti.setServo(5,20); function goC(drive) { if (drive == "B"){ smarti.setLEDs([0,0,50],[0,0,50]); smarti.setMotor(1,0.7); smarti.setMotor(2,-0.7); step = 10; counting = true; } if (drive == "R"){ smarti.setLEDs([50,0,50],[60,0,50]); smarti.setMotor(1,-0.6); smarti.setMotor(2,-0.6); step = 5; counting = true; } if (drive == "SR"){ smarti.setLEDs([50,0,50],[60,0,50]); smarti.setMotor(1,-0.55); smarti.setMotor(2,-0.55); step = 2; counting = true; } if (drive == "L"){ smarti.setLEDs([50,0,50],[50,0,50]); smarti.setMotor(1,0.6); smarti.setMotor(2,0.6); step = 5; counting = true; } if (drive == "SL"){ smarti.setLEDs([50,0,50],[50,0,50]); smarti.setMotor(1,0.55); smarti.setMotor(2,0.55); step = 2; counting = true; } if (drive == "LU"){
//Change the values before the commas below to match the
//number of the 'S' connector each servo is connected to
//on the Smartibot circuit board. Change the values after
//the comma to set the position of each servo for when the
//player presses the look up button. smarti.setServo(1,35); smarti.setServo(5,65); } if (drive == "LD"){
//Change the values before the commas below to match the
//number of the 'S' connector each servo is connected to
//on the Smartibot circuit board. Change the values after
//the comma to set the position of each servo for when the
//player presses the look down button. smarti.setServo(1,80); smarti.setServo(5,20); } if (drive == "T"){ smarti.setLEDs([50,0,50],[50,0,50]); smarti.setMotor(1,0.55); smarti.setMotor(2,0.55); step = 30; counting = true; } else if (drive == "F"){ smarti.setLEDs([50,0,0],[50,0,0]); smarti.setMotor(1,-0.7); smarti.setMotor(2,0.7); step = 10; counting = true; } else if (drive == "S"){ smarti.setLEDs([0,50,0],[0,50,0]); smarti.setMotor(1,0); smarti.setMotor(2,0); } } setInterval(function () { if (counting == true){ count = count + 1; } if (count > step){ counting = false; count = 0; smarti.setMotor(1,0); smarti.setMotor(2,0); } }, 25);