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!



FastLED Light effec...
 
Share:
Notifications
Clear all

[Solved] FastLED Light effects for Power Rangers

67 Posts
2 Users
1 Likes
1,745 Views
(@trace)
Estimable Member
Joined: 4 years ago
Posts: 170
Topic starter  

@hans Hi Hans, I also wish you a happy new year and I hope everything will go well for you and your family!

For the two challanges. I think I can find a way for button release detection like the way we detect quick button presses and button hold. Or using a library for this specific action may be the easiest way?!

And for the delay problem, the arduino-timer looks interesting but I also need to read about it and play around for some time. It sounds like an easy task. All we need is to wait a lil moment (non blocking) after buttons are pressed, before executing a void. But like it is with reality, sounding easy does not mean it is easy.

Plus I try to find a way to have something being executed for as long as a mp3 file is being played (while loop?).


   
Hans reacted
ReplyQuote
(@trace)
Estimable Member
Joined: 4 years ago
Posts: 170
Topic starter  

@hans Hi there Hans, how are you doing?

I did not look up about the delay thing and button release detection. Because I have another task, which I can probably solve mechanically, but would prefer it within the code.

It´s about the short button and hold button press function. I have implemented the little function I have found earlier which detects both, short presses and long presses. It works fine.

The function detects short button presses by the release of the button. Therefore it will get executed immediately by the shortest press.

But I would like to have it so that even the short press events needs the button to be pressed for a moment before executing. Im sure it is possible by changing some logic within the code but you know how bad I am at this kind of logic :D

I will post both codes, the original one and mine.

Here is the original code:

int LED1 = 12;
int LED2 = 13;
int button = 3;

boolean LED1State = false;
boolean LED2State = false;

long buttonTimer = 0;
long longPressTime = 250;

boolean buttonActive = false;
boolean longPressActive = false;

void setup() {

	pinMode(LED1, OUTPUT);
	pinMode(LED2, OUTPUT);
	pinMode(button, INPUT);

}

void loop() {

	if (digitalRead(button) == HIGH) {
		if (buttonActive == false) {
			buttonActive = true;
			buttonTimer = millis();
		}
		if ((millis() - buttonTimer > longPressTime) && (longPressActive == false)) {
			longPressActive = true;
			LED1State = !LED1State;
			digitalWrite(LED1, LED1State);
		}
	} else {

		if (buttonActive == true) {
			if (longPressActive == true) {
				longPressActive = false;
			} else {
				LED2State = !LED2State;
				digitalWrite(LED2, LED2State);
			}
			buttonActive = false;
		}
	}
}

 

And here is mine with led animation and sound:

long buttonTimer = 0;
long longPressTime = 3000;

boolean buttonActive = false;
boolean longPressActive = false;

//-->setup and void loop<--//

void Morph_Theme_Short_Rainbow_Long() {
  FastLED.setBrightness(10);

  int button1 = digitalRead(Coin_Button_1) == LOW;
  int button2 = digitalRead(Coin_Button_2) == LOW;
  int button3 = digitalRead(Coin_Button_3) == LOW;

  if ((digitalRead(Activate_Button) == LOW) && (button1 | button2 | button3)) {
    if (buttonActive == false) {
      buttonActive = true;
      buttonTimer = millis();
    }

    if ((millis() - buttonTimer > longPressTime) && (longPressActive == false)) {
      longPressActive = true;
      if (isRainbow) {
        fill_solid(leds, NUM_LEDS, CRGB::Black);
        FastLED.show();
        isRainbow = false;
      } else {
        isRainbow = true;
        uint8_t thisHue = beat8(50, 255);
        uint8_t deltaHue = 255 / NUM_LEDS;
        fill_rainbow(leds, NUM_LEDS, thisHue, deltaHue);
        FastLED.show();
      }
    }
  } else {
    if (buttonActive == true) {
      if (longPressActive == true) {
        longPressActive = false;

      } else {
        if (isPlayingTheme) {
          myDFPlayer.stop();
          delay(50);
          isPlayingTheme = false;
        } else {
          isPlayingTheme = true;
          myDFPlayer.playMp3Folder(10);  // ThemeSong
          delay(50);
        }
      }
      buttonActive = false;
    }
  }
  if (isRainbow) {
    uint8_t thisHue = beat8(50, 255);
    uint8_t deltaHue = 255 / NUM_LEDS;
    fill_rainbow(leds, NUM_LEDS, thisHue, deltaHue);
    FastLED.show();
  }
}

 


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

