0

TL;DR: I tried to have a random fading pattern on several leds and it leads to flickering.

Edited following @chrisl answer.

I am in the process of creating a simple lamp that show some light patterns using 6 led and an arduino uno. The goal is that depending on some inputs and a bit of randomisation, the patterns will change. For instance, only 2 lights at the same time but fading up and down randomly on all 6 led. Or 4 lights fading up and down randomly on the 6 leds.

I decided to create a struct that would be a light pattern named a particle, and this particle have a variable named led_position that shows which led it is on at a certain moment. The particle can change its position to light up an other led.

I know this is not the clearest of explanation but I hope my code will be more straightforward:

Main code #include "MyTypes.h"

int led1 = 9;    // the PWM pin the LED is attached to
int led2 = 10; 
int led3 = 11; 
int led4 = 6; 
int led5 = 3; 
int led6 = 5; 



//int led;
int brightness;
int fadeAmount;


// Definition of the different particles
particle_type particle[]={
  { 0,led1,0, 2,   false },  
  { 1,led2,50, 2,   false },  
  { 2,led3,100,  2,   false },  
  { 3,led4,80,  2,   false },
  { 4,led5,30,  2,   false},
  { 5, led6,70,  2,   false},
};

led_type led[]={
  { 3,false },  
  { 5,false },  
  { 6,false },  
  { 9,false },
  { 10,false },
  { 11,false },
};



//initiation of the particles

void initiate_particle(particle_type& particle_example,led_type led[]){



 //take a random led from list of led  
  int number=random(5);
  led[number];
  if (led[number].busy == false){ //if led non-occupied
    particle_example.led_position=led[number].led_position;
    led[number].busy = true ;//take this led as output
    } 

  else{
//    particle_example.led_position=particle_example.led_position; //keep same led
  }

  particle_example.reset = false; //reset turned off 
 // delay(30);

}

void update_light(particle_type& particle_example,led_type led[]){ //updating led brightness


  analogWrite(particle_example.led_position, particle_example.brightness);  //updating led brightness
  if (particle_example.brightness >=  160) {
    particle_example.fadeAmount = -particle_example.fadeAmount;

  }

  if (particle_example.brightness <=  160 && particle_example.brightness >=  100 ) {
    particle_example.brightness = particle_example.brightness + 2*particle_example.fadeAmount;

  }

  if (particle_example.brightness >= 50 && particle_example.brightness <=  100){ 
      particle_example.brightness = particle_example.brightness + particle_example.fadeAmount;

  }

  if (particle_example.brightness >= 0 && particle_example.brightness <=  50){ 
      particle_example.brightness = particle_example.brightness + 0.5*particle_example.fadeAmount;

  }

  if (particle_example.brightness <= 0){
    particle_example.reset= true;
    int number = particle_example.led_position;
    led[number].busy=false;
    particle_example.fadeAmount = -particle_example.fadeAmount;
  }

}

void activate_particle(particle_type& particle_example,led_type led[]){ //function to keep led activated

  if (particle_example.reset==true){ //if led not initiated or has finished its dimming down
    initiate_particle(particle_example, led); //initiate it again
  ;}

  else {
   update_light(particle_example,led); //update its brightness
  }
}

void setup() { //create led outputs

  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);
  pinMode(led6, OUTPUT);
  Serial.begin(9600); //serial for debug

}



void loop() {

  activate_particle(particle[0],led);
//  activate_particle(particle[1],led);

//  activate_particle(particle[2],led);
//  activate_particle(particle[3],led);
//  activate_particle(particle[4],led);
//  activate_particle(particle[5],led);
//  

 delay(5); // 20-17-15-12-10-7-2

}

Mytypes.h

typedef struct {
    int id;
    int led_position;
    int brightness;
    int fadeAmount;
    bool reset;
} particle_type;

typedef struct {
    int led_position;
    bool busy;
} led_type;

This seems to work more or less but I still have the problem of particles "choosing" the same led to light up and it make the led flickers.

I am struggling on this. I have tried to add a data field for busy and create a new struct for led to no avail.

Even when only one particle is on, the different leds seems to deactivate after a few rounds.

Let me know if you figure it out, thanks!

EDIT 2:

    #include "MyTypes.h"

int led0 = 3;    // the PWM pin the LED is attached to
int led1 = 5; 
int led2 = 6; 
int led3 = 9; 
int led4 = 10; 
int led5 = 11; 



//int led;
int brightness;
int fadeAmount;


// Definition of the different particles
particle_type particle[]={
  { 0,led0,0, 4,   false },  
  { 1,led1,50, 4,   false },  
  { 2,led2,100,  4,   false },  
  { 3,led3,80,  4,   false },
  { 4,led4,30, 4,   false},
  { 5,led5,70,  4,   false},
};

led_type led[]={
  { 3,false },  
  { 5,false },  
  { 6,false },  
  { 9,false },
  { 10,false },
  { 11,false },
};



//initiation of the particles

void initiate_particle(particle_type& particle_example,led_type led[]){



 //take a random led from list of led  
  int number=random(6);
  Serial.println(number);
  led[number];
  if (led[number].busy == false){ //if led non-occupied
    for (int i=0;i<6;i++){
      if (led[i].led_position==particle_example.led_position){
      led[i].busy=false;
      Serial.println("success");
      Serial.println(led[i].led_position);
      }
    }
    particle_example.led_position=led[number].led_position;
    Serial.println(particle_example.led_position);
    led[number].busy = true ;//take this led as output
    particle_example.reset = false; //reset turned off 
    } 

  else{
//  initiate_particle( particle_example,led);
}


  delay(30);

}

void update_light(particle_type& particle_example,led_type led[]){ //updating led brightness
      analogWrite(particle_example.led_position, particle_example.brightness);  //updating led brightness

  if (particle_example.brightness >=  160) {
    particle_example.fadeAmount = -particle_example.fadeAmount;
    particle_example.brightness = particle_example.brightness + 2*particle_example.fadeAmount;
  }

  else if (particle_example.brightness <  160 && particle_example.brightness >=  100 ) {
    particle_example.brightness = particle_example.brightness + 1.5*particle_example.fadeAmount;

  }

  else if (particle_example.brightness > 50 && particle_example.brightness <=  100){ 
      particle_example.brightness = particle_example.brightness + particle_example.fadeAmount;

  }

  else if (particle_example.brightness > 0 && particle_example.brightness <=  50){ 
      particle_example.brightness = particle_example.brightness + 0.25*particle_example.fadeAmount;

  }

  else if (particle_example.brightness <= 0){
    particle_example.reset= true;
    particle_example.brightness =0;
    int number = particle_example.led_position;

    if (particle_example.fadeAmount<0){
      particle_example.brightness = 0;
      particle_example.fadeAmount = -particle_example.fadeAmount;
    }
    else{
      particle_example.brightness = particle_example.brightness + 0.5*particle_example.fadeAmount;
    }

  }




}

void activate_particle(particle_type& particle_example,led_type led[]){ //function to keep led activated

  if (particle_example.reset==true){ //if led not initiated or has finished its dimming down
    initiate_particle(particle_example, led); //initiate it again
  ;}

  else {
   update_light(particle_example,led); //update its brightness
  }
}

void setup() { //create led outputs
  pinMode(led0, OUTPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(led4, OUTPUT);
  pinMode(led5, OUTPUT);

  Serial.begin(9600); //serial for debug

}



void loop() {

  activate_particle(particle[0],led);
  activate_particle(particle[1],led);
  activate_particle(particle[2],led);
//  activate_particle(particle[3],led);
//  activate_particle(particle[4],led);
//  activate_particle(particle[5],led);
//  

 delay(10); // 20-17-15-12-10-7-2

}


void loop() {

  activate_particle(particle[0],led);
  activate_particle(particle[1],led);
  activate_particle(particle[2],led);
  activate_particle(particle[3],led);
//  activate_particle(particle[4],led);
//  activate_particle(particle[5],led);
//  

 delay(10); // 20-17-15-12-10-7-2

}

Now the code works well up to 3 particles but messes things up for 4,5,6 particles with flickering and absence of light.

1 Answer 1

0

That seems like a logic problem for me. You define a "particle", which is not bound to a special LED (like a particle, that is jumping from one position to another). Then you included a busy flag, that should prevent, that a LED is used by more than one particle at a time. But you included this flag in the particle. Being busy is a state of the LED, not of the particle, so including this in the particle won't do, what you want.

If you want to use this logic, you need to create a struct, which represents the individual LED. The struct's fields would be the pin number and the busy flag. You can create the LED list with instances of this struct. Then to choose a new position for the particle, you need to check if the busy flag of that position is set. If not, choose this position and set the busy flag. Clear the flag, when you remove the particle from the position.


After your edit I see more problems. First a general problem: Currently a new particle, that want's to change it's position, needs a free (not busy) position to move to. You have 6 LED positions, so with 6 particles, there won't be any move. You can change this by freeing a LED position (setting it's busy flag to false), when the fading of a particle is finished. Still there might be timing problems with this way, depending on the overall timing behavior of the sketch (The first particle to free a LED position will not find a different free position and has to wait. This might lead to 2 particles just exchanging there positions).

Then in void update_light() you have multiple if statements, which all test the particles brightness. But inside these statements you change the brightness. So it is possible, that multiple of the if statements will execute. You should use if else if instead, so that only one of the statements can execute.

And in void initiate_particle() you check for the chosen LED position to be busy. But if the position is already busy, you are setting the particles reset flag to false anyway. That means that activate_particles() will update the particles brightness despite the fact, that the particles does not have a valid LED position currently. You should not set reset to false, if the particles hasn't got a valid LED position. And the delay at the end of the initiate function does not serve a function in my eyes.

4
  • Hi chrisl, sorry for the flood :). Thanks for your answer, now the system works better with 1 to 3 particles but still has trouble with 4,5,6 at the same time. Let me know if you have an idea. Sep 25, 2019 at 22:15
  • @Guillaume_slize I added further explanations to my answer
    – chrisl
    Sep 26, 2019 at 11:08
  • Hi Chris, thanks a lot for the long explanation. It makes things much clearer, I changed the code according to your advices but it is now experiencing some weird behavior (some led lighting just a little). Two led exchanging their positions or staying in the same when 6 lights/ particles are up is fine, I was hoping for a system that could sustain all configuration from 1 to 6, but might have to code another one for 6. Sep 26, 2019 at 11:42
  • Ok, I corrected a few mistakes and now it seems to work fine up until 4. I think 5 and 6 is too unstable for so few leds. Sep 26, 2019 at 12:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.