Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!



Adding a second but...
 
Share:
Notifications
Clear all

[Solved] Adding a second button for reverse Arduino all led strips effect

18 Posts
2 Users
1 Reactions
5,304 Views
(@bartie1967)
Active Member
Joined: 4 years ago
Posts: 10
Topic starter  

Hi Hans ,

I had no problem with the blank spot after the loop .

thx for the walkthrough.

As you suggested I started a topic because ( if I did everything correct ) non of the buttons worked after I added the codes or moddified them..

There was no error while compiling .

In the void setup where I added

"attachInterrupt (digitalPinToInterrupt (REVERSEBUTTON), changeEffectReverse, CHANGE); // reverse pressed"

there is no indication to pinMode3 ?

I'm not shure  if there has to be an indication for pin 3 , because that's the pin the reverse button is connected to .

 

So I added

pinMode(3,INPUT_PULLUP); // internal pull-up resistor

and now the original button works , but not the reverse one . If I push the reverse one  , it gets back a cyclus for a split second and then returns to the starting point of the cyclus ( in my case all lights turn off because I added a case 0 to set lights  off )

 

 

 

 

 

 

 

 


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 

Hi Bartie1967,

I'm just copying the text of the comments from the LED effects article, so that whoever reads this, can find some context.
I'll try to reply to your post in the comment after this one 😊 


 

Adding a case for an empty loop shouldn’t be too complicated.
You could add a “new” “case 0”, so that it starts with that, something like this:

    case 0  : {
                // do nothing
                break;
              }

Now for all the other cases, simply increase each number by 1. So the original “case 0” becomes “case 1”, “case 1” becomes “case 2”, etc.
You’ll have to change the first steps in the “void loop()” as well, to correct for the number of available effects. For example

  EEPROM.get(0,selectedEffect);
 
  if(selectedEffect>18) { // here 18
    selectedEffect=0;
    EEPROM.put(0,0);
  }

to (increase the bold number by 1)

  EEPROM.get(0,selectedEffect);
 
  if(selectedEffect>19) { // now becomes 19
    selectedEffect=0;
    EEPROM.put(0,0);
  }

 

Adding a second button is an option as well. As far as I recall, most Arduino’s support 2 interrupts, of which we used 1 for this project. 
I haven’t tested this, but it should look something like this:

1) Add a definition for the reverse button (if I recall correctly pin 2 and 3 are usable for interrupts):

#define REVERSEBUTTON 3

2) in “void setup()” we need to enable the second interrupt by adding this line:

  attachInterrupt (digitalPinToInterrupt (REVERSEBUTTON), changeEffectReverse, CHANGE); // reverse pressed

3) We need to make a new function to handle the reverse move:

void changeEffectReverse() {
  if (digitalRead (BUTTON) == HIGH) {
    selectedEffect--;
    EEPROM.put(0, selectedEffect);
    asm volatile (" jmp 0");
  }
}

4) We also need to make sure the selected effet doesn’t go below zero, so we need to modify the beginning of the “void loop()” function:

  EEPROM.get(0,selectedEffect);
 
  if(selectedEffect>18) { // here 18
    selectedEffect=0;
    EEPROM.put(0,selectedEffect);
  } else if(selectedEffect<0) {
    selectedEffect=18;
    EEPROM.put(0,selectedEffect);
  }

   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 

Hi Bartie1967,

you're totally correct: I should have added the setting for pin 3.
Little note though, since we defined REVERSEBUTTON to hold the pin number, it would be better to consistently use this in the code 😊 

pinMode(REVERSEBUTTON,INPUT_PULLUP); // internal pull-up resistor

I did see I made another mistake, with the new function where I typed BUTTON instead of REVERSEBUTTON:

void changeEffectReverse() {
if (digitalRead (REVERSEBUTTON) == HIGH) {
    selectedEffect--;
    EEPROM.put(0, selectedEffect);
    asm volatile (" jmp 0");
  }
}

