Go Down

Topic: delayAsync::Suggestion to simplify millis( ) for beginners (Read 795 times) previous topic - next topic

vbextreme

Forum pour millions of threads on how you use millis( ), I would try to find a solution.
My idea is this
Code: [Select]

/*********************************************/
/* Delay Async v. beta.0                     */
/* vbextreme <vbextreme@vbextreme.netai.net> */ 
/*********************************************/

uint8_t _delayAsync(uint8_t id, uint32_t ms)
{
    struct ellapsed
    {
        uint8_t id;
        uint32_t Mst;
        uint32_t mst;
        struct ellapsed* next;
    };
    static struct ellapsed* at = NULL;
    struct ellapsed* t;
   
    uint32_t mst = micros();
    uint32_t Mst = millis();
   
    if ( at && at->id == id )
    {
        if ( millis() - at->Mst >= ms - 1)
        {
            mst = at->mst;
            t = at;
            at = at->next;
            free(t);

            while ( micros() - mst < ms * 1000 );
            return 1;
        }
        return 0;
    }

    for ( t = at; t->next; t = t->next )
    {
        if ( t->next->id == id )
        {
            if ( millis() - t->next->Mst >= ms - 1)
            {
                mst = t->next->mst;
                struct ellapsed* r = t->next;
                t->next = t->next->next;
                free(r);
               
                while ( micros() - mst < ms * 1000 );
                return 1;
            }
            return 0;
        }
    }

    t = (struct ellapsed*) malloc( sizeof(struct ellapsed) );
    t->id = id;
    t->mst = mst;
    t->Mst = Mst;
   
    t->next = at;
    at = t;
   
    return 0;
}

#define delayAsync(MS) _delayAsync(__COUNTER__, MS)

/********************************************************************/


The call to delayAsync() accept argument as milliseconds and returns 0 if not yet passed to the time spent , it will return 1 if the time has passed.
The call to delayAsyncMicroseconds() accept argument as microseconds and returns 0 if not yet passed to the time spent , it will return 1 if the time has passed.

Example:
Code: [Select]

#include "delayAsync.h"

uint8_t stato = 0;

void setup() {
    Serial.begin(9600);
    pinMode(13,1);
    digitalWrite(13,0);
    stato = 0;
   
}

void loop()
{
    if ( delayAsync(500) )
    {
        stato = !stato;
        digitalWrite(13,stato);
    }

    if ( delayAsync(1000) )
    {
        Serial.println("ellapse 2s");
    }
   
}

What do you think?
Easy framework linguaggio C: https://github.com/vbextreme/EasyFramework
Hack your life: http://vbextreme.netai.net/
Unoffical Telegram group: https://telegram.me/joinchat/ALRu8ACkdTdXyz-2P7v13A

PaulS

Code: [Select]
        uint32_t Mst;
        uint32_t mst;

Variables that differ only in case are a disaster lying in wait. Don't do stupid stuff like that.

Does MS mean MicroSoft? MilliSeconds? MicroSeconds? Short names are good, within reason.
The art of getting good answers lies in asking good questions.

kowalski

There is some code in the Arduino main.cpp that could cause an issue when busy-waiting:
Code: [Select]

int main(void)
{
        ...
 setup();  
 for (;;) {
 loop();
 if (serialEventRun) serialEventRun();
 }      
 return 0;
}

Looks like serialEvent handling could be blocked?

There is yet another issue: What happens if malloc() returns NULL?

Cheers!

-dev

Don't use free/malloc.  "Dynamic memory" is not suitable for embedded devices, because it is not deterministic.  Instead, use statically-allocated pools of a maximum size.  This shows that you have not analyzed its long-term behaviour, nor experienced the frustration of random failures.

PaulS

Don't use free/malloc.  "Dynamic memory" is not suitable for embedded devices, because it is not deterministic.  Instead, use statically-allocated pools of a maximum size.  This shows that you have not analyzed its long-term behaviour, nor experienced the frustration of random failures.
I don't have a problem with free/malloc. I do have a problem with ASSuming that malloc() succeeded.
The art of getting good answers lies in asking good questions.

Robin2

Forum pour millions of threads on how you use millis( ), I would try to find a solution.
I appreciate your intentions.

But I would much prefer to try to explain to someone how to use millis() than to explain to them how to get out of a problem in your code.

And, believe me, people will get into difficulties either because of something you have missed or some stupidity (or reasonable misunderstanding) on their part.

May I respectfully suggest that you divert your efforts into writing a clear explanation of the use of millis().

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

testato

- [Guida] IDE - http://goo.gl/ln6glr
- [Lib] ST7032i LCD I2C - http://goo.gl/GNojT6
- [Lib] PCF8574+HD44780 LCD I2C - http://goo.gl/r7CstH

vbextreme

Quote from: @PaulS
Does MS mean MicroSoft? MilliSeconds? MicroSeconds? Short names are good, within reason.
MS not Microsoft otherwise I would write M$
:)
Better?

@kowalski, The delayAsync not block execution of code and therefore the serialEvent will always be executed .
I proceeded for a safe call to malloc

@/dev, The same C++ is not recommended on the MCU! but you can use along with String.


@Robin2, There are many tutorials , in all languages.
I know that she loves to millis() but does not think it is helpful to Arduino novices? or those with Arduino does not want to learn programming but simply reach his goal?




Code: [Select]

/*********************************************/
/* Delay Async v. beta.1                     */
/* vbextreme <vbextreme@vbextreme.netai.net> */ 
/*********************************************/
uint8_t _delayAsync(uint8_t id, uint32_t ms)
{
    struct ellapsed
    {
        uint8_t id;
        uint32_t usStart;
        uint32_t msStart;
        struct ellapsed* next;
    };
    static struct ellapsed* allDelay = NULL;
    struct ellapsed** ad;
   
    uint32_t usNow = micros();
    uint32_t msNow = millis();
   
    for( ad = &allDelay; NULL != *ad && (*ad)->id != id; ad = &(*ad)->next);

    if ( NULL == *ad )
    {
        struct ellapsed* newd = (struct ellapsed*) malloc( sizeof(struct ellapsed) );
            if ( NULL == newd ) return 0;
        newd->id = id;
        newd->usStart = usNow;
        newd->msStart = msNow;
        newd->next = allDelay;
        allDelay = newd;
        return 0;
    }

    if ( millis() - (*ad)->msStart >= ms - 1)
    {
        while ( micros() - (*ad)->usStart < ms * 1000 );
       
        struct ellapsed* freed = *ad;
        *ad = (*ad)->next;
       
        free(freed);
        return 1;
    }
    return 0;
}
Easy framework linguaggio C: https://github.com/vbextreme/EasyFramework
Hack your life: http://vbextreme.netai.net/
Unoffical Telegram group: https://telegram.me/joinchat/ALRu8ACkdTdXyz-2P7v13A

kowalski

@vbextreme

I see that there is still busy-wait that can delay Serial event handling. Is that correct?

Cheers!

Robin2

@Robin2, There are many tutorials , in all languages.
I may be wrong, but I have the impression that you don't think they are adequate. That is why I think it would be useful for you to write a tutorial that would satisfy you. It may then help a lot of others also.


Quote
I know that she loves to millis() but does not think it is helpful to Arduino novices? or those with Arduino does not want to learn programming but simply reach his goal?
I don't mean to be unkind, but I hope your documentation for your function will be easier to understand than this piece.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

-dev

Quote from: verbose extreme
The same C++ is not recommended on the MCU!  [citation needed]
The same has been said for assembly vs. C.  In either case, the real problem is that PC programmers, who happen to use C, C++ or VisualBasic on the PC, write inappropriate code for MCUs.  It's not the language, it's their style.  A quick google search finds this at embedded.com, this 17 year-old paper from an Embedded Systems conference, and this upvoted answer at stackoverflow, which concludes with

Quote
[C++] can be written in a very efficient manner, but it's harder to learn how to do it correctly than with C. It can sometimes work better than C at solving a problem and sometimes expressing an better interface, but again, you've got to educate yourself and not be afraid to learn how.
A prime example of this is Cosa.  It is obviously hard to write cleanly-designed, efficient, OO frameworks, as there are so few of them, IMO.

Quote
but you can use along with String.
Uh, no, and for the same reason that you shouldn't use C++ new & delete.  Even though it's easy to use and understand, it is not appropriate for MCUs.  Suggesting this reveals your inexperience.  You'll learn, one way or another.

vbextreme

Quote from: @Kowalski
I see that there is still busy-wait that can delay Serial event handling. Is that correct?
I think that you refer to this row
Code: [Select]

while ( micros() - ad->usStart < ms * 1000 );

And you are absolutely right, you could lose up to one ms ( milliseconds not Microsoft ), a small delay for greater accuracy .
But following your advice and using the Arduino philosophy I wrote two functions delayAsync() and delayAsyncMicroseconds(), in this way it will also be simpler, thanks.

@Robin2, I do not think to be able to write better documentation , they are already perfect , at least from my point of view.
But Arduino should be simple, many users do not learn to programming! they just want to turn on their Christmas tree!





@/dev, my inexperience says the when a function is not to be used must declare it "deprecated", COSA have string and use new && delete! and if COSA is a real OOP You should not use character arrays, as in your examples.
You can use strings? and you can use delayAsync.
Do not get me wrong, I think it is a good project and were very good at developing it, it seems to have some bugs but I'm sure they fix.
I'd like to remember that we are talking about Arduino .
and a pair of malloc to blink without delay will not precipitate an airplane.
Avoid the war of religion and will not answer more to OT.





new release implement delayAsyncMicroseconds()
Code: [Select]

/*********************************************/
/* Delay Async v. beta.2                     */
/* vbextreme <vbextreme@vbextreme.netai.net> */ 
/*********************************************/
uint8_t _delayAsync(uint8_t id, uint32_t ms, uint32_t(*fnctime)(void))
{
    struct ellapsed
    {
        uint8_t id;
        uint32_t start;
        struct ellapsed* next;
    };
    static struct ellapsed* allDelay = NULL;
    struct ellapsed** ad;
   
    uint32_t now = fnctime();
   
    for( ad = &allDelay; NULL != *ad && (*ad)->id != id; ad = &(*ad)->next);

    if ( NULL == *ad )
    {
        struct ellapsed* newd = (struct ellapsed*) malloc( sizeof(struct ellapsed) );
            if ( NULL == newd ) return 0;
        newd->id = id;
        newd->start = now;
        newd->next = allDelay;
        allDelay = newd;
        return 0;
    }

    if ( fnctime() - (*ad)->start >= ms)
    {
        struct ellapsed* freed = *ad;
        *ad = (*ad)->next;
        free(freed);
        return 1;
    }
    return 0;
}

#define delayAsync(MS) _delayAsync(__COUNTER__, MS, millis)
#define delayAsyncMicroseconds(MS) _delayAsync(__COUNTER__, MS, micros)


Have a good life
Easy framework linguaggio C: https://github.com/vbextreme/EasyFramework
Hack your life: http://vbextreme.netai.net/
Unoffical Telegram group: https://telegram.me/joinchat/ALRu8ACkdTdXyz-2P7v13A

Robin2

@all, new code at first post.
When you have new code post it in the correct chronological position. By changing the code in your first post you make a nonsense of all the comments that follow it. How do you expect a new reader to make sense of the Thread?

Please reinstate the Original Post and put the new code in a Reply after this Reply.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

vbextreme

Easy framework linguaggio C: https://github.com/vbextreme/EasyFramework
Hack your life: http://vbextreme.netai.net/
Unoffical Telegram group: https://telegram.me/joinchat/ALRu8ACkdTdXyz-2P7v13A

PaulS

Quote
Please reinstate the Original Post and put the new code in a Reply after this Reply.
Quote
@Robin2, done.
Well, half way, anyway.
The art of getting good answers lies in asking good questions.

Go Up