Posted by: @trace

Hi there Hans, how are you doing?

Haven't forgotten about you 😉 - just a little busy these last few days.
Will try to get back as soon possible! 


   
ReplyQuote
(@trace)
Estimable Member
Joined: 4 years ago
Posts: 170
Topic starter  

Posted by: @hans

Posted by: @trace

Hi there Hans, how are you doing?

Haven't forgotten about you 😉 - just a little busy these last few days.
Will try to get back as soon possible! 

 

Thanks Hans for letting me know. But please dont feel rushed.

 


   
ReplyQuote
(@trace)
Estimable Member
Joined: 4 years ago
Posts: 170
Topic starter  

@Hans Hi there Hans, how are you? I hope everything is good?

Sometimes, solutions can be very easy and you cant see the forest for the trees. My problem was the need to have the Activate_Button being pressed for a moment before executing anything. The code as it was, just played the mp3 as soon as you have clicke the button.

The obvious solution was to put in a second very easy line. So this part:

else {
        if (isPlayingTheme) {
          myDFPlayer.stop();
          delay(50);
          isPlayingTheme = false;
        } else {
          isPlayingTheme = true;
          myDFPlayer.playMp3Folder(10);  // ThemeSong
          delay(50);
        }
      }

Becomes this:

else {
        if (millis() - buttonTimer > 500) {
        if (isPlayingTheme) {
          myDFPlayer.stop();
          delay(50);
          isPlayingTheme = false;
        } else {
          isPlayingTheme = true;
          myDFPlayer.playMp3Folder(10);  // ThemeSong
          delay(50);
        }
      }
      }

 

So just adding a if statement with millis - buttonTimer was all I had to do to be able to push the button shortly (for a mechanical action) without having the mp3 start playing. And pushing it a bit longer for the mp3 to play. The longHold function is still working.

I hope I havent made any mistakes and the timer works fine (it looks good so far).

So there are only two or three problems left.

The first one is still the delay thing for the coinColorSelection. Just having some kind of delay (non blocking) to have some time to push the color buttons, before InsertAnimation gets started. As it is right now, its not the best solution. Sometimes the millis-function dont get recognized and the color gets selected as soon as I hit the button, no matter if I hit another button just a few milliseconds after (which is the problem of course).

The second one is the problem in reverse. As soon as two buttons are pressed (button1 && button2 for example) and I release both, but slightly after each other, then for a blink of an eye, a single button is still pressed and the code recognizes it as a color choice.

And the third problem is still a button release function. For example: releasing button1 && button2 should trigger something. Just a mp3 or maybe another animation. But for this, problem 1 and 2 needs to be solved, obviously.
Thats why this is just an option.


   
ReplyQuote
(@trace)
Estimable Member
Joined: 4 years ago
Posts: 170
Topic starter  

@Hans Hi Hans, how are you? And are there news (hopefully good) about your mother?

I kept working on the Power Rangers code and utilized parts of the code we have already done, to make some progress.

There was still the task to have a button release function and I just realized that the "click and hold button"- function has some kind of button release function in it. Because the click function recognize the button release, not the button press.

This way I was able to set some timers to have a function getting executed after the button is pressed for a moment and not right when I press it. And with this I was able to use it just like a button release function for different animations and sounds.

Using the DFPlayer mini busy pin was also usefull to start/stop some animations. So the animation is only be executed as long as the mp3 is playing.

The only problem left is the non blocking delay part for the button recognition. Maybe it is good enough as it is, but I need to test it in real life conditions first.

