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 Reactions
3,865 Views
(@trace)
Estimable Member
Joined: 5 years ago
Posts: 170
Topic starter  

Posted by: @trace

@hans Oh no, not another mysterious bug. Slowly but surly you can hire me as a bug finder 🤣 And now that you have mentioned it, sometimes, it freezes Firefox on my side too.

Hi Hans, any news? Or should I just try to post code again?

 


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

@hans Hi Hans, as I can see, the Forum works again. All previous Posts are visible now, with code. Do you think we can renew this topic, so that people can work this out with us? Or is it just a thing between you and me again? :D


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

Apologies Trace for the late/slow repsonse - it's been a week 😉 

I found where the bug in the forum is, but so far WPForo has not been very active in resolving the issue. It affects a paid plugin, which I have disabled for now.
Please feel free to renew the topic 😁 


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

@hans Hi Hans, no need for apologies. I dont want to push you our anyone else.

Too bad to hear that the problem is caused by a paid plugin. Normally you pay to have less problems 🤣 

So, how to renew this topic? Maybe I should start easy and make clear, what I want.

The first thing is, to be able to define animation colors by push button presses, not by writing it directly into the animation itself.

Here is your modified NewKitt animation. I wrote some nodes in it. As you can see, in your code, the color is defined by directly writing it into the animation. What I want is, to have this as a variable, which is then defined by different button presses.

I need to add the code as ino file. Using the "embed code" function, still freezes the page :(


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

Hi Trace!

Oh man, I have no idea where the days seem to go. Almost a week later now .... and I really meant to reply right away.
And yes: normally one would pay to have less problems. If I only could find a more reliable forum for Wordpress. 😞 

First thought that popped in my head is by using global variables for the color definitions, and use an interrupt (when a button is being pressed) that calls for a function that changes these global variables. Since the effects reads these global variables, instead of the passed on parameters, the change should be visible almost instantly.

So basically you'd define something like this in the beginning:

...
#define PIN 6
const int Coin_button_Pin = 3;  // the number of the pushbutton pin
int buttonState = 0;            // variable for reading the pushbutton status


...
// option 1: use CRGB
CRGB effectColor;

// option 2: use 3 bytes
byte effectColorRed;
byte effectColorGreen;
byte effectColorBlue;

Using CRGB seems more appropriate, but using 3 bytes works just as well and may be easier to understand and work with - depending on your preferences and experiences.

The interrupt can be set, like I've done in the second LED Effects project.

It works something like this, where BUTTON is the pin number used for your button, and "changeEffect" the name of the function that is being called when the button is pressed:

void setup()
{
  ... // first your usual setup steps

  pinMode(2,INPUT_PULLUP); // internal pull-up resistor
  attachInterrupt (digitalPinToInterrupt (BUTTON), changeEffect, CHANGE); // pressed
}

The change function could look something like this:

void changeEffect() {
  if (digitalRead (BUTTON) == HIGH) {
    // change colors here to something, for example:
    effectColorRed = 123; 
    effectColorGreen = 123;
    effectColorBlue = 123;
  }
}

 You'll have to play a little with this to see how well this does, or does not, work.
There are most certainly some downsides to using interrupts like this, and also keep in mind that an Arduino was never designed to do some sorts of multitasking.

Having said that ... multitasking can be addressed by multi-core hardware like the ESP32 (cheaper than an Arduino, yet compatible with an Arduino, powerful, comes with more memory, more speed, wifi, etc - an article on how that works).

I've played with its smaller sibling, the ESP8266, for a bit and have to say: I'm very impressed and I'll probably never buy an Arduino again. I have an ESP32 ready to play with, but it's been laying on my desk for almost a year now. Just not having enough time in a day to get to it 😁  -- but I'd be willing to explore it together now that I have even more motivation

Anyhoo - let's see how well Interrupts work for you first 😊 

 

 


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

For to mention that you have to modify the effects as well of course ... (assuming the 3 bytes to define the global colors)

For example this old code section (there are more sections):

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

  ...
  OutsideToCenter(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  CenterToOutside(red, green, blue, EyeSize, SpeedDelay, ReturnDelay);
  ...
}

void CenterToOutside(byte red, byte green, byte blue, int EyeSize, int SpeedDelay, int ReturnDelay) {
  ...
    setPixel(i, red / 10, green / 10, blue / 10);
    for (int j = 1; j <= EyeSize; j++) {
      setPixel(i + j, red, green, blue);
    }
  ...
}

Will have to be changed so it doesn't take color parameters any more (ditto when calling the function), and of course using those colors:

void InsertCoin(int EyeSize, int SpeedDelay, int ReturnDelay) {

  ...
  OutsideToCenter(EyeSize, SpeedDelay, ReturnDelay);
  CenterToOutside(EyeSize, SpeedDelay, ReturnDelay);
  ...
}

void CenterToOutside(int EyeSize, int SpeedDelay, int ReturnDelay) {
  ...
    setPixel(i, effectColorRed / 10, effectColorGreen / 10, effectColorBlue / 10);
    for (int j = 1; j <= EyeSize; j++) {
      setPixel(i + j, effectColorRed, effectColorGreen, effectColorBlue);
    }
  ...
}

 

 


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

@hans Hi Hans and no worries about your late reply. There are more important things than playing with code for a power rangers toy ;)

