A handy hint? or not. Blink without delay 3.0.

I was thinking... what's the easiest and i mean EASIEST way to create a "delay" without actually implementing a delay, for example, you
have a sensor sending the results between 0-1024.

but, when you do Serial.println(data);

so, what are your options?

Create a Delay time, measure how many seconds pass and if > 3 seconds, display(whatever); the other way is to simply

Serial.println(data)
delay(400);

but that might effect time critical routines... so a few weeks back it occurred to me ...

 int n = random(500);
 if (n==65)
   Serial.println(data);

every couple of seconds or so, you see the data coming in, is using Random? taxing on the CPU? any benefits to using this method?

is using Random? taxing on the CPU?

Relative to the println, no.

You might also think about something like

if ((millis() & 0x1ff) == 0) {
  Serial.println(data);
}

That should print something about every half a second...

cjdelphi:
any benefits to using this method?

The only benefit I can see is that you output arrives at random intervals. If that's what you wanted, this achieves it.

If what you really want is to have the output arrive at defined regular intervals while also doing other things in the meantime, then the technique demonstrated in the 'blink without delay' example sketch shows you how to achieve that.

i was offering this as a "tip" for other users and if it's worthy enough to be used as a tip.

obviously not.

westfw:

if ((millis() & 0x1ff) == 0) {

Serial.println(data);
}

If your loop takes more than half a millisecond or so, won't you miss some of the times the last 9 bits of millis() are 0? It seems you'll have your println at some pseudo-random multiple of half a second.

Well the correct way to do it is only three lines:

static unsigned long lasttime;
if (millis() - lasttime > 1000) {
  Serial.println();
  lasttime = milis();
}

I suppose you could make a macro

#define RUNEVERY(n) for (static unsigned long lasttime; millis() - lasttime > (n); lasttime = millis())

and then use it like this:

void loop() {
  int sens = analogRead(0);
  RUNEVERY(500) {
    Serial.print(F("Sens: "));
    Serial.println(sens);
  }
}

That's untested, since I don't have arduino on this computer. But if that works, I'd support it being defiend in Arduino.h --- it is extremely useful and would preempt a lot of questions on this forum. (Although there is something to be said for learning to do it the "right" way, the same can be said of "hibyte," "lowbyte," "shiftout," "bitRead," etc.)

I've never tried declaring a static variable in the initialisation expression of a for loop. It that legal?

Yes, its legal. If GCC is standard conforming, it should only be in scope for the loop that's all.

"Run every" implies that it should run N times in T time...

#define RUNEVERY(n) for (static unsigned long lasttime, unsigned long t = (n); millis() - lasttime > t; lasttime += t)

"Run after" implies that it should run after T milliseconds have elapsed...

#define RUNAFTER(n) for (static unsigned long lasttime; millis() - lasttime > (n); lasttime = millis())

The variable should be named to reduce the chances of a conflict...

#define RUNAFTER(n) for (static unsigned long _lasttime; millis() - _lasttime > (n); _lasttime = millis())

To be more Arduinoish the macro should be named in modified camel...

#define runAfter(n) for (static unsigned long _lasttime; millis() - _lasttime > (n); _lasttime = millis())

To eliminate drift, time should be sampled once...

#define runAfter(n) for (static unsigned long _lasttime, unsigned long _thistime = millis(); _thistime - _lasttime > (n); _lasttime = _thistime)

The error needs to be eliminated...

#define runAfter(n) for (static unsigned long _lasttime, unsigned long _thistime = millis(); _thistime - _lasttime >= (n); _lasttime = _thistime)

16 bit may be a better choice...

#define runAfter(n) for (static uint16_t _lasttime, uint16_t _thistime = millis(); (uint16_t)(_thistime - _lasttime) >= (uint16_t)(n); _lasttime = _thistime)

What did I forget?

static uint16_t _lasttime, uint16_t _thistime

is illegal. You might be able to do some strange things with a struct though:

#define runAfter(n) for (struct { static uint16_t last; uint16_t now; } _rA = {0, millis()}; _rA.now - _rA.last >= (n); _rA.last += (n))

That doesn't work either, though: static means something different there.

I also think that runEvery is a better name because it reads "Run every 500" (ms) which is exactly what it does. runAfter imples it only runs once, and has a built in delay.

_thistime is unnecessary if you do the += (n) trick, since then millis() wil only be called once.

so this is what I'm thinking of:

#define runEvery(t) for (static uint16_t _lasttime; millis() - _lasttime > (t); _lasttime += (t))

which is tested and works on my uno.

Thanks for checking it out though --- hopefully a macro like this one will be useful to others.

WizenedEE:

static uint16_t _lasttime, uint16_t _thistime

is illegal. You might be able to do some strange things with a struct though:

According to the standard. 6.5.3 - 3

If the for-init-statement is a declaration, the scope of the name(s) declared extends to the end of the for-statement.

But I see the static now, :frowning: . hmmm

Both the original (random) and my hack (bitwise and) don't use extra ram...
Whether they're suitable or not depends on unspecified requirements and behaviors.

Nice Macro! Very useful. I wish there was a way for beginners to find it easily while Googling.

sbright33:
I wish there was a way for beginners to find it easily while Googling.

You can give Google a helping hand. If you or anyone you know has a blog, add a paragraph or two about the macro and include a link to this topic.

pYro_65:

WizenedEE:

static uint16_t _lasttime, uint16_t _thistime

is illegal. You might be able to do some strange things with a struct though:

According to the standard. 6.5.3 - 3

If the for-init-statement is a declaration, the scope of the name(s) declared extends to the end of the for-statement.

But I see the static now, :frowning: . hmmm

Well I wasn't referring to it being a for loop, I was saying that you can't use commas to declare two variables with different types --- like one int and one float or one static int and one int.

You can give Google a helping hand.  If you or anyone you know has a blog, add a paragraph or two about the macro and include a link to this topic.

Well then I'd feel special.

Is the playground a good place to put it? Or put a feature request in the google code place.

WizenedEE:
Is the playground a good place to put it?

Yes.

Or put a feature request in the google code place.

Yes.

I believe a Github pull request increases the chances of getting it into a release.

Here's a link to the thread I just made about this macro:

http://arduino.cc/forum/index.php/topic,124974.0.html