Isabel - Ambient Orb

Made by Isabel Fleck

Learning how to use the Neopixel stick and program it to create unique light patterns in response to the period of time in which pressure is applied.

Created: December 5th, 2024

0

Intention

While the main intention of this project was to create an ambient light effect as a response to a google calendar alert. I struggled to get the IFTTT to work, and resorted to creating a different alert system that is based on the period of time in which someone is holding the pressure sensor. Much like how a calendar has different alerts and settings, this creates a different signal light based upon the period of time you hold the pressure sensor.

0

Process

As I worked through the assignment. I began by creating a basic circuit that connected purely the neopixel to the board, and tested the rainbow code on my board to see if the wiring was correct. However, while I was trying to implement this test code to my original code, I found myself being consistently faced with the error of the neopixel library not being found. After many attempts, I finally was able to get some help and learned how to add this library to my board, and was happy to see this work. From here, I wanted to explore a new way to interact with the light, and added a pressure module to my board, so that when pressed at different pressures there would be a different light setting that is triggered. Organizing the code in different events, I could then create specific light patterns within each and call them based on the amount of pressure that was applied.

0
Ambient orb Skill Dev
Isabel Fleck - https://youtu.be/tUxMzLHG2Rk
0

Outcome

    • In the end, I was able to produce a pattern of light sequences that were triggered at different pressures. I was happy with the response of the pressure and the light, as the pressure was quite finicky for some time, but after carefull readjusting of the values, I was able to produce a decent outcome.

0
#include "Particle.h"
#include "neopixel.h"

SYSTEM_MODE(AUTOMATIC);

// Define pin and NeoPixel configuration for Photon 2
#if (PLATFORM_ID == 32)
#define NEOPIXEL_PIN SPI // Use MOSI for Photon 2
#else
#define NEOPIXEL_PIN D3 // Use D3 for other Particle devices
#endif

#define NUM_PIXELS 8     // Number of LEDs in the NeoPixel strip
#define PIXEL_TYPE WS2812B // Specify the NeoPixel type

// Pressure sensor pin
#define PRESSURE_PIN A0

// Create a NeoPixel object
Adafruit_NeoPixel strip(NUM_PIXELS, NEOPIXEL_PIN, PIXEL_TYPE);

void setup() {
    strip.begin();   // Initialize NeoPixel strip
    strip.show();    // Turn off all LEDs initially
    Serial.begin(9600); // Debugging
    
    // Subscribe to events from the Particle Cloud
    Particle.subscribe("weatherEvent", weatherEventHandler);
}

// Function prototypes for weather effects
void thunderEffect();
void rainEffect();
void cloudyEffect();
void sunnyEffect();

// Function to publish weather events
void publishWeatherEvent(const char* eventName) {
    String event = String("weatherEvent/") + eventName;
    Particle.publish(event);  // Publish the event with the prefix
    weatherEventHandler(event.c_str(), ""); // Call event handler immediately
}

// Particle event handler
void weatherEventHandler(const char* event, const char* data) {
    String eventString = String(event);

    if (eventString == "weatherEvent/sunny") {
        sunnyEffect(); // Call sunny effect function
    }
    else if (eventString == "weatherEvent/cloudy") {
        cloudyEffect(); // Call cloudy effect function
    }
    else if (eventString == "weatherEvent/rainy") {
        rainEffect(); // Call rainy effect function
    }
    else if (eventString == "weatherEvent/thunder") {
        thunderEffect(); // Call thunder effect function
    }
}

void loop() {
    // Read the pressure sensor value
    int pressure = analogRead(PRESSURE_PIN);
    Serial.println(pressure); // Debugging the sensor value

    // Check how long the pressure is held
    static unsigned long pressStartTime = 0;
    static bool isPressed = false;

    if (pressure > 1000) { // Threshold for detecting a press
        if (!isPressed) {
            pressStartTime = millis(); // Start timing
            isPressed = true;
        }
    } else {
        isPressed = false;
    }

    if (isPressed) {
        unsigned long pressDuration = millis() - pressStartTime;

        if (pressDuration > 5000) {
            publishWeatherEvent("thunder");
        } else if (pressDuration > 3000) {
            publishWeatherEvent("rainy");
        } else if (pressDuration > 2000) {
            publishWeatherEvent("cloudy");
        } else if (pressDuration > 1000) {
            publishWeatherEvent("sunny");
        }
    } else {
        strip.clear(); // Turn off LEDs when not pressed
        strip.show();
    }
}

// Thunder: Blue and yellow flash
void thunderEffect() {
    for (int i = 0; i < NUM_PIXELS; i++) {
        strip.clear();
        if (i % 2 == 0) {
            strip.setPixelColor(i, strip.Color(0, 0, 128)); // Dim blue
        } else {
            strip.setPixelColor(i, strip.Color(128, 128, 0)); // Dim yellow
        }
        strip.show();
        delay(50);
    }
    strip.clear();
    strip.show();
}

// Rain: Light dim blue light
void rainEffect() {
    for (int i = 0; i < NUM_PIXELS; i++) {
        strip.clear();
        strip.setPixelColor(i, strip.Color(0, 0, 128)); // Dim blue
        strip.show();
        delay(100);
    }
}

// Cloudy: Dim violet/lavender light
void cloudyEffect() {
    static int brightness = 0;
    static int direction = 5;

    brightness += direction;
    if (brightness >= 100 || brightness <= 0) {
        direction = -direction;
    }

    uint32_t color = strip.Color(75 + brightness, 50 + brightness, 150 + brightness); // Dim lavender/violet
    for (int i = 0; i < NUM_PIXELS; i++) {
        strip.setPixelColor(i, color);
    }
    strip.show();
    delay(50);
}

// Sunny: Warm orange light
void sunnyEffect() {
    static int brightness = 0;
    static int direction = 5;

    brightness += direction;
    if (brightness >= 255 || brightness <= 50) {
        direction = -direction;
    }

    uint32_t color = strip.Color(255, 140, 0); // Warm orange
    for (int i = 0; i < NUM_PIXELS; i++) {
        strip.setPixelColor(i, color);
    }
    strip.show();
    delay(50);
}
Click to Expand
0

Reflection

In the future I would like to look at how I can apply this setup in different settings, as well as figuring out how this might fit in to a more everyday device, and work as an ambient device. Possibly hooking it up to another servo to create a flower blooming effect when in response to different lights, and applying different narratives these each of these contexts. 

0
Skill Dev Orb
Isabel Fleck - https://youtu.be/A0kywkrSECw
x
Share this Project


About

Learning how to use the Neopixel stick and program it to create unique light patterns in response to the period of time in which pressure is applied.