Problem with 'empty' wline-loops (or another way to avoid delay)

Hi,

I have a problem and I don't really see what is happening.

I want to replace delay() with my own function and use millis().

Here is the code:

unsigned long returnmilli = 0;
void mydelay(unsigned long foo)
{
  returnmilli = millis()+foo;
  while(returnmilli>=millis())
  {
    delay(1);
  }
}

It's pretty simple, call the function with a number,
the function put the number + millis() into a variable, and does a while loop as long as the millis() is smaller than the variable.

and everything works good,

the problem arrives when I remove the delay(1); inside the while-loop (I did say that I didn't want to use delay - right).

So, I remove the delay() inside the while-loop, and the system crashes immediately when the function is called.

Soft WDT reset

ctx: cont 
sp: 3fff0980 end: 3fff0be0 offset: 01b0

>>>stack>>>
3fff0b30:  0000001c 00000000 3ffefafc 401004d8  
3fff0b40:  feefeffe 00000001 00000d8a 4020671a  
3fff0b50:  00000000 000000a6 0000000b 4020677c  
3fff0b60:  0000000f 00000011 3ffefafc 3ffefbb8  
3fff0b70:  3fffdad0 00000000 3ffefbb0 402067de  
3fff0b80:  3ffe8440 0000000f 3ffefafc 40207f38  
3fff0b90:  402010ae 0000001e 3ffefafc 40207f5c  
3fff0ba0:  3fffdad0 3ffefafc 3ffef9e4 4020666e  
3fff0bb0:  feefeffe feefeffe feefeffe 3ffefbb8  
3fff0bc0:  3fffdad0 00000000 3ffefbb0 40208634  
3fff0bd0:  feefeffe feefeffe 3ffefbc0 40100718  
<<<stack<<<

 ets Jan  8 2013,rst cause:2, boot mode:(3,6)

load 0x4010f000, len 1384, room 16 
tail 8
chksum 0x2d
csum 0x2d
v09f0c112
~ld
ü


Booting....

I even tried to do some other stuff inside the wile (declare variables, serialprint's and so, but nope, it crashes).

anyone have any clues?

/M

anyone have any clues?

Must be something in the code you didn't post.

Whatever you put in the body of the while loop will cause the function to block, doing just that one thing, so be sure that you name the function appropriately. Something like myHeadInTheSandBlockingFunction().

You've created a function that does exactly the same thing as delay() (except your code won't work right when millis() rolls over...), your code has the same problem as delay()(i.e. - it blocks), but you do it using considerably more code than a simple call to delay(). What on earth is the point?

Regards,
Ray L.

(deleted)

My point is that I want to replace all delay() with mydelay()

In the loop I will do some checks for different actions such as mqtt subscriptions, buttons (pin inputs), and sometimes also check status on a website.

The exact timing is not so important (the delay is primary used from a neopixel-fade-loop and an update to a small oled screen.

I was just curios why an empty while-loop would crash. In my opinion it should just loop until the conditions was met.

It may be the housekeeping routine that crashes, but when I found the 'bug' I was fading a neopixel and called the function for 20ms each time, and that seems like a really short period.

My point is that I want to replace all delay() with mydelay()

As has been pointed out your function, when it works, will block program operation as much as the delay() function does.

Just because your function used millis() does not mean that it will not block. There are, of course, ways to use millis() for timing that does not block but what you have done is not one of them.

As I said, I will do some checks within the while-loop (in this case I wanted to combine the functions from adafruits neopixellibrary (that all uses delay(X) , and want to check for some conditions during the delays.

So I thougth that a quick search for delay() and replace with mydelay() would be quick, and that's where I found the bug.

When I have the different checks inside the loop it all works good. However, - I don't understand why a empty while-loop should restart the system.

Don't reinvent the wheel ?

What does the loop() function do as implied by its name ? Why use a while loop when the looping mechanism is already available ?

Have a look at Several things at the same time

It sounds more like an attempt to create co-operative mutlittasking. When one task needs to wait for something to do, it asks the other tasks if they have anything to do.

If that's what you want to do then make it your main loop. Don't call it myDelay().

Also, never add milliseconds, always subtract. See Nick Gammon's page.

No stop guys!

He's on the right track.

In the loop I will do some checks for different actions such as mqtt subscriptions, buttons (pin inputs), and sometimes also check status on a website.

I think MorganS sees it. Just expand the user delayLoop() to be the main loop() and he's got it. He's almost there.

-jim lee

No stop guys!

He's on the right track.

Thanks Jim ;=)

In the loop I check for mqtt-subscriptions, a button and also a pir-sensor, and it all works good. ( I don't know how it works when the millis() wraps, but I dont think it'll ever gonna happen in my case, cause this thing is only on when the bar is open ;=)

It's a quick and easy way to copy/paste the neo-pixel code-examples ( search-replace "delay" to "mydelay" ).

However, I still don't understand why a 'empty' while-loop would crash, and I guess that's a question for another time :wink:

Um.. How to explain this?

What you are trying to do with your home-rolled delay is achieve multi threaded code. Basically, start a thread, roll along for a bit then give up the processor to do whatever it wants to do for X amount of time. Then, come back and pick up where you left off, threading. UNIX uses this like candied popcorn.

Why can UNIX do this and you can't? To put it simply, UNIX keeps track of where all the threads, or processes, left off. So they can pick up again where they left off. The Arduino doesn't have this. When you leave off, there's no one with the bookmark waiting when you come back to show you where you left off.

So, as you struggle, rolling your own delay(), everyone else is down the road yelling and waving flags going "Don't go down this road! Its a dead end. It won't work like you want it to."

You have to readjust your thinking.

You wrote a loop that allows some things to go on while you wait for the right time to do your thing.

You already HAVE this loop given to you ->> void loop() { } Its a loop that lets things run until its time to do your thing. Instead of looping 'till your time is up, use the "real" loop forever and just do your thing when the time is up.

I know this won't allow you to easily import some of the stuff you see on the net for neopixels. But really, once you get a grip on doing them the "correct way".. You'll see there's not much out there worth porting.

Set a timer for when you need to take your next step. Kick back and let loop run until the timer goes off, do your step, reset the timer repeat.

The timer can be as simple as your saved milliseconds number. When now>saved, do your thing add more to saved.

I hope this helps.

-jim lee