Hello experienced coders, inexperienced students here. We are trying to do a simple project involving neopixels, we haven’t been able to find anything else online that quite does what we are trying to do with our project. We need some help to configure a pushbutton with a neopixel strip so that it activates our LED’s when we push the button and then off after another push. Anybody that could tell us how to do this or anyone who would like to look at our code here and add it to their own code to achieve our goal here would be greatly appreciated.
#include <Adafruit_NeoPixel.h>
#define PIN 6
#define NUM_LEDS 34
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);
void setup() {
strip.begin();
strip.show(); // Initialize all pixels to 'off'
}
// *** REPLACE FROM HERE ***
void loop() {
Fire(55,120,15);
}
void Fire(int Cooling, int Sparking, int SpeedDelay) {
static byte heat[NUM_LEDS];
int cooldown;
// Step 1. Cool down every cell a little
for( int i = 0; i < NUM_LEDS; i++) {
cooldown = random(0, ((Cooling * 10) / NUM_LEDS) + 2);
if(cooldown>heat[i]) {
heat[i]=0;
} else {
heat[i]=heat[i]-cooldown;
}
}
// Step 2. Heat from each cell drifts 'up' and diffuses a little
for( int k= NUM_LEDS - 1; k >= 2; k--) {
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
}
// Step 3. Randomly ignite new 'sparks' near the bottom
if( random(255) < Sparking ) {
int y = random(7);
heat[y] = heat[y] + random(160,255);
//heat[y] = random(160,255);
}
// Step 4. Convert heat to LED colors
for( int j = 0; j < NUM_LEDS; j++) {
setPixelHeatColor(j, heat[j] );
}
showStrip();
delay(SpeedDelay);
}
void setPixelHeatColor (int Pixel, byte temperature) {
// Scale 'heat' down from 0-255 to 0-191
byte t192 = round((temperature/255.0)*191);
// calculate ramp up from
byte heatramp = t192 & 0x3F; // 0..63
heatramp <<= 2; // scale up to 0..252
// figure out which third of the spectrum we're in:
if( t192 > 0x80) { // hottest
setPixel(Pixel, 255, 255, heatramp);
} else if( t192 > 0x40 ) { // middle
setPixel(Pixel, 255, heatramp, 0);
} else { // coolest
setPixel(Pixel, heatramp, 0, 0);
}
}
// *** REPLACE TO HERE ***
void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
FastLED.show();
#endif
}
void setPixel(int Pixel, byte red, byte green, byte blue) {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.setPixelColor(Pixel, strip.Color(red, green, blue));
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
leds[Pixel].r = red;
leds[Pixel].g = green;
leds[Pixel].b = blue;
#endif
}
void setAll(byte red, byte green, byte blue) {
for(int i = 0; i < NUM_LEDS; i++ ) {
setPixel(i, red, green, blue);
}
showStrip();
}
You should look at two things.
The first is the state change example in the IDE. This will allow you to in effect count the number of changes of state of the button rather than just detect if the button is being held.
Then you have to rewrite the Fire function as a state machine. I have posted this code many times here so do some more searching.
The state machine and the state change button code are run one after the other in a constant loop.
Use the forum Google search function in the upper right of this page to search for the key words of your project, like "toggle" or "flip flop". You will probably find many similar previous project discussions and code to get you started.
Grumpy_Mike:
The OP saidThat code will not turn off the show on a second push. It will only start the show on the push of a button.
I'm not that familiar with neopixels. I assumed that using .clear() and .show() if bPutOnAShow is false after toggling its state in the button read function:
Blackfin:
I'm not that familiar with neopixels. I assumed that using .clear() and .show() if bPutOnAShow is false after toggling its state in the button read function:
//toggle show boolean
bPutOnAShow ^= true;
if( !bPutOnAShow )
{
strip.clear();
strip.show();
}//if
would turn off the individual LEDs internally and then externally. Since the Fire() function is called from within loop only if bPutOnAShow is true:
if( bPutOnAShow )
Fire( 55, 120, 15);
the act of clearing and showing immediately should turn them off and leave them off until bPutOnAShow is toggled true again with another button press.
But as I mentioned, I'm not that familiar with neopixels so maybe .clear() doesn't do what I think it does.
Or am I missing something else?
Nope! this code works just fine! Thanks guys so much for giving input we appreciate it so much.
Grumpy_Mike:
Yes, the button is only looked at when the fire function has finished so while it will trigger a show a second press won’t stop it.
But it is not what you asked for.
Actually, it does. Fire() requires ~21mS to execute according to my testing. The program is responsive to the press of a switch on pin 2. It may have a bit of latency but it does work as is.
OP has verified. It could be made better by removing the delay(SpeedDelay) call at the end of Fire() and replacing it with millis(). If the OP wants to polish it he can do that himself.