Thanks for your code examples. I like the 3 byte method more. As you said, its easier to understand and select colors. Im sure I could get this working.....but.....I think I should make clear again what I want. Otherwise it would get very complicated.

The toy has 3 buttons for color selection. There are metal coins with nubs at different places. You insert a coin and the nubs are getting pressed against those buttons. For example: the red coin pushes against button 1, the yellow coin pushes against button 1 and 3, the blue coin pushes against button 2 and 3....and so on.

Difficult for me is to find out, how to make arduino read not just one button, but different button combinations for selecting a color. When I tell arduino to read button 1 it sets the color to red. But when I tell arduino to read button 1 AND 3 its not going to be yellow, becaus reading button 1 means red and button 3 is also part of the blue color selection.

Here is a video of the toy and what I want to achieve. At 7:40 you can see the nubs at the back of the coin. At 10:25 you can see the coin getting inserted and the coin recognition animation. At 10:45 the toy opens and you see the main animation. The toy also makes lights and noises when buttons are released again. So it would be great to get this too. That means, arduino has to read buttons when they get pressed (and hold) and when they are released.

But at first, it would be nice to have a solution for the multiple button color selection thing :D Then I can experiment with your interrupt solution.

And by the way, I think there is no need for multitasking, because all effects are played for themself.

https://www.youtube.com/watch?v=CxdrjpmaEjg

This post was modified 11 months ago by Trace

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

Ah I see. 😊 

You cannot put an interrupt on all these 3 buttons/switches - that would become a mess and wouldn't produce the desired effect.

How about having is one switch (a 4th switch if you will) that is always triggered when a coin is inserted.
For example in the center of the coin.
This can then trigger the interrupt and read the 3 pins for the other switches in the "changeEffect" function?

Or is that not an option either?

Note: While trying to see what I could find, I did run into this article, which may or may not be helpful. I found it rather cumbersome to read. Thought I'd mention it anyway 😉 


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

@hans So the 4th button just triggers the interrupt and then within the interrupt, I can read the 3 buttons pressed (or not pressed) by the coin? Because the 3 button thing is necessary due to the original coins.

How do I set this up?

Then I can try to understand what is written in the article you have mentioned and maybe get my head wrapped around it.


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

@hans Here is what I thought could work as a color selection:

 

#include <FastLED.h>


#define LED_PIN 1
#define LED_COUNT 48


CRGB leds[LED_COUNT];


#define BUTTON_1 2
#define BUTTON_2 3
#define BUTTON_3 4


CRGB currentColor = CRGB::Black;

void setup() {

  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, LED_COUNT);


  pinMode(BUTTON_1, INPUT_PULLUP);
  pinMode(BUTTON_2, INPUT_PULLUP);
  pinMode(BUTTON_3, INPUT_PULLUP);
}

void loop() {

  bool button1 = digitalRead(BUTTON_1) == LOW;
  bool button2 = digitalRead(BUTTON_2) == LOW;
  bool button3 = digitalRead(BUTTON_3) == LOW;

  if (button1 && button2) {
    currentColor = CRGB::Red;
  } else if (button1 && button3) {
    currentColor = CRGB::Yellow;
  } else if (button2 && button3) {
    currentColor = CRGB::Blue;
  } else if (button1) {
    currentColor = CRGB::Green;
  } else if (button2) {
    currentColor = CRGB::Pink;
  } else if (button3) {
    currentColor = CRGB::White;
  } else {
    currentColor = CRGB::Black;
  }

  for (int i = 0; i < LED_COUNT; i++) {
    leds[i] = currentColor;
  }

  FastLED.show();
}

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

This is my 7th attempt to post a reply - I found that certain ads screw up the forum. Oh well. 

Back to the Power Rangers.

So ideally you'd want the 3 buttons "in position" when firing the interrupt, so reading the 3 buttons gives us the correct answer. There are several ways we can do this, I'm sure, but for testing I'd use a separate button. I'd also assume that the color remains as long as the coin is inserted. So maybe we can use that at a later time.

To get an interrupt going, you'd need to set it up in "void setup()", so the Arduino knows what function to call when the button changes state.
Looking at your code, assuming you indeed want to use LOW instead of HIGH, then you could do something like this.

Note: at a later time we can look at a more elegant way to read the buttons.

#include <FastLED.h>


#define LED_PIN 1
#define LED_COUNT 48


CRGB leds[LED_COUNT];


#define BUTTON_1 2
#define BUTTON_2 3
#define BUTTON_3 4

#define BUTTON_4 5 // random number, may want to pick a better pin if needed


CRGB currentColor = CRGB::Black;

void setup() {
  FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, LED_COUNT);

  pinMode(BUTTON_1, INPUT_PULLUP);
  pinMode(BUTTON_2, INPUT_PULLUP);
  pinMode(BUTTON_3, INPUT_PULLUP);
  
  // steps to setup the Interrupt for BUTTON_4
  pinMode(BUTTON_4,INPUT_PULLUP); // internal pull-up resistor
  attachInterrupt (digitalPinToInterrupt (BUTTON_4), changeEffect, CHANGE);
  
  // start with all LEDs black
  fill_solid(leds, LED_COUNT, CRGB::Black); // FastLED build-in function
  FastLED.show();
}

void loop() {
  // you could do something here or do a tiny delay here or nothing at all
}

void changeEffect(){
  bool button1 = digitalRead(BUTTON_1) == LOW;
  bool button2 = digitalRead(BUTTON_2) == LOW;
  bool button3 = digitalRead(BUTTON_3) == LOW;

  if (button1 && button2) {
    currentColor = CRGB::Red;
  } else if (button1 && button3) {
    currentColor = CRGB::Yellow;
  } else if (button2 && button3) {
    currentColor = CRGB::Blue;
  } else if (button1) {
    currentColor = CRGB::Green;
  } else if (button2) {
    currentColor = CRGB::Pink;
  } else if (button3) {
    currentColor = CRGB::White;
  } else {
    currentColor = CRGB::Black;
  }

  fill_solid(leds, LED_COUNT, currentColor);
  FastLED.show();
}

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

@hans I had to write more than one reply too.

Yes, the color stays the same as long as the coin is inserted. So the coin does nothing more than selecting the color for every following led animation. My goal is to have a lil animation when the coin gets inserted, but then goes back to black. When you then press another button, the main animation starts with its selected color and stops when this button is released.

Can you explain why we need the interrupt? My previous code with if_else works just fine. But your code does not work at all?!

Do you know wokwi? I use it as a breadboard. Unfortunately I cant post any links to it, cause your forum thinks it is spam. So I try to write the link in text. The first link is my previous code without interrupt. And the second link is your code with interrupt.

https://wokwi.com/projects/383766773705810945    <- my code

https://wokwi.com/projects/383766374082997249    <- your code

 

You can hit the green play button and then switch buttons at the dip-switch. You can also change the code and save it.

And the reason why your code does not work, could be the wokwi tool of course. I just dont have an arduino here right now to test your code in real life.

This post was modified 11 months ago 2 times by Trace

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

Seems the Forum and Google Ads conflict somehow. 😞 

Anyhoo - you're right; the interrupt may not be needed.
Maybe I made it more complicated than it needs to be indeed 😊

The general idea was to do something else in "void loop()", that is not related to the LEDs.
The interrupt would make sure that the button changes are detected, no matter what you do in the main loop.

However, it's a very valid point that you code should do the trick, if this is the only thing the Arduino has to do.
Apologies for going overboard 😁 

I do know Wokwi indeed - fun for some basic testing for sure, and the links work (not sure why this forum would flag that as spam - if only I could find an alternative forum).

Having said that: my code may not work for several reasons, maybe because Wokwi doesn't support hardware interrupts?


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

@hans Maybe there are just a few minor bugs in the forum but I am the one who discover them. Could Bugfinder be a superhero name? 🤣 

It could be possible that wokwi does not support a few things. But I got a new arduino here, so I can test everything in real life.

Maybe we need the interrupt function. Because I think it will get complicated soon. I like to works in sections. So I can understand them better and add more and more to it. So lets just try to use my color selection part for now.

For example: How to combine the button selection I have written, with a LED effect in here:

Red, green and blue is not possible anymore. But exchange them with "currentColor" also does not work of course.

void CenterToOutside(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);
}

 

 

This post was modified 11 months ago by Trace

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

Working in chuncks is always a good approach - this is what I do myself as well. Start with basic building blocks and make sure they work before combining them 😊 

currentColor can still be used, like so (if I'm not mistaken): replace "red" with "currentColor.red".
So the code would look something like this:

void CenterToOutside(int EyeSize, int SpeedDelay, int ReturnDelay) {
  for (int i = ((NUM_LEDS - EyeSize) / 2); i >= 0; i--) {
    setAll(0, 0, 0);

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

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

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

or if you're lazy and would like to avoid typos:

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

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

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

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

(untested code as usual)

😊 


   
ReplyQuote
Page 2 / 5
Share: