It’s a little hard for me to classify this post, so troubleshooting it is. I’ve got a photon driving a strip of LEDs and pre-programmed a bunch of patterns into it for different times of the year that use the FastLED library to display. Up until today I’ve just been running color palettes for the most part, but I thought I’d add a new function where the strip could be set to any color, based on the touched area of an image, by way of a canvas color check using the MIT app inventor.
The Android app itself gets the hex color value based on where a finger has touched the image. I parse it in the app to send a string to the Photon formatted as “0x000000”. The Photon then takes that string, converts it to a hex value and feeds it to the fill_solid function of FastLED before displaying it to the strip.
I’m getting somewhat inconsistent results though. The colors it’s able to display (or that it understands) seem very limited and while in this particular mode (vs the other patterns I’ve laid out) it’s SUPER slow to respond when I try to change to another color. It’s as if there’s some other function or loop running that’s causing it to choke. I’m fairly certain this is nothing Photon specific, but the Particle community has been a good source of all around help for this kind of stuff, so I thought I’d ask. Here’s the entirety of my code, the gist of which is this: My app sends a changeMode command to tell it to use the fill_solid function based on whatever currentColor is set. Then the app sends a changeColor command to update that currentColor. Also, there’s a twinkle, but that’s workin fine.
// This #include statement was automatically added by the Particle IDE.
#include <FastLED.h>
#include "Particle.h"
FASTLED_USING_NAMESPACE;
#define LED_PIN 4
#define COLOR_ORDER GRB
#define CHIPSET WS2811
#define NUM_LEDS 301 //88 for testing, 300 for prodction
#define BRIGHTNESS 50
#define FRAMES_PER_SECOND 30
bool gReverseDirection = false;
unsigned long previousMillis = 0;
unsigned long currentMillis;
unsigned long twinkleMillis = 0;
int eepValue;
int eepAddr = 2;
int mode;
int maxShells = round(NUM_LEDS / 30);
int lifespan = 30;
long totalModes = 5;
int changeToColor(String newColor);
uint32_t currentColor=0x000000;
NSFastLED::CRGB leds[NUM_LEDS];
CRGBPalette16 gPal;
void runColor(String currentColor);
void runRainbow();
void twinkle();
void fireworks();
void runPalette(NSFastLED::CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurrentPalette);
class FireworkShell {
int stringPos; //origin of the blast
int age; //how long the blast has been on the string
int maxLife; //how old this one can get
uint8_t hue; //color of the shell
public:
FireworkShell(int xPos, int howOld, int deathAge, uint8_t shellColor) {
stringPos = xPos;
age = howOld;
maxLife = deathAge;
hue = shellColor;
}
void Update() {
if (age < maxLife) {
int newPosR = stringPos + age;
int newPosL = stringPos - age;
if (newPosR < NUM_LEDS) leds[newPosR] += CHSV(hue, 255, 255);
if (newPosL >= 0) leds[newPosL] += CHSV(hue, 255, 255);
if (age > 0) {
int tailR = newPosR - 1;
int tailL = newPosL + 1;
if (tailR > 0 && tailR < NUM_LEDS) {
leds[tailR] = CHSV(hue + 40, 255, random(50, 200));
}
if (tailL > 0 && tailL < NUM_LEDS) {
leds[tailL] = CHSV(hue + 40, 255, random(50, 200));
}
}
}
if (age < maxLife + 20) {
age++;
} else {
age = 0;
hue = random(0, 213);
maxLife = random(5, lifespan);
stringPos = random(0, NUM_LEDS);
//Serial.println(maxLife);
}
}
};
FireworkShell shells[] = {
FireworkShell(random(0, NUM_LEDS), 0, random(5, lifespan), random(0, 255)),
FireworkShell(random(0, NUM_LEDS), 0, random(5, lifespan), random(0, 255)),
FireworkShell(random(0, NUM_LEDS), 0, random(5, lifespan), random(0, 255)),
FireworkShell(random(0, NUM_LEDS), 0, random(5, lifespan), random(0, 255)),
FireworkShell(random(0, NUM_LEDS), 0, random(5, lifespan), random(0, 255)),
FireworkShell(random(0, NUM_LEDS), 0, random(5, lifespan), random(0, 255)),
FireworkShell(random(0, NUM_LEDS), 0, random(5, lifespan), random(0, 255)),
FireworkShell(random(0, NUM_LEDS), 0, random(5, lifespan), random(0, 255)),
FireworkShell(random(0, NUM_LEDS), 0, random(5, lifespan), random(0, 255)),
FireworkShell(random(0, NUM_LEDS), 0, random(5, lifespan), random(0, 255))
};
void setup() {
delay(3000); // sanity delay
FastLED.addLeds<CHIPSET, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
FastLED.setBrightness( BRIGHTNESS );
//FastLED.setMaxPowerInVoltsAndMilliamps(5, 1500);
randomSeed(analogRead(0));
//Serial.begin(9600);
Particle.variable("mode",mode);
Particle.function("updateMode", modeChange);
Particle.function("changeColor", changeToColor);
Particle.variable("newColor", currentColor);
EEPROM.get(eepAddr, eepValue);
if(eepValue == 0xFFFF) {
// EEPROM was empty -> initialize value
mode = 0;
}else{
mode = eepValue;
}
//mode = 0;
}
extern const TProgmemRGBGradientPalettePtr gGradientPalettes[];
void loop()
{
currentMillis = millis();
//Particle.publish("Mode is ", String (mode));
switch (mode) {
case 0:
runRainbow();
twinkle();
break;
case 1:
//runColor(CRGB::Blue);
runPalette(leds, NUM_LEDS, gGradientPalettes[0]);
twinkle();
break;
case 2:
runPalette(leds, NUM_LEDS, gGradientPalettes[1]);
twinkle();
break;
case 3:
runPalette(leds, NUM_LEDS, gGradientPalettes[2]);
twinkle();
break;
case 4:
runPalette(leds, NUM_LEDS, gGradientPalettes[3]);
twinkle();
break;
case 5:
runPalette(leds, NUM_LEDS, gGradientPalettes[4]);
twinkle();
break;
case 6:
fireworks();
break;
case 7:
runPalette(leds, NUM_LEDS, gGradientPalettes[5]);
twinkle();
case 8:
runPalette(leds, NUM_LEDS, gGradientPalettes[6]);
twinkle();
case 9:
runPalette(leds, NUM_LEDS, gGradientPalettes[7]);
twinkle();
case 10:
runColor(currentColor);
twinkle();
break;
}
}
int changeToColor(String newColor){
Particle.publish("Color received is ", String (newColor));
currentColor = strtol(newColor, NULL, 16);
Particle.publish("Hex received is ", currentColor);
}
int modeChange(String newMode){
int modeNum = newMode.toInt();
mode = modeNum;
EEPROM.put(eepAddr, modeNum);
}
void runColor(uint32_t currentColor) {
if (currentMillis - previousMillis >= 200) {
previousMillis = currentMillis;
fill_solid(leds, NUM_LEDS, currentColor);
}
}
void runRainbow() {
if (currentMillis - previousMillis >= 30) {
previousMillis = currentMillis;
static uint8_t hue = 0;
fill_rainbow(leds, NUM_LEDS, hue++);
FastLED.show();
}
}
void twinkle() {
//create random twinkle
int rp = random(500,2000);
if (currentMillis - twinkleMillis >= rp) {
twinkleMillis = currentMillis;
int pixel = random(NUM_LEDS);
leds[random(NUM_LEDS)] = CRGB::White;
FastLED.show();
}
}
void fireworks() {
EVERY_N_MILLISECONDS(30){
fadeToBlackBy(leds, NUM_LEDS, 30);
Serial.println(maxShells);
for (int i = 0; i < maxShells; i++) {
shells[i].Update();
}
FastLED.show();
};
}
void runPalette(NSFastLED::CRGB* ledarray, uint16_t numleds, const CRGBPalette16& gCurrentPalette)
{
if (currentMillis - previousMillis >= 30) {
previousMillis = currentMillis;
static uint8_t startindex = 0;
startindex--;
fill_palette( ledarray, numleds, startindex, (256 / NUM_LEDS) + 1, gCurrentPalette, BRIGHTNESS, LINEARBLEND);
FastLED.show();
}
}
DEFINE_GRADIENT_PALETTE( holly_gp) {
0, 0, 255, 0, //green
48, 0, 255, 0, //green
49, 255, 0, 0, //red
64, 255, 0, 0, //red
65, 0, 255, 0, //green
114, 0, 255, 0, //green
115, 255, 0, 0, //red
118, 255, 0, 0, //red
119, 0, 255, 0, //green
168, 0, 255, 0, //green
169, 255, 0, 0, //red
184, 255, 0, 0, //red
185, 0, 255, 0, //green
234, 0, 255, 0, //green
235, 255, 0, 0, //red
255, 255, 0, 0 //red
};
DEFINE_GRADIENT_PALETTE( candycane_gp) {
0 , 128, 128, 128, //white
32 , 128, 128, 128, //white
33 , 255, 0, 0, //red
66 , 255, 0, 0, //red
67 , 128, 128, 128, //white
100 , 128, 128, 128, //white
101 , 255, 0, 0, //red
134 , 255, 0, 0, //red
135 , 128, 128, 128, //white
168 , 128, 128, 128, //white
169 , 255, 0, 0, //red
202 , 255, 0, 0, //red
203 , 128, 128, 128, //white
236 , 128, 128, 128, //white
237 , 255, 0, 0, //red
255 , 255, 0, 0 //red
};
DEFINE_GRADIENT_PALETTE( snowynight_gp) {
0, 163, 182, 199,
41, 188, 192, 200,
117, 117, 157, 240,
204, 117, 224, 240,
255, 163, 182, 199
};
DEFINE_GRADIENT_PALETTE( silvergold_gp) {
0, 237,121, 1,
25, 237,121, 1,
51, 229,149, 1,
76, 222,178, 1,
102, 237,215, 59,
127, 255,255,255,
153, 118,164,188,
178, 46,101,145,
204, 19, 60, 95,
229, 4, 31, 56,
255, 4, 31, 56
};
// Gradient palette "es_autumn_04_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/es/autumn/tn/es_autumn_04.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 20 bytes of program space.
DEFINE_GRADIENT_PALETTE( autumn_gp ) {
0, 71, 135, 0,
101, 88, 1, 0,
165, 210, 22, 1,
234, 255,166, 42,
255, 255,166, 42
};
// Gradient palette "grand_old_flag_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/pj/3/tn/grand-old-flag.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 128 bytes of program space.
DEFINE_GRADIENT_PALETTE( grand_old_flag_gp ) {
0, 1, 2,105,
94, 1, 2,105,
99, 199, 1, 7,
104, 199, 1, 7,
109, 255,255,255,
117, 255,255,255,
122, 199, 1, 7,
124, 199, 1, 7,
130, 255,255,255,
137, 255,255,255,
145, 199, 1, 7,
150, 199, 1, 7,
155, 255,255,255,
160, 255,255,255,
165, 199, 1, 7,
170, 199, 1, 7,
175, 255,255,255,
181, 255,255,255,
188, 199, 1, 7,
191, 199, 1, 7,
198, 255,255,255,
204, 255,255,255,
209, 199, 1, 7,
211, 199, 1, 7,
219, 255,255,255,
224, 255,255,255,
229, 199, 1, 7,
234, 199, 1, 7,
239, 255,255,255,
244, 255,255,255,
249, 199, 1, 7,
255, 199, 1, 7
};
// Gradient palette "christmas_candy_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/ocal/tn/christmas-candy.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 44 bytes of program space.
DEFINE_GRADIENT_PALETTE( christmas_candy_gp ) {
0, 255,255,255,
25, 255, 0, 0,
51, 255,255,255,
76, 0, 55, 0,
102, 255,255,255,
127, 255, 0, 0,
153, 255,255,255,
178, 0, 55, 0,
204, 255,255,255,
229, 255, 0, 0,
255, 255,255,255
};
// Gradient palette "green_purple_gp", originally from
// http://soliton.vm.bytemark.co.uk/pub/cpt-city/km/tn/green-purple.png.index.html
// converted for FastLED with gammas (2.6, 2.2, 2.5)
// Size: 260 bytes of program space.
DEFINE_GRADIENT_PALETTE( green_purple_gp ) {
0, 255, 155, 0,
40, 255, 155, 0,
49, 0, 0, 0,
96, 0, 0, 0,
107, 0, 254, 0,
179, 0, 254, 0,
183, 203, 0,255,
255, 203, 0,255
};
const TProgmemRGBGradientPalettePtr gGradientPalettes[] = {
holly_gp,
candycane_gp,
snowynight_gp,
silvergold_gp,
autumn_gp,
grand_old_flag_gp,
christmas_candy_gp,
green_purple_gp,
};