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!



LED Effects - Star ...
 
Share:
Notifications
Clear all

[Solved] LED Effects - Star Trek Phaser Array

223 Posts
14 Users
33 Likes
82.2 K Views
(@trace)
Estimable Member
Joined: 4 years ago
Posts: 170
 

I don´t know if my last post got posted.

So I write it again but shorter.

Maybe there is no original MP3 Module. Take a look at DFRobot, it is a company from China and the module is calles DFPlayer. So it seems it is a module from them.

I have never had any problems with Arduino or any other clones. But you are right, if it is just a few €, there is no need to buy a clone.

AZDelivery is the place where I buy them online. They are in Germany but also ship in Europe.

With my first code where I had Sound and Light, it wasn´t necessary to sync it. The Arduino just sent a "play" signal to the DFPLayer, so the DFPLayer started the audio file, while the Arduino just continued its code, which is a simple light effect. The only thing I had to do was to adjust the length of the audio to match the time it takes for the LED effect.

Here I just dubbed a phaser sound to the light effect:

Phaser light


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

Hi Trace,

just watched you YouTube video - that is sooooo cool, love it! 

Apologies about the forum, it's not the best forum out there, but it is the only one that natively integrates with WordPress (without it being huge on resources).
I'm still looking for a different forum ... but whatever I run into is either having a very poor connection with WordPress (old, outdated, unstable, etc), or it is super resource hungry (very slow loading of pages).

I tried ordering some MP3 modules last night, from AliExpress, to find out that my debit card needs updating (it expires the end of this month and I'm still waiting for a new card from the bank). I did find one with embedded memory - so no SD card needed - for the same price. This could be interesting as well, since in my experience (Raspberry Pi), SD cards over time tend to start failing.

Thanks for the company info - I'll see what they have! 

Good to hear that no syncing of sound was needed once you managed to get the duration of the MP3 to match the LEDs - much easier than trying to do this in code for sure 

Love what you're doing in your project - wish I had the time and space for that as well.
It already took me a day to make a simple piece of wood with my LED and Arduino mounted on it (so I can help others quicker, without having to find and connect all the components).


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

Hi Hans,

thanks for your praise. The big part of this work is made by you

I don´t order over AliExpress. For me it feels kinda cheesy and I always think about customs. And it could be that those modules are really cheap clones from the "original" DFPLayer. But maybe Iam just overcautious

Maybe it will be necessary to sync (or trigger it at the correct part of the code) with the kind of code needed for WS2812. We will see.
At the weekend I will try to find time to add sound. Maybe I can figure it out by myself

The time for my projects is also a big problem for me. That´s why I always try to gather everything I need, before I start. So it could be I start to build the Enterprise much later than I would like to.

Your ability to write a working code without having the parts to test it is astounding and a great skill. So how can you help quicker with just a piece of wood???

What about using a breadboard?

PS: rather a bumpy but helpful forum than a super working one without great help


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

Hi Trace,

you're welcome, but really the most work is building the Enterprise and adding all these features. The laser is just one of the items  ...

AliExpress does indeed offer questionable items. But ... I've had quite a lot of luck with them, getting a lot of things really cheap. I've purchased a cheap i7 based PC (runs dedicated as my pfSense firewall), wireless doorbell, quite a few LED strips and LED lamps, even a really cheap Bluetooth headset, several ODB devices for cars, etc.
But you're right; some stuff is a fake knock-off ...

As for sound; the challenge may be to get the MP3 to match the LEDs walking up to the aiming point. The challenge is that the shortest loop will be when the "aim" is in the middle, and the longest loop is when the "aim" is at the end or the beginning of the strip. So with 60 LEDs (as an example): The shortest loop is 30 LEDs, the longest is 60 LEDs ... but maybe I'm overthinking it now haha. Or maybe we should make the loop always the maximum ... but that could mean that a "charge" will take a bit before it shows a moving LED.

Time is indeed an issue. Right now I do IT consulting, so i do have gaps of time when I feel like it. But it doesn't matter if I have one afternoon or a whole week ... it's gone before I know it .

Thanks for the compliment on coding ... I like coding (for the fun of it).
The issue is that I'm temporary staying in a house that is just too small for all my stuff. So I have to store my stuff every time I'm done with something.
Each time when I want to do a LED effect though, I'll have to dig up all the parts (LED strip, breadboard, power supply, Arduino, wires, switched etc). So this takes a lot of time.
Now I created a fixed setup, on that piece of wood, with all the components fixed on it, even the LED strip. So now I can store it as one item, and grab it and be ready right away when I need it.
It's simple, but saves a lot of time ... (see attached image)

As for the forum; I don't like this one (bbPress) one bit, but it natively is build specifically for WordPress.
But the alternatives are just not good when it comes to integration. I've started yet another search for a replacement ... but no luck so far.


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

Hi Hans,

I hope your luck with AliExpress will stay as long as possible.

The
"aim" (moving LED from each side of the strip) is already the charging.
But you are right. The time it takes for the LED to travel the stripe
is different. Maybe I can set the sound so that it matches most of the
time. For me it is ok when the sound is off for a few milliseconds or
so.

I don´t get what you mean with making the loop always the
maximum and that the charge will then take a moment before the LED is
showing. Do you mean to code the effect in a way that every single aim
and shoot takes the same time, which will mean that for a long travel
(shoot at the end of the stripe) the LED will wait for a moment before
start traveling? So the sound is already playing a few milliseconds
before the LED effect starts?!

My "workstation" is in the kitchen. That means I also have to store everything when I´m done. And yes, this is frustrating.

Your solution with the piece of wood is a good idea and saves a lot of setup time.

PS: Everytime I want to reply, I have to submit it several times before it get posted. If this gets posted now, then the problem is the Smileys.


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

Yeah .. getting sound in sync may be a little challenge ...

But this may work:

Make (for example) 3 effects, with each a different "aim" time.
So for example with 60 LEDs:

1) for the shortest aim (shot takes place in the center, 30 steps before shooting)
2) for the longest aim (shot takes place at the beginning or end, 60 steps)
3) one for in the middle (45 steps)