Also I was able to make a blink pattern with different on off timings, so I can sync a simple blinking animation for a simple mp3 by looking at the timings within the mp3 and set them in code by hand. The way I did it seems to be more complicated than necessary. But it was possible to implement it to the coin release void.

Feel free to tell me what you think. Maybe some other ideas for too complicated parts or any flaws?
Here is the full code:

#define FASTLED_INTERNAL  // just used to mute the Pragma messages when compiling
#include "FastLED.h"
#include <EEPROM.h>

#define PIN 6
#define NUM_LEDS 26

CRGB leds[NUM_LEDS];

#define Coin_Button_1 3    // Coin button 1
#define Coin_Button_2 4    // Coin button 2
#define Coin_Button_3 5    // Coin button 3
#define Morph_Button 7     // Morph open button
#define Activate_Button 8  // Activate button

#define Busy_Pin 9

CRGB prevcoinColor = CRGB::Black;
CRGB coinColor = CRGB::Black;

boolean isPlayingMorph = false;
boolean isPlayingTheme = false;
boolean isRainbow = false;
boolean isPlayingNoCoin = false;

//↓↓=============== Button Selection Delay (not working correctly but maybe good enough) ===============↓↓//
unsigned long previousMillis = 0;
const long interval = 1500;
//↑↑=============== Button Selection Delay (not working correctly but maybe good enough) ===============↑↑//

//↓↓=============== Theme_Short_Rainbow_Long ===============↓↓//
long buttonTimer = 0;
long longPressTime = 3000;  //activate functions when button hold for 3 seconds

boolean buttonActive = false;
boolean longPressActive = false;
//↑↑=============== Theme_Short_Rainbow_Long ===============↑↑//

//↓↓=============== Morpher Jammed ===============↓↓//
long buttonTimer2 = 0;
long longPressTime2 = 1500;  // activate functions when button hold for 1,5 seconds

boolean buttonActive2 = false;
boolean longPressActive2 = false;
//↑↑=============== Morpher Jammed ===============↑↑//

//↓↓=============== Coin Release ===============↓↓//
long buttonTimer3 = 0;
long longPressTime3 = 3000;  //Pseudo-time, necessary for button release function to work

boolean buttonActive3 = false;
boolean longPressActive3 = false;
//↑↑=============== Coin Release ===============↑↑//

//↓↓=============== Morpher Close ===============↓↓//
long buttonTimer4 = 50;      //standard is 0, 50 for testing
long longPressTime4 = 3000;  //Pseudo-time, necessary for button release function to work

boolean buttonActive4 = false;
boolean longPressActive4 = false;
//↑↑=============== Morpher Close ===============↑↑//

//↓↓=============== No Coin Morph ===============↓↓//
long buttonTimer5 = 0;
long longPressTime5 = 1000;  //activate functions when button hold for 1 second

boolean buttonActive5 = false;
boolean longPressActive5 = false;
//↑↑=============== No Coin Morph ===============↑↑//

//↓↓=============== Coin Release Animation Timings ===============↓↓//
// Define the on and off timings
const double onTime1 = 100;
const double offTime1 = 160;
const double onTime2 = 100;
const double offTime2 = 170;
const double onTime3 = 100;
const double offTime3 = 40;
const double onTime4 = 100;
const double offTime4 = 160;
const double onTime5 = 70;
const double offTime5 = 215;
const double onTime6 = 80;
const double offTime6 = 500;

int state = 0;  // Define the current state of the state machine
//↑↑=============== Coin Release Animation Timings ===============↑↑//

//↓↓=============== DFPlayer mini initiation ===============↓↓//
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"

SoftwareSerial mySoftwareSerial(10, 11);  // RX, TX
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
//↑↑=============== DFPlayer mini initiation ===============↑↑//