Maybe this fixes the issue, but without seeing the full code, it will remain a guess.
That's why it is always good to attach the ino file to your post (if the forum already lets you attach files) or paste the code in a the text (mark as code with the "<>" button above).


   
ReplyQuote
(@bartie1967)
Active Member
Joined: 4 years ago
Posts: 10
Topic starter  

@hans

 

thx for the response . I'm gonna try it out as soon after I solved another problem..

Instead of the arduino little button , I installed a big hospital push button .

But if I push that new button , it seems that it always jumps to strobe effect and the halloween eyes effect .

Is it because it has a 1meter wire on it or that the push button gives a false contact ?

Or can I put a delay on the button or something ?

 


   
ReplyQuote
(@bartie1967)
Active Member
Joined: 4 years ago
Posts: 10
Topic starter  

I don't get it Hans

 

i now even have that loop glitch with an arduino button..

 


#include "FastLED.h"
#include <EEPROM.h>
#define NUM_LEDS 24
CRGB leds[NUM_LEDS];
#define PIN 6

#define BUTTON 2
byte selectedEffect = 0;
#define REVERSEBUTTON 3


void setup()
{
FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
pinMode(2, INPUT_PULLUP); // internal pull-up resistor
attachInterrupt (digitalPinToInterrupt (BUTTON), changeEffect, CHANGE); // pressed
pinMode(REVERSEBUTTON, INPUT_PULLUP); // internal pull-up resistor
attachInterrupt (digitalPinToInterrupt (REVERSEBUTTON), changeEffectReverse, CHANGE); // reverse pressed

}
void changeEffectReverse() {
if (digitalRead (REVERSEBUTTON) == HIGH) {
selectedEffect--;
EEPROM.put(0, selectedEffect);
asm volatile (" jmp 0");
}
}
// REPLACE FROM HERE
void loop() {
EEPROM.get(0, selectedEffect);

if (selectedEffect > 18) { // here 18
selectedEffect = 0;
EEPROM.put(0, selectedEffect);
} else if (selectedEffect < 0) {
selectedEffect = 18;
EEPROM.put(0, selectedEffect);
}

switch (selectedEffect) {

case 0 : {
// RGBLoop - no parameters
RGBLoop();
break;
}

case 1 : {
// FadeInOut - Color (red, green. blue)
FadeInOut(0xff, 0x00, 0x00); // red
FadeInOut(0xff, 0xff, 0xff); // white
FadeInOut(0x00, 0x00, 0xff); // blue
break;
}

case 2 : {
// Strobe - Color (red, green, blue), number of flashes, flash speed, end pause
Strobe(0xff, 0xff, 0xff, 10, 50, 1000);
break;
}

case 3 : {
// HalloweenEyes - Color (red, green, blue), Size of eye, space between eyes, fade (true/false), steps, fade delay, end pause
HalloweenEyes(0xff, 0x00, 0x00,
1, 4,
true, random(5, 50), random(50, 150),
random(1000, 10000));
HalloweenEyes(0xff, 0x00, 0x00,
1, 4,
true, random(5, 50), random(50, 150),
random(1000, 10000));
break;
}

case 4 : {
// CylonBounce - Color (red, green, blue), eye size, speed delay, end pause
CylonBounce(0xff, 0x00, 0x00, 4, 10, 50);
break;
}

case 5 : {
// NewKITT - Color (red, green, blue), eye size, speed delay, end pause
NewKITT(0xff, 0x00, 0x00, 8, 10, 50);
break;
}

case 6 : {
// Twinkle - Color (red, green, blue), count, speed delay, only one twinkle (true/false)
Twinkle(0xff, 0x00, 0x00, 10, 100, false);
break;
}

case 7 : {
// TwinkleRandom - twinkle count, speed delay, only one (true/false)
TwinkleRandom(20, 100, false);
break;
}

case 8 : {
// Sparkle - Color (red, green, blue), speed delay
Sparkle(0xff, 0xff, 0xff, 0);
break;
}

case 9 : {
// SnowSparkle - Color (red, green, blue), sparkle delay, speed delay
SnowSparkle(0x10, 0x10, 0x10, 20, random(100, 1000));
break;
}

case 10 : {
// Running Lights - Color (red, green, blue), wave dealy
RunningLights(0xff, 0x00, 0x00, 50); // red
RunningLights(0xff, 0xff, 0xff, 50); // white
RunningLights(0x00, 0x00, 0xff, 50); // blue
break;
}

case 11 : {
// colorWipe - Color (red, green, blue), speed delay
colorWipe(0x00, 0xff, 0x00, 50);
colorWipe(0x00, 0x00, 0x00, 50);
break;
}

case 12 : {
// rainbowCycle - speed delay
rainbowCycle(20);
break;
}

case 13 : {
// theatherChase - Color (red, green, blue), speed delay
theaterChase(0xff, 0, 0, 50);
break;
}

case 14 : {
// theaterChaseRainbow - Speed delay
theaterChaseRainbow(50);
break;
}

case 15 : {
// Fire - Cooling rate, Sparking rate, speed delay
Fire(55, 120, 15);
break;
}


// simple bouncingBalls not included, since BouncingColoredBalls can perform this as well as shown below
// BouncingColoredBalls - Number of balls, color (red, green, blue) array, continuous
// CAUTION: If set to continuous then this effect will never stop!!!

case 16 : {
// mimic BouncingBalls
byte onecolor[1][3] = { {0xff, 0x00, 0x00} };
BouncingColoredBalls(1, onecolor, false);
break;
}

case 17 : {
// multiple colored balls
byte colors[3][3] = { {0xff, 0x00, 0x00},
{0xff, 0xff, 0xff},
{0x00, 0x00, 0xff}
};
BouncingColoredBalls(3, colors, false);
break;
}

case 18 : {
// meteorRain - Color (red, green, blue), meteor size, trail decay, random trail decay (true/false), speed delay
meteorRain(0xff, 0xff, 0xff, 10, 64, true, 30);
break;
}
}
}

