So I hooked up 5 LED diodes to digital outputs as seen in code with current limiting resistors, everything works in that regard. I'm trying to gradually fade up and down the brightness to represent the graph in the picture. It should simulate Christmas lights on a certain diode in different time intervals this effect lasts. I tried it before with the delay() function, but I found out I cannot do "multithreading" with it so I used millis() function for parallel execution. My code won't work as intended so I asked it here how would someone implement parallel execution of having this effect happening differently on every LED diode.
Variable bright cancels out to 0 so I need to figure out how to independently change the value of different brightness variables. So I should add different brightness variables to each LED and try it out?
Thank you everybody for your solutions, I'm going to rewrite the blh64's code in an array of structs for better readability. A little problem I have is that transition is not smooth as I used the delay() function before like I can see every step, not like a smooth rising/falling linear curve.
How about an array of structs each with data about a single LED and a single function ?
True, it would be more elegant, but probably not best for a beginner to understand. A brute force method is just fine for 5 leds. Probably not for 50 leds.
hrterminator:
Thank you everybody for your solutions, I'm going to rewrite the blh64's code in an array of structs for better readability. A little problem I have is that transition is not smooth as I used the delay() function before like I can see every step, not like a smooth rising/falling linear curve.
It was configured that way. Just change
static int step = 2;
to
static int step = 1;
Also if you want a really natural fade you have to have gamma correction.
blh64:
True, it would be more elegant, but probably not best for a beginner to understand. A brute force method is just fine for 5 leds. Probably not for 50 leds.
The brute force method is certainly easy to write and understand, but however many LEDs are involved such a crude method offends me, hence my suggestion. I like my programs not only to work but to be elegant, but each to their own
I see that the OP has embraced the idea of using an array of structs
#include <multiMap.h>
#include <timeObj.h>
#include <idlers.h>
#define PROFILE_MS 400 // Total time that the profile spans.
#define CHANGE_MS 2 // How much time between recalculating new brightness values.
// Create a class that takes a time,value profile and plays it as a PWM.
// And, runs in the background.
class mappedAnalog : public idler {
public:
mappedAnalog(multiMap* inMap,int inPin,float inChange,float totalMs);
virtual ~mappedAnalog(void);
void start(float delayMs=0);
virtual void idle(void);
multiMap* ourProfile;
int pin;
int frameMs;
float changeMs;
float profileMs;
timeObj changeTimer;
bool delaying;
};
mappedAnalog::mappedAnalog(multiMap* inMap,int inPin,float inChange,float totalMs) {
ourProfile = inMap;
pin = inPin;
frameMs = 0;
changeMs = inChange;
profileMs = totalMs;
changeTimer.setTime(changeMs,false);
delaying = false;
}
mappedAnalog::~mappedAnalog(void) { }
void mappedAnalog::start(float delayMs) {
if (delayMs>0) {
changeTimer.setTime(delayMs);
delaying = true;
}
hookup();
pinMode(pin,OUTPUT);
frameMs = 0;
changeTimer.start();
}
void mappedAnalog::idle(void) {
float newBright;
if (delaying) {
if(changeTimer.ding()) {
changeTimer.setTime(changeMs);
changeTimer.start();
delaying = false;
}
} else {
if (changeTimer.ding()) {
if (frameMs>=profileMs) {
frameMs = 0;
} else {
frameMs = frameMs + changeMs;
}
newBright = ourProfile->map(frameMs);
analogWrite(pin, round(newBright));
changeTimer.start();
}
}
}
// ********************* Program starts here *********************
multiMap profile; // Your time / brightness profile.
mappedAnalog* LED1; // An LED
mappedAnalog* LED2; // ANother..
mappedAnalog* LED3; // Notice these are actually just global pointers to LED objects. Make as many as you need.
void setup(void) {
profile.addPoint(0,0); // Build the pofile by adding points (time in ms, brighness value)
profile.addPoint(PROFILE_MS/2,255); // Second point.
profile.addPoint(PROFILE_MS,0); // Last point. ( You can actually add as many points as you like. Go crazy! )
LED1 = new mappedAnalog(&profile,3,CHANGE_MS,PROFILE_MS); // Create first LED object. Address of profile, pin num, frame rate, total time for profile.
LED1->start(); // Fire uip first LED.
LED2 = new mappedAnalog(&profile,9,CHANGE_MS,PROFILE_MS); // Create second LED.
LED2->start(200); // Fire it up with a prese delay before starting.
LED3 = new mappedAnalog(&profile,10,CHANGE_MS,PROFILE_MS); // Third LED
LED3->start(250); // And again a delay from time 0 for actual start.
}
void loop(void) {
idle(); // Runs all the background things.
}
If you would like to try this you'll need to grab LC_baseTools from the library manager.