Go Down

Topic: Delays and unsigned long (Read 3323 times) previous topic - next topic

Nick Gammon

You have a good point, although I'm still uneasy about that code.

Why can't delay look like this?

Code: [Select]

void delay(unsigned long ms)
{
  ms *= 1000;  // turn into microseconds
  unsigned long start = micros ();
  while (micros () - start < ms)
    { }
}


I know, that will wrap around after 71 minutes, but who delays that long?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

GoForSmoke


You have a good point, although I'm still uneasy about that code.

Why can't delay look like this?

Code: [Select]

void delay(unsigned long ms)
{
  ms *= 1000;  // turn into microseconds
  unsigned long start = micros ();
  while (micros () - start < ms)
    { }
}


I know, that will wrap around after 71 minutes, but who delays that long?



LOL, Procrastinators!

Really though, that code looks like it might be efficient or sumthing.  XD
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Nick Gammon


Really though, that code looks like it might be efficient or sumthing.  XD


Or this, which handles longer delays:

Code: [Select]

void delay(unsigned long ms)
{
  unsigned long start;
 
  // short delays, allow for the fact that we might
  // be half-way through a millisecond
  if (ms < 60000)
    {
    ms *= 1000;  // turn into microseconds
    start = micros ();
    while (micros () - start < ms)
      { }
    }  // end of if short delay
  else
    {  // longer delays
    start = millis ();
    while (millis () - start < ms)
      { }
    }  // end of longer delay
}


Bit long-winded maybe.

I'm inclined to go with the simple one:

Code: [Select]

void delay(unsigned long ms)
{
  unsigned long start = millis ();
  while (millis () - start < ms)
    { }
}


And just warn users that for very short delays, the time may be out a bit depending on how far through the next "millis" tick you start. However for short delays there is always delayMicroseconds.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

GoForSmoke

The code in reply # 30 is the better one.

Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Jim_Socks

WOW!

I got taken away on a short notice work trip, but I didn't expect to see three pages of replies when I returned!  You guys got way into it!

I am glad you spotted my folly with the = instead of ==, I'll fix that right away.

As for the suggestion that I should just pass delay(); an unsigned long- if you look at my code from page one, you will see that the array used AND the "pourdelay" ARE in fact unsigned long variables.  I am only hoping you can spot where I am overlooking something I am passing delay that isn't- as that would be an easy fix!

The discussion as to how delay works was a bit over my head, but what I pulled from it is that even though delay accepts an unsigned long variable, it still won't count past a regular integer?  (In the original post, I realized that 32 seconds alluded to it stopping after reaching integer length- I just hoped it wasn't true?)

So,if I follow discussion on the last page...  I should create a new version of the delay function, which will be able to count higher but slightly less accurately?  Let me know if I understood that incorrectly?

P.S.  Due to the pumps I am using and the vertical distance being covered by the lines, the pour is very slow.  I'll fix that later by ordering bigger pumps... maybe... it's still more convenient than digging out all the ingredients in a seven ingredient drink...- but for now anyways pour times can easily exceed 32 seconds even for regular sized drinks.  Sorry, Goforsmoke- no giant drinks here  ;)

Additionally, with the power supply I have used- only one pump is capable of running at any given time.  The idea that I should have the computer checking other sensors or running other pumps or doing anything at all whilst pumping isn't something I am interested in incorporating.  The code already keeps track of every bottle and alerts me when they reach a certain level- which is all the help I require from it.  When it is pouring- that's all I want it doing.

If I can fix this delay problem- I will be in business here.  Fingers crossed that I can!

Nick Gammon


So,if I follow discussion on the last page...  I should create a new version of the delay function, which will be able to count higher but slightly less accurately?  Let me know if I understood that incorrectly?


Delay should not fail after 32 seconds, something else will be wrong.
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

GoForSmoke

You're not using CO2 pressure to drive the liquids? Any chance to feed from overhead and use gravity?

Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

UKHeliBob

Quote
As for the suggestion that I should just pass delay(); an unsigned long- if you look at my code from page one, you will see that the array used AND the "pourdelay" ARE in fact unsigned long variables.  I am only hoping you can spot where I am overlooking something I am passing delay that isn't- as that would be an easy fix!

volume is a byte, not an unsigned long. 
Code: [Select]
void countandpour(byte array, byte volume)
So what will the result of the multiplication be ?
Code: [Select]
unsigned long pourdelay = 0;
pourdelay = volume * 9250;
delay(pourdelay);

Could it ever result in a negative number ?
Using delay() with a negative number never seems to end.  Sound familiar ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

GoForSmoke



volume is a byte, not an unsigned long. 
Code: [Select]
void countandpour(byte array, byte volume)
So what will the result of the multiplication be ?
Code: [Select]
unsigned long pourdelay = 0;
pourdelay = volume * 9250;
delay(pourdelay);

Could it ever result in a negative number ?


How does an unsigned number ever result in a negative?
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

UKHeliBob

I don't know.  Hence the question.
Would multiplying a byte by an unsigned long result in an unsigned long ?

This certainly does not produce the result that I would expect at first sight, but no doubt there is an explanation
Code: [Select]
unsigned long pourdelay = 0;
byte volume = 100;

void setup()
{
  Serial.begin(9600);
  pourdelay = volume * 9250;
  Serial.print("pourdelay is ");
  Serial.println(pourdelay);
}

void loop(){}


Output
Code: [Select]
pourdelay is 7496
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

GoForSmoke


Code: [Select]
unsigned long pourdelay = 0;
byte volume = 100;

void setup()
{
  Serial.begin(9600);
  pourdelay = volume * 9250;
  Serial.print("pourdelay is ");
  Serial.println(pourdelay);
}

void loop(){}


Output
Code: [Select]
pourdelay is 7496


I see an 8-bit unsigned multiplied by a positive value signed int being assigned to an unsigned long.

Try this, it's tested and gives the answer I expect:

Code: [Select]
unsigned long pourdelay = 0UL;
byte volume = 100;

void setup( void )
{
  Serial.begin(9600);
  pourdelay = (unsigned long)volume * 9250UL;
  Serial.print("pourdelay is ");
  Serial.println(pourdelay);
}

void loop( void ){}


Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

UKHeliBob

Yours works as expected.  Of course it does, but that is not what the OP is doing in his routine.

In my routine, why does 100 * 9250 equal 7496 ?
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

pYro_65

#42
Mar 01, 2013, 02:27 pm Last Edit: Mar 01, 2013, 02:30 pm by pYro_65 Reason: 1
volume is promoted to int, and the result overflows 16-bits

100 * 9250 = 11100001110101001000

shortened to 16 bits is 0001110101001000
which is 7496


GoForSmoke

That's what mixed-types math can do for anyone.
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

UKHeliBob

And mixed type maths is what the OP is using, so all bets are off as to what he is actually using as a parameter to delay()
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Go Up