Mind Over Melon

From LVL1
Jump to navigation Jump to search

Mind Over Melon is a LVL1 project made by Chris and Brad. It's purpose is simple: Destroy watermelons with your mind. It uses a Star Wars Force Trainer toy attached to an Arduino FIO with Xbee, paired to another Arduino + Xbee, attached to a 200psi Solenoid Valve. The solenoid valve dumps CO2 into the melon when brain activity reaches a certain threshold.

Hardware

The melon fits over a 3/4" copper pipe full of holes. The pipe is fitted to 1/2" tubing, which connects to a solenoid valve. The solenoid valve is directly connected to a CO2 tank, regulated to 200 PSI.

We used this solenoid valve: http://www.ebay.com/itm/ws/eBayISAPI.dll?ViewItem&item=300615692386&ssPageName=ADME:L:OU:US:1123#ht_2096wt_872

Headset

The Force Trainer headset was hacked using instructions from http://frontiernerds.com/brain-hack. An Arduino Fio ties into the headset through a SoftSerial connection. It reads only the attention level and relays the value over the Xbee back to the base station.

Brain library here.

SoftSerial library here.

#include <Brain.h>
#include <NewSoftSerial.h>

// Set up the brain parser, pass it the serial object you want to listen on.

// Create a NewSoftSerial connection, TX on pin 2, and RX on pin 3
// Download the library here: http://arduiniana.org/libraries/NewSoftSerial/
NewSoftSerial softBrain(2, 3);

Brain brain(softBrain);

void setup() {
  // Start the hardware serial.
  Serial.begin(9600);
}

void loop() {
  if (brain.update()) {
    Serial.print(brain.readAttention());
  }
}

Base Station

The base station consists of an Xbee, 10 LEDs, a relay, and a potentiometer. The relay triggers the solenoid when needed, as the solenoid draws 3A@12v.

The 10 LEDs are attached to D2 - D11 on the Arduino, and are used as an LED bar graph. The relay to fire the melon is on pin D12. The potentiometer acts as a difficulty setting, and is attached to A0. The headset delivers output values ranging from 0-100, so the difficulty knob adjusts the threshold from 0-100 in increments of 10.

Once the threshold is exceeded, the valve is held open for 1 second, then there is a cooldown period of 5 seconds, to allow us to remove the user's headset, so they don't set the machine off again.

The code is below:


void lineGauge(int value);
void lineDDR();
void configureDifficulty();
void explode();

enum state { CONFIG, EXPLODE, DISABLE };

int previousDifficulty;
state melonState;

int brainDifficulty;

int difficultyTimeout;
#define TIMEOUTRESET 2500
#define DISABLEPERIOD 10000

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
  pinMode(12, OUTPUT);
  lineDDR();
  Serial.begin(9600);
  previousDifficulty = analogRead(A0);
  lineGauge(0);
}



// the loop routine runs over aand over again forever:
void loop() {
  if(analogRead(A0) >= previousDifficulty + 10 || analogRead(A0) <= previousDifficulty - 10)
  {
    previousDifficulty = analogRead(A0);
    melonState = CONFIG;
    difficultyTimeout = TIMEOUTRESET;
  }
  
  switch(melonState)
  {
   case CONFIG:
     configureDifficulty();
     break;
   case EXPLODE:
     explode();
     break; 
   case DISABLE:
     delay(DISABLEPERIOD);
     lineGauge(0);
     melonState = EXPLODE;
     while (Serial.read() >= 0);
     break;
  }
}

int lineOutput(int input)
{
  int difficultyScale = map(input, 0, 100, 0, 255);
  int test = map(min((difficultyScale * 10) / brainDifficulty, 255), 0, 255, 1, 10);
  return test;
}

void configureDifficulty()
{
  int out = map(analogRead(A0), 0, 1023, 0, 9);
  lineGauge(1 << out);
  difficultyTimeout--;
  delay(1);
  if(difficultyTimeout <= 0)
  {
    melonState = EXPLODE;
    brainDifficulty = map(analogRead(A0), 0, 1023, 1, 10);
  }
  
}

void explode()
{
  int incomingByte;
      if (Serial.available() > 0) {  
        // read the incoming byte:
        incomingByte = Serial.read();
        Serial.println((int)incomingByte);
        int outfactor = lineOutput((int)incomingByte);
        lineGauge(pow(2, outfactor));
        if(outfactor == 10)
        {
         digitalWrite(12, HIGH);
         delay(1000);
         digitalWrite(12, LOW);
         melonState = DISABLE;
        }
       }
  
}

void lineDDR()
{
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
}

void lineGauge(int value)
{
  unsigned int extraValue = ~value;
  byte toPortD = (extraValue & 0b00111111) << 2;
  byte toPortB = (extraValue & 0b1111000000) >> 6;
  PORTD = toPortD;
  PORTB = toPortB;
  
}