An Ambient Orb

Made by Yuhan Wu

Create an ambient display of notification using webhook to trigger the display by IFTTT.

Created: December 3rd, 2023

0

Outcome

    • Below is image of particle serial monitor showing the function triggered by applet and information on IFTTT activity page, as well as the completed code.
    • Also the video contains the process of operation.

0
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>

#define PIXEL_PIN D2
#define PIXEL_COUNT 16
#define PIXEL_TYPE WS2812

Adafruit_NeoPixel strip = Adafruit_NeoPixel( PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE );

uint32_t w = strip.Color(255, 255, 255);
uint32_t r = strip.Color(255, 0, 0);
//container for strip.Color

int Brightness = 0;             // container for map the elapsed time
int interval = 60000;           // fade duration
unsigned long lastFade = 0;
unsigned long start = 0;
unsigned long elapsedTime = 0;
//variable to store brightness
//lu data for fade and refade

bool fadeFlag = false;
//flag to trigger fading

void setup() {
    
    Serial.begin(9600);
    
    strip.begin();
    strip.show();
    
    Particle.function( "ambientOrb" , ambientOrb );
    Particle.function( "turnRed", turnRed );
    //testing with red
    setColor(w);
    //default color white
    Serial.println("Setup");

}

void loop() {
    
    if (fadeFlag) {
    start = millis();
    Serial.println("Call fade function");
    Serial.printlnf("Start Time   : %5.2lu ms", start);
    fade(w, r, false);

    start = millis();
    Serial.println("Call refade function");
    Serial.printlnf("Start Time   : %5.2lu ms", start);
    fade(r, w, true);

    fadeFlag = false; // Reset the flag after fading
  }
}

int ambientOrb( String cmd ){
    if (cmd == "fade") {
        fadeFlag = true; // Set the flag to trigger fade in the loop
        Serial.println("Flag to fade");
        return 1;
    } else {
        setColor(w);
        return 0;
    }
}

int turnRed( String command ){
    if ( command == "red" ){
        setColor(r);
        Serial.println("Set to Red");
        return 1;
    }else{
        setColor(w);
        Serial.println("Reset to Default Color");
        return -1;
    }
}

void fade(uint32_t oColor, uint32_t dColor, bool refade){
    unsigned long now = millis();
    int n = 0;                      
    //counter for serial port
    while (now - start <= interval) {
        now = millis();
        elapsedTime = now - start;
        n++;
        //activate counter
        Serial.println(n);
        Serial.println(refade ? "Re-Fading" : "Fading");
        int mapBrightness;
        if (refade) {
            mapBrightness = map(elapsedTime, 0, interval, 0, 255);
        } else {
            mapBrightness = map(elapsedTime, 0, interval, 255, 0);
        }
        //define fade direction based on bool input
        uint32_t f = strip.Color(255, mapBrightness, mapBrightness);
        // Calculate the brightness based on the elapsed time
        // Container for strip.Color
        for (int i = 0; i < strip.numPixels(); i++) {
            strip.setPixelColor(i, f);
        }
        strip.show();
        // Update color to neopixel
        Serial.printlnf("Elapsed Time : %5.2lu ms", elapsedTime);
        Serial.printlnf("Brightness   : %5.2lu", mapBrightness);
        Serial.println();
        delay(1000);
    }
    Serial.println(refade ? "Re-Fade function ended" : "Fade function ended");
}

void setColor(uint32_t color){
    for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, color);
    }
    strip.show();
}
//setColor function to change color immediatly
Click to Expand
0
Skill Dev 3 Ambient Orb
DIOT-Max - https://youtu.be/EUEalhnlFdM
0

Debugging for simple ambient orb

Using dht sensor in dev 2 gave me a chance to interact with serial monitor and it helps a lot. (Here as well.) I added Serial.println whenever calling a function or when a part of code was executed to document the progress.
With screenshots of particle serial monitor, the process of coding for a simple is clearly kind of all related to the usage of millis();.

The first error was caused by missing part of code to initialize start time to set up the function using elapsed time for mapping brightness. Second one is also kind of a relevant mistake, caused by leaving out a initialization for fading back.

0

And finally, the particle serial monitor is listening to the fading speed of the argon and counting the the times that the fading functions is activated.

0

