Hello everyone,
I have an Arduino sketch from Youtube, for running ws2812b Stripes. These are soundcontrolled and the various scenes can be switched by a button: a short press switches scene by scene, a long press activates an automatic switching through mode.
Everything is working well.
However, I'm looking for a way to switch from the party mode to a cozy mode (discreet warm white light, without sound control)
Maybe ther're two ways for doing this:
- a specific scene is activated by a second button or
- a specific scene (preferably the first) is excluded from automatic mode.
My question is what is the easiest way to do this? Can anyone help?
I basically understand what the program does, but until I get a detailed understanding of c++ to do this little manipulation, I already have a gray beard I think.
Here's the code from: Arduino sound reactive VU meter WS2812B LEDs
// --------------------------------
// -- VU Meter - Scott's version --
// --------------------------------
#include <FastLED.h>
#include <EEPROM.h>
#include <JC_Button.h>
# define LEFT_OUT_PIN 6 // Left channel data out pin to LEDs [6]
# define RIGHT_OUT_PIN 5 // Right channel data out pin to LEDs [5]
# define LEFT_IN_PIN A5 // Left aux in signal [A5]
# define RIGHT_IN_PIN A4 // Right aux in signal [A4]
# define BRIGHTNESS_PIN A2 // Brightness potentiometer in [A2]
# define SENSITIVITY_PIN A1 // Sensitivity potentiometer in [A1]
# define BTN_PIN 3 // Push button on this pin [3]
# define DEBOUNCE_MS 20 // Number of ms to debounce the button [20]
# define LONG_PRESS 500 // Number of ms to hold the button to count as long press [500]
# define N_PIXELS 18 // Number of pixels in each string [18]
# define MAX_MILLIAMPS 500 // Maximum current to draw [500]
# define COLOR_ORDER GRB // Colour order of LED strip [GRB]
# define LED_TYPE WS2812B // LED string type [WS2812B]
# define DC_OFFSET 0 // DC offset in aux signal [0]
# define NOISE 0 // Noise/hum/interference in aux signal [0]
# define SAMPLES 64 // Length of buffer for dynamic level adjustment [64]
# define TOP (N_PIXELS + 2) // Allow dot to go slightly off scale [(N_PIXELS + 2)]
# define PEAK_FALL 20 // Rate of peak falling dot [20]
# define N_PIXELS_HALF (N_PIXELS / 2)
# define PATTERN_TIME 10 // Seconds to show eaach pattern on auto [10]
# define STEREO true // If true, L&R channels are independent. If false, both L&R outputs display same data from L audio channel [true]
uint8_t volCountLeft = 0; // Frame counter for storing past volume data
uint16_t volLeft[SAMPLES]; // Collection of prior volume samples
uint16_t lvlLeft = 0; // Current "dampened" audio level
uint16_t minLvlAvgLeft = 0; // For dynamic adjustment of graph low & high
uint16_t maxLvlAvgLeft = 512;
uint8_t volCountRight = 0; // Frame counter for storing past volume data
uint16_t volRight[SAMPLES]; // Collection of prior volume samples
uint16_t lvlRight = 0; // Current "dampened" audio level
uint16_t minLvlAvgRight = 0; // For dynamic adjustment of graph low & high
uint16_t maxLvlAvgRight = 512;
CRGB ledsLeft[N_PIXELS];
CRGB ledsRight[N_PIXELS];
uint8_t myhue = 0;
void vu4(bool is_centered, uint8_t channel);
void vu5(bool is_centered, uint8_t channel);
void vu6(bool is_centered, uint8_t channel);
void vu7(bool show_background);
void vu8();
void vu9();
void vu10();
void balls();
void fire();
void juggle();
void ripple(boolean show_background);
void sinelon();
void rainbow(uint8_t rate);
// --------------------
// --- Button Stuff ---
// --------------------
uint8_t state = 0;
int buttonPushCounter = 0;
bool autoChangeVisuals = false;
Button modeBtn(BTN_PIN, DEBOUNCE_MS);
void incrementButtonPushCounter() {
buttonPushCounter = (buttonPushCounter + 1) %16;
EEPROM.write(1, buttonPushCounter);
}
int sensitivity = 0;
void setup() {
delay(1000); // power-up safety delay
analogReference(INTERNAL);
FastLED.addLeds < LED_TYPE, LEFT_OUT_PIN, COLOR_ORDER > (ledsLeft, N_PIXELS).setCorrection(TypicalLEDStrip);
FastLED.addLeds < LED_TYPE, RIGHT_OUT_PIN, COLOR_ORDER > (ledsRight, N_PIXELS).setCorrection(TypicalLEDStrip);
FastLED.setMaxPowerInVoltsAndMilliamps(5, MAX_MILLIAMPS);
modeBtn.begin();
Serial.begin(57600);
buttonPushCounter = 0;
buttonPushCounter = (int)EEPROM.read(1); // load previous setting
Serial.print("Starting pattern ");
Serial.println(buttonPushCounter);
}
void loop() {
// Read button
modeBtn.read();
switch (state) {
case 0:
if (modeBtn.wasReleased()) {
Serial.print("Short press, pattern ");
Serial.println(buttonPushCounter);
incrementButtonPushCounter();
autoChangeVisuals = false;
}
else if (modeBtn.pressedFor(LONG_PRESS))
state = 1;
break;
case 1:
if (modeBtn.wasReleased()) {
state = 0;
Serial.print("Long press, auto, pattern ");
Serial.println(buttonPushCounter);
autoChangeVisuals = true;
}
break;
}
// Switch pattern if on auto
if(autoChangeVisuals){
EVERY_N_SECONDS(PATTERN_TIME) {
incrementButtonPushCounter();
Serial.print("Auto, pattern ");
Serial.println(buttonPushCounter);
}
}
// Run selected pattern
switch (buttonPushCounter) {
case 0:
vu4(false, 0);
if (STEREO) vu4(false, 1);
else copyLeftToRight();
break;
case 1:
vu4(true, 0);
if (STEREO) vu4(true, 1);
else copyLeftToRight();
break;
case 2:
vu5(false, 0);
if (STEREO) vu5(false, 1);
else copyLeftToRight();
break;
case 3:
vu5(true, 0);
if (STEREO) vu5(true, 1);
else copyLeftToRight();
break;
case 4:
vu6(false, 0);
if (STEREO) vu6(false, 1);
else copyLeftToRight();
break;
case 5:
vu7(true);
copyLeftToRight();
break;
case 6:
vu8();
copyLeftToRight();
break;
case 7:
vu9();
break;
case 8:
vu10();
break;
case 9:
vu7(false);
copyLeftToRight();
break;
case 10:
sinelon();
break;
case 11:
balls();
break;
case 12:
juggle();
break;
case 13:
fire();
break;
case 14:
ripple(true);
break;
case 15:
rainbow(10);
break;
}
sensitivity = analogRead(SENSITIVITY_PIN);
FastLED.setBrightness(map(analogRead(BRIGHTNESS_PIN),0,1023,0,255));
}
// ------------------
// -- VU functions --
// ------------------
uint16_t auxReading(uint8_t channel) {
uint16_t height = 0;
if(channel == 0) {
int n = analogRead(LEFT_IN_PIN); // Raw reading from left line in
n = abs(n - 512 - DC_OFFSET); // Center on zero
n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum
lvlLeft = ((lvlLeft * 15) + n) >> 4; // "Dampened" reading else looks twitchy (>>3 is divide by 32)
volLeft[volCountLeft] = n * ((float)(1023 - sensitivity) / 512);
volCountLeft = (volCountLeft + 1) % SAMPLES;
// Calculate bar height based on dynamic min/max levels (fixed point):
height = TOP * (lvlLeft - minLvlAvgLeft) / (long)(maxLvlAvgLeft - minLvlAvgLeft);
}
else {
int n = analogRead(RIGHT_IN_PIN); // Raw reading from mic
n = abs(n - 512 - DC_OFFSET); // Center on zero
n = (n <= NOISE) ? 0 : (n - NOISE); // Remove noise/hum
lvlRight = ((lvlRight * 15) + n) >> 4; // "Dampened" reading (else looks twitchy)
volRight[volCountRight] = n * ((float)(1023 - sensitivity) / 512); // Save sample for dynamic leveling
volCountRight = (volCountRight +1 ) % SAMPLES;
// Calculate bar height based on dynamic min/max levels (fixed point):
height = TOP * (lvlRight - minLvlAvgRight) / (long)(maxLvlAvgRight - minLvlAvgRight);
}
height = min(height, TOP);
return height;
}
void copyLeftToRight() {
for (uint8_t i = 0; i < N_PIXELS; i++) {
ledsRight[i] = ledsLeft[i];
}
}
/*
* Function for dropping the peak
*/
uint8_t peakLeft, peakRight;
void dropPeak(uint8_t channel) {
static uint8_t dotCountLeft, dotCountRight;
if(channel == 0) {
if(++dotCountLeft >= PEAK_FALL) { //fall rate
if(peakLeft > 0) peakLeft--;
dotCountLeft = 0;
}
} else {
if(++dotCountRight >= PEAK_FALL) { //fall rate
if(peakRight > 0) peakRight--;
dotCountRight = 0;
}
}
}
/*
* Function for averaging the sample readings
*/
void averageReadings(uint8_t channel) {
uint16_t minLvl, maxLvl;
// minLvl and maxLvl indicate the volume range over prior frames, used
// for vertically scaling the output graph (so it looks interesting
// regardless of volume level). If they're too close together though
// (e.g. at very low volume levels) the graph becomes super coarse
// and 'jumpy'...so keep some minimum distance between them (this
// also lets the graph go to zero when no sound is playing):
if(channel == 0) {
minLvl = maxLvl = volLeft[0];
for (int i = 1; i < SAMPLES; i++) {
if (volLeft[i] < minLvl) minLvl = volLeft[i];
else if (volLeft[i] > maxLvl) maxLvl = volLeft[i];
}
if ((maxLvl - minLvl) < TOP) maxLvl = 10;
minLvlAvgLeft = (minLvlAvgLeft * 63 + minLvl) >> 6; // Dampen min/max levels
maxLvlAvgLeft = (maxLvlAvgLeft * 63 + maxLvl) >> 6; // (fake rolling average)
}
else {
minLvl = maxLvl = volRight[0];
for (int i = 1; i < SAMPLES; i++) {
if (volRight[i] < minLvl) minLvl = volRight[i];
else if (volRight[i] > maxLvl) maxLvl = volRight[i];
}
if ((maxLvl - minLvl) < TOP) maxLvl = 10;
minLvlAvgRight = (minLvlAvgRight * 63 + minLvl) >> 6; // Dampen min/max levels
maxLvlAvgRight = (maxLvlAvgRight * 63 + maxLvl) >> 6; // (fake rolling average)
}
}
I'm explicitly not asking for a ready-made solution, but for good and helpful tips to find the right way.
Thanks al lot
Here is my attempt to do this with a second button. But it doesn't work properly:
...
int run;
int buttonPin;
void setup()
{
....
run = 0; //starts stopped
buttonPin = 7; //whatever pin your button is plugged into
pinMode(buttonPin, INPUT_PULLUP);
}
void loop()
{
if(digitalRead(buttonPin) == LOW) //funcitons based off of button pulling input pin LOW
{
if(run == 0)
{
run = 255;
}
else
{
run = 0;
}
}
if(run > 0)
{
//code for only run if button was pressed, stops running when button pressed again, so forth...
}
}