An Ambient Orb
Made by Yuhan Wu
Made by Yuhan Wu
Create an ambient display of notification using webhook to trigger the display by IFTTT.
Created: December 3rd, 2023
// 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
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.
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.
// 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
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.
A hands-on introductory course exploring the Internet of Things and connected product experiences.
Create an ambient display of notification using webhook to trigger the display by IFTTT.