void changeEffect() {
if (digitalRead (BUTTON) == HIGH) {
selectedEffect++;
EEPROM.put(0, selectedEffect);
asm volatile (" jmp 0");
}
}


// *************************
// ** LEDEffect Functions **
// *************************

void RGBLoop() {
for (int j = 0; j < 3; j++ ) {
// Fade IN
for (int k = 0; k < 256; k++) {
switch (j) {
case 0: setAll(k, 0, 0); break;
case 1: setAll(0, k, 0); break;
case 2: setAll(0, 0, k); break;
}
showStrip();
delay(3);
}
// Fade OUT
for (int k = 255; k >= 0; k--) {
switch (j) {
case 0: setAll(k, 0, 0); break;
case 1: setAll(0, k, 0); break;
case 2: setAll(0, 0, k); break;
}
showStrip();
delay(3);
}
}
}

void FadeInOut(byte red, byte green, byte blue) {
float r, g, b;

for (int k = 0; k < 256; k = k + 1) {
r = (k / 256.0) * red;
g = (k / 256.0) * green;
b = (k / 256.0) * blue;
setAll(r, g, b);
showStrip();
}

for (int k = 255; k >= 0; k = k - 2) {
r = (k / 256.0) * red;
g = (k / 256.0) * green;
b = (k / 256.0) * blue;
setAll(r, g, b);
showStrip();
}
}

void Strobe(byte red, byte green, byte blue, int StrobeCount, int FlashDelay, int EndPause) {
for (int j = 0; j < StrobeCount; j++) {
setAll(red, green, blue);
showStrip();
delay(FlashDelay);
setAll(0, 0, 0);
showStrip();
delay(FlashDelay);
}

delay(EndPause);
}

