Need help regarding delays

Hi Guys,

Bear with me for questions that could be obvious to many of you.

I am unable to get the desired output from the following program. I would like to know where I am going wrong.

/*
MADHAV
07122015
FLASHING AN Led with MULTIPLE TIMINGS - simulating a PWM without Analog Input

*/

int Led = 13; // Led connected on pin 13.
int cyctime = 5000; // Cycle time = 2 secs
int ton = 100; // Ontime = 0
int toff = 4900; // Offtime = 0

void setup() {
// put your setup code here, to run once:
pinMode (Led, OUTPUT); // configured pin 13 as output
}

void loop() {
// put your main code here, to run repeatedly:
digitalWrite (Led, HIGH); // switched the Led ON
delay (cyctime - ton); // ON time shall be 2000 - 100 = 1900 ms
digitalWrite (Led, LOW); // switched the Led OFF
delay (cyctime - toff); // OFF delay shall be 2000 - 1900 = 100ms
// the pulse shall look like a ON time of 1900 ms followed by OFF time of 100mS

if (ton >= 100 && toff <= 4900) // as this is true, the below code should be executed
{
toff = cyctime - 500; //
toff = toff; // toff now shall be 4500

ton = 0 + 500;
ton = ton; // ton now shall be 500
}
else
{
ton = 100; // reset to earlier values
toff=4900; // reset to earlier values
}
}

 toff = toff;

What do you think this will do?

I am unable to get the desired output from the following program.

What is the desired output? How does that differ from what you actually get?

@aarg:

Thanks first.
I get you. It was redundant.

@PaulS:

Thanks again.
I was looking for an output that goes like this.

In the first iteration, I wanted to get a larger ton and shorter toff. Second iteration slightly lesser ton (by 500 ms) and slightly larger toff. Third lesser ton and more toff .............and that way.

I factor I noticed was the 500mS which could not give me multiple iterations. I am decreasing it by 100 ms and observe.

PaulS:
What is the desired output? How does that differ from what you actually get?

@PaulS:

Thanks a ton, I really appreciate your help with your time and guidance to newbies like me.

I finally got it, with the below code. Now it gives me satisfaction to tell my daughter that I can do some coding too. Once again, thanks a ton.

/*
MADHAV
07122015
FLASHING AN Led with MULTIPLE TIMINGS - simulating a PWM without Analog Input

*/
int Led = 13; // Led connected on pin 13.
int cyctime = 1000; // Cycle time = 2 secs
int ton = 0; // Ontime = 0
int toff = 1000; // Offtime = 0
int konst = 100;

void setup() {
// put your setup code here, to run once:
Serial.begin (9600);
pinMode (Led, OUTPUT); // configured pin 13 as output
}

void loop() {
// put your main code here, to run repeatedly:
digitalWrite (Led, HIGH); // switched the Led ON
delay (cyctime - ton); // ON time shall be 5000 - 0 = 5000 ms
digitalWrite (Led, LOW); // switched the Led OFF
delay (cyctime - toff); // OFF delay shall be 5000 - 5000 = 0ms
// the pulse shall look like a ON time of 1900 ms followed by OFF time of 100mS

if (ton >= 0 && ton < 1000) //if this is true, the below code should be executed
{
ton = ton + konst; // ton now shall be 250
}
else
{
ton = 0;
}

if (toff <= 1000 && toff > 0)
{
toff = abs(toff - konst);
}
else
{
toff = 1000;
}
Serial.print ("ton =");
Serial.println (ton);
Serial.print ("toff =");
Serial.println (toff);
}

if (toff <= 1000 && toff > 0)

Can I suggest that you arrange this the way you think? One does not normally say "if the value is between 1000 and 0...". One normally says "if the value is between 0 and 1000...". There is no reason code can't be written that way.

Thank you PaulS, you are right in suggesting "the way we think".

You may be interested in the demo Several Things at a Time which uses millis() to manage timing.

The Arduino can do nothing during a delay().

...R

Robin2:
The Arduino can do nothing during a delay().

Wrong.

(Since version 1.5.1. Using millis() is still the better way.)

odıpıqıbo:
Wrong.

¿ǝuoʎuɐ 'ʎɐןǝpʇɹɐɯs ˙ʍʍǝ

/dev:
¿ǝuoʎuɐ 'ʎɐןǝpʇɹɐɯs ˙ʍʍǝ

How did you do that upside down text bit?

That function is just about the stupidest one I have ever seen. And from someone I considered reasonably intelligent, too.

PaulS:
How did you do that upside down text bit?

For example ɯoɔ˙ʇxǝʇuʍopǝpᴉsdn.

_ͧ̓ͦ̋͏̳̗̳͓̬͈̱P̣͎̞̻̗̘̮̿̍̓ͦ͗̐ͭ̄͜͡͝ȧ̼̬̫͇̲̱̊̈ͤͥͥ͘͡ͅuͦ҉̢̟̥̮̪̟͕l͍̩̝̰̠͔͒ͣ̽̄̓ͬ̓̆̀S̴̜͙ͪ͆͌͋ͦͥ̑ͭ.͛ͧ̑͏͈̥̤̗͘:
How did you do that upside down text bit?

fliptext.org. It's surprising what you can find in a font.

No reason to get flippant.

 void delay(unsigned long ms) 
 { 
         uint16_t
start = (uint16_t)micros(); 
         while (ms > 0) { 
             yield();
             if (((uint16_t)micros() - start) >= 1000) { 
             ms--;
             start += 1000; 
             }
         } 
 }

So what does yield() do? It is not called out anywhere else on that page.

It is weakly bound to a do-nothing function. You can write your own version, and the linker will use it instead. Hence my comparison to the TinyGPS's smartDelay... which isn't. The Arduino gods surely love polling. See also SerialEvent.

Cheers,
/dev

I have said the following in another Thread about this new-fangled delay().

There is a great difference between {A} a system in which something is actively done within a delay() - such as code that might be put into a function called yield() and {B} a system in which things only happen when they are required.

With the new-fangled-delay() you have to consciously plan for what should happen during an interval. With millis() you can just write code that works when you want it to work.

In any particular "delay" interval nothing may need to happen but perhaps every 7th, 13th 23rd something does need to happen. If you use millis() you don't even need to think about that - just arrange for when things should happen.

Whoever thought up that new-fangled-delay was IMHO confused between the event driven environment in a PC operating system and the much simpler environment in an MCU - probably the same person that thought serialEvent() was a good idea.

...R

probably the same person that thought serialEvent() was a good idea.

You (charitably) misspelled idiot.

madhavdivya:
Thank you PaulS, you are right in suggesting "the way we think".

Arduino has a clock that maintains a 32-bit unsigned value as milliseconds since startup.

At any time you can copy that value into an unsigned long variable, it marks the time it was set.
At any later time you may subtract the time mark value from the current millis() value (always increasing 1000 times per second) and get the difference in time.
Always use the later time minus the earlier time. Since they are unsigned, the answer will always be correct even when the time being subtracted is higher value.. it is like a clock, from 11 to 1 is 2 hours.

So you can tell time difference then you can make:

void loop()
{
  // some code here -- maybe a button that turns the "timer" on or off by setting timeWait

  if ( timeWait ) // this lets the timer be turned off and on by set timeWait to 0 or > 0
  {
    if ( millis() - timeStart >= timeWait ) // trigger warning! LOL!
    {
      // do that thing you waited for without delay()!
      timeStart += timeWait; // and now set up to do it again.
    }
  } 

  // some code here
}

The other code can change the wait, stop or start the timer, and do any without adding indent levels to the timer code itself. The 'reaching in' is done through the variables in those triggering if() statements.

This is a basis to make very responsive code able to do many things together. As long as loop() runs quickly the code will be able to check times and pin states to react quickly.
If you have a process that will take more than 200 microseconds (analog read takes 105, digital read is faster than 1) then see about breaking it into sub-tasks to run 1 per pass through loop(). It will get done soon anyway when loop() is running more than 1000 times a second.

void loop()
{
  static byte runSubTask = 0; // it is 0 to start. static local variables keep their value unlike non-static. 

  // some code

  switch ( runSubTask )
  {
    case 0 :
    // code for the first sub-task
    runSubTask = 1;  // this could have an if() and case 0 would run again until the if() succeeded.
    break;

    case 1 :
    // code for the next sub-task
    runSubTask = 2;  
    break;

    case 2 :
    // code for the next sub-task
    runSubTask = 0;  
    break;
  }

  // some code
}

I have put the code for sub-tasks like above inside of a function to get rid of many delay()s.

void myTasks()
{
  static byte runSubTask = 0; // it is 0 to start. static local variables keep their value unlike non-static. 

  if ( timeWait ) // this lets the timer be turned off and on by set timeWait to 0 or > 0
  {
    if ( millis() - timeStart < timeWait ) // time is NOT up yet
    {
      return; // so come back later
    }
    else
    {
      timeWait = 0; // time is up, turn the timer off
    }
  }

  switch ( runSubTask )
  {
    case 0 :
    // code for the first sub-task
    timeStart = millis();
    timeWait = 500;      // next sub task to run 500 millis after "now"
    runSubTask = 1;  // this could have an if() and case 0 would run again until the if() succeeded.
    break;

    case 1 :
    // code for the next sub-task
    runSubTask = 2;  
    break;

    case 2 :
    // code for the next sub-task
    runSubTask = 0;  
    break;
  } 
}

Time as unsigned long is good for 49.7-some days as the longest countable interval.

Robin2:
In any particular "delay" interval nothing may need to happen but perhaps every 7th, 13th 23rd something does need to happen. If you use millis() you don't even need to think about that - just arrange for when things should happen.

Using delay makes user intervention and other real time sense and react processes a real pain.

A lot of code seems made to run about as fast as it was written.....