Skill Dev III - Wei Liang
Made by Wei Liang
Made by Wei Liang
Created: November 30th, 2020
In this lab we will learn to use neopixels to achieve ambient design and IFTTT to trigger the design by certain information.
The tricky part of this exercise is to build a reverse for loop to turn off each pixel one by one.
The initial condition of the reverse loop should be uint16_t i=strip.numPixels()-1, since the maximum number of the pixel should be 15 given the fact that the numbers list from 0 to 15 in the neopixel library.
I only use one function to achieve both loops by adding an indicator showing if the loop inside the function is in ascending or descending order.
Actually, I left one pixel out since if I terminate the reverse loop at i>=o instead of i>0, all the pixels turn off but the loop also terminates. Thus I have to leave one pixel out and directly start the next loop.
The video is attached.
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D4
#define PIXEL_COUNT 16
#define PIXEL_TYPE WS2812
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
void setup() {
strip.begin();
strip.setBrightness(50);
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
uint8_t wait = 500;
uint32_t c = strip.Color(255, 255, 255);
uint32_t off = strip.Color(0, 0, 0);
colorWipe(c, wait, 0);
colorWipe(off, wait, 1);
}
// Fill the dots one after the other with a color, wait (ms) after each one
void colorWipe(uint32_t c, uint8_t wait, uint8_t reverse) {
if (reverse == 0) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
} else if (reverse == 1) {
for(uint16_t i=strip.numPixels()-1; i>0; i--) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
} else {
return;
}
return;
}
Click to Expand
I use colorAll function to turn on all the pixels at a certain color simultaneously. The key difference between colorAll and colorWipe is the positioning of strip.show() function - if it is inside the loop, it is lighting up the neopixel one by one; if it is outside the loop, it is turning all the neopixel on/off simualtaneously.
The video is attached.
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D4
#define PIXEL_COUNT 16
#define PIXEL_TYPE WS2812
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
void setup() {
strip.begin();
strip.setBrightness(50);
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
uint8_t wait = 200;
uint32_t red = strip.Color(255, 0, 0);
uint32_t blue = strip.Color(0, 0, 255);
uint32_t green = strip.Color(255, 255, 0);
uint32_t white = strip.Color(255, 255, 255);
colorAll(blue, wait);
colorAll(red, wait);
colorAll(green, wait);
colorAll(white, wait);
}
// Set all pixels in the strip to a solid color, then wait (ms)
void colorAll(uint32_t c, uint8_t wait) {
uint16_t i;
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
}
strip.show();
delay(wait);
}
Click to Expand
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D4
#define PIXEL_COUNT 16
#define PIXEL_TYPE WS2812
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
void setup() {
strip.begin();
strip.setBrightness(50);
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
uint64_t wait = 500;
uint32_t c = strip.Color(255, 255, 255);
uint32_t off = strip.Color(0, 0, 0);
colorSingle(c, wait);
}
// Fill the dots one after the other with a color, wait (ms) after each one
void colorSingle(uint32_t c, uint64_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
strip.setPixelColor(i, 0);
}
}
Click to Expand
I wrote only one Particle.function instead of three by parsing the command input. The format of input should be r,g,b that each of the letters represents the Red, Green, and Blue components. The remaining of the Particle.function calls colorAll function to light the pixels.
The video is attached.
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D4
#define PIXEL_COUNT 16
#define PIXEL_TYPE WS2812
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
int redValue = 255; // Full brightness for an Cathode RGB LED is 0, and off 255
int greenValue = 255; // Full brightness for an Cathode RGB LED is 0, and off 255
int blueValue = 255; // Full brightness for an Cathode RGB LED is 0, and off 255
void setup() {
strip.begin();
strip.setBrightness(50);
strip.show(); // Initialize all pixels to 'off'
Particle.function("set_color", colorSingle);
Particle.variable("Red", redValue);
Particle.variable("Green", greenValue);
Particle.variable("Blue", blueValue);
}
void loop() {
}
int colorSingle(String command) {
String colors[3];
char charBuf[20];
char *token;
uint32_t c;
uint8_t wait = 200;
const char *s = ",";
int i = 1;
command.toCharArray(charBuf, 20);
/* get the first token */
token = strtok(charBuf, s);
colors[0] = token;
/* walk through other tokens */
while( token != NULL ) {
token = strtok(NULL, s);
colors[i] = token;
i++;
}
redValue = colors[0].toInt();
greenValue = colors[1].toInt();
blueValue = colors[2].toInt();
Particle.publish("status","changing color");
c = strip.Color(redValue, greenValue, blueValue);
colorAll(c, wait);
return 1;
}
// Set all pixels in the strip to a solid color, then wait (ms)
void colorAll(uint32_t c, uint8_t wait) {
uint16_t i;
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
}
strip.show();
delay(wait);
}
Click to Expand
The final practice exercise needs to combine neopixel with IFTTT. My IFTTT set up is as follows:
When any google calendar is 15 minutes away, call the Particle.function with the input of time duration of the alert. For simplicity of the demonstration, the time duration of each phase is set as only 1 minute.
The three phases of the alerts are inline with the advanced requirement on the course website:
// This #include statement was automatically added by the Particle IDE.
#include <neopixel.h>
// IMPORTANT: Set pixel COUNT, PIN and TYPE
#define PIXEL_PIN D4
#define PIXEL_COUNT 16
#define PIXEL_TYPE WS2812
Adafruit_NeoPixel strip = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, PIXEL_TYPE);
int redValue = 0; // Full brightness for an Cathode RGB LED is 0, and off 255
int greenValue = 0; // Full brightness for an Cathode RGB LED is 0, and off 255
int blueValue = 0; // Full brightness for an Cathode RGB LED is 0, and off 255
unsigned long lastFade = 0;
void setup() {
strip.begin();
strip.setBrightness(50);
strip.show(); // Initialize all pixels to 'off'
// Particle.function("fade_up", colorFadeUp);
// Particle.function("to_red", colorFadeRed);
// Particle.function("fade_out", colorFadeOut);
Particle.function("time input", colorSeq);
Particle.variable("Red", redValue);
Particle.variable("Green", greenValue);
Particle.variable("Blue", blueValue);
}
void loop() {
}
int colorSeq(String command) {
unsigned long t = command.toInt();
uint64_t wait = t * 1000;
uint32_t c;
c = strip.Color(redValue, greenValue, blueValue);
colorAll(c, wait);
lastFade = millis();
while(millis() - lastFade <= t * 60 * 1000) {
redValue += 4;
greenValue += 4;
blueValue += 4;
c = strip.Color(redValue, greenValue, blueValue);
colorAll(c, wait);
}
lastFade = millis();
while(millis() - lastFade <= t * 60 * 1000) {
greenValue -= 4;
blueValue -= 4;
c = strip.Color(redValue, greenValue, blueValue);
colorAll(c, wait);
}
lastFade = millis();
while(millis() - lastFade <= t * 60 * 1000) {
redValue -= 4;
c = strip.Color(redValue, greenValue, blueValue);
colorAll(c, wait);
}
colorAll(0, wait);
return 1;
}
int colorFadeUp(String command) {
int t = command.toInt();
uint64_t wait = t * 1000;
uint32_t c;
c = strip.Color(redValue, greenValue, blueValue);
colorAll(c, wait);
unsigned long now = millis();
while(now - lastFade <= t * 60 * 1000) {
redValue += 4;
greenValue += 4;
blueValue += 4;
c = strip.Color(redValue, greenValue, blueValue);
colorAll(c, wait);
now = millis();
}
}
int colorFadeRed(String command) {
int t = command.toInt();
uint64_t wait = t * 1000;
uint32_t c;
redValue = 255;
greenValue = 255;
blueValue = 255;
unsigned long lastFade = 0;
c = strip.Color(redValue, greenValue, blueValue);
colorAll(c, wait);
unsigned long now = millis();
while(now - lastFade <= t * 60 * 1000) {
greenValue -= 4;
blueValue -= 4;
c = strip.Color(redValue, greenValue, blueValue);
colorAll(c, wait);
now = millis();
}
return 1;
}
int colorFadeOut(String command) {
int t = command.toInt();
uint64_t wait = t * 1000;
uint32_t c;
redValue = 255;
greenValue = 0;
blueValue = 0;
unsigned long lastFade = 0;
c = strip.Color(redValue, greenValue, blueValue);
colorAll(c, wait);
unsigned long now = millis();
while(now - lastFade <= t * 60 * 1000) {
redValue -= 4;
c = strip.Color(redValue, greenValue, blueValue);
colorAll(c, wait);
now = millis();
}
colorAll(0, wait);
return 1;
}
// Set all pixels in the strip to a solid color, then wait (ms)
void colorAll(uint32_t c, uint64_t wait) {
uint16_t i;
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
}
strip.show();
delay(wait);
}
// Button press interrupt service routine
void buttonPressInterrupt(){
buttonPressFlag = true;
}
Click to Expand
The video below shows the process of the alert: how the alert is triggered by a google calendar event; the pixels fade up from dim white to solid white (increasing RGB values simultaneously in 1 minute); then fade the pixels from solid white to solid red (decreasing green and blue values from 255 to 0 in 1 minute); then fade out the pixels to dark (decreasing red value from 255 to 0 in 1 minute)