void HalloweenEyes(byte red, byte green, byte blue,
int EyeWidth, int EyeSpace,
boolean Fade, int Steps, int FadeDelay,
int EndPause) {
randomSeed(analogRead(0));

int i;
int StartPoint = random( 0, NUM_LEDS - (2 * EyeWidth) - EyeSpace );
int Start2ndEye = StartPoint + EyeWidth + EyeSpace;

for (i = 0; i < EyeWidth; i++) {
setPixel(StartPoint + i, red, green, blue);
setPixel(Start2ndEye + i, red, green, blue);
}

showStrip();

if (Fade == true) {
float r, g, b;

for (int j = Steps; j >= 0; j--) {
r = j * (red / Steps);
g = j * (green / Steps);
b = j * (blue / Steps);

for (i = 0; i < EyeWidth; i++) {
setPixel(StartPoint + i, r, g, b);
setPixel(Start2ndEye + i, r, g, b);
}

showStrip();
delay(FadeDelay);
}
}

setAll(0, 0, 0); // Set all black

delay(EndPause);
}

void CylonBounce(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {

for (int i = 0; i < NUM_LEDS - EyeSize - 2; i++) {
setAll(0, 0, 0);
setPixel(i, red / 10, green / 10, blue / 10);
for (int j = 1; j <= EyeSize; j++) {
setPixel(i + j, red, green, blue);
}
setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10);
showStrip();
delay(SpeedDelay);
}

delay(ReturnDelay);

for (int i = NUM_LEDS - EyeSize - 2; i > 0; i--) {
setAll(0, 0, 0);
setPixel(i, red / 10, green / 10, blue / 10);
for (int j = 1; j <= EyeSize; j++) {
setPixel(i + j, red, green, blue);
}
setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10);
showStrip();
delay(SpeedDelay);
}

delay(ReturnDelay);
}

void NewKITT(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
LeftToRight(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
RightToLeft(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
}

// used by NewKITT
void CenterToOutside(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
for (int i = ((NUM_LEDS - EyeSize) / 2); i >= 0; i--) {
setAll(0, 0, 0);

setPixel(i, red / 10, green / 10, blue / 10);
for (int j = 1; j <= EyeSize; j++) {
setPixel(i + j, red, green, blue);
}
setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10);

setPixel(NUM_LEDS - i, red / 10, green / 10, blue / 10);
for (int j = 1; j <= EyeSize; j++) {
setPixel(NUM_LEDS - i - j, red, green, blue);
}
setPixel(NUM_LEDS - i - EyeSize - 1, red / 10, green / 10, blue / 10);

showStrip();
delay(SpeedDelay);
}
delay(ReturnDelay);
}

// used by NewKITT
void OutsideToCenter(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
for (int i = 0; i <= ((NUM_LEDS - EyeSize) / 2); i++) {
setAll(0, 0, 0);

setPixel(i, red / 10, green / 10, blue / 10);
for (int j = 1; j <= EyeSize; j++) {
setPixel(i + j, red, green, blue);
}
setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10);

setPixel(NUM_LEDS - i, red / 10, green / 10, blue / 10);
for (int j = 1; j <= EyeSize; j++) {
setPixel(NUM_LEDS - i - j, red, green, blue);
}
setPixel(NUM_LEDS - i - EyeSize - 1, red / 10, green / 10, blue / 10);

showStrip();
delay(SpeedDelay);
}
delay(ReturnDelay);
}

// used by NewKITT
void LeftToRight(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
for (int i = 0; i < NUM_LEDS - EyeSize - 2; i++) {
setAll(0, 0, 0);
setPixel(i, red / 10, green / 10, blue / 10);
for (int j = 1; j <= EyeSize; j++) {
setPixel(i + j, red, green, blue);
}
setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10);
showStrip();
delay(SpeedDelay);
}
delay(ReturnDelay);
}

// used by NewKITT
void RightToLeft(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
for (int i = NUM_LEDS - EyeSize - 2; i > 0; i--) {
setAll(0, 0, 0);
setPixel(i, red / 10, green / 10, blue / 10);
for (int j = 1; j <= EyeSize; j++) {
setPixel(i + j, red, green, blue);
}
setPixel(i + EyeSize + 1, red / 10, green / 10, blue / 10);
showStrip();
delay(SpeedDelay);
}
delay(ReturnDelay);
}

