Arduino Forum

Development => Other Software Development => Topic started by: avandalen on Oct 10, 2016, 01:37 pm

Title: VirtualDelay
Post by: avandalen on Oct 10, 2016, 01:37 pm
Introduction

The standard delay() function blocks the Arduino which is not allowed sometimes. We can find several examples on Internet to overcome this, but there was no method to use non-blocking delays on an easy way. Therefore, I have built the VirtualDelay library. It has been kept as simple as possible to save memory space and optimize the speed.
See the whole article HERE (http://www.avdweb.nl/arduino/libraries/virtualdelay.html)

Advantages of the VirtualDelay library



Interface

There are 2 member functions, see the examples how to use.
done() Use this if we need just one delay.
proceed() Use this if we need more delays with one VirtualDelay object. End with done().

Notes

The VirtualDelay must always run inside a loop, but this is usually the case with embedded software such as the Arduino platform.
We need an "if" statement, in contrast with the standard delay() function.
The timing of VirtualDelay starts at the beginning of the sketch in contrast to delay() which starts at the function itself.

The simplest VirtualDelay example

Here a simple blinking LED sketch with the VirtualDelay:

#include <Arduino.h>
#include <VirtualDelay.h>
 
const byte ledPin = 13;
 
bool b;
VirtualDelay virtualDelay(millis);
 
void setup()
{ pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
}
 
void loop()
{ if(virtualDelay.done(500)) digitalWrite(ledPin, b=!b); // the LED blinks on and off
}


Title: Re: VirtualDelay
Post by: Robin2 on Oct 10, 2016, 04:02 pm
Interesting. Thanks for sharing.

Can you explain how it works?

As far as I can see this
Code: [Select]
    if(virtualDelay.done(500))  {
        digitalWrite(ledPin, b=!b); // the LED blinks on and off
    }

is equivalent to this
Code: [Select]
    if (millis() - previousMillis >= 500) {
        previousMillis += 500;
        digitalWrite(ledPin, b=!b);
    }


...R
Title: Re: VirtualDelay
Post by: avandalen on Oct 10, 2016, 04:12 pm
Interesting. Thanks for sharing.

Can you explain how it works?

As far as I can see this
Code: [Select]
    if(virtualDelay.done(500))  {
        digitalWrite(ledPin, b=!b); // the LED blinks on and off
    }

is equivalent to this
Code: [Select]
    if (millis() - previousMillis >= 500) {
        previousMillis += 500;
        digitalWrite(ledPin, b=!b);
    }


...R
Yes it is equivalent in this example I suppose.
Title: Re: VirtualDelay
Post by: Robin2 on Oct 10, 2016, 06:31 pm
Can you explain, please, how your program works?

...R
Title: Re: VirtualDelay
Post by: rhuseman on Nov 15, 2016, 05:53 pm
where can I download the .zip for this library?  I don't see it on arduino's website or the site above (http://www.avdweb.nl/arduino/libraries/virtualdelay.html (http://www.avdweb.nl/arduino/libraries/virtualdelay.html))
Title: Re: VirtualDelay
Post by: Qdeathstar on Nov 16, 2016, 12:34 am
It seems like you've managed to turn a round wheel square. Intriguing.
Title: Re: VirtualDelay
Post by: jimLee on Dec 03, 2016, 07:29 am
Haha don't let them get you down. I tried to share my solution to the blocking delay() deal and I was told that it was something like "empty code that adds no functionality." or something similar.

If it helps you great. I know I'd be far less happy without mine. (It fixes what I don't want to think about.) I suppose that people just think different. Therefore different things stump different people.

-jim lee
Title: Re: VirtualDelay
Post by: Robin2 on Dec 03, 2016, 11:05 am
Writing a program for a microprocessor is very different from writing a program for a PC that runs at 1.6GHz and had 2 Gigabytes or more of RAM.

IMHO thorougly learning Blink Without Delay helps people to see the design of microprocessor programs from a more useful point of view.

...R
Title: Re: VirtualDelay
Post by: pYro_65 on Dec 04, 2016, 04:18 am
Writing a program for a microprocessor is very different from writing a program for a PC that runs at 1.6GHz and had 2 Gigabytes or more of RAM.
...and??

Running multiple sections at once, and timing is in no way specific to uc's and the capabilities of the device really mean nothing here. If you think that millis() is some 'special' type of event management you are quite mistaken.

In fact the BWoD example is extremely trivial compared to systems with multiple cores and threading. Getting something to trigger at a certain value of 'millis()' in no way compares to synchronization of threads using mutex's and semaphores. And before you say it, yes there are many microprocessors that have multiple cores and there are even OS's for AVR which have threading models in them.


IMHO thorougly learning Blink Without Delay helps people to see the design of microprocessor programs from a more useful point of view.
So you hide the design and useful features of the processor in functions like millis() but turn your nose up at code that uses millis() inside it. Learning to use this library for instance will still give someone the ability to understand timing principles.

And I'm sure you are quick to dismiss operating systems for the AVR, however threading and synchronization are fundamental parts of modern computing. On powerful multi core uc's the basic single threading approach you know and love may mean that you can never use the real potential of the CPU.

It is far more beneficial to be able to use tools written for a purpose than to hack a specific piece of hardware to bits trying to understand its intricacies. You should never prematurely optimize Robin, just get some results then improve.
Title: Re: VirtualDelay
Post by: Robin2 on Dec 04, 2016, 10:50 am
Even as I was writing Reply #7 I was conscious that I was not expressing what I wanted to say very well, but at the time it was the best I could come up with.

My objection is not about using tools (I habitually use an electric saw rather than a hand saw) but about the business of visualizing how a microprocessor program needs to be constructed.

You, yourself say "Running multiple sections at once, and timing is in no way specific to uc's" which leads me to believe that you (consciously or unconsciously) understand what needs to happen. Perhaps you have forgotten when you didn't.

But when I see people struggling to understand BWoD I see people who do NOT understand what needs to happen. My objection to hiding the innards of BWoD is because doing so delays the moment when they reach that understanding. And, from what I have seen here on the Forum, those newbies also make a lot of other silly mistakes that are also associated with that absence of understanding.

I guess I see BWoD as the equivalent of learning the alphabet if one wants to read and write.

When a person is writing a program for a PC it mostly does not matter whether it uses CPU cycles or RAM efficiently and people who do not understand stuff can get perfectly satisfactory results. You cannot ignore the limitations of an MCU.

...R
Title: Re: VirtualDelay
Post by: pYro_65 on Dec 04, 2016, 11:31 am
I guess I see BWoD as the equivalent of learning the alphabet if one wants to read and write.
You pointed out in reply #1 that the two examples are equivalent. A beginner could use either version to learn the same concept of triggering an event after a certain amount of time, rather than waiting/delaying.

You have simply taken preference for one high level API over the other. And neither show any fundamentals of micro-controllers as they implement the low level functionality internally.

And both causes a waste of cycles if millis() can be entirely removed and the hardware timer callback used directly, as every millisecond, or whatever true resolution millis() has, an interrupt is run.

But I guess you see it as fine to "ignore the limitations" when the benefit of an easy to use high level API makes your code simpler to understand... This library is providing the same benefits you are endorsing with the Arduino API, but at the same time are arguing against.

Don't get me wrong, a trade off for efficiency vs ease of use is fine when it is within your programs constraints, however, here you are comparing an orange with an orange.
Title: Re: VirtualDelay
Post by: Robin2 on Dec 04, 2016, 03:34 pm
I think we are each looking at different aspects of the same thing. Let's agree to disagree.

...R
Title: Re: VirtualDelay
Post by: pYro_65 on Dec 05, 2016, 06:42 am
Let's agree to disagree.

...R
Never!
Its a fight to the death.

I do not see how the skills learned in one of the above mentioned examples are not commutative with the other. Maybe you're talking about mostly unimportant stuff like the long value or the use of the >= comparison...

Title: Re: VirtualDelay
Post by: alah on Jun 16, 2017, 01:56 pm
Thanks, seems interesting, but,  what about the download link?
Title: Re: VirtualDelay
Post by: bobcousins on Jun 19, 2017, 05:43 pm
Thanks, seems interesting, but,  what about the download link?
There doesn't appear to be a zip download, but you can copy and paste the code from the web page (linked in first post).
Title: Re: VirtualDelay
Post by: avandalen on Sep 04, 2017, 05:01 pm
----- IMPORTANT -----

The library has been completely rewritten because there was a bug in the function proceed(). see:
http://www.avdweb.nl/arduino/libraries/virtualdelay.html (http://www.avdweb.nl/arduino/libraries/virtualdelay.html)
Title: Re: VirtualDelay
Post by: rhubka on Oct 19, 2017, 02:47 am
Thanks avandalen

I've downloaded your updated Delay library from Github
Github (https://github.com/avandalen/VirtualDelay)

I'm going to start playing with it.

The thought of the Delay() stopping code execution drives me crazy. >:(

Cheers

Rick Hubka

Title: Re: VirtualDelay
Post by: sechen on Dec 13, 2017, 09:28 pm
Hi!
Does it work with Leonardo?
According description it's great but can't compile
Title: Re: VirtualDelay
Post by: avandalen on Feb 06, 2018, 04:32 pm
Thanks avandalen

I've downloaded your updated Delay library from Github
Github (https://github.com/avandalen/VirtualDelay)

I'm going to start playing with it.

The thought of the Delay() stopping code execution drives me crazy. >:(

Cheers

Rick Hubka
try the new version, everything is tested

Title: Re: VirtualDelay
Post by: avandalen on Feb 06, 2018, 04:33 pm
Hi!
Does it work with Leonardo?
According description it's great but can't compile
yes AVR and SAMD21
Title: Re: VirtualDelay
Post by: TonyWilk on Feb 09, 2018, 07:33 am
Hi,
I'm sure we're in 'better mousetrap' territory here and these things are prone to personal preferences, but here's my view...

On your linked page, you ought to have several examples of your library which tries to show how it simplifies the code and makes it more readable.

At the moment it seems to show how much of an unreadable nightmare you can create.

In your post you give:

void loop()
{ if(virtualDelay.done(500)) digitalWrite(ledPin, b=!b); // the LED blinks on and off
}

and on the page:

void loop()
{ singleDelay.start(400); // calls while running are ignored
  if(singleDelay.elapsed()) digitalWrite(ledPin, b=!b); // blink the onboard LED 400ms, 400ms off
}

...which just highlights to me that there is a problem in using this library and making it obvious and readable.
Having hidden functionality and/or side-effects to methods which requires you to comment it just to save a line of code is not a good idea.

I'd prefer:

if( singleDelay.stopped() )
  singleDelay.setRepeatingInterval(400);
if( singleDelay.elapsed() )
  //do the LED thing


Yours,
  TonyWilk


Title: Re: VirtualDelay
Post by: avandalen on Feb 09, 2018, 12:22 pm
Dear Tony

Thank you for your comments, I always like to hear if something can be improved

There is no virtualDelay.done  function anymore in the new version:
http://www.avdweb.nl/arduino/libraries/virtualdelay.html

>> I'd prefer:
if( singleDelay.stopped() )
  singleDelay.setRepeatingInterval(400);
if( singleDelay.elapsed() )
  //do the LED thing


Yes, that looks good, but I have no time to rewrite the library. Maybe we can change just the names of some functions to make it better understandable?
Title: Re: VirtualDelay
Post by: TonyWilk on Feb 09, 2018, 12:47 pm
Hi,
Maybe we can change just the names of some functions to make it better understandable?
Yes, I think that the actual names of methods can make a great deal of difference to the usability of a class.

In some cases it might be handy to simply provide some aliases for different use-cases (I know there are different opinions on this)
for example:

myclass.setTimeout( 250 );
if( myclass.hasTimedOut() )
...

myclass.setRepeatingInterval( 100 );
if( myclass.intervalHasElapsed() )
...

... could be that hasTimedOut() and intervalHasElapsed() are internally identical.

Yours,
 TonyWilk




Title: Re: VirtualDelay
Post by: avandalen on Feb 09, 2018, 10:29 pm
Hi,
Yes, I think that the actual names of methods can make a great deal of difference to the usability of a class.

In some cases it might be handy to simply provide some aliases for different use-cases (I know there are different opinions on this)
for example:

myclass.setTimeout( 250 );
if( myclass.hasTimedOut() )
...

myclass.setRepeatingInterval( 100 );
if( myclass.intervalHasElapsed() )
...

... could be that hasTimedOut() and intervalHasElapsed() are internally identical.

Note that DO_ONCE is still needed sometimes.
Can you please change the 5 examples with your function names?
Hi,
Yes, I think that the actual names of methods can make a great deal of difference to the usability of a class.

In some cases it might be handy to simply provide some aliases for different use-cases (I know there are different opinions on this)
for example:

myclass.setTimeout( 250 );
if( myclass.hasTimedOut() )
...

myclass.setRepeatingInterval( 100 );
if( myclass.intervalHasElapsed() )
...

... could be that hasTimedOut() and intervalHasElapsed() are internally identical.
I'm curious how your idea will work with the 5 examples in:
http://www.avdweb.nl/arduino/libraries/virtualdelay.html
Can you test it with the 5 examples? (Note that DO_ONCE is still needed sometimes)