rfidge

rfidge

An Obnoxious, Singing RFID Refridgerator

Within a matter of years, RFID technologies will supplant UPC as the standard for tracking consumer food products. Everything we buy from a grocery store will be tracked and monitored by thin radio transmitters embedded into its packaging.

Industrialists love RFID for its ability to track individual units from the factory floor to shipping plants to the stores, and eventually, into the homes of consumers. Appliances will get smarter and be able to use this information to inform cooking and buying habits.

rfidge provides a glimpse into the dual nature of future RFID ubiquity. On one hand, rfidge knows what's inside of it at all times, and provides a way of visualizing that information in a totally new way. This generative techno music based on the contents of rfidge illustrates the flip side of this coin in how potentially annoying it can become.

This piece challenges you to reconsider your notions about what it means for a technology to be convenient, and what implications this coming technological ubiquity presents on a larger scale. Although this refrigerator does nothing more than sing about your food, the same setup could easily be used towards much darker ends.

Each item is tagged with a particular code, which is linked in a database to a particular sound loop. rfidge knows what's inside of it by tracking the tags as they go in and out. Every time the door is opened, rfidge generatively composes a song based upon its contents. Adding or removing items affects the song accordingly in real time.

How It Works

Although the technology is on its way, most of what I eat doesn't have RFID tags yet, so I affixed tags onto them myself. Basically, RFID tags transmit tiny radio signals when activated by a reader, and send a unique identifying code to that reader. (Wikipedia has a good entry, in case you want to know the details)

When a widescale implementation of RFID hits the market, those IDs can be queried against a database from the manufacturer, which will store information about when and where it was packaged, stored, and sold. For this piece, though, I mapped the small set of tags to my inventory of techno loops.

A Processing program waits for an RFID Phidget module to send a signal reading. When a signal is detected, it is checked against the list of codes assigned to techno beats for the respective food, and if there's a match, it will cue the loop. The program keeps track of what's gone in and out of the fridge, so when a conveniently-placed RFID tag on the hinge on the fridge signals that it's open, a techno song is randomly generated based on what's inside of it. That same tag on the hinge stops the beat when the door is closed again.

The Album Version

Images

Thumb Computer Thumb S Pellegrino Thumb S Pellegrino Bottom Thumb Dressing Thumb Camera

Media

Code

Below is the Processing code that drove the project:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
import com.phidgets.*;
import com.phidgets.event.*;

import ddf.minim.*;

int LOOP_LENGTH = 8000;

static final boolean ON = true;
static final boolean OFF = false;

RFIDPhidget rfid;

static RFIDTag[] tags;

static RFIDTag[] activeTags;
static int loopCount = 0;
static int timer = -1;

static boolean fridgeIsOpen = false;

final String[] CODES = new String[]{"0e0072efe0", "0e0072f4c5", "0e0072ea58",  "0e0072df65", "0e0072eb56", "0b0094cefa"};
final String[] FILES = new String[]{"Apple.wav",  "Milk.wav",   "Ketchup.wav", "Yogurt.wav", "Eggs.wav",   "Grapes.wav"};

void setup()
{
  Minim.start(this);

  tags = new RFIDTag[FILES.length];
  for(int i = 0; i < tags.length; i++)
  {
    String code = CODES[i];
    String file = FILES[i];
    tags[i] = new RFIDTag(code, file);
  }

  try
  { 
    rfid = new RFIDPhidget();

    rfid.addTagGainListener(new TagGainListener(){
      public void tagGained(TagGainEvent oe){
        println(oe);
      }
    }
    );
    rfid.addTagLossListener(new TagLossListener(){
      public void tagLost(TagLossEvent oe){
        RFIDTag.process(oe.getValue());
        println(oe);
      }
    }
    );

    Thread thread = new PhidgetThread();
    thread.start();
  }

  catch(Exception e){
  }

  for(int i = 0; i < tags.length; i++)
  {
    tags[i].initialize();
  }

  activeTags = RFIDTag.active();
}

void draw()
{
  if(fridgeIsOpen)
  {
    if(activeTags == null)
    {
      activeTags = RFIDTag.active();
      shuffle(activeTags);
    }
    else if(timer == -1 || millis() - timer >= LOOP_LENGTH)
    { 
      try
      {
        if(loopCount < activeTags.length)
        {
          RFIDTag tag = activeTags[loopCount];
          tag.unmute();
          println("+ " + tag.toString()); 
          loopCount++;
        }
      }
      catch(ArrayIndexOutOfBoundsException oobe)
      {
        println(oobe);
      }
      timer = millis();
    }
  }
}

void stop()  
{
  try
  {
    rfid.close();
    for(int i=0; i < tags.length; i++)
    {
      tags[i].off();
    }
    super.stop();
  }
  catch(Exception e){
  }
}


static class RFIDTag
{
  static final String DOOR_CODE = "0e0043dca2";

  String code;
  String name;
  AudioPlayer song;
  boolean state;

  static void process(String c)
  {
    if(DOOR_CODE.equals(c))
    {
      if(fridgeIsOpen)
      {
        Refridgerator.close(); 
      }
      else
      {
        Refridgerator.open();
      }
    }
    else
    {
      for(int i=0; i < tags.length; i++)
      {
        RFIDTag tag = tags[i];
        if(tag.code.equals(c))
        {
          tag.trigger();
        }
      }
    }
  }

  static RFIDTag[] active()
  {
    RFIDTag[] temp = new RFIDTag[tags.length];
    int count = 0;
    for(int i = 0; i < tags.length; i++)
    {
      RFIDTag tag = tags[i];
      if(tag.state == ON)
      {
        temp[count] = tag; 
        count++;
      }
    } 
    //return temp;
    return (RFIDTag[]) subset(temp, 0, count);
  }

  static void rewind()
  {
    for(int i = 0; i < tags.length; i++)
    {
      tags[i].song.rewind();
    } 
  }

  public RFIDTag(String c)
  {
    new RFIDTag(c, "nothing.wav");
  }

  public RFIDTag(String c, String s)
  {
    code = c;
    song = Minim.loadFile(s);
    name = s;
  }

  void initialize()
  {
    song.loop();
    song.mute();
  }

  void trigger()
  {
    if(state == OFF)
    {
      on();
    }
    else
    {
      off();
    }
    println("- " + this.toString());
    activeTags = RFIDTag.active();
  }

  void on()
  {
    state = ON;
    unmute();
  }

  void off()
  {
    state = OFF;
    mute(); 
  }

  void mute()
  {
    song.mute(); 
  }

  void unmute()
  {
    song.unmute(); 
  }

  String state()
  {
    if(state == ON)
    {
      return "ON";
    } 
    else
    {
      return "OFF"; 
    }
  }

  String isMuted()
  {
    if(song.isMuted())
    {
      return "Muted";
    }
    return "";
  }

  String toString()
  {
    return name + "\t" + state() + "\t" + isMuted();
  }
}

static class Refridgerator
{
  static void open()
  {
    println("== Refridgerator Door Opened");
    fridgeIsOpen = true;
    shuffle(activeTags);
    RFIDTag.rewind();
  }

  static void close()
  {
    timer = -1;
    loopCount = 0;
    println("== Refridgerator Door Closed");
    fridgeIsOpen = false;
    for(int i = 0; i < tags.length; i++)
    {
      tags[i].mute();
    }
  }
}

class PhidgetThread extends Thread {
  public void run(){
    try{
      
    rfid.openAny();
    rfid.waitForAttachment();

    // println("Serial: " + rfid.getSerialNumber());
    // println("Outputs: " + rfid.getOutputCount());

    rfid.setAntennaOn(true);
    rfid.setLEDOn(true);
    System.in.read();
    }
    catch(Exception e){}
  }
}

public static void exch(Object[] a, int i, int j) {
  Object swap = a[i];
  a[i] = a[j];
  a[j] = swap;
}

public static void shuffle(Object[] a) {
  int N = a.length;
  for (int i = 0; i < N; i++) {
    int r = i + (int) (Math.random() * (N-i));   // between i and N-1
    exch(a, i, r);
  }
}

Colophon

PhidgetRFID
USB Interface to read RFID tags
Processing
RFID signal handling and music sequencing
Mimim
Amazingly great Processing library for sound
GarageBand
Recording of original vocal loops
1PixelOut
Aweseome flash audio player, as used above
Giant Eagle
Distributors of fine food products in Pittsburgh

Thanks

A hearty thanks goes to Professor Mark Gross and Jet for teaching the course and for helping out with materials at the last minute; my roommate for helping me carry the fridge back after I pulled a muscle in the process; Bob Kollar for lending me a nicer camera for the documentation; Derk for giving me that first power supply, even though it fried my first RFID reader; and all of my classmates, who gave me valuable feedback throughout the project.