void Twinkle(byte red, byte green, byte blue, int Count, int SpeedDelay, boolean OnlyOne) {
setAll(0, 0, 0);

for (int i = 0; i < Count; i++) {
setPixel(random(NUM_LEDS), red, green, blue);
showStrip();
delay(SpeedDelay);
if (OnlyOne) {
setAll(0, 0, 0);
}
}

delay(SpeedDelay);
}

void TwinkleRandom(int Count, int SpeedDelay, boolean OnlyOne) {
setAll(0, 0, 0);

for (int i = 0; i < Count; i++) {
setPixel(random(NUM_LEDS), random(0, 255), random(0, 255), random(0, 255));
showStrip();
delay(SpeedDelay);
if (OnlyOne) {
setAll(0, 0, 0);
}
}

delay(SpeedDelay);
}

void Sparkle(byte red, byte green, byte blue, int SpeedDelay) {
int Pixel = random(NUM_LEDS);
setPixel(Pixel, red, green, blue);
showStrip();
delay(SpeedDelay);
setPixel(Pixel, 0, 0, 0);
}

void SnowSparkle(byte red, byte green, byte blue, int SparkleDelay, int SpeedDelay) {
setAll(red, green, blue);

int Pixel = random(NUM_LEDS);
setPixel(Pixel, 0xff, 0xff, 0xff);
showStrip();
delay(SparkleDelay);
setPixel(Pixel, red, green, blue);
showStrip();
delay(SpeedDelay);
}

void RunningLights(byte red, byte green, byte blue, int WaveDelay) {
int Position = 0;

for (int i = 0; i < NUM_LEDS * 2; i++)
{
Position++; // = 0; //Position + Rate;
for (int i = 0; i < NUM_LEDS; i++) {
// sine wave, 3 offset waves make a rainbow!
//float level = sin(i+Position) * 127 + 128;
//setPixel(i,level,0,0);
//float level = sin(i+Position) * 127 + 128;
setPixel(i, ((sin(i + Position) * 127 + 128) / 255)*red,
((sin(i + Position) * 127 + 128) / 255)*green,
((sin(i + Position) * 127 + 128) / 255)*blue);
}

showStrip();
delay(WaveDelay);
}
}

void colorWipe(byte red, byte green, byte blue, int SpeedDelay) {
for (uint16_t i = 0; i < NUM_LEDS; i++) {
setPixel(i, red, green, blue);
showStrip();
delay(SpeedDelay);
}
}

void rainbowCycle(int SpeedDelay) {
byte *c;
uint16_t i, j;

for (j = 0; j < 256 * 5; j++) { // 5 cycles of all colors on wheel
for (i = 0; i < NUM_LEDS; i++) {
c = Wheel(((i * 256 / NUM_LEDS) + j) & 255);
setPixel(i, *c, *(c + 1), *(c + 2));
}
showStrip();
delay(SpeedDelay);
}
}

// used by rainbowCycle and theaterChaseRainbow
byte * Wheel(byte WheelPos) {
static byte c[3];

if (WheelPos < 85) {
c[0] = WheelPos * 3;
c[1] = 255 - WheelPos * 3;
c[2] = 0;
} else if (WheelPos < 170) {
WheelPos -= 85;
c[0] = 255 - WheelPos * 3;
c[1] = 0;
c[2] = WheelPos * 3;
} else {
WheelPos -= 170;
c[0] = 0;
c[1] = WheelPos * 3;
c[2] = 255 - WheelPos * 3;
}

return c;
}