void setup() {
  FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  //FastLED.setBrightness(30);   //set global brightness -> is off due to brightness settings for each void
  fill_solid(leds, NUM_LEDS, CRGB::Black);  //probably not needed
  FastLED.show();

  pinMode(Coin_Button_1, INPUT_PULLUP);    //button for Coin recognition
  pinMode(Coin_Button_2, INPUT_PULLUP);    //button for Coin recognition
  pinMode(Coin_Button_3, INPUT_PULLUP);    //button for Coin recognition
  pinMode(Morph_Button, INPUT_PULLUP);     //button for when Morpher is opened
  pinMode(Activate_Button, INPUT_PULLUP);  //button for click and hold functions (red button at the toy)


  //↓↓=============== DFPlayer mini setup ===============↓↓/
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);
  if (!myDFPlayer.begin(mySoftwareSerial, true, false)) {  //Use softwareSerial to communicate with mp3. true, false added removes popping sound
    while (true)
      ;
  }
  myDFPlayer.setTimeOut(500);       //Set serial communictaion time out 500ms
  myDFPlayer.volume(1);             //Set volume value (0~30).
  myDFPlayer.EQ(DFPLAYER_EQ_BASS);  //Set equalizer NORMAL, POP, ROCK, JAZZ, CLASSIC, BASS
  myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
}
//↑↑=============== DFPlayer mini setup ===============↑↑//

void loop() {

  coinColorSelection();              //Coin Insert Color Recognition function
  CoinInsertAnimation(1, 50);        //Coin Insert Animation (3 times for longer animation)
  CoinInsertAnimation(1, 50);        //Coin Insert Animation (3 times for longer animation)
  CoinInsertAnimation(1, 50);        //Coin Insert Animation (3 times for longer animation)
  MorphAnimation(100);               //Sparkle with CoinColor and PlayMorph Sound (higher number = more sparkle)
  PlayMorph();                       //Morph Sound for MorphAnimation
  Morph_Theme_Short_Rainbow_Long();  //Short press plays and stops Theme Song, long press shows Rainbow
  NoCoinSparkle(1000);               //sparkle animation when no coin is inserted but Morpher gets open (higher number = more sparkle)
  NoCoinSound();                     //Sound when no coin is inserted
  Morpher_Jammed();                  //Animation and Sound when Morpher is jammed but activate button is pressed (hold)
  Coin_Release();                    //Sound when the coin gets released
  Morpher_Closing();                 //Animation and Sound when Morpher gets closed
  NoCoinMorph();                     //Animation and Sound when no coin is inserted, Morpher gets open and activate button is pressed (hold)

  //CoinReleaseAnimation(); // TEST
}

//↓↓=============== Coin Color Selection ===============↓↓//
void coinColorSelection() {

  bool button1 = digitalRead(Coin_Button_1) == LOW;
  bool button2 = digitalRead(Coin_Button_2) == LOW;
  bool button3 = digitalRead(Coin_Button_3) == LOW;

  prevcoinColor = coinColor;  // assign old color before determining new color

  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    // Check for button combinations and assign the corresponding colors to coinColor
    if (button1 && button2) {
      coinColor = CRGB(20, 0, 0);  //Tyranosaurus - red
      if (prevcoinColor != coinColor) {
        myDFPlayer.playMp3Folder(1);
      }
    } else if (button1 && button3) {
      coinColor = CRGB(0, 20, 0);  //Dragonzord - green
      if (prevcoinColor != coinColor) {
        myDFPlayer.playMp3Folder(4);
      }
    } else if (button2 && button3) {
      coinColor = CRGB(20, 0, 10);  //Pterodactyl - pink
      if (prevcoinColor != coinColor) {
        myDFPlayer.playMp3Folder(5);
      }
    } else if (button1) {
      coinColor = CRGB(20, 20, 0);  //Sabertoothtiger - yellow
      if (prevcoinColor != coinColor) {
        myDFPlayer.playMp3Folder(2);
      }
    } else if (button2) {
      coinColor = CRGB(0, 5, 5);  //Mastodon - "black" (skyblue)
      if (prevcoinColor != coinColor) {
        myDFPlayer.playMp3Folder(6);
      }
    } else if (button3) {
      coinColor = CRGB(0, 0, 20);  //Triceratops - blue
      if (prevcoinColor != coinColor) {
        myDFPlayer.playMp3Folder(3);
      }
    } else {
      coinColor = CRGB::Black;
    }
  }
}
//↑↑=============== Coin Color Selection ===============↑↑//

