I don't have to !
It was my brain power versus your assumptions ![]()
doesn't that suggest loop() takes > 1 msec to execute?
and consider the units (seconds)
why?
ok, if millis () behaves as you suggest, then the approach Terry described should work.
but i wonder how accurate the timing needs to be if the OP is asking how to do this on this Arduino forum. does the accuracy need to be within 1ms over a 24 hour period or 1 sec?
i've worked on a number projects maintaining time within a couple nsec accuracy. depends on the OPs requirements
but keep in mind the OP thought this was a multi-tasking problem
I removed the completely off-topic posts. Everyone, please try to focus the replies here on helping vignesh_skp with their project. You are welcome to open a separate topic for the interesting tangential discussions.
i believe the following will remain aligned to the starting millis() value without drifting using the Terry method
i ran the millis() code on the laptop and found that it increments twice every 42 tics and reason for odd start time. note how while the cycle is an even 100, the first interval expire at 43 while the 3rd at 142
43 42 5 On test
47 47 95 Off test
142 142 5 On test
147 147 95 Off test
242 242 5 On test
247 247 95 Off test
342 342 5 On test
347 347 95 Off test
442 442 5 On test
447 447 95 Off test
542 542 5 On test
547 547 95 Off test
642 642 5 On test
647 647 95 Off test
742 742 5 On test
747 747 95 Off test
842 842 5 On test
847 847 95 Off test
942 942 5 On test
947 947 95 Off test
1042 1042 5 On test
1047 1047 95 Off test
1142 1142 5 On test
1147 1147 95 Off test
1242 1242 5 On test
1247 1247 95 Off test
1342 1342 5 On test
1347 1347 95 Off test
1442 1442 5 On test
1447 1447 95 Off test
1542 1542 5 On test
1547 1547 95 Off test
1642 1642 5 On test
1647 1647 95 Off test
1742 1742 5 On test
1747 1747 95 Off test
1842 1842 5 On test
1847 1847 95 Off test
1942 1942 5 On test
1947 1947 95 Off test
2042 2042 5 On test
2048 2047 95 Off test
2142 2142 5 On test
2147 2147 95 Off test
2242 2242 5 On test
2247 2247 95 Off test
2342 2342 5 On test
2347 2347 95 Off test
2442 2442 5 On test
2447 2447 95 Off test
2542 2542 5 On test
2547 2547 95 Off test
2642 2642 5 On test
2647 2647 95 Off test
struct Led {
const byte PinLed;
const unsigned long MsecStart;
const unsigned long MsecOn;
const unsigned long MsecOff;
const char *desc;
unsigned long msecLst;
unsigned long msecPeriod;
};
Led leds [] = {
#if 0
{ 10, 0, 300, 300, "MV1" },
{ 11, 10, 240, 360, "EV2" },
{ 12, 246, 4, 296, "DRAIN" },
{ 13, 310, 240, 360, "EV1" },
#else
{ 12, 42, 5, 95, "test" },
#endif
};
const int Nled = sizeof(leds) / sizeof(Led);
const int K = 1; // scale timing for testing
enum { Off = HIGH, On = LOW };
char s [80];
// -----------------------------------------------------------------------------
void loop ()
{
unsigned long msec = millis ();
char *t;
Led *p = leds;
for (int n = 0; n < Nled; n++, p++) {
// check for led timeout
if (msec - p->msecLst >= p->msecPeriod) {
p->msecLst += p->msecPeriod;
if (On == digitalRead (p->PinLed)) {
digitalWrite (p->PinLed, Off);
p->msecPeriod = p->MsecOff * K;
t = (char*) "Off";
}
else {
digitalWrite (p->PinLed, On);
p->msecPeriod = p->MsecOn * K;
t = (char*) "On";
}
sprintf (s, " %6lu %6lu %6lu %3s %s",
msec, p->msecLst, p->msecPeriod, t, p->desc);
Serial.println (s);
}
}
}
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (9600);
Serial.println ();
Led *p = leds;
for (int n = 0; n < Nled; n++, p++) {
pinMode (p->PinLed, OUTPUT);
digitalWrite (p->PinLed, Off);
p->msecPeriod = p->MsecOff;
p->msecLst = -(p->MsecOff - p->MsecStart) * K;
}
}
@gcjr Is this all and what you are talking about?
p->msecLst += p->msecPeriod;
versus
p->msecLst = msec;
Each method has its place. Here, if your belief is in some truth, the first method is preferred works.
a7
the earlier version is simpler, and as already mentioned, not sure what the OPs requirements are.
i didn't realize millis() skipped values.
i didn't think the challenge was avoiding the slip. i thought it was to how to initialize them to start precisely
you're having a hard time reading 44 lines of code?
lots of code has been reviewed. we used git. some in Android.
Kernighan advocates simple variable names in Practice of Programming.
'p' for ptr. i first saw this approach looking at Unix process management code
You can keep denying it, and I appreciate that you think tossing a beginner into some water somewhat deeper than she might be able to even tread, let alone swim in, is an effective teaching method, but you do use some techniques that are, well, advanced. Or obscure. Or clever.
Often unnecessarily very too deeper.
I know everyone arrives at whatever level they claim for themselves; I think the most effective path is through an understanding of the very simplest way to do things, no matter they be naive or literal or embarrassing or whatever.
Step by step. You know what we are all talking about.
a7
a variable which holds the value from millis(), to be used the next time and called "previousMillis" makes imho more sense than to call it just timeStamp and compare it in the next iteration with something called currentTime. At least you could have called that variable currentTimeStamp.
You want to compare timeStamps, don't you?
For a non English native speaker like me (obvious), previousMillis makes as much sense as millis().
i'd sincerely appreciate it if you would point out what you think is advanced. even better an alternate approach that you believe would better suited for the OP (probably arrays)
i don't know the experience level of the OP and he mentioned multi-tasking.
i've heard very experienced programers describe how difficult it was for them to understand C++ code and i often see people posting code using classes
i'm more than happy to explain more if the OP asks, and i have.
but is this a coding question or an algorithm question (multitasking?)
+1. Or two, is that allowed?
I've always been very bad at naming things, but I have settled on now for the current reading of the clock (millls()), and lastTime or a variation of last<Whatecer>.
I like the idea of explicitly calculating elapsedTime, I'll see if we can scare up a name for it that we like better, don't hold your collective breath on that.
And the stripped out code is good, except there's either no refreshing of the timeStanp or I have too much sand in my eyes.
FWIW, comments in code sections managing time can just be confusing. I routinely ignore comments in amateur code as they can redundant noise, misleading or just plain wrong. In 44 lines of code one might argue that an full understanding of the purpose of the code and the mechanics of the algorithm being coded is better than line by line commentary.
A wrinkle that I think makes some things even better, and has the added benefit of out-denting the controlled code, is to reverse the test, viz:
if (elapsedTime < interval) // too soon to even look at the button?
return; // yes. maybe next time
// do whatever
timeStanp += interval; // throw the stone down the road
which fits in well with dragging someone over an essential idea of state machinery in hand-made "muktitasking" - functiions that are called very frequently and only occasionally, when it is time to, take a step further in whatever process they are managing.
I've said this is hard until it is easy. I know of no one who didn't experience some kind of Aha! moment. For some, later than sooner.
Much of this is so much simpler IRL, where one can gauge the progress of the student(s) and probe with alternate angles until a connection is made. Knowing where the student is at seems key - when we deal with ppl still trying to debug their voids by trying an if loop instead of a while loop, who don't even get that lines of code do things and are run one at a time and do those things just like that, your nose on the code line by line, it is hard. And the fact that solutions can be found or are offered complete here you go on these fora just reduces the motivation, for many, that it takes to read code and see how it does the task it was written for.
There is nothing more gratifying than hearing from a noob that she gets it and… it will change the way she codes from now on.
a7
here are 2 less advanced versions
const byte PinLed [] = { 10, 11, 12, 13 };
const unsigned long MsecStart [] = { 0, 10, 246, 310 };
const unsigned long MsecOn [] = { 300, 240, 4, 240 };
const unsigned long MsecOff [] = { 300, 360, 296, 360 };
const char *desc [] = { "MV1", "EV2", "DRAIN", "EV1" };
const int Nled = sizeof(PinLed);
unsigned long msecLst [Nled];
unsigned long msecPeriod [Nled];
const int K = 1; // scale timing for testing
enum { Off = HIGH, On = LOW };
char s [80];
// -----------------------------------------------------------------------------
void loop ()
{
unsigned long msec = millis ();
char *t;
for (int n = 0; n < Nled; n++) {
// check for led timeout
if (msec - msecLst [n] >= msecPeriod [n]) {
msecLst [n] += msecPeriod [n];
if (On == digitalRead (PinLed [n])) {
digitalWrite (PinLed [n], Off);
msecPeriod [n] = MsecOff [n] * K;
t = (char*) "Off";
}
else {
digitalWrite (PinLed [n], On);
msecPeriod [n] = MsecOn [n] * K;
t = (char*) "On";
}
sprintf (s, " %6lu %6lu %6lu %3s %s",
msec, msecLst [n], msecPeriod [n], t, desc [n]);
Serial.println (s);
}
}
}
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (9600);
Serial.println ();
for (int n = 0; n < Nled; n++) {
pinMode (PinLed [n], OUTPUT);
digitalWrite (PinLed [n], Off);
msecPeriod [n] = MsecOff [n];
msecLst [n] = -(MsecOff [n] - MsecStart [n]) * K;
}
}
const byte Pin0 = 10;
const byte Pin1 = 11;
const byte Pin2 = 12;
const byte Pin3 = 13;
const unsigned long MsecStart0 = 0;
const unsigned long MsecStart1 = 10;
const unsigned long MsecStart2 = 246;
const unsigned long MsecStart3 = 310;
const unsigned long MsecOn0 = 300;
const unsigned long MsecOn1 = 240;
const unsigned long MsecOn2 = 4;
const unsigned long MsecOn3 = 240;
const unsigned long MsecOff0 = 300;
const unsigned long MsecOff1 = 360;
const unsigned long MsecOff2 = 296;
const unsigned long MsecOff3 = 360;
const char *desc0 = "MV1";
const char *desc1 = "EV2";
const char *desc2 = "DRAIN";
const char *desc3 = "EV1";
unsigned long msecLst0;
unsigned long msecLst1;
unsigned long msecLst2;
unsigned long msecLst3;
unsigned long msecPeriod0;
unsigned long msecPeriod1;
unsigned long msecPeriod2;
unsigned long msecPeriod3;
unsigned long msec;
const int K = 1; // scale timing for testing
enum { Off = HIGH, On = LOW };
char s [80];
char *t;
// -----------------------------------------------------------------------------
void check (
const byte & Pin,
const unsigned long & MsecStart,
const unsigned long & MsecOn,
const unsigned long & MsecOff,
unsigned long & msecLst,
unsigned long & msecPeriod,
const char *desc)
{
if (msec - msecLst >= msecPeriod) {
msecLst += msecPeriod;
if (On == digitalRead (Pin)) {
digitalWrite (Pin, Off);
msecPeriod = MsecOff * K;
t = (char*) "Off";
}
else {
digitalWrite (Pin, On);
msecPeriod = MsecOn * K;
t = (char*) "On";
}
sprintf (s, " %6lu %6lu %6lu %3s %s",
msec, msecLst, msecPeriod, t, desc);
Serial.println (s);
}
}
// -----------------------------------------------------------------------------
void init (
const byte & Pin,
const unsigned long & MsecStart,
const unsigned long & MsecOn,
const unsigned long & MsecOff,
unsigned long & msecLst,
unsigned long & msecPeriod,
const char *desc)
{
pinMode (Pin, OUTPUT);
digitalWrite (Pin, Off);
msecPeriod = MsecOff;
msecLst = -(MsecOff - MsecStart) * K;
}
// -----------------------------------------------------------------------------
void loop ()
{
msec = millis ();
check (Pin0, MsecStart0, MsecOn0, MsecOff0, msecLst0, msecPeriod0, desc0);
check (Pin1, MsecStart1, MsecOn1, MsecOff1, msecLst1, msecPeriod1, desc1);
check (Pin2, MsecStart2, MsecOn2, MsecOff2, msecLst2, msecPeriod2, desc2);
check (Pin3, MsecStart3, MsecOn3, MsecOff3, msecLst3, msecPeriod3, desc3);
}
// -----------------------------------------------------------------------------
void setup ()
{
Serial.begin (9600);
Serial.println ();
init (Pin0, MsecStart0, MsecOn0, MsecOff0, msecLst0, msecPeriod0, desc0);
init (Pin1, MsecStart1, MsecOn1, MsecOff1, msecLst1, msecPeriod1, desc1);
init (Pin2, MsecStart2, MsecOn2, MsecOff2, msecLst2, msecPeriod2, desc2);
init (Pin3, MsecStart3, MsecOn3, MsecOff3, msecLst3, msecPeriod3, desc3);
}
This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.