void theaterChase(byte red, byte green, byte blue, int SpeedDelay) {
for (int j = 0; j < 10; j++) { //do 10 cycles of chasing
for (int q = 0; q < 3; q++) {
for (int i = 0; i < NUM_LEDS; i = i + 3) {
setPixel(i + q, red, green, blue); //turn every third pixel on
}
showStrip();

delay(SpeedDelay);

for (int i = 0; i < NUM_LEDS; i = i + 3) {
setPixel(i + q, 0, 0, 0); //turn every third pixel off
}
}
}
}

void theaterChaseRainbow(int SpeedDelay) {
byte *c;

for (int j = 0; j < 256; j++) { // cycle all 256 colors in the wheel
for (int q = 0; q < 3; q++) {
for (int i = 0; i < NUM_LEDS; i = i + 3) {
c = Wheel( (i + j) % 255);
setPixel(i + q, *c, *(c + 1), *(c + 2)); //turn every third pixel on
}
showStrip();

delay(SpeedDelay);

for (int i = 0; i < NUM_LEDS; i = i + 3) {
setPixel(i + q, 0, 0, 0); //turn every third pixel off
}
}
}
}

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

void BouncingColoredBalls(int BallCount, byte colors[][3], boolean continuous) {
float Gravity = -9.81;
int StartHeight = 1;

float Height[BallCount];
float ImpactVelocityStart = sqrt( -2 * Gravity * StartHeight );
float ImpactVelocity[BallCount];
float TimeSinceLastBounce[BallCount];
int Position[BallCount];
long ClockTimeSinceLastBounce[BallCount];
float Dampening[BallCount];
boolean ballBouncing[BallCount];
boolean ballsStillBouncing = true;

for (int i = 0 ; i < BallCount ; i++) {
ClockTimeSinceLastBounce[i] = millis();
Height[i] = StartHeight;
Position[i] = 0;
ImpactVelocity[i] = ImpactVelocityStart;
TimeSinceLastBounce[i] = 0;
Dampening[i] = 0.90 - float(i) / pow(BallCount, 2);
ballBouncing[i] = true;
}

while (ballsStillBouncing) {
for (int i = 0 ; i < BallCount ; i++) {
TimeSinceLastBounce[i] = millis() - ClockTimeSinceLastBounce[i];
Height[i] = 0.5 * Gravity * pow( TimeSinceLastBounce[i] / 1000 , 2.0 ) + ImpactVelocity[i] * TimeSinceLastBounce[i] / 1000;

if ( Height[i] < 0 ) {
Height[i] = 0;
ImpactVelocity[i] = Dampening[i] * ImpactVelocity[i];
ClockTimeSinceLastBounce[i] = millis();

if ( ImpactVelocity[i] < 0.01 ) {
if (continuous) {
ImpactVelocity[i] = ImpactVelocityStart;
} else {
ballBouncing[i] = false;
}
}
}
Position[i] = round( Height[i] * (NUM_LEDS - 1) / StartHeight);
}

ballsStillBouncing = false; // assume no balls bouncing
for (int i = 0 ; i < BallCount ; i++) {
setPixel(Position[i], colors[i][0], colors[i][1], colors[i][2]);
if ( ballBouncing[i] ) {
ballsStillBouncing = true;
}
}

showStrip();
setAll(0, 0, 0);
}
}

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

// used by meteorrain
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
}

// REPLACE TO HERE




// ***************************************
// ** FastLed/NeoPixel Common Functions **
// ***************************************

// Apply LED color changes
void showStrip() {
#ifdef ADAFRUIT_NEOPIXEL_H
// NeoPixel
strip.show();
#endif
#ifndef ADAFRUIT_NEOPIXEL_H
// FastLED
FastLED.show();
#endif
}

// Set a LED color (not yet visible)
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
}

// Set all LEDs to a given color and apply it (visible)
void setAll(byte red, byte green, byte blue) {
for (int i = 0; i < NUM_LEDS; i++ ) {
setPixel(i, red, green, blue);
}
showStrip();
}

[/code]

 

 

 


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 
Posted by: @bartie1967

But if I push that new button , it seems that it always jumps to strobe effect and the halloween eyes effect

