Pages: [1] 2 3 4   Go Down
Author Topic: Delays and unsigned long  (Read 2882 times)
0 Members and 1 Guest are viewing this topic.
Illinois, US
Offline Offline
Jr. Member
**
Karma: 2
Posts: 97
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi guys!

I am feeding a delay(); an unsigned long variable- but it acts funny with anything over int size (32k)

Do delays have trouble with large numbers that won't fit in an int?

(by "acting funny" I mean that if the number I feed it is over int size, it delays forever instead of stopping. I need it to delay anywhere between 3 seconds and 200 seconds. I am hoping to accomplish that simply by using an unsigned long- but it never stops delaying if I try anything over 32 seconds)

Thanks in advance!
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 109
Posts: 4066
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Example code please.
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 94
Posts: 4758
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Guess which one delay() is,

http://www.nongnu.org/avr-libc/user-manual/group__util__delay__basic.html



Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Illinois, US
Offline Offline
Jr. Member
**
Karma: 2
Posts: 97
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Firstly, way up top in the code is this:
Code:
byte drinkozarray[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
byte drinkozprevarray[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
unsigned long pumpcompensatearray[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

Then there is "pouramount" which is used inside of "countandpour", which is then used inside of "pour"

Here is "pouramount":
Code:
 
 
void pouramount(byte drink, byte &previousdrink, unsigned long &runtime, byte volume)
{
unsigned long pourdelay = 0;

 if(drink < previousdrink) {
    previousdrink = 0;
    runtime = 0;          //when I refill the bottle and reset the count, this should reset the added runtime too.
  }
    else if(drink >= previousdrink) {
    previousdrink = drink;
    runtime = runtime + 925 * volume;  //this should add 925ms for each full oz poured to account for lack in bottle backpressure
  }                                   // seeing as every 10 qtr oz I pour, the rate drops by about one qtr oz
 
 if (volume >= 1, volume < 32){
  pourdelay = volume * 9250;
  delay(pourdelay); //9250ms = one quarter ounce.  This way, when I type in my ingredients, I just tell it how many quarter oz to pour
 }
 
else if (volume = 0){
  delay(1157);               //This gives me a way to specify a "dash", or 1/8th ounce in a recipe, without getting all math crazy
  runtime = runtime + 116;
}
else if (volume = 33){
  delay(3053);
  runtime = runtime - 305250;  //This gives me a way to specify a "third", or 1/3rd ounce in a recipe, without getting all math crazy
  runtime = runtime + 305;
}

delay(1250);  //this account for the pump spin-up time, while it's pumping liquid but none has yet come out of the nozzle
  delay(runtime); //this should add the extra backpressure acounting time to the runtime of the pump.

}

Here is countandpour:
Code:
void countandpour(byte array, byte volume) {
    if(volume >= 1, volume < 32) {
      drinkozarray[array] = drinkozarray[array] + volume;
    }
    else if(volume = 33) {
           drinkozarray[array] = drinkozarray[array] + 2;
    }
   
   pouramount(drinkozarray[array], drinkozprevarray[array], pumpcompensatearray[array], volume);

}

and last but not least, here is "pour":
Code:
void pour(byte array, int drink, byte volume)
{
  switch (drink)
  {
  case vodkas:
    digitalWrite(latch, 0);
      lightredpour1();
      pour_vodka();
    digitalWrite(latch, 1);
      countandpour(array, volume);
    break;

  case rumlts:
    digitalWrite(latch, 0);
      lightredpour1();
      pour_rumlt();
    digitalWrite(latch, 1);
      countandpour(array, volume);
    break;

//etc, etc...

You'll notice that "pour" also calls "pour_vodka();" and "lightredpour1();"
The function with the liquor name just looks like this:
Code:
void pour_vodka()
{
  shiftOut(data, clock,MSBFIRST, shiftoutarray[1]);
  shiftOut(data, clock, MSBFIRST, shiftoutarray[0]);
  shiftOut(data, clock, MSBFIRST, shiftoutarray[0]);
  //vodka = vodka + volume;
}

void pour_rumlt()
{
  shiftOut(data, clock,MSBFIRST, shiftoutarray[2]);
  shiftOut(data, clock, MSBFIRST, shiftoutarray[0]);
  shiftOut(data, clock, MSBFIRST, shiftoutarray[0]);
}

//etc, etc...

And the "lightredpour();" function just controls effect lighting, changing it to red lights while pouring.


NOW to my original problem, which occurs inside "pouramount();"
I try to feed delay
Code:
unsigned long pourdelay = 0;
pourdelay = volume * 9250;
delay(pourdelay);
and if the result is anything over 32k, the delay just never ends.  What is going on?  (Additionally, I know my code is probably sloppy... I am still a dummy at this and I am working on that.  Please try to stick to the delay problem I'm having instead of the ugliness of my code- as I would like it to work first before I spend lots of time optimizing something that doesn't work in the first place)

Oh and for those of you that have been helping me since the beginning- IT WORKS!  I have booze in it, and it is pouring recipes!  Until I fix this delay issue though, if a pour has to last longer than 32 seconds- it just pours until the end of time LOL.
Logged

Illinois, US
Offline Offline
Jr. Member
**
Karma: 2
Posts: 97
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

From the website link Goforsmoke posted:

Quote
Thus, at a CPU speed of 1 MHz, delays of up to about 262.1 milliseconds can be achieved.

Since the uno is 16 Mhz, does that mean it can only delay for 4,193.6 milliseconds?  That can't be right.  You said to guess which one delay(); is, but I am not sure either one of them is?  How can I use that in my situation (see above code)?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Thus, at a CPU speed of 1 MHz, delays of up to about 262.1 milliseconds can be achieved.

If that was true, 16MHz would be 16 milliseconds.

Try using the millis() function:

Code:
time = millis();
while (millis() <= time + 300000
{
}

That should wait until the CPU has counted up 300000 milliseconds. Pretty much the same as Delay only you are comparing values, not setting them.

Make sure time is unsigned long.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 94
Posts: 4758
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Then the Arduino version is extended at the least. What can I say? I almost never use delay().

Don't use delay(). Learn how BlinkWithoutDelay works. It will benefit you even after this project is done.

I'd also suggest using a sensor (if the stream will be lit red then a light detector might do) to tell when liquid is leaving the nozzle rather than waiting a default 1.25 seconds and some code to check how long that takes to warn you something may be wrong.

Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Illinois, US
Offline Offline
Jr. Member
**
Karma: 2
Posts: 97
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@ Maltelec:

I really would rather use Delay();

I don't want my CPU doing anything else while it's pouring, so delay works fine for me.  Plus, once this is up and running it will never be unplugged- so when millis rolls over in 72 days I don't want to be surprised by any implications that could have anywhere in the miles-long code I wrote.  Delay(); is simple, and doesn't rely on the 72-day long millis clock.

If I can make it work using delay();, I would like to.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 36
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

If you used the Wait command, it won't do anything while it is waiting, it is just like Delay.

Only code within the Wait function is executed:

wait (While something =/!=/</>/<=/>= something else)
{
Do this while waiting
}

Carry on here after the Wait has ended.
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 109
Posts: 4066
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

When used correctly there is no problem with millis() rolling over.

As to not being able to use large values with the delay() function, it takes an unsigned long as its argument and they can go up to  4,294,967,295 so you have plenty of time on your hands.  In your code what type of variable is volume ?  32 seconds is a very suspicious number.  Could the delay actually be 32.767 seconds I wonder ?

If you Serial.print pourdelay just before the delay() what values do you get ?
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 94
Posts: 4758
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@ Maltelec:

I really would rather use Delay();

I don't want my CPU doing anything else while it's pouring, so delay works fine for me.  Plus, once this is up and running it will never be unplugged- so when millis rolls over in 72 days I don't want to be surprised by any implications that could have anywhere in the miles-long code I wrote.  Delay(); is simple, and doesn't rely on the 72-day long millis clock.

If I can make it work using delay();, I would like to.

It's 49.7-some days and rollover only makes that the longest interval you can measure.

If you use timing instead of delay you can run more than 1 gun with a single controller as well as check sensors to watch for problems. OTOH some people like their devices to be as dumb as possible since their people are always both observant and right. But me, I live in a different world.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

New Jersey
Offline Offline
Faraday Member
**
Karma: 65
Posts: 3638
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

When used correctly there is no problem with millis() rolling over.

As to not being able to use large values with the delay() function, it takes an unsigned long as its argument and they can go up to  4,294,967,295 so you have plenty of time on your hands.  In your code what type of variable is volume ?  32 seconds is a very suspicious number.  Could the delay actually be 32.767 seconds I wonder ?

If you Serial.print pourdelay just before the delay() what values do you get ?

Looks like this is the culprit, volume is a byte. Try changing 9250 to 9250UL. If that doesn't fix it, cast volume to be unsigned long too.
Logged

Poole, Dorset, UK
Offline Offline
Edison Member
*
Karma: 50
Posts: 2202
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Or just make volume unsiged byte.

Mark
Logged

East Anglia (UK)
Offline Offline
Faraday Member
**
Karma: 109
Posts: 4066
May all of your blinks be without delay()
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Code:
Oh and for those of you that have been helping me since the beginning- IT WORKS!  I have booze in it, and it is pouring recipes! 
Until I fix this delay issue though, if a pour has to last longer than 32 seconds- it just pours until the end of time LOL.

Please accept my apologies.  I meant to suggest that we don't fix the problem and all order a very large drink !
Logged

Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 94
Posts: 4758
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Or just make volume unsiged byte.

Mark

Still going to have trouble fitting 9250.
Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Pages: [1] 2 3 4   Go Up
Jump to: