Vol. 16: Hacking the Glade Wisp

Make your own scent output peripheral from a piezo air freshener.

By Wayne Holder

Photos by Wayne Holder



+ Downloads & Extras:

Single Wisp Control Code

void setup () {
  DDRD = 0xFF;
}

void atomize (char pins) {
  unsigned int ii;
  char kk;
  while (digitalRead(8) == HIGH)
    ;
  for (ii = 0; ii < 2000; ii++) {
    PORTD |= pins;
    for (kk = 0; kk < 12; kk++)
      ;
    PORTD &= !pins;
    for (kk = 0; kk < 12; kk++)
      ;
  }
}

void loop() {
  atomize(0x04);
  delay(2000);
}

In the code, the DDRD and PORTD keywords configure the Arduino's D0-D7 pins as outputs to be controlled directly, by using the Arduino's port manipulation commands. The nested loops in the atomize() function toggle the D2 pin (specified by passing in the value 0x04) on and off a total of 2,000 times, with a very short pause after each change. The values I chose for the delay loops make the Arduino's output roughly match the Wisp controller's, but with a shorter, 2-second delay between puffs. You may have seen other code that controls the Arduino's digital outputs by calling digitalWrite(), but this would be too slow to generate a 150MHz signal.

You can experiment with setting the loops to count up to values other than 2,000 and 12 to see how this changes the atomization process, but note that shorter delay times may not give the circuit's 3,300µF capacitor enough time to fully recharge between puffs, which will result in significantly decreased vapor output.

"Orchestra of Fragrance" Keyboard-Controlled Wisp Array Code

Because the Arduino's PORTD value lets you write to all of its digital outputs at the same time, 1 Arduino can control up to 6 Wisps simultaneously. You simply connect each Wisp to a different output pin and pass different values into the atomize() function.

Using the Arduino programming environment's Serial Monitor feature, you can send keyboard characters to the Arduino, which lets you create an instrument that plays fragrances, live. Just make sure to avoid using pins D0 and D1, which share their function with the serial port.

For example, the following code reads an input character and uses it to select which of 4 different Wisps to puff. Typing the 2 key commands the Wisp that's connected to pin D2, typing 3 commands pin D3, and so on.


void setup () {
  DDRD = 0xFF;
  Serial.begin(9600);
}

void atomize (char pins) {
  unsigned int ii;
  char kk;
  for (ii = 0; ii < 2000; ii++) {
    PORTD |= pins;
    for (kk = 0; kk < 12; kk++)
      ;
    PORTD &= !pins;
    for (kk = 0; kk < 12; kk++)
      ;
  }
}

void loop() {
  char cc = Serial.read();
  switch (cc) {
  case '2':
    atomize(0x04);
    break;
  case '3':
    atomize(0x08);
    break;
  case '4':
    atomize(0x10);
    break;
  case '5':
    atomize(0x20);
    break;
  }
}

To set this up, load the code to the Arduino board, then click the Serial Monitor button, which is the rightmost button at the top of the Arduino's development environment. This will display a set of controls near the bottom of the window. Select 9,600 baud, then type a number (2-5) into the text box and press Send. This should trigger the corresponding pin, and the Wisp it’s connected to.


MAKE: AMENDS Errata for This Article

 !

Correction for page 163
In Steps 2 and 3, references to a 150MHz signal should have been to a 150KHz signal.


Join the conversation -- every MAKE article has an online page that includes a place for discussion. We've made these RSS and Atom feeds to help you watch the discussions: subscribe.