one element by loop() loop turn
i think i found my answer here
Chasing LEDs millis
So what your saying is to have your code with minimal blocking using millis to limit its availablility to the main loop?
void loop() {
Constantly refresh/show updates,
Use millis as switch to limit blocking code run time. (for loops in here)
Use millis as second switch to limit blocking code run time (for loops in here)
Why "limiting" blocking code with millis or anything else?
Why not get rid of the blocking code altogether ?
What do you want that for loop to do ?
If there is nothing in the body of a for loop to block its execution then it is OK to use it
Ok so i have an
arrayofleds = 1,2,3,4,5..,12
is should say
int i =0;
every x milliseconds (if i > ((/sizeof arrayofleds)-1)
{
i+1;
};
every x milliseconds UpdateLEDS[i]
for(int j = 1; j <= LightWidthFix; j++) { ///Fill LEDS between two points
leds[i + j].setRGB(red, green, blue);
}
That for loop should be finding the leds between I (First LED) and J (Last LED) and Updating the colour values. but because the LED's are in a circle they overlap the array size at the begining and end of the cycle meaning basic math wont give me usable numbers (It exceeds the array size negative and possitive)
where is than
part of this if
?
It is a TWO DIFFERENT PROBLEMS.
Let's choose the some basic index - the led, which will be a starting point of your color sequence.
So all your code can be divided to two part:
-
Incrementing basic index every NNN mS of time - it can be easily done by each turn of loop() without a
for
cycle -
Calculation of the led numbers, based on basic index - with taking into account the transition through the beginning and end of the cycle and updating its colors.
This task does not depend on the cycle at all and can be framed as a separate procedure
This for
loop doesn't contain delays of another blocking elements, so it have not considered as "blocking" itself and not violate a "non-blocking" paradygm
Consider something like this
const byte ledPins[] = { 3, 5, 6, 9 };
const byte NUM_LEDS = sizeof(ledPins) / sizeof(ledPins[0]);
void setup()
{
Serial.begin(115200);
}
void loop()
{
nextCurrentLed();
}
void nextCurrentLed()
{
static byte count = 0;
const int period = 2000;
const unsigned long currentTime = millis();
static unsigned long startTime = currentTime;
if (currentTime - startTime >= period)
{
Serial.print("current LED number = ");
Serial.println(count);
startTime = currentTime;
nextAndPrevious(count);
count++;
count = count % NUM_LEDS;
}
}
void nextAndPrevious(byte count)
{
Serial.print("previous LED number = ");
Serial.println((byte)(count - 1) % NUM_LEDS);
Serial.print("next LED number = ");
Serial.println((count + 1) % (NUM_LEDS));
Serial.println();
}
I got it working as desired. Thanks for helping me understand Millis more and modulo seems very usefull.
If you see anything in this that you hate or think i should do differently or thanks simply redundant don't hesitate to bring it up.
#include "FastLED.h"
#define NUM_LEDS 12 // Enter the total number of LEDs on the strip
#define PIN 5 // LED signal Pin
int LightWidth = 3; //Set the number of active LED's
int delayDuration = 100;
CRGB leds[NUM_LEDS];
void setup() {
Serial.begin(9600);
FastLED.addLeds<WS2812B, PIN, GRB>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.setMaxPowerInVoltsAndMilliamps(5, 500); // limit power of LED strip to 5V, 500mA
FastLED.clear(); // Init LEDs to "off"
}
void loop() {
//////(int red, int green, int blue, int LightWidth, int delayDuration)
Beacon(204, 136, 0, LightWidth, delayDuration);
}
void Beacon(int red, int green, int blue, int LightWidth, int delayDuration){
int LightWidthFix = LightWidth - 1;
for(int i = 0; i <= ((NUM_LEDS -LightWidth) + LightWidthFix); i++) {
FastLED.clear();
FastLED.show();
leds[i].setRGB(red/10, green/10, blue/10); ///Create Primary Leading LED
int j; ///Create second Trailing LED
if (i < LightWidthFix ) {
j = (i + NUM_LEDS) - LightWidthFix;
leds[j].setRGB(red/10, green/10, blue/10);
}
else{
j = i -LightWidthFix;
leds[j].setRGB(red/10, green/10, blue/10);
}
if ((i>0)&&(i<LightWidthFix)){ ///Fill from Low fix
Serial.println("FILL LOW");
for (int l = i; l >= 0; l--) {
leds[l].setRGB(red, green, blue);
}
}
if ((j<NUM_LEDS)&&(j>(NUM_LEDS-LightWidth))){ ///Fill To High fix
Serial.println("FILL HIGH");
for (int l = j; l < NUM_LEDS; l++) {
leds[l].setRGB(red, green, blue);
}
}
if ((i>=LightWidthFix)&&(j<=(NUM_LEDS-LightWidth))){ ///Fill To Main Cycle
Serial.println("FILL MAIN");
for (int t = 0; t <= LightWidthFix; t++){
leds[j+t].setRGB(red, green, blue);
}
}
FastLED.show();
delay(delayDuration);
}
}
Sorry, did you forget to insert a new code?
I see this everything is the same as before - blocking for
loop and delay.
And this code has no millis at all.
I see a led sequence of four leds
The first led in the sequence might be dim, I don't care, it is the first led. The second led will be the bright led.
There is no need to clear all the leds every time. The fourth led in the sequence turns the led off.
So I put four leds in a sequence and let them rotate around:
// Forum: https://forum.arduino.cc/t/fastled-visual-looping-issue/1134527
// This Wokwi project: https://wokwi.com/projects/366722641131463681
//
// A led sequence of four leds:
// The first is dim
// The second is bright
// The third is dim
// The fourth is off (the default is off)
#include <FastLED.h>
#define NUM_LEDS 12 // Number of NeoPixel leds
#define PIN 5 // Data pin for ledstrip
int index = 0; // index of led at the front
CRGB leds[NUM_LEDS];
CRGB sequence[4] = {CRGB::DarkViolet, CRGB::Violet, CRGB::DarkViolet, CRGB::Black};
void setup()
{
FastLED.addLeds<WS2812B, PIN, GRB>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
FastLED.clear(); // turn all leds off
}
void loop()
{
EVERY_N_MILLISECONDS(150)
{
// put the sequence somewhere on the leds
for(int i=0; i<4; i++)
leds[ToIndex(index-i)] = sequence[i];
// Update the ledstrip
FastLED.show();
// advance index for next time
index++;
if(index >= NUM_LEDS)
index = 0;
}
}
// Bring a number into the range of the array.
// A negative number can not be too large.
// but it will work for this code.
int ToIndex(int i)
{
if(i < 0)
i += NUM_LEDS;
return(i % NUM_LEDS);
}
Try it in Wokwi simulation:
EVERY_N_MILLISECONDS(150)
{
// put the sequence somewhere on the leds
for(int i=0; i<(sizeof sequence); i++)
leds[ToIndex(index-i)] = sequence[i];
Firstly, YOINK ima borrow this code.
Secondly it's more modular if you do this. Then you only need to change the definitions to update the number of leds in sequence.
EDIT: I lied. Millis is crap. I hate everything. :poop:
Fixed it.
int LEDSequence [5] = {CRGB::LightCoral , CRGB::Goldenrod ,CRGB::Goldenrod , CRGB::LightCoral, CRGB::Black};
CRGB sequence[5] = {CRGB::LightCoral , CRGB::Goldenrod ,CRGB::Goldenrod , CRGB::LightCoral, CRGB::Black};
void loop()
{
EVERY_N_MILLISECONDS(150)
{
// put the sequence somewhere on the leds
for(int i=0; i<(sizeof(LEDSequence)); i++)
leds[ToIndex(index-i)] = sequence[i];
// Update the ledstrip
FastLED.show();
That does not fix it. I'm sorry to say, but that code is not good
The normal way is to divide the whole array by the size of an element.
These show both ways to get the element size. They are both okay.
void setup()
{
Serial.begin(115200);
Serial.println(sizeof(sequence)/sizeof(sequence[0]));
Serial.println(sizeof(sequence)/sizeof(CRGB));
See how did you know that CRGB is something to get the size of?
Like i can simply count through CRGB leds[NUM_LEDS];
so why do i need to /sizeof (CRGB);?
Any single variable type, structure or class has a size and can be an object of sizeof()
. Any variable of these types also can be "sized" by this function - so you even don't need to know, what is CRGB - type or instance
The FastLED array is not initialized for certain values.
So it makes sense to do this:
#define NUM_LEDS 12 // Number of NeoPixel leds
CRGB leds[NUM_LEDS];
By doing that, the 'NUM_LEDS' can be used in the sketch.
Suppose that the "sequence" array can be any size, then the code would be this:
CRGB sequence[] = {CRGB::DarkViolet, CRGB::Violet, CRGB::DarkViolet, CRGB::Black};
In the code, the number of elements of the array has to be calculated. It is an array of CRGB things, so the element size is such a CRGB thing.
int n = sizeof(sequence)/sizeof(CRGB);
for(int i=0; i<n; i++)
leds[ToIndex(index-i)] = sequence[i];
That works, and I have my sketch at Wokwi updated for that: FastLED, a led sequence of four leds - Wokwi ESP32, STM32, Arduino Simulator
However, it you like to have 'NUM_SEQUENCE_LEDS' and use that for the array:
#define NUM_SEQUENCE_LEDS 4
CRGB sequence[NUM_SEQUENCE_LEDS] = { ...
That is okay as well. It is less flexible code, but it is good and it works.
i cant believe it took me this long to see the value of millis in led control. It means i can do things like fading an LED over time without other code blocking the execution of the fade causing visual jitter and general unpleasantness.
For example. It allows me to have an animation run every 100 millis but fade an led within that animation every 5 millis.
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.