• Selected Work
  • About
Menu

Nick Wallace

Design | Technology | Fabrication
  • Selected Work
  • About
hand_midterm.gif

Midterm -- Rock, Paper, Scissors Robot

October 24, 2017

For the midterm, Tong Wu and I built an interactive installation that lets a person play “Rock, Paper, Scissors” against a robotic hand by wearing a glove outfitted with flex sensors.

3D Printed Hand & Forearm

To build the hand and forearm, we used the models from InMoov, an open source project for a 3D printed life-size robot. All of the joints are connect with PLA filament or 3D printed bolts. The finger movements are controlled by high strength fishing line, which runs down through the fingers/arm like tendons to a servo bed at the end.

02-3DPrinting04-3DPrinting05-3DPrinting

07-Servos

Flex Sensitive Glove

On the glove there are two flex sensors, a “start” button, and a “throw” button. These are all sewed into a right-hand glove and connected to a Nano mounted on a perf board. The Arduino is connected to a nRF24L01 wireless transceiver that talks to an identical transceiver on the robot hand.

To play the game, the player puts on the glove, presses the “start" button, then press the “throw” button twice, and makes a hand gesture indicating his/her choice of rock, paper, or scissors.

RPS-player_bb

09-Sewing sensors and other components10-Sewing the glove

Robotic Hand & Forearm Assembly

12-Assembling the hand+forearm

13-Assembling the hand+forearm

Playing the game

Player code

// include SPI and radio libs
#include <SPI.h>
#include <'RF24.h>
#include <'nRF24L01.h>

// define flex sensor pins
#define sensorPointer A0
#define sensorPinkie A1

// define button pins
#define startButton 2
#define tapButton 3

// initialize button variables
int gameState = 0;
int lastGameState = 0;
int throwInput = 0;
int lastThrowInput = 0;
int throwCount = 0;
int computerStart = 4;
int playerChoice = 0;

// initialize radio and variables
RF24 radio(8, 9);
int msg[1];
const uint64_t pipe = 0xE8E8F0F0E1LL;

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

  // start radio transmitter on channel 115
  radio.begin();
  radio.setChannel(115);
  radio.openWritingPipe(pipe);
  radio.stopListening();

  // set sensor inputs
  pinMode(sensorPointer, INPUT);
  pinMode(sensorPinkie, INPUT);

  // set button inputs
  pinMode(startButton, INPUT);
  pinMode(tapButton, INPUT);

}

void loop() {
  // has the player triggered the game to start
  gameState = digitalRead(startButton);
  if (gameState == HIGH && lastGameState == LOW) {
    Serial.println("Game started!");

    // tell computer to start game
    msg[0] = computerStart;
    radio.write(msg, 1);
    Serial.println("Sent start game to computer");
    computerStart++;

    // wait till player throws 2 times
    while (throwCount != 2) {
      throwInput = digitalRead(tapButton);
      delay(100);

      // increase the count after each tap
      if (throwInput == HIGH) {
        throwCount++;
        Serial.print("Throw count: ");
        Serial.println(throwCount);

        // send update to computer
        msg[0] = computerStart++;
        radio.write(msg, 1);

        delay(100);
      }
    }
    delay(10);

    // reset throw variables
    throwCount = 0;
    computerStart = 4;

    // get user input
    userChoice();
    Serial.print("Player choice: ");
    Serial.println(playerChoice);
    Serial.println("paper = 1, scissors = 2, rock = 3");
    Serial.println();

    msg[0] = playerChoice;
    radio.write(msg, 1);
  }

  // reset game state
  lastGameState = gameState;

}

void userChoice() {
  // get player choice based on sensors
  int pinkieSensor = analogRead(sensorPinkie);
  pinkieSensor = map(pinkieSensor, 650, 460, 0, 100);   // map values 0-100
  Serial.print("Pinkie sensor: ");
  Serial.println(pinkieSensor);
  if ( pinkieSensor > 40) {   // finger is bent
    pinkieSensor = 1;
  } else {
    pinkieSensor = 0;
  }
  int pointerSensor = analogRead(sensorPointer);
  pointerSensor = map(pointerSensor, 550, 400, 0, 100);   // map values 0-100
  Serial.print("Pointer sensor: ");
  Serial.println(pointerSensor);
  if ( pointerSensor > 40) {  // finger is bent
    pointerSensor = 1;
  } else {
    pointerSensor = 0;
  }

  // no sensors flex = paper, pinkie flexed = scisors, both flexed = rock
  if (pinkieSensor == 1 && pointerSensor == 1) {    //rock
    playerChoice = 3;
  } else if (pinkieSensor == 1 & pointerSensor == 0) {   //scisors
    playerChoice = 2;
  } else {    // paper
    playerChoice = 1;
  }
}

Rrobot hand code:

// include SPI, radio, and servo libs
#include <SPI.h>
#include <'RF24.h>
#include <'nRF24L01.h>
#include <'Servo.h>

// define servo finger pins
#define servoThumb 6
#define servoPointer 5
#define servoMiddle 4
#define servoRing 3
#define servoPinkie 2

// setup radio
RF24 radio(7, 8);

// initialize servo fingers
Servo thumbFinger, pointerFinger, middleFinger, ringFinger, pinkieFinger;

// initialize game variables
int aiChoice = 0;
int playerChoice = 0;

// initialize radio variables
int msg[1];
const uint64_t pipe = 0xE8E8F0F0E1LL;

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

  // attach the servos
  thumbFinger.attach(servoThumb);
  pointerFinger.attach(servoPointer);
  middleFinger.attach(servoMiddle);
  ringFinger.attach(servoRing);
  pinkieFinger.attach(servoPinkie);

  // set fingers straight
  thumbFinger.write(0);
  pointerFinger.write(0);
  middleFinger.write(0);
  ringFinger.write(0);
  pinkieFinger.write(0);

  // start the radio receiver on channel 115
  radio.begin();
  radio.setChannel(115);
  radio.openReadingPipe(1, pipe);
  radio.startListening();

  // generate seed for random function via floating pin
  randomSeed(analogRead(A2));
}

void loop() {

  // wait to receive start code from player
  while (msg[0] != 4) {
    radio.read(msg, 1);
    Serial.println("Waiting to start game...");
  }

  Serial.println();
  Serial.println("----------------------------------");
  Serial.println("Game started!");
  aiChoice = random(300); // generate psuedo-random number 0-300
  aiChoice = map(aiChoice, 0, 300, 1, 3);

  while (msg[0] != 5) {
    radio.read(msg, 1);
  }
  // count to one
  Serial.println("Moving fingers to 1...");
  pinkieFinger.write(180);
  ringFinger.write(180);
  middleFinger.write(180);
  thumbFinger.write(180);
  delay(100);

  while (msg[0] != 6) {
    radio.read(msg, 1);
  }
  // count to two
  Serial.println("Moving fingers to 2...");
  Serial.println();
  delay(100);

  // move robot hand per computer choice
  switch (aiChoice) {
    case 1:   // paper
      // leave all fingers open
      delay(2000);
      Serial.println("Computer choice: paper");
      break;
    case 2:   // scissors
      // move thumb, ring, and pinkie fingers
      pinkieFinger.write(180);
      ringFinger.write(180);
      thumbFinger.write(180);
      delay(2000);
      Serial.println("Computer choice: scissors");
      break;
    case 3:   // rock
      // move all fingers
      pinkieFinger.write(180);
      ringFinger.write(180);
      middleFinger.write(180);
      pointerFinger.write(180);
      thumbFinger.write(180);
      delay(2000);
      Serial.println("Computer choice: rock");
      break;
  }
  Serial.println();

  // wait for choice from player
  while (msg[0] != 1 && msg[0] != 2 && msg[0] != 3) {
    radio.read(msg, 1);
    Serial.println("Waiting for player choice");
  }
  playerChoice = msg[0];
  Serial.println();
  Serial.print("Player choice: ");
  Serial.println(playerChoice);
  Serial.println("paper = 1, scissors = 2, rock = 3");
  Serial.println();

  // compare choices to see who wins
  if (playerChoice == aiChoice) {   // tie game
    // countdown code and throw again code here
    //break;
    Serial.println("Tie game!");

  } else {
    switch (aiChoice) {

      // computer chooses paper
      case 1:
        switch (playerChoice) {
          case 2: // player chooses scissors
            // player wins!
            Serial.println("Player wins!");
            // scissors cuts paper
            break;
          case 3: //player chooses rock
            // computer wins!
            Serial.println("Computer wins!");
            // paper wraps rock
            break;
        }
        break;

      // computer chooses scissors
      case 2:
        switch (playerChoice) {
          case 1: // player chooses paper
            // computer wins!
            Serial.println("Computer wins!");
            // scissors cuts paper
            break;
          case 3: // player chooses rock
            // player wins!
            Serial.println("Player wins!");
            // rock crushes scissors
            break;
        }
        break;

      // computer chooses rock
      case 3:
        switch (playerChoice) {
          case 1: // player chooses paper
            // player wins!
            Serial.println("Player wins!");
            // paper covers rock
            break;
          case 2: // player chooses scissors
            // computer wins!
            Serial.println("Computer wins!");
            // rock crushes scissors
            break;
        }
        break;
    }
  }
  Serial.println("----------------------------------");
  Serial.println();

  // reset game variables
  playerChoice = 0;
  aiChoice = 0;

  // reset servos
  thumbFinger.write(0);
  pointerFinger.write(0);
  middleFinger.write(0);
  ringFinger.write(0);
  pinkieFinger.write(0);

 delay(1000); 
}
In Fall 2017, ITP Tags Physical Computing
← Final (Planning) -- The HandFinal -- RAIN-MKR →

© 2020 Nick Wallace