Hi,
I wrote a complex day shedule for LEDs.
You can define day schedules (programs) and align them to single LEDs (chanels).
You can change the programs for a chanel during runtime.
You can switch a temporary "non-changing-light" for a chanel.
The programs are defined with "brightnesses"; they may be corrected by gamma-arrays to get the output values for the pin.
I would like to transform this code into a library, but I need some major help.
1.) I do not have an arduino around, so I cannot test it right now.
2.) I use a lot of arrays. For most of them I do not know its size during compiling time. Do I have to declare huge arrays to be on the safe side?
3.) How do I save this code to use it as a library?
4.) Any other suggestions are welcome, too.
Here is my code:
#define max_milliseconds 86400000 // milliseconds per day
#define max_chanels 15 // 3x RGBWW
#define max_programs 15 // should be at least max_chanels
#define max_events 100 // max. changes per day
#define max_gamma 6 // should be one for each color (0rgbww)
#define max_nameLength 12 // maximum length of program name
class cEvent
{
public:
long time; // timestamp | milliseconds until 00:00
byte bright; // brightness | 0-255
};
class cProgram
{
public:
char name[max_nameLength];
cEvent arrEvents[max_events];
int SizeArrEvent; // size of the array arrEvents
};
class cChanel
{
public:
cProgram *currProgram; // pointer to current program
cProgram *strdProgram; // pointer to standard program
int actEvent; // active event | or rather passed event
byte pin; // pin for this chanel
byte gamma_ID; // ID of color | ID of corresponding gamma array
long tmpEndTime; // end time of temporary setting
boolean tmpActive; // status of temporary setting
};
cProgram arrPrograms[max_programs]; // array of all possible programs
cProgram arrTmpProg[max_chanels]; // array of temporary programs for each chanel
cChanel *arrChanels[max_chanels]; // array of all active chanels | one chanel has one pin
byte arrGamma[max_gamma][256]; // array to get LED-value from brightness
// ****************************************************************
// extern SETUP functions
// sets the initial settings
void LED_init()
{
long tmpTime[2];
byte tmpBright[2];
// arrGamma[0] is simply linear
for (byte i = 0; i <=255; i++) {arrGamma[0][i] = i;}
byte o = 22;
// chanel 0 has sunrise at 07:00 (2h) and sunset at 17:00 (2h)
tmpTime[0] = 25200000;
tmpTime[1] = 32400000;
tmpTime[2] = 61200000;
tmpTime[3] = 68400000;
tmpBright[0] = 0;
tmpBright[0] = 191;
tmpBright[0] = 191;
tmpBright[0] = 0;
LED_setProgram(0, "Standard", 4, tmpTime, tmpBright);
LED_setChanel(0, 14, 0);
LED_alignProg2Chan(0, 0);
// FOR TEST: chanel 1 starts rising 20 seconds after program start, holds 3 seconds and dims down again
long tmpNow = getDayTime();
tmpTime[0] = tmpNow + 20000;
tmpTime[1] = tmpTime[0] + 5000;
tmpTime[2] = tmpTime[0] + 3000;
tmpTime[3] = tmpTime[0] + 10000;
tmpBright[0] = 0;
tmpBright[0] = 255;
tmpBright[0] = 255;
tmpBright[0] = 0;
LED_setProgram(1, "Test", 4, tmpTime, tmpBright);
LED_setChanel(1, 15, 0);
LED_alignProg2Chan(1, 1);
}
// sets a given program. Defines its name and events.
void LED_setProgram(byte prog_ID, String strName, int evCnt, long arrTime[], byte arrBright[])
{
strName.toCharArray(arrPrograms[prog_ID].name,max_nameLength); // convert the String to a char array
arrPrograms[prog_ID].SizeArrEvent = evCnt;
for (int ev = 0; ev < evCnt; ev++) {
arrPrograms[prog_ID].arrEvents[ev].time = arrTime[ev];
arrPrograms[prog_ID].arrEvents[ev].bright = arrBright[ev];
}
}
//sets a given chanel. Defines its pin and gamma correction array.
void LED_setChanel(byte chan_ID, byte pin, byte calc_ID)
{
arrChanels[chan_ID]->pin = pin;
arrChanels[chan_ID]->gamma_ID = calc_ID;
arrChanels[chan_ID]->currProgram = &arrPrograms[0];
arrChanels[chan_ID]->strdProgram = &arrPrograms[0];
arrChanels[chan_ID]->actEvent = 0;
arrChanels[chan_ID]->tmpActive = false;
}
// ****************************************************************
// extern LOOP functions
// sets a given program for a given chanel
void LED_alignProg2Chan(byte prog_ID, byte chan_ID)
{
arrChanels[chan_ID]->currProgram = &arrPrograms[prog_ID];
}
// sets a non-changing program and starts it for a given chanel
void LED_setTMP(byte chan_ID, long endTime, byte brightness)
{
// set the tmp program to given brightness
arrTmpProg[chan_ID].arrEvents[0].time = 0;
arrTmpProg[chan_ID].arrEvents[0].bright = brightness;
arrTmpProg[chan_ID].arrEvents[1].time = 10000;
arrTmpProg[chan_ID].arrEvents[1].bright = brightness;
// sets the tmp program as current program
arrChanels[chan_ID]->currProgram = &arrTmpProg[chan_ID];
arrChanels[chan_ID]->tmpEndTime = endTime;
arrChanels[chan_ID]->tmpActive = true;
}
// function to be called in the main-loop
void LED_loop(long tNow)
{
for (byte i = 0; i < max_chanels; i++) {
if (arrChanels[i]->tmpActive) {
if (arrChanels[i]->tmpEndTime == 0) { // 0 is for endless
if (tDiff(tNow,arrChanels[i]->tmpEndTime) < (max_milliseconds - 3000)) { // still active
arrChanels[i]->currProgram = &arrTmpProg[i];
} else {
arrChanels[i]->tmpActive = false;
arrChanels[i]->currProgram = arrChanels[i]->strdProgram;
}
}
}
}
// if this is to slow than I change to one pin per loop
for (byte chanel = 0; chanel < max_chanels;chanel++) {setBrightness(chanel,tNow);}
}
// ****************************************************************
// intern functions
// get time of day in milliseconds from 00:00
long getDayTime()
{
}
// calculates the time difference between timeA and timeB
long tDiff(long timeB, long timeA)
{
// rollover
if (timeB < timeA) timeB = timeB + max_milliseconds;
return (timeB - timeA);
}
// checks if event is last event and calculates next event
int nextEvent(int Ch, int event)
{
if (event < arrChanels[Ch]->currProgram->SizeArrEvent) {
return event + 1;
} else {
return 0;
}
}
//calculates and sets value of a single chanel (pin)
void setBrightness(byte Ch, long time)
{
int event;
long time1;
long time2;
boolean eventChecked = false;
do
{
event = arrChanels[Ch]->actEvent;
time1 = arrChanels[Ch]->currProgram->arrEvents[event].time;
time2 = arrChanels[Ch]->currProgram->arrEvents[nextEvent(Ch, event)].time;
// move to next event if necessary
if ((tDiff(time,time2)) < (tDiff(time,time1))) {arrChanels[Ch]->actEvent = nextEvent(Ch,event);} else {eventChecked = true;}
} while (!eventChecked);
byte bright1 = arrChanels[Ch]->currProgram->arrEvents[event].bright;
byte bright2 = arrChanels[Ch]->currProgram->arrEvents[nextEvent(Ch, event)].bright;
// milliseconds per one increment
int millisPerInk = round((tDiff(time2,time1)) / (bright2 - bright1));
byte brightness = byte(bright1 + ((tDiff(time,time1)) / millisPerInk));
byte value = arrGamma[arrChanels[Ch]->gamma_ID][brightness];
analogWrite(arrChanels[Ch]->pin, value);
}
void setup()
{
LED_init();
}
void loop()
{
long tNow = getDayTime();
// check if temporary programs are active
LED_loop(tNow);
}
Kevin