Go Down

Topic: Need help with adding a button to code...15 dollars (Read 269 times) previous topic - next topic

ShelledWalnuts

Jul 31, 2018, 12:50 am Last Edit: Jul 31, 2018, 01:26 am by ShelledWalnuts
Greetings,
 
I am working on a project for my daughter's cosplay. I have a circuit that is going to light up a ws2812b (neopixel) strip. I need a to wire a button up to my Arduino Nano on one of the pins that, when pressed, starts the effect one time only, then turns the strip black (off) and waits for the next button press. I believe that for someone who knows code real well, this is a trivial request. I am offering 15 dollars through paypal. Please explain how you set it up. Once its loaded and I check it out, you get paid.

Here's a good link describing how FastLED and NeoPixels work. - https://www.tweaking4all.com/hardware/arduino/adruino-led-strip-effects/#LEDStripEffectMeteorRain


Thanks!


Code: [Select]
#include "FastLED.h"
#define NUM_LEDS 50
CRGB leds[NUM_LEDS];
#define PIN 5

void setup()
{
  FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
}

void loop() {
  meteorRain(0xff,0xff,0xff,10, 64, true, 30);
}

void meteorRain(byte red, byte green, byte blue, byte meteorSize, byte meteorTrailDecay, boolean meteorRandomDecay, int SpeedDelay) { 
setAll(0,0,0);
 
  for(int i = 0; i < NUM_LEDS+NUM_LEDS; i++) {
   
   
    // fade brightness all LEDs one step
    for(int j=0; j<NUM_LEDS; j++) {
      if( (!meteorRandomDecay) || (random(10)>5) ) {
        fadeToBlack(j, meteorTrailDecay );       
      }
    }
   
    // draw meteor
    for(int j = 0; j < meteorSize; j++) {
      if( ( i-j <NUM_LEDS) && (i-j>=0) ) {
        setPixel(i-j, red, green, blue);
      }
    }
   
    showStrip();
    delay(SpeedDelay);
  }
}

void fadeToBlack(int ledNo, byte fadeValue) {
 #ifdef ADAFRUIT_NEOPIXEL_H
    // NeoPixel
    uint32_t oldColor;
    uint8_t r, g, b;
    int value;
   
    oldColor = strip.getPixelColor(ledNo);
    r = (oldColor & 0x00ff0000UL) >> 16;
    g = (oldColor & 0x0000ff00UL) >> 8;
    b = (oldColor & 0x000000ffUL);

    r=(r<=10)? 0 : (int) r-(r*fadeValue/256);
    g=(g<=10)? 0 : (int) g-(g*fadeValue/256);
    b=(b<=10)? 0 : (int) b-(b*fadeValue/256);
   
    strip.setPixelColor(ledNo, r,g,b);
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   leds[ledNo].fadeToBlackBy( fadeValue );
 #endif 
}

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();
}


wvmarle

I don't see you reading any button in that code.

Anyway, what you need is a finite state machine. A press on a button sets it in the state that plays the LED sequence, when that sequence is finished, the state is reset.

For lack of comments and detailed description I'm not all too clear what you're trying to do with that code but here's the basic outline.

Code: [Select]

enum ledStates {   // List of available states.
  LED_IDLE,
  LED_METEOR
};
uint8_t ledState = LED_IDLE;

void loop() {
  if (digitalRead(buttonPin) == LOW) {
    ledState = LED_METEOR;
  }
  switch (ledState) {
    case LED_METEOR:
      meteorRain(0xff,0xff,0xff,10, 64, true, 30);
      ledState = LED_IDLE;
      break;

    case LED_IDLE:
      break;
  }
}


You have to declare a variable called buttonPin that has the pin number of the button; and that it's wired active low.

This is in a way overkill (it can be simpler as your meteorRain() function returns only after the whole sequence has been done) but it's the most flexible base implementation as it allows you to add more sequences and buttons easily.

To make the code more responsive, rewrite meteorRain() to return quickly - it will become a finite state machine in itself as it goes through the sequence - and you can have your suit react to the button while it plays sequences. E.g. when playing a second button press interrupts the sequence by playing a short fade-out. Many possibilities with this technique, and as you separate the control from the function it becomes very flexible and easy to extend.
Quality of answers is related to the quality of questions. Good questions will get good answers. Useless answers are a sign of a poor question.

Go Up