Cloud lightning neopixel and LED lamp with a "mode" button

Hi all! Im Mike.

I recently started up a cloud lightning lamp project.

Sorta new at this stuff but i like electronics and use to code alot on a PC game called Operation flashpoint. SO i figured i could pull it off.

I'm just about completed for the most part.

An Arduino uno r3 is being used with several flicker leds as lightning bolts 1 and 2 and a neopixel stick 8 as the 3rd.

I found a neopixel lightning code on GitHub by Molly Nicholas (thanx!)

Wrote a simple, random code for my led clusters, then had to combine with the neopixel code so it all looks grand. Heres a vid of it....

Havent built an enclosure yet...I want to add a little more.

I would like to be able to press a button and have a neopixel mood light code activate. One thatll fade through all colors slowly. Then when i push it again(or push a second button), it goes back to lightning.

Heres the lightning code. Forgive its sloppiness...you should have seen my OFP snippets. :wink:

#include <Adafruit_NeoPixel.h>

// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip)
int NUM_LEDS = 8;
int LED_PIN = 9;


const int HIGH_STRIKE_LIKELIHOOD = 5;
const int LOW_STRIKE_LIKELIHOOD = 10;
int currentDataPoint = 0;
int chance = LOW_STRIKE_LIKELIHOOD;

int led = 11;
long randNumber;
long randNumber2;
long randNumber3;
int led2 = 10;

Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);


// Simple moving average plot
int NUM_Y_VALUES = 17;

float yValues[] = {
  0,
  7,
  10,
  9,
  7.1,
  7.5,
  7.4,
  12,
  15,
  10,
  0,
  3,
  3.5,
  4,
  1,
  7,
  1
};

float simple_moving_average_previous = 0;
float random_moving_average_previous = 0;

float (*functionPtrs[10])(); //the array of function pointers
int NUM_FUNCTIONS = 2;

void setup() {
  
  Serial.begin(9600);
  randomSeed(digitalRead(0));
  pinMode(led, OUTPUT);
  pinMode(led2, OUTPUT);
  
  
  // Neopixel setup
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

  // initializes the array of function pointers.
  functionPtrs[0] = simple_moving_average;
  functionPtrs[1] = random_moving_average;
}

void loop() {
  

  
  if ((chance) > 1) {
    int led = random(NUM_LEDS);
    for (int i = 0; i < 10; i++) {
      // Use this line to keep the lightning focused in one LED.
      // lightningStrike(led):
      // Use this line if you want the lightning to spread out among multiple LEDs.
      lightningStrike(random(NUM_LEDS));
    }
    // Once there's been one strike, I make it more likely that there will be a second.
    chance = HIGH_STRIKE_LIKELIHOOD;
  } else {
    chance = LOW_STRIKE_LIKELIHOOD;
  }
  turnAllPixelsOff();
  delay(1000);
   
  
}

void turnAllPixelsOff() {
  for (int i = 0; i < NUM_LEDS; i++) {
    strip.setPixelColor(i, 0);
  }
  strip.show();
  
  
  { 
 randNumber = random(1000);
 Serial.println(randNumber);
 randNumber2 = random(10000);
 Serial.println(randNumber2);
 randNumber3 = random(150);
 Serial.println(randNumber3);
 

  delay(50);
  
   digitalWrite(led, HIGH);   
  delay(randNumber);               
  digitalWrite(led, LOW);    
  delay(randNumber2); 
  
   digitalWrite(led2, HIGH);   
  delay(randNumber3);               
  digitalWrite(led2, LOW);    
  delay(randNumber2);
  
  digitalWrite(led2, HIGH);   
  delay(randNumber);               
  digitalWrite(led2, LOW);    
  delay(randNumber2);
  
  
  };
  
}

void lightningStrike(int pixel) {
  float brightness = callFunction(random(NUM_FUNCTIONS));
  float scaledWhite = abs(brightness*500);
  
  strip.setPixelColor(pixel, strip.Color(scaledWhite, scaledWhite, scaledWhite));
  strip.show();
  delay(random(5, 100));
  currentDataPoint++;
  currentDataPoint = currentDataPoint%NUM_Y_VALUES;
  
}

float callFunction(int index) {
  return (*functionPtrs[index])(); //calls the function at the index of `index` in the array
}

// https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average
float simple_moving_average() {
  uint32_t startingValue = currentDataPoint;
  uint32_t endingValue = (currentDataPoint+1)%NUM_Y_VALUES;
  float simple_moving_average_current = simple_moving_average_previous + 
                                  (yValues[startingValue])/NUM_Y_VALUES - 
                                  (yValues[endingValue])/NUM_Y_VALUES;

  simple_moving_average_previous = simple_moving_average_current;
  
  return simple_moving_average_current;
   
}



// Same as simple moving average, but with randomly-generated data points.
float random_moving_average() {
  float firstValue = random(1, 10);
  float secondValue = random(1, 10);
  float random_moving_average_current = random_moving_average_previous +
                                  firstValue/NUM_Y_VALUES -
                                  secondValue/NUM_Y_VALUES;
                                                                    
                                  
  random_moving_average_previous = random_moving_average_current;

  return random_moving_average_current;
  
 
}

My brain is fried...Could someone come up with a standard button mode change? I have the button hooked up as per the example files, into PIN 2. Will it need to be 2 buttons?

One to turn on lightning and a one for mood.

Only other way im thinking of is to use my other uno and and get another neopixel stick and have it for mood light. But thats a waste of resources.

I would be most grateful if i could get some help...if not, no worries.

My brain is fried...Could someone come up with a standard button mode change? I have the button hooked up as per the example files, into PIN 2. Will it need to be 2 buttons?

One to turn on lightning and a one for mood.

The state change detection example has all the code you need. Each time the switch becomes pressed, increment a counter. When the value in the counter is even (counter % 2 == 0), do one thing. When it is odd, do the other thing.

Of course, all those delay()s means that the switch will be quite unresponsive.