This could be "bounce" effect that is seen with some push buttons.
To minimize that add a delay (for example: delay(200); )to the changeEffect and/or changeEffectReverse functions, just before this line:

asm volatile ("  jmp 0");

So maybe something like this, replacing that line:

delay(200);
asm volatile (" jmp 0");

Since I cannot test here, you'll have to play with the value 200.

I'm not sure if that will fix all the issues, let me know if it doesn't so I can go through your code.
If possible please add the code as an attachment (not required, and maybe not even possible for you [yet]).


   
ReplyQuote
(@bartie1967)
Active Member
Joined: 4 years ago
Posts: 10
Topic starter  

 

@hans

Hi , thx for your patience and quick replies.... This is by far the best forum ever....

I don't think I can add attachments.

You added a a case 0  in the void loop " do nothing" .

Doesn't  it has to be specified in the "LED EFFECT FUNCTIONS" as well ??

 


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 

To answer your email (I've attached the code to your post):

Main issues:

  • Case 0 is not executed

This would suggest that either the variable "selectedEffect" is not reaching zero, or something goes wrong with the case statement.
I looked at your code, and it looks correct (I'm not able to test this at the moment).

Note: You could use "case 0" also to set the LEDs to black over and over again. Something like this:

 case 0 : {
// set all LEDs to black
setAll(0,0,0);
showStrip;
break;
}

 

  • When pressing the button (in a single button setup), sometimes an effect is skipped.

This is caused by the so called "bounce" effect, where the Arduino registers the button being pressed more than once, even though you really only pressed the button one time only. 

Pushbuttons often generate spurious open/close transitions when pressed, due to mechanical and physical issues: these transitions may be read as multiple presses in a very short time fooling the program.

To prevent that from happening we can add a timer to make sure there is enough time between detected button presses.
Note: my previous delay suggestion has a flaw. I just realized that the interrupt will ignore that if triggered twice.

So we can do this (for example) like so:

In the beginning of the code (where we define for example the BUTTON pin), one needs to define a variable to register the last time a button press was detected, and a constant to define the minimum time between two button presses.

unsigned long lastPressed = 0;  // last time the button was pressed in milliseconds
#define bounceDelay 50 // minimum time between two button presses

In the changeEffect() function, we want to see if the button was indeed pressed, and that the time between this button press en the previous button press is at least a certain time (bounceDelay). If these criteria are met: continue to do what normally would be done. We do need to register the time here as well. To make sure we avoid more than one bounce, I register the time even when a bounce occured.

void changeEffect() {
if (digitalRead (BUTTON) == HIGH) && ( lastPressed + bounceDelay < millis() ) ) {
lastPressed = millis();
selectedEffect++;
EEPROM.put(0, selectedEffect);
asm volatile (" jmp 0");
}
lastPressed = millis();
}

So,... if the button was pressed AND ( lastPressed time + bounceDelay ) is less than the current time: Button was pressed!
Else ... ignore the registered button press.

The value of "bounceDelay" is set to 50 in this example. If effects still get skipped, then increase this value, for example to 100. You may have to test a few values, as the bounce effect can be different per push button (mine for example does not seem to experience the bounce effect at all).

 

  • Using two buttons for the same function

The idea of using an RF remote AND a button, to change effects, could be done by adding the second "button" to PIN 3 and by adding a suitable interrupt for that. You already kinda did that before.

Since we're potentially using the other button, we should add a second changeEffect function for that second button.
Note: for the RF "button" we may not need to debounce, but it will not hurt to have it in there anyway.

#define BUTTON2 3

...

void setup() {
...
  pinMode(BUTTON2, INPUT_PULLUP); // internal pull-up resistor
  attachInterrupt (digitalPinToInterrupt (BUTTON2), changeEffect2, CHANGE); // pressed
...
}

...

void changeEffect2() {
if (digitalRead (BUTTON2) == HIGH) && ( lastPressed + bounceDelay < millis() ) ) {
lastPressed = millis();
selectedEffect++;
EEPROM.put(0, selectedEffect);
asm volatile (" jmp 0");
}
lastPressed = millis();
}

 


   
ReplyQuote
(@bartie1967)
Active Member
Joined: 4 years ago
Posts: 10
Topic starter  
Posted by: @hans