//↓↓=============== Coin insert LED Animation ===============↓↓//
void CoinInsertAnimation(int EyeSize, int SpeedDelay) {
  FastLED.setBrightness(255);
  if (prevcoinColor != coinColor) {

    byte red = coinColor.red;
    byte green = coinColor.green;
    byte blue = coinColor.blue;

    for (int i = 0; i <= ((NUM_LEDS - EyeSize) / 2); i++) {
      fill_solid(leds, NUM_LEDS, CRGB::Black);
      FastLED.show();

      leds[i] = CRGB(red / 10, green / 10, blue / 10);

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

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

      FastLED.show();
      delay(SpeedDelay);
    }

    for (int i = ((NUM_LEDS - EyeSize) / 2); i >= 0; i--) {
      fill_solid(leds, NUM_LEDS, CRGB::Black);
      FastLED.show();

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

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

      FastLED.show();
      delay(SpeedDelay);

      fill_solid(leds, NUM_LEDS, CRGB::Black);
      FastLED.show();
    }
  }
}
//↑↑=============== Coin insert LED Animation ===============↑↑//

//↓↓=============== Morphing LED Animation ===============↓↓//

void MorphAnimation(fract8 chanceOfGlitter) {
  FastLED.setBrightness(255);

  bool button4 = digitalRead(Morph_Button) == LOW;
  bool button1 = digitalRead(Coin_Button_1) == LOW;
  bool button2 = digitalRead(Coin_Button_2) == LOW;
  bool button3 = digitalRead(Coin_Button_3) == LOW;

  if ((button4) && (button1 | button2 | button3)) {

    if (!isRainbow) {
      fill_solid(leds, NUM_LEDS, CRGB::Black);
      FastLED.show();

      fill_solid(leds, NUM_LEDS, coinColor);
      if (random8() < chanceOfGlitter) {
        leds[random16(NUM_LEDS)] += CHSV(0, 0, 255);
      }
      FastLED.show();


      //fill_solid(leds, NUM_LEDS, CRGB::Black); // probably not needed
      //FastLED.show();
    }
  }
}
//↑↑=============== Morphing LED Animation ===============↑↑//

//↓↓=============== Morphing Sound ===============↓↓//
void PlayMorph() {
  FastLED.setBrightness(40);

  bool button4 = digitalRead(Morph_Button) == LOW;
  bool button1 = digitalRead(Coin_Button_1) == LOW;
  bool button2 = digitalRead(Coin_Button_2) == LOW;
  bool button3 = digitalRead(Coin_Button_3) == LOW;

  if ((button4) && (button1 | button2 | button3)) {
    if (!isPlayingMorph) {
      fill_solid(leds, NUM_LEDS, coinColor);
      FastLED.show();
      myDFPlayer.playMp3Folder(14);  // Morpher opens Sound
      delay(800);
      myDFPlayer.loopFolder(2);  // Morphing Sound
      delay(50);
      isPlayingMorph = true;
    }
  } else {
    if (isPlayingMorph) {
      myDFPlayer.stop();
      delay(50);
      isPlayingMorph = false;
    }
  }
}
//↑↑=============== Morphing Sound ===============↑↑//


//↓↓=============== Theme Song and Rainbow Test ===============↓↓//
void Morph_Theme_Short_Rainbow_Long() {
  FastLED.setBrightness(10);

  bool button1 = digitalRead(Coin_Button_1) == LOW;
  bool button2 = digitalRead(Coin_Button_2) == LOW;
  bool button3 = digitalRead(Coin_Button_3) == LOW;
  bool button4 = digitalRead(Morph_Button) == LOW;

  if ((digitalRead(Activate_Button) == LOW) && (button1 | button2 | button3) && button4) {
    if (buttonActive == false) {
      buttonActive = true;
      buttonTimer = millis();
    }

    if ((millis() - buttonTimer > longPressTime) && (longPressActive == false)) {
      longPressActive = true;
      if (isRainbow) {
        fill_solid(leds, NUM_LEDS, CRGB::Black);
        FastLED.show();
        isRainbow = false;
      } else {
        isRainbow = true;
        uint8_t thisHue = beat8(50, 255);
        uint8_t deltaHue = 255 / NUM_LEDS;
        fill_rainbow(leds, NUM_LEDS, thisHue, deltaHue);
        FastLED.show();
      }
    }
  } else {
    if (buttonActive == true) {
      if (longPressActive == true) {
        longPressActive = false;

      } else {
        if (millis() - buttonTimer >= 500) {
          if (isPlayingTheme) {
            myDFPlayer.stop();
            delay(50);
            isPlayingTheme = false;
          } else {
            isPlayingTheme = true;
            myDFPlayer.playMp3Folder(10);  // ThemeSong
            delay(50);
          }
        }
      }
      buttonActive = false;
    }
  }
  if (button4 == LOW) {
    fill_solid(leds, NUM_LEDS, CRGB::Black);
    FastLED.show();
    isRainbow = false;
  } else if (isRainbow) {
    uint8_t thisHue = beat8(50, 255);
    uint8_t deltaHue = 255 / NUM_LEDS;
    fill_rainbow(leds, NUM_LEDS, thisHue, deltaHue);
    FastLED.show();
  }
}
//↑↑=============== Theme Song and Rainbow Test ===============↑↑//

//↓↓=============== NoCoin Animation Test ===============↓↓//

void NoCoinSparkle(fract8 chanceOfGlitter) {
  FastLED.setBrightness(255);

  bool button4 = digitalRead(Morph_Button) == LOW;
  bool button1 = digitalRead(Coin_Button_1) == HIGH;
  bool button2 = digitalRead(Coin_Button_2) == HIGH;
  bool button3 = digitalRead(Coin_Button_3) == HIGH;

  if ((button4) && (button1 && button2 && button3)) {
    while (digitalRead(Busy_Pin) == LOW) {
      if (random8() < chanceOfGlitter) {
        leds[random16(NUM_LEDS)] += CHSV(random8(), 255, 255);
      }
      FastLED.show();

      fill_solid(leds, NUM_LEDS, CRGB::Black);
      FastLED.show();
    }
  }
}
//↑↑=============== NoCoin Animation Test ===============↑↑//

//↓↓=============== NoCoin Sound ===============↓↓//
void NoCoinSound() {

  bool button4 = digitalRead(Morph_Button) == LOW;
  bool button1 = digitalRead(Coin_Button_1) == HIGH;
  bool button2 = digitalRead(Coin_Button_2) == HIGH;
  bool button3 = digitalRead(Coin_Button_3) == HIGH;

  if ((button4) && (button1 && button2 && button3)) {
    if (!isPlayingNoCoin) {
      myDFPlayer.playMp3Folder(11);  // crackle Sound
      delay(50);
      isPlayingNoCoin = true;
    }
  } else {
    if (isPlayingNoCoin) {
      myDFPlayer.stop();
      delay(50);
      isPlayingNoCoin = false;
    }
  }
}
//↑↑=============== NoCoin Sound ===============↑↑//

//↓↓=============== Morpher Jammed ===============↓↓//
void Morpher_Jammed() {
  FastLED.setBrightness(10);

  bool button4 = digitalRead(Morph_Button) == HIGH;

  if ((digitalRead(Activate_Button) == LOW) && button4) {
    if (buttonActive2 == false) {
      buttonActive2 = true;
      buttonTimer2 = millis();
    }
    if ((millis() - buttonTimer2 > longPressTime2) && (longPressActive2 == false)) {
      longPressActive2 = true;
      myDFPlayer.playMp3Folder(8);  // Zordon Speech
      delay(50);
      while (digitalRead(Busy_Pin) == LOW) {
        uint8_t thisHue = beat8(100, 255);
        uint8_t deltaHue = 255 / NUM_LEDS;
        fill_rainbow(leds, NUM_LEDS, thisHue, deltaHue);
        FastLED.show();
      }
    }
  } else {
    fill_solid(leds, NUM_LEDS, CRGB::Black);
    FastLED.show();
    if (buttonActive2 == true) {
      if (longPressActive2 == true) {
        longPressActive2 = false;
      }
      buttonActive2 = false;
    }
  }
}
//↑↑=============== Morpher Jammed ===============↑↑//

//↓↓=============== Coin Release Test ===============↓↓//
void Coin_Release() {
  FastLED.setBrightness(40);

  bool button1 = digitalRead(Coin_Button_1) == LOW;
  bool button2 = digitalRead(Coin_Button_2) == LOW;
  bool button3 = digitalRead(Coin_Button_3) == LOW;

  if (button1 | button2 | button3) {
    if (buttonActive3 == false) {
      buttonActive3 = true;
      buttonTimer3 = millis();
    }
  } else {
    if (buttonActive3 == true) {
      if (longPressActive3 == true) {
        longPressActive3 = false;
      } else {
        myDFPlayer.playMp3Folder(12);  // Power Rangers Beep
        delay(50);

        while (digitalRead(Busy_Pin) == LOW) {
          switch (state) {
            case 0:  // On state 1
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = coinColor;  // Set all LEDs to white
              }
              FastLED.show();  // Update LEDs
              delay(onTime1);
              state = 1;  // Transition to next state
              break;

            case 1:  // Off state 1
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = CRGB::Black;  // Set all LEDs to black
              }
              FastLED.show();  // Update LEDs
              delay(offTime1);
              state = 2;  // Transition to next state
              break;

            case 2:  // On state 2
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = coinColor;  // Set all LEDs to blue
              }
              FastLED.show();  // Update LEDs
              delay(onTime2);
              state = 3;  // Transition to next state
              break;

            case 3:  // Off state 2
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = CRGB::Black;  // Set all LEDs to black
              }
              FastLED.show();  // Update LEDs
              delay(offTime2);
              state = 4;  // Transition to the first state (on state)
              break;

            case 4:  // On state 3
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = coinColor;  // Set all LEDs to blue
              }
              FastLED.show();  // Update LEDs
              delay(onTime3);
              state = 5;  // Transition to next state
              break;

            case 5:  // Off state 3
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = CRGB::Black;  // Set all LEDs to black
              }
              FastLED.show();  // Update LEDs
              delay(offTime3);
              state = 6;  // Transition to the first state (on state)
              break;

            case 6:  // On state 4
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = coinColor;  // Set all LEDs to blue
              }
              FastLED.show();  // Update LEDs
              delay(onTime4);
              state = 7;  // Transition to next state
              break;

            case 7:  // Off state 4
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = CRGB::Black;  // Set all LEDs to black
              }
              FastLED.show();  // Update LEDs
              delay(offTime4);
              state = 8;  // Transition to the first state (on state)
              break;

            case 8:  // On state 5
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = coinColor;  // Set all LEDs to blue
              }
              FastLED.show();  // Update LEDs
              delay(onTime5);
              state = 9;  // Transition to next state
              break;

            case 9:  // Off state 5
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = CRGB::Black;  // Set all LEDs to black
              }
              FastLED.show();  // Update LEDs
              delay(offTime5);
              state = 10;  // Transition to the first state (on state)
              break;

            case 10:  // On state 6
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = coinColor;  // Set all LEDs to blue
              }
              FastLED.show();  // Update LEDs
              delay(onTime6);
              state = 11;  // Transition to next state
              break;

            case 11:  // Off state 6
              for (int i = 0; i < NUM_LEDS; i++) {
                leds[i] = CRGB::Black;  // Set all LEDs to black
              }
              FastLED.show();  // Update LEDs
              delay(offTime6);
              state = 0;  // Transition to the first state (on state)
              break;
          }
        }
      }
      buttonActive3 = false;
    }
  }
}
//↑↑=============== Coin Release Test ===============↑↑//

//↓↓=============== Morpher Closing Test ===============↓↓//

void Morpher_Closing() {
  FastLED.setBrightness(60);

  bool button4 = digitalRead(Morph_Button) == LOW;

  if (button4) {
    if (buttonActive4 == false) {
      buttonActive4 = true;
      buttonTimer4 = millis();
    }
  } else {
    if (buttonActive4 == true) {
      if (longPressActive4 == true) {
        longPressActive4 = false;
      } else {
        myDFPlayer.playMp3Folder(7);  // Morpher Closing Sound
        delay(50);
        while (digitalRead(Busy_Pin) == LOW) {
          fill_solid(leds, NUM_LEDS, coinColor);
          FastLED.show();
        }
      }
      buttonActive4 = false;
    }
  }
}
//↑↑=============== Morpher Closing Test ===============↑↑//

//↓↓=============== No Coin Morph ===============↓↓//
void NoCoinMorph() {

  bool button1 = digitalRead(Coin_Button_1) == HIGH;
  bool button2 = digitalRead(Coin_Button_2) == HIGH;
  bool button3 = digitalRead(Coin_Button_3) == HIGH;
  bool button4 = digitalRead(Morph_Button) == LOW;

  if ((digitalRead(Activate_Button) == LOW) && (button1 && button2 && button3) && button4) {
    if (buttonActive5 == false) {
      buttonActive5 = true;
      buttonTimer5 = millis();
    }
    if ((millis() - buttonTimer5 > longPressTime5) && (longPressActive5 == false)) {
      longPressActive5 = true;
      myDFPlayer.playMp3Folder(13);  // Alarm Alpha 5
      delay(50);
      while (digitalRead(Busy_Pin) == LOW) {

        fill_solid(leds, NUM_LEDS, CHSV(0, 255, 30));
        float breath = (exp(sin(millis() / 430.0 * PI)) - 0.36787944) * 108.0;
        FastLED.setBrightness(breath);
        FastLED.show();
      }
    }
  } else {
    fill_solid(leds, NUM_LEDS, CRGB::Black);
    FastLED.show();
    if (buttonActive5 == true) {
      if (longPressActive5 == true) {
        longPressActive5 = false;
      }
      buttonActive5 = false;
    }
  }
}
//↑↑=============== No Coin Morph ===============↑↑//


   
ReplyQuote
(@trace)
Estimable Member
Joined: 4 years ago
Posts: 170
Topic starter  

@Hans Here is already a little improvement: I was thinking about a much simpler solution for a breathing led effect. So why not using a sinewave with beatsin8 function.

So this part within the NoCoinMorph void:

      while (digitalRead(Busy_Pin) == LOW) {

        fill_solid(leds, NUM_LEDS, CHSV(0, 255, 30));
        float breath = (exp(sin(millis() / 430.0 * PI)) - 0.36787944) * 108.0;
        FastLED.setBrightness(breath);
        FastLED.show();
      }

Becomes this:

      while (digitalRead(Busy_Pin) == LOW) {

        uint8_t sinBeat  = beatsin8(80, 0, 5, 0, 0);
        FastLED.setBrightness(sinBeat);
        fill_solid(leds, NUM_LEDS, CRGB::Red);
        FastLED.show();
      }

Here is an explanation for everyone:

The first number is beats per minute, second is lowest value of the sinewave (0-255), third is highest value (0-255), fourth is timebase in milliseconds and the fifth is phase offset (0-255).

The soundfile has a 80 BPM (alarm sound), I want the sinewave with the lowest value at 0 (leds off) and the highest value at 5 (brightness) and no timebase or phase offset.

This sinewave is then used to control the brightness of the LEDs.

Feel free to further improve or discuss about the whole program.


   
ReplyQuote
Page 5 / 5
Share: