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 Reactions
90.6 K Views
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2805
Topic starter  

Hi Hans, I hope your busy week isn't too stressful and the solution for my “steady color with pulsing meteor effect” problem is not too difficult.
I was trying some stuff but had no luck. So I spend some time on another effect.
I used your New-KITT sketch to make something like this:
Phaser effect
The only thing missing is the pulsing effect (pulsing again :D ) when the phaser is firing like here 0:02 , 0:06 , 0:10.
If it is easier to achieve, the pulsing effect could affect the entire sketch, instead of only when the light is still.
Also it would be great to have a fade to black after each fire impulse. But thats not necessary.
Here is the modified New-KITT sketch:

void loop() {
  PhaserBank(0xff, 0x3c, 0x00, 1, 15, 2000);
}
void PhaserBank(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay){
  PhaserBank1(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  PhaserBank2(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  PhaserBank3(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  PhaserBank4(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  }
void PhaserBank1(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = 0; i<=((60-EyeSize)/2); i++) {
    setAll(0,0,0);
    FastLED.setBrightness(10);
   
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    if (i > 28) {
      FastLED.setBrightness(80);  
      
    }
    
  }
       
    setPixel(60-i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(60-i-j, red, green, blue);
    
   }
    showStrip();
    
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
  
}
void PhaserBank2(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = 0; i<=((30-EyeSize)/2); i++) {
    setAll(0,0,0);
    FastLED.setBrightness(10);
   
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    if (i > 13) {
      FastLED.setBrightness(80);  
    }
    
  }
     
    setPixel(30-i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(30-i-j, red, green, blue);
    }
   
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
  
}

void PhaserBank3(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = 0; i<=((80-EyeSize)/2); i++) {
    setAll(0,0,0);
    FastLED.setBrightness(10);
   
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    if (i > 38) {
      FastLED.setBrightness(80);  
    }
    
  }
     
    setPixel(80-i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(80-i-j, red, green, blue);
    }
   
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
  
}

void PhaserBank4(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  for(int i = 0; i<=((100-EyeSize)/2); i++) {
    setAll(0,0,0);
    FastLED.setBrightness(10);
   
    setPixel(i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(i+j, red, green, blue);
    if (i > 48) {
      FastLED.setBrightness(80);  
    }
    
  }
      
    setPixel(100-i, red/10, green/10, blue/10);
    for(int j = 1; j <= EyeSize; j++) {
      setPixel(100-i-j, red, green, blue);
    }
   
    showStrip();
    delay(SpeedDelay);
  }
  delay(ReturnDelay);
  
}
// REPLACE TO HERE
void showStrip() {
 #ifdef ADAFRUIT_NEOPIXEL_H
   // NeoPixel
   strip.show();
 #endif
 #ifndef ADAFRUIT_NEOPIXEL_H
   // FastLED
   FastLED.show();
 #endif
}
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
}
void setAll(byte red, byte green, byte blue) {
  for(int i = 0; i < NUM_LEDS; i++ ) {
    setPixel(i, red, green, blue);
  }
  showStrip();
}

As I said before, take your time, no need to hurry. And a happy new year!!!
PS: I hope the code is not too long to be posted here


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

I'll try to get to it in the next few days ... it is one of those things where I have to dig up my stuff, and set it up to do some testing.
But at the moment I'm working on one of my larger projects, which I hope to finish in the the next few days. Your question is next in line for sure! 


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

Hello Hans,

first of all, thanks again for your great forum and your help.

The topic-title is wrong. The effect posted here is for the Star Trek Phaser Array, not "Steady color with pulsing meteor effect".

I have tried a lot of things to get the effect I want (pulsing phaser fire as seen in the video timestamps). But all I got working is the change in brightness when both light points meet.

Phaser

Effect best seen here 0:19.

Another thing is to have the running light always starting at both ends and clash together on different areas.
Take a look here: 0:01 you can see the light starting right, coming
towars left and near the end the light starts from the left to meet the
light from the right. Vise versa at 0:06.

I got this effect working in Void PhaserBank4 by letting one point start at i=0 and the other point starting at 100-i. But this only works with positive numbers. So I cant get this effect working for a fire shoot on the left. Because letting one point start at i=-100 and the other at 60 doesn´t work.

To get all those effects, is it maybe easier to write a new code?


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

Alrighty then ... it took me a lot more time to find all my stuff, write the code and studying the YouTube video, I did have a lot of fun with it ... so here we go.

So I made it configurable, so you can modify it relatively easy for your purposes.

The function "startrek_phaser" takes the following parameters:

PhaserRed, PhaserGreen, PhaserBlue: define the color of the LEDs (0xff, 0x90, 0 = orange).

TargetLED: The LED at what position needs to be "fired" (use "-1" for a random position).

PhaserWidth: the number of LEDs used to "walk" to the aiming position. 4 seemed nice.

ShootingWidth: the number of LEDs used when "firing" and here 3 or 4 seems nice.

msAimDelay: the milliseconds delay between each step when "walking" to the firing position (less = faster), 10 seemed good here.

PulsateAmount: how many times the phaser needs to pulse when firing - I picked 20.

msPulsateDelayBright: the milliseconds delay while "firing" before going to a darker color (less = shorter), 60 seemed good.

msPulsateDelayDarker: the milliseconds delay while "firing" before going to a brighter color (less = shorter), 40 seemed good.

Since you may want to tweak this as well, I've defined 3 values (didn't want to add even more parameters to the function);

DimmingPhaserAim: the amount the outer LEDs will dim while aiming

DimmingShoot: the amount the outer LEDs will dim when firing

DimmingPulsing: the amount the outer LEDs will dim when pulsating while firing.

Note: When the phaser is made of an odd number of LEDs (for example "3"), then the middle LED will be the bright one.

When the [haser is made of an even number of LEDs (>3) then the middle 2 LEDs will be bright.

I'll try to post 2 videos (I lack the super cool Enterprise model), one normal and one diffused (I just held some toilet paper above it).

So here my code, let me know what you think ...

#include "FastLED.h"
#include <EEPROM.h>
#define NUM_LEDS 60
CRGB leds[NUM_LEDS];
#define PIN 6
void setup()
{
  FastLED.addLeds<WS2811, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
  randomSeed(analogRead(0)); // for a better random
}
void loop() 
{
  startrek_phaser( 0xff, 0x90, 0, -1, 4, 4, 10, 20, 60, 40); // TargetLED = -1 = random pick
  delay(1000); // delay between phase shots
}
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;
  
  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);
    
  }
}
// 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
 Hans
(@hans)
Famed Member Admin
Joined: 11 years ago
Posts: 2805
Topic starter  

Here the videos - it took me some effort. The videos I recorded were 4K, and became to big to post. So I had to downsize them to 1080p.


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

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

And the INO file for the Arduino IDE ...


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

Hi Hans,

I don´t know what to say. Really, I´m speechless!

It is exactly what I was looking for and even more. To be able to set various parameters is great (had some funny color issues by tweaking them too hard).

Compared to my quick and dirty, copy and paste sketch, yours is a lot of clever and hard work. Many thanks for that!

There are two additional things I would like to implement.

Which line I can change to have the LED not stay on after pulsing? So after the pulsing the LED goes off. But it is not essential.

The second things is, the code is so complex, I don´t know where to put a push button command and how to have the effect play like 3 times after pushing the button?

It would be nice to push a button, have the effect play 3 (or so) times and after pushing it again, have the effect play again for 3 times. Will it still be shooting at random places then?


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

Hi Trace,

glad to hear you like the code 

Like I said: it was a fun little project, and if fully functional, maybe I'll add it to the LED effects article.

As for your questions;

1) Dark laser after pulsing effect

I did not think about that haha ...
The best place would be to add "setAll(0,0,0);" at the end of the "startrek_phaser()"" function.

So:

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
  ... setAll(0,0,0); // <-- add this just before the last accolade
}

2) Where to put the push button

Well, the best way would be in the "void loop()" function - this is where you'd usually do things. 

Start by pretending the "startrek_phaser()" function code does not exist and implement a push button activity as you'd normally would do.

Then when the button gets pushed, call the "startrek_phaser()" function 3 times, or make a short for-loop that calls "startrek_phaser()" function 3 times.

For example, start with this push-button example for the Arduino and slightly modify it to respond to a button push (seeing the button being released as the "push"), so you'll get something like the code below. Note: I removed the ledPIN from that example, since we do not use it here.

...
// constants won't change. They're used here to set pin numbers:
#define buttonPin 2; // the number of the pushbutton pin
int buttonState = 0; // variable for reading the pushbutton status
... void setup() {
  ...
  // initialize the pushbutton pin as an input:
  pinMode(buttonPin, INPUT);
}
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) {
    // turn phaser on 3x:
    startrek_phaser( 0xff, 0x90, 0, -1, 4, 4, 10, 20, 60, 40); startrek_phaser( 0xff, 0x90, 0, -1, 4, 4, 10, 20, 60, 40); startrek_phaser( 0xff, 0x90, 0, -1, 4, 4, 10, 20, 60, 40);
  } 
}
...

So all combined and untested (bold is what I have added) you should get something like this:

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

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

}
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) {
    // turn phaser on 3x:
    startrek_phaser( 0xff, 0x90, 0, -1, 4, 4, 10, 20, 60, 40);
    startrek_phaser( 0xff, 0x90, 0, -1, 4, 4, 10, 20, 60, 40);
    startrek_phaser( 0xff, 0x90, 0, -1, 4, 4, 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;
  
  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);
}
// 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();
}

Hope this helps!

Are you actually having or building a Enterprise model?


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

Hi Hans,

again all I can say is THANK YOU!

I
really like your structure of Loop and Void. Have the function in a void
and call it in the loop, makes the pushbutton function easy.
Yesterday
I was trying to add the pushbutton within the void and failed. I´m
still thinking too difficult to get the right solutions.
But your replies are really good stuff to learn from.

In your code was a little syntax error ( ; after define pushbutton). But then it worked flawless.

I also added brightness ( less brightness is better for testing or it will burn your eyes :D ) and put a lil delay after every shoot (changes are bold). Now it is spot on.

#include "FastLED.h"
#include <EEPROM.h>
#define NUM_LEDS 60
CRGB leds[NUM_LEDS];
#define PIN 6
#define buttonPin 2     // the number of the pushbutton pin (removed syntax error ; )
int buttonState = 0;     // variable for reading the pushbutton status

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);
}
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) {
    // 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;
 
  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();
}

And you helped me more than I could ever expect. THANKS!!!

Depending on how much leisure time I will have this year, I´m going to start building the Enterprise D from AMT in 1/1000.

If you want to see some of my projects, you can just take a look at my youtube channel:

Trace Berlin


From now on, I will mention you and your forum in my next building videos.


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

Hi Trace!

You're welcome!
I'm happy to hear you've got it to work as you wanted it, and good to hear my explanation is helpful for you (if you're interested; I did write an easy to read intro to programming on the Arduino - sorry for the typo haha, excellent that you figured it out yourself.
And ... I VERY much appreciate mentioning my website with your projects/YouTube channel - that is very helpful for me! 

As for the "loop" and "setup" functions; this is the standard approach for every Arduino sketch.
"setup" is ran only once, at startup, and "loop" will keep running and repeating until you power down the Arduino.

I like to keep both as clean a possible, and implement functions (like the startrek_phaser) to separate. This way I can use them in a relatively easy and easy to follow way.

Adding brightness is a good option too. I'm guessing that picking a less bright color would do the trick as well. Worth a try.

Keep us posted here on your project! I love Star Trek, so I'd be very interested to see how things are going with your project(s).
Having free time is an issue ... I know hahah ... 


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

Hi Hans!

I will take a closer look at your tutorial about programming, cause I like your art of programming and the way you explain things.

The "loop" and "setup" is clear. But I very often read sketches with a single void and some parts of the sketch are written in the void, some in the loop. That way it is very difficult to understand such code.

I´m sure I will need help from you and the forum in the future. Cause I also want to combine our great phaser sketch with sound (DFPlayer mini). The challange will be to push a button, have a soundfile played (computer beep as a "button pressed" feedback) then the phaser sketch will start with the phaser sound.
In a much easier code, I already got this working (just combined two online found sketches).

And another effect could be a warp jump. The engines are glowing with a steady color and after pushing a button, the light gets bright with a white flash and is dimming down again. With variable speeds for the fade in, flash and fade out.
I also got this working (code also found online), but with normal LED´s, which is easier but not that versatile in contrast to WS2812.

When you like Star Trek, you hopefully will like my 2009 Enterprise videos and the Deep Space Nine video.


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

Thank you for the compliments! 

Developers that only one "void" should probably learn to work a little cleaner, but that is just my opinion.
The Arduino "standard" dictates both "setup()" and "loop()" as the functions that always exist.

I was already wondering about the sound haha. I had never heard of DFPlayer mini - but did find them dirt cheap at AliExpress (here and here).
I may order a few of those. €1 is not much! And at Amazon.de they can be had cheap as well - but from the comments there I see one has to be careful what version to get.
I did find an excellent guide for this by the way at DFRobot.com.
One of these days I should get one ... and a speaker with that haha.

Sounds like a major (cool) project you're working on.

I'll take a look at your videos for sure!


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

Hi Hans!

Thanks for subrscribing on Youtube.

You have never heard about the soundmodule? You will like it. It can also be used as a standalone solution. That is what I did before Arduino. You only need Voltage, two buttons and a speaker.
Never heard about different versions. Maybe you have seen the older and bad working WTV020. Don´t buy this one!

The module number of the DFPlayer mini is MP3-TF-16P. Then you will have the correct one.

I can send you a working LED-effect with sound code if you want. It is again a Star Trek related code for lighting a Klingon Bird of Prey.


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

You're welcome 

I've heard about sound modules before, back in the day when they would hack those postcards, that make sound when you open them. But not like this one.
Where did you get yours? When I Google "DFPlayer mini MP3-TF-16P" I still get the feeling that most of them are the "cheap" knock off models.
Having had experience with "fake" Arduino's, Ethernet shields, and other "fun" stuff, I'd rather spend €4 on one well working module than €12 on 5 not so great modules haha 

For sound + phaser, we'd have to figure a way to keep things in sync, but then again this may not be as complicated, we will see 
Let me first see that I get one of those modules. If I read the module specs right, this may actually be pretty simple to do ... or not haha.


   
ReplyQuote
Page 1 / 15
Share: