<
>
back to all cubes

Balloon Cube

Pushing on the cube inflates the balloon... how far?

When Udi Oren started to work on this cube, he tested a few simple pumps that we bought for this task. The pumps didn't give the expected outcome, so we found a simple solution: we got our hands on a discarded blood pressure monitor and re-purposed its pump and valve. The pump worked great and inflated the balloon in a rate that felt right. The valve took care of deflating the balloon.

We wanted the inflation rate to be controlled by the user, so we used the input from an FSR (Force sensitive resistor) placed between two sheets of 4 millimeters plexiglass. This required frequent re-calibration of the response, because the FSR's reading when idle slowly changed with time (the plexiglass sheets applied some force on it, and this force changed between activations). The software took care of that.

We introduced another FSR - this time to measure the force applied by the inflating balloon on the walls of the cube. We tried to prevent the ballon from ripping from over-inflation or from pressing against the sharp electric components.

Arduino code - download here

/*
  CUBES originally created by the interaction Lab, Holon Institute of Technology for the Design Museum Holon.
  http://interaction.shenkar.ac.il
  This work is licensed under a Creative Commons Attribution 3.0 Unported License

  Balloon Cube by Udi Oren
*/

// We had lots of troubles with the hardware setup of the upper sensor. It is sandwitched between two thin layers of
// Perspex Resist, and it isn't very stable. We are doing automatic calibration when the cube isn't touched for  30 seconds,
// but this is risky (what if the user touches the cube while it calibrates?)
// bottom line - it isn't perfect yet...

#define USER_PIN 3          // analog pin connected to top sensor (for blowing the balloon)
#define OVERPRESSURE_PIN 2  // analog pin connected to vertical, internal sensor, which the balloon touches when it is pretty big
#define VALVE_PIN 2         // digital output pin where the release valve is connected (ON = valve closed) 
#define PUMP_PIN 3          // gidital output pin where the air pump is connected.

#define MIN_USER_CHANGE 70                // minimum increase in read sensor value to account as user pressing the sensor
#define MAX_USER_CHANGE_FOR_UNTOUCHED 5   // the sensor value need to stay in these matgins for 30 seconds to start calibration
#define OVERPRESSURE 2                    // when the internal sensor reaches this value, we account it as touched and halt the pump 
#define HALT_TIME 15000                   // when internal sensor is touched, we halt the pump this long (15 seconds)
#define UNTOUCHED_TIME_TO_CALIBRATE 30000 // time needed to be untouched (maximum change = 5) to start calibration of sensor

long user;  // net user input (to be explaind down). it is long and not int from historic reasons (we used to filter it...)
int puser;  // previous user reading

int userBase;  // this holds the calibration number - the sensor reading when not touched.
boolean halting = false;  // a flag for doing a halt for 15 seconds. during this time the pump is only allowed to run slowly, for user feedback
unsigned long haltTime;   // keep timing of halting
unsigned long untouchedTime = 0;  // keep timing for untouched (to start calibration)

void setup() {
  Serial.begin(115200);
  pinMode (VALVE_PIN, OUTPUT);
  pinMode (PUMP_PIN, OUTPUT);
  pinMode (LED_BUILTIN, OUTPUT);
  digitalWrite (LED_BUILTIN, HIGH); // after turning cube on, put on the table and let calibrate until led turns off
  delay(2000);
  calibrate();
  delay(100);
  digitalWrite (LED_BUILTIN, LOW);
}

void loop() {
  int reading = analogRead(USER_PIN);
  user = reading - userBase;
  Serial.print(analogRead(OVERPRESSURE_PIN));
  Serial.print('\t');
  Serial.print(reading);
  Serial.print('\t');
  Serial.println(user);

  if (abs(puser - user) <= MAX_USER_CHANGE_FOR_UNTOUCHED) {
    if (millis() - untouchedTime > UNTOUCHED_TIME_TO_CALIBRATE) {
      Serial.println("Cal");
      calibrate();
      untouchedTime = millis();
    }
  } else {
    untouchedTime = millis();
  }

  puser = user;

  if ( user > MIN_USER_CHANGE)
    pump (255);
  else
    pump(0);

  if (analogRead(OVERPRESSURE_PIN) >= OVERPRESSURE)
    halt();

  delay(50);
}

void halt() {
  Serial.println("Halt");
  halting = true;
  haltTime = millis();
}

void pump(int p) {
  if (p > 0) {
    if (halting) {
      if (millis() - haltTime > HALT_TIME) {
        halting = false;
      } else {
        digitalWrite (VALVE_PIN, LOW);
        analogWrite (PUMP_PIN, p / 4);
      }
    } else {
      digitalWrite (VALVE_PIN, HIGH);
      analogWrite (PUMP_PIN, p);
    }
  } else {
    digitalWrite (VALVE_PIN, LOW);
    digitalWrite (PUMP_PIN, LOW);
  }
}

void calibrate() {
  long d = 0;
  for (int i = 0; i < 100; i++) {
    d += analogRead(USER_PIN);
    delay(1);
  }
  d /= 100l;
  userBase = (int)d;
}

Parts:

(1x) Arduino Mini Pro 5V

(2x) TIP112 - Darlington Transistor

(1x) FSR - Forse Sensitive Resistor - 0.5"

(1x) FSR - Small Force Sensitive Resistor

(2x) 10kOhm Resistors

(2x) 1N914 Fast Switching Diode

(1x) 7.2V Li-Po Battery

(1x) 5.5/2.1mm Jack Socket

(1x) Air pump (from blood pressure monitor)

images