Site icon Making Studio

Ben’s Halloween Costume

Bonsai Breathing Backpack

Air pollution is rampant. biodiversity loss is at a critical level. My halloween costume is a discursive project that sparks conversation around humanity’s future quality of life. I built a personal oxygen device that creates a symbiotic relationship between a human and a single tree. The human and the tree exchange Carbon Dioxide for Oxygen to keep both organisms alive. The tree is held in a clear terrarium to enable photosynthesis, with a tube running from the encasement on the top to a gas mask on the human’s face. LED lights are placed under the lid of the encasement to create an organic, dynamic display that symbolizes life.

Arduino Techniques

I experimented with an Adafruit 12 RGBW neopixel display. Adafruit 24 RGB neopixel display and I experimented with different sketches including a Breathe. I settled on a continuous rainbow loop that runs around the top of the tree, forming a continuous halo.

Materials

Steps

  1. create terrarium arrangement in canister
  2. solder wires to neopixel display
  3. select neopixel script to run
  4. hot glue neopixel display to interior of canister lid
  5. attach nebulizer tube to canister lid

Code

//Initialize
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma, change to 1:
#define LED_PIN     1

// How many NeoPixels are attached to the Arduino?
#define TOTAL_LEDs  25

// NeoPixel brightness, 0 (min) to 255 (max)
#define BRIGHTNESS 50 // Set BRIGHTNESS to about 1/5 (max = 255)


// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(TOTAL_LEDs, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)

int MaximumBrightness = 255;
int SpeedFactor;
int StepDelay;

void setup() {
  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  // Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(BRIGHTNESS);
}

void loop()
{
  //breathe(255, 0.008, 5);
  rainbow(10);

}

void breathe(float MaximumBrightness, float SpeedFactor, float StepDelay)
{
  // Make the lights breathe
  for (int i = 0; i < 6000; i++) {
    // Intensity will go from 10 - MaximumBrightness in a "breathing" manner
    float intensity = MaximumBrightness /2.0 * (1.0 + sin(SpeedFactor * i));
    strip.setBrightness(intensity);

    // Now set every LED to that color
    for (int ledNumber=0; ledNumber<TOTAL_LEDs; ledNumber++) {
      strip.setPixelColor(ledNumber, 93, 153, 255);
    }

    strip.show();
    //Wait a bit before continuing to breathe
    delay(StepDelay);
  }
}

// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
  // Hue of first pixel runs 5 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  // means we'll make 5*65536/256 = 1280 passes through this loop:
  for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
    // strip.rainbow() can take a single argument (first pixel hue) or
    // optionally a few extras: number of rainbow repetitions (default 1),
    // saturation and value (brightness) (both 0-255, similar to the
    // ColorHSV() function, default 255), and a true/false flag for whether
    // to apply gamma correction to provide 'truer' colors (default true).
    
    strip.rainbow(firstPixelHue);
    // Above line is equivalent to:
    // strip.rainbow(firstPixelHue, 1, 255, 255, true);
      // Make the lights breathe
  for (int i = 0; i < MaximumBrightness; i++) {
    // Intensity will go from 10 - MaximumBrightness in a "breathing" manner
    int intensity = i;
    strip.setBrightness(intensity);
    
    // // Now set every LED to that color
    // for (int ledNumber=0; ledNumber<TOTAL_LEDs; ledNumber++) {
    //   strip.setPixelColor(ledNumber, 93, 153, 255);
    // }

    //strip.show();
    //Wait a bit before continuing to breathe
    //delay(StepDelay);
  }
    strip.show(); // Update strip with new contents
    delay(wait);  // Pause for a moment
  }
}

Circuit

Exit mobile version