Fun with Sphero Robots At My First Domain Hackathon

hackathon Jul 03, 2019

Back in March 2019, I joined my first Hackathon at Domain!

What is a Hackathon? It's a 2-day event that gives developers the chance to work on non-sprint work, and work on whatever we want to do! You can work with new and cool technologies that you don't normally work with everyday.

Joining was a spur-of-the-moment decision. I always thought that to take part in these events, you needed an idea that had business value. But our CTO assured me, it's all about having fun with the technology!

The day before the event, I remembered I had two Sphero robots at home that I hadn't taken out of the boxes yet.

Challenge accepted!

Introducing R2-D2 and BB-9E

These robots don't need introduction if you're a Star Wars fan!

R2-D2 is one of the droids with Luke Skywalker in the original Star Wars Trilogy. BB-9E is a First Order droid from the Sequel Trilogy.

(Sphero also made a BB-8 robot, but I don't have one myself.)

Sphero have done a fantastic job  with these robots. They're small and cute, but more importantly, well-made. The appearance, sounds, and movements are faithful to the actual droids in the films.

They can be controlled via Bluetooth using either the Sphero Droids app or the Sphero Edu app. I used the latter for my Hackathon project.

For a while these were just display pieces at home. The Hackathon gave me an opportunity to play with them. And I'm glad I did!

Magic-8 Ball with BB-9E

Remember those magic 8-ball toys that could "predict the future" when you shake them?

For this project I remixed an existing Magic Ball project from Sphero Edu and added a few touches of my own.

I changed the wording of the replies to be Star Wars related, and used different BB-9E animations for each type of answer.

Unlike R2-D2, BB-9E doesn't have a built-in speaker so the sounds come from the app. Also, I learned the hard way that you have to be gentle while shaking BB-9E - the head falls off easily!


var predictor = 0;

// colours
const WHITE = {r: 255, g: 255, b: 255};
const GREEN = {r: 0, g: 255, b: 0};
const YELLOW = {r: 255, g: 255, b: 0};
const RED = {r: 255, g: 0, b: 0};
const BLACK = {r: 0, g: 0, b: 0};

async function startProgram() {
	await Animation.BB9E.Positive.Greetings.play();
	setMainLed(WHITE);
	await speak('What is your question?');
	
	while(true) {
		await waitForInteraction();
	}
}


async function waitForInteraction() {
	setStabilization(false);	// required to use accelerometer
	
	if (Math.sqrt((getAcceleration().x ** 2) + (getAcceleration().y ** 2) + (getAcceleration().z ** 2)) > 5) {
		setMainLed(BLACK);
		await Sound.BB9E.Chatty.play();
		await strobe({ r: 255, g: 255, b: 255 }, 0.2, 10);
		
		await getPrediction();
		await reset();
	}
	
	await delay(0.025);
}

async function getPrediction() {
	predictor = getRandomInt(1,3);
	
	switch(predictor) {
		case 1:
			await Animation.BB9E.WWM.Happy.play();
			setMainLed(GREEN);
			await speak(getYesAnswer());
			break;
		case 2:
			await Animation.BB9E.WWM.Bored.play();
			setMainLed(YELLOW);
			await speak(getMaybeAnswer());
			break;
		case 3:
			await Animation.BB9E.WWM.Ominous.play();
			setMainLed(RED);
			await speak(getNoAnswer());
			break;
	}
}

async function reset() {
	await delay(1);
	predictor = 0;
	await speak('What is your question?');
	setMainLed(WHITE);
}

function getYesAnswer() {
	var randomAnswer = getRandomInt(1,2);
	switch(randomAnswer) {
		case 1:
			return "Affirmative";
		case 2:
			return "The force is with you";
	}
}

function getMaybeAnswer() {
	var randomAnswer = getRandomInt(1,2);
	switch(randomAnswer) {
		case 1:
			return "The force is hazy, try again";
		case 2:
			return "Concentrate and ask again";
	}
}

function getNoAnswer() {
	var randomAnswer = getRandomInt(1,2);
	switch(randomAnswer) {
		case 1:
			return "Negative";
		case 2:
			return "No, it's a trap!";
	}
}

Collision Detection with R2-D2

This is a simple project wherein R2-D2 would move in one direction until it hits an obstacle, upon which it would reverse its direction and continue moving that way.

Unfortunately it wasn't as straightforward as I thought it would be.

For R2-D2 to register a collision, the obstacle would have to hit its main body. However, the way R2-D2 moves means its legs are forward and its body is leaning back when it hits a wall. Hence, the collision is never detected!

Since I couldn't rely on wall collisions registering, I had to strike the body myself to demonstrate the collision detection. This needed to be done carefully though - if I struck too hard, R2-D2 would fall over!


var droid = RobotType.BB9E;

async function startProgram() {
	droid = getConnectedRobotType();
	
	if (droid === RobotType.R2D2) {
		await Animation.R2D2.Positive.Excited.play();
	}
	else if (droid === RobotType.BB9E) {
		await Animation.BB9E.WWM.Ominous.play();
	}
	
	setSpeed(100);
	await spin(360, 1);
	await delay(1.5);
	
	setHeading(0);
	
	while (true) {
		setMainLed({
			r: 0,
			g: 255,
			b: 0
		});
		
		await roll(getHeading(), 200, 2);
	}
}

async function onCollision() {
	
	setMainLed({ r: 255, g: 0, b: 0 });
	
	if (droid === RobotType.R2D2) {
		await Animation.R2D2.Negative.No.play();
	}
	else if (droid === RobotType.BB9E) {
		await Animation.BB9E.Negative.play();
	}
	
	setHeading(getHeading() + 180);
	
	await delay(0.5);
	setMainLed({ r: 0, g: 255, b: 0 });
}

registerEvent(EventType.onCollision, onCollision);

The Showcase

Part of the Hackathon is to showcase your findings in a 5-minute presentation. It was a totally nerve-wracking experience, but so worth it.

As an introverted and shy person, I don't like public speaking but I'm glad I pushed myself to get up there and talk.

Even though I didn't completely finish my demos (ran out of time!), the feedback afterwards was great! People think I'm some robot whisperer now 🤣

Having a Hackathon in your own workplace? I encourage everyone to join these types of events! It's a fun way to re-energise your coding passion, with the added benefit of increasing your visibility in the office.

Kristina Alberto

Software engineer from Sydney. I work at Domain Group.