I'd guess this would be adequate for most scenarios, but it could be refined of course.
As I understand from the MP3 module, one can store multiple MP3's on the SD card.

If you look in the code, you'll see that I determine the "maxSteps" - which would be where you could do the selection of the proper MP3 file.

void startrek_phaser( ... ) 
{  
  ...

  int StepsLeftside  = PhaserAim;             // 0 - PhaserAim
  int StepsRightside = NUM_LEDS-PhaserAim; // PhaserAim - NUM_LEDS
  
  int maxSteps = max( StepsLeftside, StepsRightside ); <--- HERE
  
  int LEDPos;  ...

Maybe something like (pseudo code):

if(maxSteps>50) { 
  // start the longest MP3
}
else if (maxSteps>40) {
// start the medium length MP3
}
else {
// start the shortest MP3
}

I took the example values based on "around" the medium (45), more than 5 higher (50) = long, less that 5 lower (40) = shortest, else take the medium.
But you can tinker with the values and number or variants.

Anyhoo - just an idea ... 

Workstation: yeah mine is in the living room. The biggest problem is that my previous home was significantly larger, and now I have to cram it all in a smaller space.
Thank goodness this is only temporary ...

Forum: are you typing smileys, or are you selecting a smiley from the button bar above the text?
I have noticed with another forum, that a smiley causes the forum to think the message is empty.
I've not seen it with bbPress though, but may it is OS or browser specific. (I use Google Chrome under macOS - I'll try to post a test message after this one)


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

Test message 1: using typed smileys ...

😊 😉 😜 


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

Test message 2: using smileys from the buttons above the text:


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

Hmm, seems to work on macOS ... feel free to post a few text messages yourself ... I'd be interested in finding out if this is a problem or not. 😁 


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

Hi Hans,

just a fun fact: Your messages and answering them have become a daily routinge :D  (used a typed Smiley)

If I got time tomorrow, I will try to impelent sound to the light effect and I will try out your idea with different MP3 length. Or I can arrange the soundeffect in a way that it will match "every" situation, some of them better, others not, but still fine in terms of the visual effect.    (used Smiley from the bar)

I always used the Smileys from the bar, cause I thought there could be problems with typed Smileys. When you look at some earlier messages, you will see that I already have used the bar smiley successfully.


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

Hi Trace!

Yeah, I have a routine; every morning I go through all my messages (email, forum, etc) and try to answer them if possible.
Sometimes (like building your phaser effect) it takes a little bit more time ... 

So ... the smileys didn't cause the issue then I guess (sorry for not looking back at earlier messages to see if you had use them before - I could have thought that myself haha).

As for the sound effect ...
As far as I know the module (very limited) you can pull a pin HIGH to make it play an MP3.
Is there a way to control the speed of playback (I recall reading a certain number of speeds, or where those sample rate?).

Anyhoo - stretching/shrinking the time for playback may be a challenge, but I'd be curious what in the end the solution will be ...

Enjoy your weekend 


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

Hi Hans!

It is weird. I have tried to send some test-messages
with Smileys (from the bar) and it didn´t work. If this message gets
posted now, than it has something to do with the smileys, cause I
deleted them.

To play a file using the DFPlayer is more easy than
pulling a Pin to High. There are several commands for playing just a
single file, a specific folder, play a specific file in a specific
folder, Next, Previous and so on.

