The Cabinut Part 2

October 11, 2011

The Cabinut's one and only behavior isolated on BJ Fogg's behavior grid. It focusses on developing a one-time, positively reinforcing hot trigger for an existing behavior and then scaling the behavior over time.
This trigger just ain't hot enough!
An alarm is a negative reinforcer - not cool.
The sweet spot
The hot trigger (see video below) was designed with "delightfully complimentary" sounds and placed so that it worked immediately upon opening and closing the cabinet door.I just stuck a post-it over the edge of the door and used an ultra-sonic range finder to track when the door opened and closed.The Arduino / Wave Shield / Speaker setup on a pretty dusty shelf. It's mostly out of sight.

This week’s DIY Health assignment asked us take a look at our previous behavior assignment and based on new insights which we’ve acquired from BJ Fogg’s behavior grid and analyze what we are really asking the user of our experiment to do. Often we think we’ve asked a very simple task of our user, but in fact the simple task may be composed of numerous steps and contingent behaviors. Once we’ve determined how behaviors that are in the system, to classify each behavior on the behavior grid in order to give us some insight in to how we might approach the task of building a lasting impact.

Taking a look again at The Cabinut I believe the task to only be composed of the single familiar (i.e. Blue Behavior on the grid) behavior (closing a cabinet door) to be triggered only and immediately after another familiar behavior (opening a cabinet door). The triggering behavior really needs no classification on the grid, because I don’t really care what happens with this behavior. Maybe I could try to eliminate the behavior, possibly by removing all the cabinet doors (i.e. “shooting the dog in Karen Pryor’s words) but I feel confident that doing so would be a bit too disruptive without trying other methods first. Aside from this option, scaling the opening behavior in either direction would probably have no impact (I’m guessing). The reason I say this is because I believe that the instances of failing to close the cabinet behavior are not merely a percentage of the total number of opening instances, but more likely a function of how late my wife is when she wakes up. This is taking me down a rabbit hole, but a better method might involve setting an extra alarm so she has plenty of time to close any open cabinets.

Assuming that:

  1. I’m not going to attempt to affect the triggering behavior in any way, and
  2. that I don’t want to leave to chance the hypothesis that if she gets up extra early she’ll close any open cabinets

The only other behavior that needs to be classified is the closing behavior, which is a familiar behavior. She’s closed them before and is perfectly capable of doing achieving the task. So I’d like to focus on getting the behavior to occur once, then over a span and eventually making it a no-brainer for her. This is basically what I had set up previously, however looking back at how I was trying to achieve this after reading Karen Pryor’s Don’t Shoot The Dog I notice a couple of things that are not quite as precise or as positive as they could be.

I first thought I could create an alarm attached to the door. If the door opened and it wasn’t closed within a given amount of time there would be an obnoxious noise, or a negative reinforcer. Judging by the name alone you can see that this isn’t the best way to achieve behavior change. Using this approach, my wife’s one and only reward for doing a behavior is to be spared an extremely painful noise (I even bought a couple door alarms which are psychotic). Not cool.

Then I figured I could achieve the same effect just by putting a post-it note on the front door so she’ll always see it and check the cabinets. But this isn’t hot enough of a trigger, and even if it seems to have been working for a little bit with a promise to paint our apartment, it’s power is going to fade for sure.

Knowing these things I think a better way to go about this is to use a hot trigger attached to the cabinet door and have it fire when the door opens and again when it closes. The idea is to create a cognitive link (and a delightful and pleasurable one at that) between the two behaviors so that the first never occurs without the second ALSO occurring. One way to do this is to use two audio bits that are complimentary and by hearing the first and NOT the second leaves a strange incomplete feeling. Like a drumroll without a cymbal crash.

A further step might include some kind of data collection, and the accumulation of (e.g.) 100 straight successful cabinet closures without any prolonged “left-open” periods could warrant a reward – much in the way that a whistle tells a dolphin that it has earned a fish but it only gets to eat the fish after it gets ten whistle-blows. This increases the incentive, and if the complimentary trigger outputs are fun and delightful – hey what’s to stop you!

Stay tuned – hopefully more to come.

2011.10.16 Update

I built a hot trigger (photos above in the slide show) that uses AOL Instant Messenger audio cues that will hopefully be sticky enough so that the equally complimentary behaviors of opening and closing a door will attach to desire to hear the second sound immediately after the first. First test is in the morning.

Technical Notes
I used an Arduino with a audio wave shield and an ultrasonic range finder. Code (just slightly adapted from examples to play my own files in a desired range) uses the WaveHC library, and is below:

#include
#include
#include
#include "WaveUtil.h"
#include "WaveHC.h"

SdReader card;    // This object holds the information for the card
FatVolume vol;    // This holds the information for the partition on the card
FatReader root;   // This holds the information for the filesystem on the card
FatReader f;      // This holds the information for the file we're play

WaveHC wave;      // This is the only wave (audio) object, since we will only play one at a time

#define DEBOUNCE 100  // button debouncer

// this handy function will return the number of bytes currently free in RAM, great for debugging!
int freeRam(void)
{
  extern int  __bss_end;
  extern int  *__brkval;
  int free_memory;
  if((int)__brkval == 0) {
    free_memory = ((int)&free_memory) - ((int)&__bss_end);
  }
  else {
    free_memory = ((int)&free_memory) - ((int)__brkval);
  }
  return free_memory;
} 

void sdErrorCheck(void)
{
  if (!card.errorCode()) return;
  putstring("\n\rSD I/O error: ");
  Serial.print(card.errorCode(), HEX);
  putstring(", ");
  Serial.println(card.errorData(), HEX);
  while(1);
}

int potPin = 0;    // Analog input pin that the potentiometer is attached to
int potValue = 0;   // value read from the pot
int led = 9;    // PWM pin that the LED is on.  n.b. PWM 0 is on digital pin 9
boolean open;

void setup() {
  // set up serial port
  Serial.begin(9600);
  putstring_nl("WaveHC with 6 buttons");

  putstring("Free RAM: ");       // This can help with debugging, running out of RAM is bad
  Serial.println(freeRam());      // if this is under 150 bytes it may spell trouble!

  // Set the output pins for the DAC control. This pins are defined in the library
  pinMode(2, OUTPUT);
  pinMode(3, OUTPUT);
  pinMode(4, OUTPUT);
  pinMode(5, OUTPUT);

  //  if (!card.init(true)) { //play with 4 MHz spi if 8MHz isn't working for you
  if (!card.init()) {         //play with 8 MHz spi (default faster!)
    putstring_nl("Card init. failed!");  // Something went wrong, lets print out why
    sdErrorCheck();
    while(1);                            // then 'halt' - do nothing!
  }

  // enable optimize read - some cards may timeout. Disable if you're having problems
  card.partialBlockRead(true);

  // Now we will look for a FAT partition!
  uint8_t part;
  for (part = 0; part < 5; part++) {     // we have up to 5 slots to look in
    if (vol.init(card, part))
      break;                             // we found one, lets bail
  }
  if (part == 5) {                       // if we ended up not finding one  :(
    putstring_nl("No valid FAT partition!");
    sdErrorCheck();      // Something went wrong, lets print out why
    while(1);                            // then 'halt' - do nothing!
  }

  // Lets tell the user about what we found
  putstring("Using partition ");
  Serial.print(part, DEC);
  putstring(", type is FAT");
  Serial.println(vol.fatType(),DEC);     // FAT16 or FAT32?

  // Try to open the root directory
  if (!root.openRoot(vol)) {
    putstring_nl("Can't open root dir!"); // Something went wrong,
    while(1);                             // then 'halt' - do nothing!
  }

  // Whew! We got past the tough parts.
  putstring_nl("Ready!");
  //
  open = false;
}

void loop() {
  potValue = analogRead(potPin); // read the pot value
  Serial.print(potValue, BYTE);      // print the pot value back to the debugger pane
  //Serial.println(",", DEC);      // print the pot value back to the debugger pane
  if (potValue < 20 && open==true) {     playfile("close-01.wav");     open=false;   }   if (potValue > 30 && open==false ) {
    playfile("OPENI.wav");
    open=true;
  } else {
    //playfile("");
  }

  delay(10);                     // wait 10 milliseconds before the next loop
}

// Plays a full file from beginning to end with no pause.
void playcomplete(char *name) {
  // call our helper to find and play this name
  playfile(name);
  while (wave.isplaying) {
    // do nothing while its playing
  }
  // now its done playing
}

void playfile(char *name) {
  // see if the wave object is currently doing something
  if (wave.isplaying) {// already playing something, so stop it!
    wave.stop(); // stop it
  }
  // look in the root directory and open the file
  if (!f.open(root, name)) {
    putstring("Couldn't open file ");
    Serial.print(name);
    return;
  }
  // OK read the file and turn it into a wave object
  if (!wave.create(f)) {
    putstring_nl("Not a valid WAV");
    return;
  }

  // ok time to play! start playback
  wave.play();
}
x

Hi there. I'm a design & code creative living, working and studying in sunny Brooklyn, NY. I'm currently finishing my thesis project at ITP and looking forward to what comes next.

Keywords: Design, User Experience, Interaction Design, Product Design, Visual Communication, Branding, Processing, Data Visualization, HTML, CSS, Javascript, Python

CV - download cv (pdf - 180kb)

Contact

Education

2010.09 — 2012.05 (expected)

Master of Professional Studies
Interactive Telecommunication Program (ITP) Tisch School of the Arts, New York University

2010.09 — 2004.05

BA Visual Communications with minor in Art History
The George Washington University
Graduated Cum Laude
National Society of Collegiate Scholars
Spring 2003 semester at Sydney University, AU

Work Experience

2012.01 — present

Interaction Designer & Developer, SumAll, New York, NY

I'm currently working on an amazing data product with an incredible team here in SoHo. Check us out!

2011.06 — 2011.09

UX Designer, Microsoft Bing, Bellevue, WA

Worked with design, editorial, dev and program management teams to scope, design and develop prototypes for soon-to-be-released Bing.com feature during a summer internship. The internship culminated in two presentations of the feature prototypes to senior leadership at Microsoft as well as the Bing design team.

2007.02 — 2010.08

Graphic & Interaction Designer, Empax, Inc., New York, NY

Created a range of environmental, print and interactive materials to promote nonprofit clients and their causes. responsible for designing and presenting brand strategies, identities, print collateral, environmental signage, animation, user experience and interface, content management system setup and third party plug-in and data integration, search engine optimization, user analytics and testing.

2006.12 — 2011.08

Freelance Graphic & Interaction Design Consultant, New York, NY

Worked as a sole proprietor with various clients from retail, music, film, nonprofit, real estate and technology industries to create and improve existing brand and user experiences across many platforms and media.

2004.04 — 2006.01

Graphic Designer, The George Washington University Communication & Creative Services, Washington, DC

Worked with project management and external production vendors to deliver a range of print and interactive material related to university publications and communications initiatives. responsibilities included design and implementation of print collateral, posters, animation, environmental signage, web publication and press checks.

Selected Publications

2011.07

Freakonomics (Web),
“What Would it Be Like to Climb 26 Years of Federal Spending?”

2011.04

Flowingdata (Web),
“Physically climb over budget data with Kinect”, by Nathan Yau

2011.02

Logo Lounge 6 (Book),
by Catharine Fishel and Bill Gardner, Rockport Publishers - Gedenk Logo

2010.12

“A Bartender That Pours The Perfect Shot, Every Shot”, by Matt Buchanan

2009.11

Basic Logos (Book),
by Index Book - The 2007 Gotham Awards Logo

2008.10

Print Magazine,
“Dialogue: Martin Kace”, by Steven Heller - The Alliance for Climate Protection Website

Selected Exhibitions

2010.12

ITP Winter show 2010, NYC

2011.04

Data Viz Challenge Party, hosted by Eyebeam and Google, NYC

2011.05

ITP Spring Show 2011, NYC

Other Experience

2006.01 — 2006.12

English Teacher, NOVA Japan, Kure-shi, Hiroshima-ken, Japan
Taught and mentored students of all ages and abilities in small to medium-sized classes to improve proficiency in english linguistics and conversation.