Coding process for simple ambient orb

The first idea is to create a function like calling out colors and let the strip fade. A fade function that use the logic of setColor, with the help of mapping overall brightness using elapsed time to evaluate the current progress.

With a function of void fade(uint32_t oColor, uint32_t dColor, bool refade), and call strip.Color containers w and r, it actually combines a void fade () with a void refade().  

The complete code for a simple orb is as followed. And the function could work when called on particle console.

0
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>

#define PIXEL_PIN D2
#define PIXEL_COUNT 16
#define PIXEL_TYPE WS2812

Adafruit_NeoPixel strip = Adafruit_NeoPixel( PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE );

uint32_t w = strip.Color(255, 255, 255);
uint32_t r = strip.Color(255, 0, 0);
//container for strip.Color

int Brightness = 0;             // container for map the elapsed time
int interval = 60000;           // fade duration
unsigned long lastFade = 0;
unsigned long start = 0;
unsigned long elapsedTime = 0;
//variable to store brightness
//lu data for fade and refade

void setup() {
    
    Serial.begin(9600);
    
    strip.begin();
    strip.show();
    
    Particle.function( "ambientOrb" , ambientOrb );
    Particle.function( "turnRed", turnRed );
    //testing with red
    setColor(w);
    //default color white
    Serial.println("Setup");

}

int ambientOrb( String cmd ){
     if ( cmd == "fade" ){
        start = millis();
        Serial.println("Call fade function");
        Serial.printlnf("Start Time   : %5.2lu ms", start);
        fade(w, r, false);
        
        start = millis();
        Serial.println("Call refade function");
        Serial.printlnf("Start Time   : %5.2lu ms", start);
        fade(r, w, true);
        return 1;    
    }else{
        setColor(w);
        return 0;
    }
}

int turnRed( String command ){
    if ( command == "red" ){
        setColor(r);
        Serial.println("Set to Red");
        return 1;
    }else{
        setColor(w);
        Serial.println("Reset to Default Color");
        return -1;
    }
}

void loop() {
}

void fade(uint32_t oColor, uint32_t dColor, bool refade){
    unsigned long now = millis();
    int n = 0;                      
    //counter for serial port
    while (now - start <= interval) {
        now = millis();
        elapsedTime = now - start;
        n++;
        //activate counter
        Serial.println(n);
        Serial.println(refade ? "Re-Fading" : "Fading");
        int mapBrightness;
        if (refade) {
            mapBrightness = map(elapsedTime, 0, interval, 0, 255);
        } else {
            mapBrightness = map(elapsedTime, 0, interval, 255, 0);
        }
        //define fade direction based on bool input
        uint32_t f = strip.Color(255, mapBrightness, mapBrightness);
        // Calculate the brightness based on the elapsed time
        // Container for strip.Color
        for (int i = 0; i < strip.numPixels(); i++) {
            strip.setPixelColor(i, f);
        }
        strip.show();
        // Update color to neopixel
        Serial.printlnf("Elapsed Time : %5.2lu ms", elapsedTime);
        Serial.printlnf("Brightness   : %5.2lu", mapBrightness);
        Serial.println();
        delay(1000);
    }
    Serial.println(refade ? "Re-Fade function ended" : "Fade function ended");
}

void setColor(uint32_t color){
    for (int i = 0; i < strip.numPixels(); i++) {
    strip.setPixelColor(i, color);
    }
    strip.show();
}
//setColor function to change color immediatly
Click to Expand
0

However, IFTTT trigger the Orb but returning timed out error. After discussing with Zhenfang I tested with the setColor function to check my settings for IFTTT and it actually works. So the question may be resulted from calling and waiting for return in the ambientOrb function that takes longs than the maximum website server waiting time. So the change needed is to remove the call and response outside of the particle function that works with web hook, replaced with a bool that serve as a flag to trigger the fade functions.

0

Reflection

When bump into errors, testing with different parts of code to check the external settings could work as a way of debugging.

Serial monitor is also an important reminder of certain part of code that was neglecting or wasn't executed.

x
Share this Project

Courses

48-675 Designing for the Internet of Things 24

· 11 members

A hands-on introductory course exploring the Internet of Things and connected product experiences.


About

Create an ambient display of notification using webhook to trigger the display by IFTTT.