void changeEffect() {
if (digitalRead (BUTTON) == HIGH) && ( lastPressed + bounceDelay < millis() ) ) {
lastPressed = millis();
selectedEffect++;
EEPROM.put(0, selectedEffect);
asm volatile (" jmp 0");
}
lastPressed = millis();
}

this gives me a error

backup:193:3: error: 'lastPressed' was not declared in this scope
lastPressed = millis();
^~~~~~~~~~~
exit status 1
expected identifier before '(' token

 

Yep , case 0 now displays correct....... Thx Hans

 

the 2 nd buttons I need to check later today ....


   
ReplyQuote
(@bartie1967)
Active Member
Joined: 4 years ago
Posts: 10
Topic starter  

here is the code i made .

 

The buttons also give me an error

 


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 
Posted by: @bartie1967

this gives me a error

backup:193:3: error: 'lastPressed' was not declared in this scope
lastPressed = millis();
^~~~~~~~~~~
exit status 1
expected identifier before '(' token

My first guess: It looks like I may have made a typo in this line (which can be found in changeEffect and changeEffect2):

if (digitalRead (BUTTON2) == HIGH) && ( lastPressed + bounceDelay < millis() ) ) {
woopsie one ")" too many --^

which should be

if (digitalRead (BUTTON2) == HIGH) && ( lastPressed + bounceDelay < millis() ) {

Error messages can be quite confusing. When looking at this one it tells me initially that "lastPressed" was not defined. Since I assume you added this line at the beginning, this seem odd:

unsigned long lastPressed = 0;  // last time the button was pressed in milliseconds

Right after that the error indicates an error with the round bracket "(" and ")", so I looked at that line an noticed I had typed one ")" too many.

Unfortunately, the code you  posted is not the one with the error, since the error points to line 193, which looks different in the code you attached.


   
ReplyQuote
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2728
 

Coming back to your email:

The ESP8266 is in essence an Arduino on steroids ... faster, smaller, more memory, etc.

Using the WiFi part is optional. If you prefer to use a button and an RF switch, like you did with your Arduino, then you do not need to use the WiFi feature.

If you do want to use the WiFi option, then yes one of the methods to control the lights (for example) would be through a web-interface (call it a "mini website").
You will however have to provide the "content" for this yourself.
This can be by sending text (see the ESP8266 example) we can send through the server as a response to a request from the client (computer, cellphone, tablet, etc).

Another, more complex, approach is by using a SPIFFS file system on the flash part of an ESP8266. This would allow you to store actual text files and such on the ESP8266.
I would not recommend this method until you're more familiar with the ins and outs of Arduino programming and especially the technical features of the ESP8266.
Here an article that describes this. Again: not for beginners. 😉 


   
ReplyQuote
(@bartie1967)
Active Member
Joined: 4 years ago
Posts: 10
Topic starter  

@hans

You have been a big help Hans . I'm not gonna tweak it anymore or ask questions , because i can't get all the new features in the sketch  at work without errors.

My daughter is gonna be happy , and I think dad is a little to picky . Maybe I just want stuff in the sketch that she will never use .

I will try to install it on a ESP8266 in the future .

 

Happy holidays and keep save

 

 


   
ReplyQuote
(@bartie1967)
Active Member
Joined: 4 years ago
Posts: 10
Topic starter  

Hand

 

just one more question

 

 

can you add a brightness function to the entire sketch please ?

Is it a big job to do one with a potentiometer?

if it's to much work just a setting in the sketch


   
ReplyQuote
(@bartie1967)
Active Member
Joined: 4 years ago
Posts: 10
Topic starter  

found it

 

#define BRIGHTNESS 100


   
Hans reacted
ReplyQuote
Page 1 / 2
Share: