FadeIn and FadeOut functions - hard

Hello,

im begginer in arduino programming and i am asking for your help. :'( I try to do two functions for fadein and fadeout leds. Actually to fade them or out one by one but the next led to start fading at the half of the time the previously led started.

The parameters of the functions need to contain an array of the led pins and the time for the overal fading, becouse i like the code to be clean.

There is a scheme that im trying to do :confused:

http://forum.arduino.cc/index.php?topic=498033.0

Hi, Welcome to the forum.

Please read the first post in any forum entitled how to use this forum. http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code. It will be formatted in a scrolling window that makes it easier to read.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom.. :)

Hi Tom,

Yes I know its so stupid to ask someone to make the code. I was long ago also software developer. This morning I had an exam and I dont have much time to post the code I writed. Later I will post the scheme and the code. Hopefully someone helps :)

If I read this right, you have a string of LEDs and you want one to start fading when the previous one has faded to 50%?

How many steps do you want in the fade? Does it have to be linear?

I used this as a fade routine in my “Worm” sketch (it makes a little worm run around on a 12x12 field of WS2182 LEDs (neopixels);

 t = 0;
    do
    {
      strip.setPixelColor(Worm[t], RVal * ((float)t / (float)head), GVal * ((float)t / (float)head), BVal * ((float)t / (float)head)); //(fade by t automatically removes tail pixel)
      Worm[t] = Worm[(t + 1)];
      t = t + 1;
    } while (t <= head);

Some explanation;
head is the length of the worm - also the number of elements in the Worm array. Each element in the array holds the pixel number of the LEDs that are in the worm.

I’m using do…while right now but I guess a for() loop would also work.

By multiplying the RGB values of the LEDs by t/head, if head=5, the “tail” pixel is multiplied by 0/5, so is turned off, then the other pixels are multiplied by 1/5, 2/5 etc until the head pixel is at full brightness (5/5).

Don’t forget to use (float) if you defined your variables as int or it won’t work!

As I said, not sure if it’s what you wanted, but something to consider.

I try many for and while variants but without success and still can't get the desired effect without using delay() :confused:

int led1 = 9;           // PWM pin
int led2 = 10;          // PWM pin
int led3 = 11;          // PWM pin
int signalIn = 2;       // Signal pin
int fadeTime = 5000;    // Overal fading time in ms
int readSignal = 0;


void fadeIn(int myArray[], int time){
  int arraySize = sizeof(myArray);
  double interuptTime = time/(arraySize+1);

  /* ?!?? */
  
}

void fadeOut(int myArray[], int time){
  int arraySize = sizeof(myArray);
  double interuptTime = time/(arraySize+1);

  /* ?!?? */
  
}


void setup()
{
  pinMode(signalIn, INPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  //Serial.begin(9600);
  
}

void loop()
{
  readSignal = digitalRead(signalIn);
  
  if(readSignal == HIGH ){
    int myFadeIn[3] = {led1, led2, led3};
    fadeIn(myFadeIn, fadeTime);
  }else{
    int myFadeOut[3] = {led3, led2, led1};
    fadeOut(myFadeOut, fadeTime);   
  }
  
}

Ah...traditional LEDs...I’m using the addressable ones. You’re going to have to be messing with voltages and resistances to control your fade....pthats not something I can help with really, sorry.

Could you use the modern LEDs? They have chips in so give you total control over colour and brightness from a single pin. The link is to my “worm” sketch...is it anything close to what you are looking for?

https://youtu.be/ZxgqMy8Mu58

There’s also somewhere a Knight Rider type sweep light sketch using the same LEDs...maybe that would help?

GreyArea: Ah...traditional LEDs...I’m using the addressable ones. You’re going to have to be messing with voltages and resistances to control your fade....pthats not something I can help with really, sorry.

Could you use the modern LEDs? They have chips in so give you total control over colour and brightness from a single pin. The link is to my “worm” sketch...is it anything close to what you are looking for?

https://youtu.be/ZxgqMy8Mu58

There’s also somewhere a Knight Rider type sweep light sketch using the same LEDs...maybe that would help?

The thing is that i will use this pins to control MOSFETs. The LEDs are only for illustration. Your "worm" its not excatly the same effect i'm trying to make. It needs to fadeIn and stays on 100% until i call the fadeOut function. So if then i call fadeIn pin1,pin2,pin3 to fully ON and then fadeOut pin1,pin3 to fully OFF, the pin2 have to stay ON. if it was a php or javascript, so far i had done it :D

maguss4o: I try many for and while variants but without success and still can't get the desired effect without using delay() :confused:

Look at https://www.arduino.cc/reference/en/language/functions/analog-io/analogwrite/ and https://www.arduino.cc/en/Tutorial/PWM

In the Arduino IDE, the Fade example is under File/Examples/01.Basics/Fade

Then you just have to fade each of brighness1,2 and 3. If, as you say, "if it was a php or javascript, so far i had done it", then a couple of lines to do that shouldn't be a problem.

Yours, TonyWilk

You need to convert a time (in milliseconds) into a PWM value (0..255). If the LED's have to fade in and out in 1 second, then the code would be something like:

#define FADE_DURATION 500.0f
#define LED_PIN 6

unsigned long fade_start, loop_millis;
byte fade_in;

void bounceLED() {

  //Has the bouncing started?
  if (fade_start > loop_millis) return;

  //Calculate percentage of completion (from 0..1)
  float pct = (float)(loop_millis - fade_start) / FADE_DURATION;

  if (pct >= 1) {

    //Fade has completed, set max / min value
    analogWrite(LED_PIN, fade_in ? 255 : 0);

    //Flip direction
    fade_in ^= 1;

    //Restart time
    fade_start = loop_millis;

  }

  //Set fade in value
  else if (fade_in) analogWrite(LED_PIN, round(255.0 * pct));

  //Set fade out value
  else analogWrite(LED_PIN, 255 - round(255.0 * pct));

}

void setup() {

  //Set pin mode
  pinMode(LED_PIN, OUTPUT);

  //Fade in or out?
  fade_in = 1;

  //Start time of fade
  fade_start = millis();

}

void loop() {

  //Store millis()
  loop_millis = millis();

  //Bounce the LED
  bounceLED();

}

Now, it should be easy for you to turn "fade_start" and "fade_in" into arrays of 3 (one for each LED) and modify "bounceLED" to take an argument which references an index of the created arrays. You then offset the "fade_start" for each LED by 500 millis in order to create your effect.

Please mind that I have not tested the code and just written it from my head :)

Ok so I think there are better people than me helping you now...I had to look up MOSFET...i just like playing with twinkly LEDs... :-)

GreyArea: Ok so I think there are better people than me helping you now...I had to look up MOSFET...i just like playing with twinkly LEDs... :-)

And that is fun too.. Just flashing LEDs can teach you a massive amount about Arduino code. But you learnt something as well, MOSFETs.. That is the purpose of the forum. Tom.... :)

[quote author=TomGeorge link=msg=3551318 date=1515201315 But you learnt something as well, MOSFETS.. [/quote]

Heh...”learned” might be a bit strong. I know what the term is now; but I also know the term “Saturn V Rocket”...in neither case is it an indication that I know how to use one... :o

GreyArea: [quote author=TomGeorge link=msg=3551318 date=1515201315 But you learnt something as well, MOSFETS..

Heh...”learned” might be a bit strong. I know what the term is now; but I also know the term [u]“Saturn V Rocket”.[/u]..in neither case is it an indication that I know how to use one... :o

Didn't they just light the wick and walk away really quickly.....

Where am I wrong in fadeIn function? It’s fading only led1 and others only flashing.

int led1 = 9;      // PWM pin
int led2 = 10;      // PWM pin
int led3 = 11;      // PWM pin
int fadeTime = 5000;  // Overal fading time in ms

void fadeIn(int myArray[], int time){
  int arraySize = sizeof(myArray);
  double sectionFade = (time/(arraySize+2))/10;
  int br = 0;

  for(int i = 0; i<arraySize+1; i++){
    digitalWrite(myArray[i], LOW);
  }

  for(int a = 1; a<=arraySize+2; a++){
    for(int b = 0; b<=sectionFade; b+=5){
      Serial.println("-----------");
      int brightness = map(b, 0, sectionFade, 0, 127);
      for(int i = 1; i<=arraySize+1; i++){

        if(i == a){
          br = brightness;
        }else if((i % 2) == 0){
          br = brightness*2;
        }
        
        analogWrite(myArray[a-i], br);
        
      }
      delay(50);
    }  
  }

  for(int i = 0; i<arraySize+1; i++){
    digitalWrite(myArray[i], HIGH);
  }
  
}

void fadeOut(int myArray[], int time){
  int arraySize = sizeof(myArray);
  double sectionFade = time/(arraySize+2);

  for(int i = 0; i<arraySize+1; i++){
    digitalWrite(myArray[i], LOW);
  }
  delay(2000);
  // ????
}

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  Serial.begin(9600);  
  Serial.println("== SERIAL START ===");

}

void loop() {
  int myFadeIn[3] = {led1, led2, led3};
  fadeIn(myFadeIn, fadeTime);
  
  int myFadeOut[3] = {led3, led2, led1};
  fadeOut(myFadeOut, fadeTime);


}

You have a lot of bugs and mishaps in your code, please check my comments here:

void fadeIn(int myArray[], int time){

  //sizeof returns the size in bytes, each int is 2 bytes so you are getting
  //twice the size of the array, it should be: sizeof(myArray) / sizeof(int)
  //and this is causing all your for loops to get out of bounds
  int arraySize = sizeof(myArray);

  //Why + 2?
  double sectionFade = (time/(arraySize+2))/10;
  int br = 0;

  //why + 1? You are reading an out of bounds value here i<arraySize+1 : 0..3 and not 0..2
  for(int i = 0; i<arraySize+1; i++){
    digitalWrite(myArray[i], LOW);
  }

  //Again: Why + 2?
  for(int a = 1; a<=arraySize+2; a++){
    for(int b = 0; b<=sectionFade; b+=5){

      //The contents of this block makes no sense to me :-/

      Serial.println("-----------");
      int brightness = map(b, 0, sectionFade, 0, 127);
      for(int i = 1; i<=arraySize+1; i++){

        if(i == a){
          br = brightness;
        }else if((i % 2) == 0){
          br = brightness*2;
        }
       
        analogWrite(myArray[a-i], br);
       
      }
      delay(50);
    } 
  }

Using timing (see example above) is far the easiest way to do it. Unless you really have to, you should also avoid using blocking code :slight_smile:

Danois90:
You have a lot of bugs and mishaps in your code, please check my comments here:

Using timing (see example above) is far the easiest way to do it. Unless you really have to, you should also avoid using blocking code :slight_smile:

This was a mistake :confused:

Now the code is that below and it works - almost. I suspect that the next LED doesn’t start fading when the previous is on 50%.
There is one more thing:

  • how to adapt the functions not to use delay() ?
int led1 = 9;      // PWM pin
int led2 = 10;      // PWM pin
int led3 = 11;      // PWM pin
int fadeTime = 5000;  // Overal fading time in ms

void fadeIn(int myArray[], int time, int arraySize) {  
  Serial.println("++fadeIn START");
  int sectionFade = (time / (arraySize + 1));
  int brightness, realBrightness = 0;

  for (int a = 0; a < arraySize + 1; a++) {
    for (int sectionTime = 0; sectionTime < sectionFade; sectionTime += 10) {

      realBrightness = map(sectionTime, 0, sectionFade, 0, 128);
      for (int i = 0; i < arraySize; i++) {
        if (i == a) {
          analogWrite(myArray[i], realBrightness);
        } else if (i + 1 == a) {
          analogWrite(myArray[i], realBrightness + 128);
          if (realBrightness+128 > 254) {
            analogWrite(myArray[i], 255);
          }
        }
      }
      delay(10);
    }
  }
  Serial.println("++fadeIN STOP");
}

void fadeOut(int myArray[], int time,  int arraySize) {
  Serial.println("//fadeOut START");
  int sectionFade = (time / (arraySize + 1));
  int brightness, realBrightness = 0;

  for (int a = 0; a < arraySize + 1; a++) {
    for (int sectionTime = 0; sectionTime < sectionFade; sectionTime += 10) {
      
      realBrightness = map(sectionTime, 0, sectionFade, 255, 127);
      for (int i = 0; i < arraySize; i++) {
        if (i == a) {
          analogWrite(myArray[i], realBrightness);
        } else if (i + 1 == a) {
          analogWrite(myArray[i], realBrightness-127);
          if (realBrightness-127 < 1) {
            analogWrite(myArray[i], 0);
          }
        }
      }
      delay(10);
    }
  }
  Serial.println("//fadeOut STOP");
}

void setup() {
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);

  Serial.begin(9600);
  Serial.println("== SERIAL START ===");


}

void loop() {
  int myFadeIn[3] = {led1, led2, led3};
  fadeIn(myFadeIn, fadeTime, 3);
  delay(2000);

  int myFadeOut[3] = {led3, led2, led1};
  fadeOut(myFadeOut, fadeTime, 3);
  delay(5000);
}

You are really making it hard for your self… Check this:

//The number of pins / LED's is constant, so do not calculate for each iteration
#define LED_COUNT 3

void doFade(int myArray[], int time, bool inverted) {

  //The duration of a single transition is half of "time"
  float duration = (float)time * 0.5f; //Multiply is faster than division
  
  //Store current millis()
  unsigned long ms = millis();
  
  //Start time of each transition
  unsigned long start[LED_COUNT];
  start[0] = ms; //immediately
  start[1] = ms + round(duration * 0.5f); //Middle of first transition
  start[2] = ms + round(duration); //End of first transition

  //Do forever
  do {

    //For loop for individual transistions, only executed if start >= ms
    for (int i = 0; i < LED_COUNT; i++) if (start[i] >= ms) {

      //Calculate the percentage done 0.1 .. 1.0
      float pct = (float)(ms - start[i]) / duration;

      //If pct > 1 then the transition is complete
      bool done = (pct >= 1);
      if (done) pct = 1.0f;

      //Calculate pin value
      int value = round(255.0f * pct);

      //Set pin value
      analogWrite(myArray[i], inverted ? 255 - value : value);

      //If this pin is done and i last LED, then we exit the method
      if (done && (i >= LED_COUNT-1)) return;

    }

    //If start[i] < ms, set to origin since the transition has not started
    else analogWrite(myArray[i], inverted ? 255 : 0);

    //Re-read millis() for next iteration
    ms = millis();

  } while (true);
}

void fadeIn(int myArray[], int time) { doFade(myArray, time, false); }
void fadeOut(int myArray[], int time) { doFade(myArray, time, true); }

The code is untested and written from my head, but should only require minor modifications. If this is part of your education then please make sure to understand the code and re-create it instead of consider it homework done! :wink:

EDIT: Couple of “int” rectified to “long” :slight_smile:

Quote Tom on Saturn V…

‘Didn’t they just light the wick and walk away really quickly…’

Not quite - a very complex procedure.

And the apollo lander computer was a great triumph of it’s time.

Allan

allanhurst: Quote Tom on Saturn V...

'Didn't they just light the wick and walk away really quickly.....'

Not quite - a very complex procedure.

And the apollo lander computer was a great triumph of it's time.

Allan

LOL. I have some small toroids I bought on eBay, going to have a go at making some simple hardwired mag-core memory. Just a couple of 8bit words, the rings are very small, I don't know if standard ferrite type will work. I haven't found out what actual material they were. There is some good YouTube stuff on the history and a couple of guys who have made some mag-core of their own. Tom.... :) PS.Then I find this gem. http://www.corememoryshield.com/