Yes, the different "speed" numbers are just sample rates.

If you tell me how to put in a video, I can show you my result so far.

Attaching the MP4 works, but hitting "submit" just loads the page and nowthing happens after that.


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

It is weird indeed ... the smileys have been functioning since 2014, so I wonder what has changed (probably one of those updates I didn't ask for) ... 

I do like the simplicity of DFPlayer and I'll order some once I get my new back card (it expires this month, so payments no longer work online and my bank hasn't send me a new one yet ).

Posting video has a size limitation unfortunately (mixed setting between WordPress, bbPress, one or the other ini file, etc).
Every time I change the limitations, I run into them again with the next (bigger) video file.
I do pull any video I make through HandBrake to get the smallest file I can get though - which often helps.
But you can also email me the video (webmaster at tweaking4all dot com).


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

Or it has something to do with my system. Remember the problems with my screenname and password?!

Im sure you will like the DFPlayer. My video is now just about 6MB big, so I try it again. What does "insert into content" do?


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

And here is the code. Thanks to your structure of coding, it was easy to find the correct lines where to put in the DF command lines.
As you can see I trigger one MP3 for pushbutton sound effect and another MP3 for the phaser effect.

First I was thinking about merging the soundeffect 3 times into one MP3, but then I realized that I only need one MP3 and it gets

triggered everytime the effect is triggered. So if I want 4 instead of 3 shootings, I don´t have to merge a new MP3 file for 4 shootings, it just gets

triggered 4 times then.

The DFPlayer code parts are bold. And I hope the code has no syntax mistakes, cause the "source code" function put every line of code in a seperate line and I had to delete the spare lines.

#include "FastLED.h"
#include <EEPROM.h>
#define NUM_LEDS 60
CRGB leds[NUM_LEDS];
#define PIN 7
#define buttonPin 3     // the number of the pushbutton pin
int buttonState = 0; // variable for reading the pushbutton status

//=============== DFPlayer mini ===============//
#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 ===============//


void setup()
{
  FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  randomSeed(analogRead(0)); // for a better random
  FastLED.setBrightness(20);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);

//=============== DFPlayer mini setup ===============//
  mySoftwareSerial.begin(9600);
  Serial.begin(115200);
  if (!myDFPlayer.begin(mySoftwareSerial)) {  //Use softwareSerial to communicate with mp3.
    while(true);
  }
  myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms
  myDFPlayer.volume(20);  //Set volume value (0~30).
  myDFPlayer.EQ(DFPLAYER_EQ_NORMAL);
  myDFPlayer.outputDevice(DFPLAYER_DEVICE_SD);
//=============== DFPlayer mini setup end ===============//

 
}
void loop()
{
  // read the state of the pushbutton value:
  buttonState = digitalRead(buttonPin);
  // check if the pushbutton is pressed. If it is, the buttonState is HIGH:
  if (buttonState == HIGH) {
    myDFPlayer.playMp3Folder(5); // plays MP3 file number 5 which is a button sound
    delay(1000); // this delay needs to be at least as long as the MP3 button sound file to give it enough time to be played

    // turn phaser on 3x:
    startrek_phaser( 0xff, 0x90, 0, -1, 4, 3, 10, 20, 60, 40);
    startrek_phaser( 0xff, 0x90, 0, -1, 4, 3, 10, 20, 60, 40);
    startrek_phaser( 0xff, 0x90, 0, -1, 4, 3, 10, 20, 60, 40);
  }
}


void startrek_phaser(byte PhaserRed, byte PhaserGreen, byte PhaserBlue, int TargetLED,
                     byte PhaserWidth, byte ShootingWidth, int msAimDelay,
                     int PulsateAmount, int msPulsateDelayBright, int msPulsateDelayDarker)
{
  // These define how much the outer LEDs sim during Aiming, Shooting and Pulsating
  #define DimmingPhaserAim 200
  #define DimmingShoot     128
  #define DimmingPulsing   128

  int PhaserHalf = PhaserWidth/2; // division will take integer part: 3/2 = 1.5 -> 1,  4/2 = 2 -> 2
  int PhaserCenterWidth = 2 - (PhaserWidth%2); // odd numbers: 1, even numbers: 2
  int PhaserAim;
  myDFPlayer.playMp3Folder(1); // plays MP3 file number 1 which is the phaser sound

  if(TargetLED==-1)
  {
    PhaserAim = random(NUM_LEDS);     // Pick random aim point
   
    if(PhaserAim<PhaserHalf)         // just making sure we do not go out of the range of LEDs
    {
      PhaserAim = PhaserWidth;
    }
    else if(PhaserAim+PhaserHalf>NUM_LEDS)
    {
      PhaserAim = NUM_LEDS-PhaserHalf;
    }
  }
  else
  {
    PhaserAim = TargetLED;
  }
 
  int StepsLeftside  = PhaserAim;             // 0 - PhaserAim
  int StepsRightside = NUM_LEDS-PhaserAim;    // PhaserAim - NUM_LEDS
 
  int maxSteps = max( StepsLeftside, StepsRightside );
 
  int LEDPos;
 
  // move LEDs from outside to phaser position
 
  for(int counter=0; counter<=maxSteps; counter++)
  {
    setAll(0,0,0); // set all LEDs dark
    // Left side towards aim point
   
    LEDPos    = PhaserAim-maxSteps+counter;
   
    if( LEDPos >= 0 ) {
      for (int PhaserBlock = 0; PhaserBlock<PhaserWidth; PhaserBlock++)
      {
        if(LEDPos+PhaserBlock>0)
        {
          leds[LEDPos+PhaserBlock] = CRGB( PhaserRed, PhaserGreen, PhaserBlue);
          // only center (odd width) or center 2 LEDs (even width) should be bright, others need to fade
          if  ( ( (PhaserCenterWidth==1) && (PhaserBlock!=PhaserHalf) ) ||
                ( (PhaserCenterWidth==2) && (PhaserBlock!=PhaserHalf-1) && (PhaserBlock!=PhaserHalf) ) )
          {
            leds[LEDPos+PhaserBlock].fadeLightBy( DimmingPhaserAim );
          }
        }
      }
    }
    // Right side towards aim point
    LEDPos = PhaserAim+maxSteps-counter;
   
    if( LEDPos < NUM_LEDS ) {
      for (int PhaserBlock = 0; PhaserBlock<PhaserWidth; PhaserBlock++)
      {
        if(LEDPos+PhaserBlock<NUM_LEDS)
        {
          leds[LEDPos+PhaserBlock] = CRGB( PhaserRed, PhaserGreen, PhaserBlue);
          // only center (odd width) or center 2 LEDs (even width) should be bright, others need to fade
          if  ( ( (PhaserCenterWidth==1) && (PhaserBlock!=PhaserHalf) ) ||
                ( (PhaserCenterWidth==2) && (PhaserBlock!=PhaserHalf-1) && (PhaserBlock!=PhaserHalf) ) )
          {
            leds[LEDPos+PhaserBlock].fadeLightBy( DimmingPhaserAim );
          }
        }
      }
    }
    FastLED.show();
    delay(msAimDelay);
  }

  // pulsing LEDs when firing phaser
  LEDPos     = PhaserAim;

  PhaserHalf = ShootingWidth/2; // division will take integer part: 3/2 = 1.5 -> 1,  4/2 = 2 -> 2
  PhaserCenterWidth = 2 - (ShootingWidth%2); // odd numbers: 1, even numbers: 2

  setAll(0,0,0); // set all to black since shooting width may be different than aiming width

  for(int counter=0; counter<PulsateAmount; counter++) {
   
    // Set phaser at aim position to the usual brightness
    for (int PhaserBlock = 0; PhaserBlock<ShootingWidth; PhaserBlock++)
    {
      leds[LEDPos+PhaserBlock] = CRGB( PhaserRed, PhaserGreen, PhaserBlue);
      // only center (odd width) or center 2 LEDs (even width) should be bright, others need to fade
      if  ( ( (PhaserCenterWidth==1) && (PhaserBlock!=PhaserHalf) ) ||
            ( (PhaserCenterWidth==2) && (PhaserBlock!=PhaserHalf-1) && (PhaserBlock!=PhaserHalf) ) )
      {
        leds[LEDPos+PhaserBlock].fadeLightBy( DimmingShoot );
      }
    }
    FastLED.show();
    delay(msPulsateDelayBright);
    // Make the outer LEDs pulsate (not the center LED or LEDs)
    for (int PhaserBlock = 0; PhaserBlock<ShootingWidth; PhaserBlock++)
    {
      if  ( ( (PhaserCenterWidth==1) && (PhaserBlock!=PhaserHalf) ) ||
            ( (PhaserCenterWidth==2) && (PhaserBlock!=PhaserHalf-1) && (PhaserBlock!=PhaserHalf) ) )
      {
        leds[LEDPos+PhaserBlock].fadeLightBy( DimmingPulsing );
      }
    }
    FastLED.show();
    delay(msPulsateDelayDarker);
  }

  setAll(0,0,0);
  delay(500);
}

// 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++ ) {
    leds = CRGB(red, green, blue);
  }
 
  FastLED.show();
}

   
ReplyQuote
Page 2 / 15
Share: