Programming 20 minutes fade sequence for LED array

Dear Arduino Community,

I am currently working on an art installation that utilises 16 led strips (LinearZ 52 toshiba ssc led strip Zhaga Sunlike). These run off 4 led drivers (Meanwel LCM-60 230v)- 1 driver for four strips. The drivers have a pwm modulation option and so I am using a single arduino nano (chinese clone) to modulate all of them with 1pwm pin each.

the idea is to create a compostion for the lights that fades them in and out, leaves them at different opacities, strobes,... basicaly creates various light intensities that change over fixed period of time. I imagine this to be a 20 minute loop.

i tryied various ways of going around this but it only worked partially (which is confusing) or not at all (which is also confusing:). First I attempted nested seqence of if / else if / else if / else if / ... but it only seems to work for first few elses and than it doesnt (which i dont get). than i tried creating various functions (i hope this is the right term?) that would be called from outside the void loop () to make the code more concise, but to no vail.

and now im just stuck :stuck_out_tongue:

I am attaching the code i came up with this far, together with picture of the hardware for wiing for illustration.
I can confirm that arduino can control the leds' fading (but for some reason cant bring it all the way down to turn it off, which is nevertheless a minor issue now) but i cant get it to do the sequence correctly.

can anyone please suggest a solution?
thank you very much!

code for my if - else if - else if aproach that worked at the beggining but didnt when i added more time sequenceses

#define strip1 3
#define strip2 5
#define strip3 6 
#define strip4 9

int brightness = 0;    // how bright the LED is
int fadeAmount = 1;    // how many points to fade the LED by
unsigned long currentTime;


void setup() {
  
    pinMode (strip1,OUTPUT);
    pinMode (strip2,OUTPUT);
    pinMode (strip3,OUTPUT);
    pinMode (strip4,OUTPUT);
    Serial.begin(9600);
}

void loop() {

  currentTime = millis();
  
  analogWrite(strip1, brightness);
  analogWrite(strip2, brightness);
  analogWrite(strip3, brightness);
  analogWrite(strip4, brightness);


if (currentTime >= 0 && currentTime <=15000) {  // fades leds in and out for 150seconds
    brightness = brightness + fadeAmount;
    if (brightness <= 0 || brightness >= 255) {   
        fadeAmount = -fadeAmount;
      }
    delay(10);
  }
  
else if (currentTime > 15000 && currentTime <=30000) {  // fades leds in and out FASTER for another 150sec 
  int fadeAmount2 = fadeAmount*4;
  brightness = brightness + fadeAmount2;
  if (brightness <= 0 || brightness >= 250) {  
        fadeAmount2 = -fadeAmount2;
    }
  }

else if (currentTime > 30000 && currentTime <=45000) {  // same as above, stays at maximum brightness. i didnt continue further
  int fadeAmount2 = fadeAmount*4;
  brightness = brightness + fadeAmount2;
  }
  
  Serial.println (currentTime);
}

code for the functions approach

#define strip1 3
#define strip2 5
#define strip3 6 
#define strip4 9

unsigned long currentTime; 
int output;
int brightness = 0;
//int fadeAmount = 5;

void setup() {
  
    pinMode (strip1,OUTPUT);
    pinMode (strip2,OUTPUT);
    pinMode (strip3,OUTPUT);
    pinMode (strip4,OUTPUT);
    Serial.begin(9600);
    
}
int time1 () {    //function 1 

     int fadeAmount = 1;
     brightness = brightness + fadeAmount;
 
  if (brightness <= 0 || brightness >= 255) {
     fadeAmount = -fadeAmount;
     delay (50);
  }
    
     return brightness; 
} 

int time2 () {  // function 2

     int fadeAmount = 5;
     brightness = brightness + fadeAmount;
 
  if (brightness <= 0 || brightness >= 255) {
     fadeAmount = -fadeAmount;
     delay (10);
  }
    
     return brightness; 
} 
void loop() {

 currentTime = millis();

 if (currentTime >= 0 && currentTime <= 10000) { //call function 1
 output = time1;
 }
 
 if (currentTime > 10000 && currentTime <= 20000) { //call function 2
  output = time2;
 }
 
 Serial.println (currentTime);
 
 analogWrite (strip1, output);
 analogWrite (strip2, output);
 analogWrite (strip3, output);
 analogWrite (strip4, output);
 
  
}

thanks for any comments to my approaches or even to suggesting a completely dufferent appraoch.
im all ears :slight_smile:

Where did you see that these LED drivers can be controlled with PWM.
I only see a DALI interface mentioned (no experience with that).
Leo..

You definitely need to look into arrays (you're using numbers in variable names, that's a sign you need arrays).

You may also want to look into structs, where you can bundle a bunch of variables into a single one (and that in turn can be used in an array). This way you can set for each strip the current state - brightness, maybe a fade rate, or whatever makes sense.

In your program you then iterate over the array setting the different strips to their required brightness.

A separate loop would read the timed sequence and update those parameters as needed.

+1 karma for using code tags in your first post.

code for my if - else if - else if aproach that worked at the beggining but didnt when i added more time sequenceses

Important tip: never say things like "didn't work" or "to no avail" on this forum, it drives everyone crazy. Instead, you must describe what you wanted or expected to happen and what actually did happen. Then we have a chance to understand the problem and suggest solutions.

That said, I did spot this:

else if (currentTime > 30000 && currentTime <=45000) {  // same as above, stays at maximum brightness. i didnt continue further

It's possible that times over 32,000 are causing a problem. Try putting "45000UL" instead of "45000". Get into habit of doing that for any number that gets compared with millis().

And this

output = time1;

When calling a function, you must use brackets, like this:

output = time1();

Bit silly helping OP with code for the wrong hardware.
I doubt that mosfet/PWM will work with these CC supplies.

Dali controller.
Leo..

Wawa:
Bit silly helping OP with code for the wrong hardware.
I doubt that mosfet/PWM will work with these CC supplies.

OP claims theirs can be dimmed that way:

mrchefiadegabinete:
I can confirm that arduino can control the leds' fading (but for some reason cant bring it all the way down to turn it off,

Depending on the actual circuit used, PWM will work on constant current supplies (switching it on and off real fast). It may still be a terrible idea, though: the internal components may get totally stressed out and as a result die young. Stress is generally not a good thing. Especially capacitors can get pretty upset having to deal with PWM signals.

Data sheet
3 in 1 dimming function
https://www.meanwell.com/Upload/PDF/LCM-60(EO)/LCM-60(EO)-SPEC.PDF

‧Output constant current level can be adjusted by applying one of the three methodologies between DIM+ and DIM-:
0 ~ 10VDC, or 10V PWM signal or resistance

If that LED supply can be controlled three ways (resistive/voltage/data), then switching the DIM pins with an opto coupler would be much better than switching the LED string with a mosfet (for which that supply is not designed for).
I did not see the resistive/voltage dimming option in the .pdf that OP had attached.
Leo..

You need to develop programs in small, incremental steps.
Start with one channel only.
Use a single led and resistor on one output PWM pin.
Use a simple test routine like the one below and get the resistor and led to function.

//Initializing LED Pin
int led_pin = 6;
void setup() {
  //Declaring LED pin as output
  pinMode(led_pin, OUTPUT);
}
void loop() {
  //Fading the LED
  for(int i=0; i<255; i++){
    analogWrite(led_pin, i);
    delay(5);
  }
  for(int i=255; i>0; i--){
    analogWrite(led_pin, i);
    delay(5);
  }
}

Now, you need to decide to either get all your hardware working or develop your program for one channel. Get that working. Then expand to four, both in code and in hardware. Change one thing and a time. Change two things and if it doesn’t work, you don’t know what you did wrong.

Looking at one of your sections of code, let’s go line by line:

if (currentTime >= 0 && currentTime <=15000) {  // fades leds in and out for 150seconds
    brightness = brightness + fadeAmount;
    if (brightness <= 0 || brightness >= 255) {   
        fadeAmount = -fadeAmount;
      }
    delay(10);
  }

Two points about comparing the value returned by millis():

  1. There are 1000 milliseconds in a second so a count of 15000 is only 15 seconds, not 150.
  2. Millis() returns a value that increments to 2^32 before repeating. That’s 49.7 days, which is 4,294,967,296. milliseconds. You have use a second time value that offsets the value returned by millis() for this to work on your desired cycle.

Brightness is declared as an integer which means it can be a value between -32767 and 32768 and since you never reset it, that’s the range it counts through which is probably not what you want. The upper 8 bits bits get thrown away when the analogWrite() function is called so it may kind-of-sort-of looks like it works.

I’m not actually sure what it will do with respect to the brightness and the range at which it changes, I can just see that using an integer and than using that 16 bit value for a function call that only uses an 8 bit bit value will usually result in not what you expected. It is something that C and C++ will typically complain about but the Arduino environment hides this behavior known as type checking to make the language easier to use.

Thank you for all your answers! much appreciated!
ill reply to each of you in its own post

PaulRB:
+1 karma for using code tags in your first post.
Important tip: never say things like "didn't work" or "to no avail" on this forum, it drives everyone crazy. Instead, you must describe what you wanted or expected to happen and what actually did happen. Then we have a chance to understand the problem and suggest solutions.

thanks! ill keep that in mind! :slight_smile:

PaulRB:
That said, I did spot this:

else if (currentTime > 30000 && currentTime <=45000) {  // same as above, stays at maximum brightness. i didnt continue further

It's possible that times over 32,000 are causing a problem. Try putting "45000UL" instead of "45000". Get into habit of doing that for any number that gets compared with millis().

can you please tell me what the UL stand for? should i just use it in everywehre where i count millis? if so can you explain me why? ive never came across this.

PaulRB:
And this

output = time1;

When calling a function, you must use brackets, like this:

output = time1();

thanks! good point :stuck_out_tongue:

WattsThat:
You need to develop programs in small, incremental steps.
Start with one channel only.
Use a single led and resistor on one output PWM pin.
Use a simple test routine like the one below and get the resistor and led to function.

//Initializing LED Pin

int led_pin = 6;
void setup() {
 //Declaring LED pin as output
 pinMode(led_pin, OUTPUT);
}
void loop() {
 //Fading the LED
 for(int i=0; i<255; i++){
   analogWrite(led_pin, i);
   delay(5);
 }
 for(int i=255; i>0; i--){
   analogWrite(led_pin, i);
   delay(5);
 }
}

WattsThat:
Now, you need to decide to either get all your hardware working or develop your program for one channel. Get that working. Then expand to four, both in code and in hardware. Change one thing and a time. Change two things and if it doesn’t work, you don’t know what you did wrong.

thanks! that does make sense

WattsThat:
Looking at one of your sections of code, let’s go line by line:

if (currentTime >= 0 && currentTime <=15000) {  // fades leds in and out for 150seconds

brightness = brightness + fadeAmount;
   if (brightness <= 0 || brightness >= 255) {  
       fadeAmount = -fadeAmount;
     }
   delay(10);
 }



Two points about comparing the value returned by millis():

1) There are 1000 milliseconds in a second so a count of 15000 is only 15 seconds, not 150.
2) Millis() returns a value that increments to 2^32 before repeating. That’s 49.7 days, which is 4,294,967,296. milliseconds. You have use a second time value that offsets the value returned by millis() for this to work on your desired cycle.

Brightness is declared as an integer which means it can be a value between -32767 and 32768 and since you never reset it, that’s the range it counts through which is probably not what you want. The upper 8 bits bits get thrown away when the analogWrite() function is called so it may kind-of-sort-of looks like it works. 

I’m not actually sure what it will do with respect to the brightness and the range at which it changes, I can just see that using an integer and than using that 16 bit value for a function call that only uses an 8 bit bit value will usually result in not what you expected. It is something that C and C++ will typically complain about but the Arduino environment hides this behavior known as type checking to make the language easier to use.

yes, my bad about the millis. i do get the maths ussualy :stuck_out_tongue:
2nd point - so i shall reset brightness at the end of each for loop? i was expeecting it to only move within the 0-255 range as i set it up that way in for loop. or am i missing something here?
3rd point about 8bit and 16bit. yes i do declare brightness to be int as i gathered pwm value is expected to be int. i am unshure about how that realates to 8 or 16bit registers... but if there is something i can do to programe it better please do let me know.
thank you!

Wawa:
If that LED supply can be controlled three ways (resistive/voltage/data), then switching the DIM pins with an opto coupler would be much better than switching the LED string with a mosfet (for which that supply is not designed for).
I did not see the resistive/voltage dimming option in the .pdf that OP had attached.
Leo..

hey leo.
yes it can be dimmed and the mosfets do work. nevertheless, do you reckon opto coupler would perform significantly better? would you be able to reccommend particualr type? also i need to dim four of them. should i get four or are there ways of dimming it with one large coupler?

"UL" stands for "Unsigned Long" and indicates the value should be treated as a 32-bit unsigned integer. Yes, is a good idea to use it everywhere you are comparing a value to millis(), as I said before. If you don't, the value might be treated as a 16-bit signed integer, which can only hold values between -32768 and +32767.

Dimming a Meanwell LED driver with an opto coupler is all over this forum.
Try those key words in the search field on top of this page.
Here's one of them.
Leo..

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.