Go Down

Topic: Time functions (Read 4518 times) previous topic - next topic

Krodal

#15
Jul 24, 2012, 02:37 am Last Edit: Jul 24, 2012, 02:46 am by Krodal Reason: 1
This is the millis led blink : http://arduino.cc/en/Tutorial/BlinkWithoutDelay

Here is some code.
But I'm not happy with it. I should have created an command queue after all.
The MultiBlink is better programming: http://arduino.cc/playground/Code/MultiBlink

Valve 1 activates at time '0', and Valve 2 activates at time '140'.
You can make that '140' any value, even '0' or while Valve 1 is still active.

Code: [Select]

// Indepent valve control
//
// I would like to use a hardware timer,
// and a queue with times and events.
// But it's only for two valves,
// so I use variables for everything.
// But then I needed some kind of state machine,
// which makes it unnecessary complicated.
//

// Set the times.
// The start time is independent of each other.
const unsigned int valve_1_start    = 0;   // time for valve 1
const unsigned int valve_1_duration = 55;  // size of first drop in ms
const unsigned int valve_2_start    = 140; // time for valve 2
const unsigned int valve_2_duration = 55;  // size of second drop in ms
const unsigned int wait = 6000;      // wait a few seconds before starting all over

#define STATE_WAITING_FOR_ACTIVATING 0
#define STATE_VALVE_ON               1
#define STATE_DONE                   2


void setup()
{
 // initialize the digital pins as an output.

 pinMode(6, OUTPUT);
 pinMode(7, OUTPUT);
 
 Serial.begin(9600);
 
}

void loop()
{
 // Timing for valve 1 and 2 are totally independent.
 // Calculate the times in milliseconds.
 unsigned long currentMillis           = millis();
 unsigned long valve_1_start_millis    = currentMillis + valve_1_start;
 unsigned long valve_1_duration_millis = currentMillis + valve_1_start + valve_1_duration;
 unsigned long valve_2_start_millis    = currentMillis + valve_2_start;
 unsigned long valve_2_duration_millis = currentMillis + valve_2_start + valve_2_duration;
 unsigned long wait_millis             = currentMillis + wait;

 int valve_1_state = STATE_WAITING_FOR_ACTIVATING;
 int valve_2_state = STATE_WAITING_FOR_ACTIVATING;

 int ready = false;

 // run a (very fast) loop in which is checked if something needs to be done.
 while(!ready)
 {
   currentMillis = millis();


   // Check to see if it's time to do something for valve 1.
   switch (valve_1_state)
   {
   case STATE_WAITING_FOR_ACTIVATING:
     if (currentMillis >= valve_1_start_millis)
     {
       digitalWrite(6, HIGH);    // Turns ON Relay 3  on digital pin 6 (blue)
       valve_1_state = STATE_VALVE_ON;  
//        Serial.println(F("Valve 1 On"));
     }
     break;
   case STATE_VALVE_ON:
     if (currentMillis >= valve_1_duration_millis)
     {
       digitalWrite(6, LOW);     // Turns OFF Relay 3 on digital pin 6
       valve_1_state = STATE_DONE;  
//        Serial.println(F("Valve 1 Off"));
     }
     break;
   case STATE_DONE:
   default:
     break;
   }
   

   // Check to see if it's time to do something for valve 2.
   switch (valve_2_state)
   {
   case STATE_WAITING_FOR_ACTIVATING:
     if (currentMillis >= valve_2_start_millis)
     {
       digitalWrite(7, HIGH);    // Turns ON Relay 2 on digital pin 7 (yellow)
       valve_2_state = STATE_VALVE_ON;  
//        Serial.println(F("Valve 2 On"));
     }
     break;
   case STATE_VALVE_ON:
     if (currentMillis >= valve_2_duration_millis)
     {
       digitalWrite(7, LOW);     // Turns OFF Relay 2 on digital pin 7
       valve_2_state = STATE_DONE;  
//        Serial.println(F("Valve 2 Off"));
     }
     break;
   case STATE_DONE:
   default:
     break;
   }


   // Check to see if we need to start all over again.
   if (valve_1_state == STATE_DONE && valve_2_state == STATE_DONE && currentMillis >= wait_millis)
   {
     ready = true;
   }
 }
}

Nick Gammon

Quote
I only want the event to happen once then stop

...
Code: [Select]
// Check to see if we need to start all over again.

Why check to see if we need to start over again, then?
Please post technical questions on the forum, not by personal message. Thanks!

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

Krodal


Quote
I only want the event to happen once then stop

...
Code: [Select]
// Check to see if we need to start all over again.

Why check to see if we need to start over again, then?

Oh, well, I thought "once per loop". So I used the loop() function for a complete sequence, and run a second loop inside it to keep track of time. The original code starts again after a few seconds, so that's what did.

Nick Gammon


One thing I would like to know. Why is everything dealing with blinking LEDs, when I only want the event to happen once then stop


You want something to happen. Then something else a bit later. Then repeat (or do you?). It's almost like blinking two LEDs at different rates, isn't it? Of course, you don't have to have LEDs on the pins, you could have, say, valves.

http://www.gammon.com.au/blink
Please post technical questions on the forum, not by personal message. Thanks!

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

GoForSmoke


Still studying all of the examples. One thing I would like to know. Why is everything dealing with blinking LEDs, when I only want the event to happen once then stop


Blink Without Delay shows how to use the clock to make things happen (turn led/whatever On or Off) when you want without holding everything else up.

With 1 blinking light you might want to add a variable with a name like stopLed that starts = FALSE and add that into your conditionals ( if statements and like ) so that stopLed must be true to keep on blinking. With more than 1, an array ( stopLed[ leds ] ) would be better.

That's one way to add control, by using variables that your code sets and checks. Throw in user I/O through the Serial Monitor or switches/buttons/sensors if you want. Code is your clay to mold to your own needs. The kinds of complexity or simpleness you can get up to through code are literally up to you and the limits of your hardware (UNO has 2k RAM for example).
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Ramigrafx

#20
Jul 24, 2012, 11:19 am Last Edit: Jul 24, 2012, 11:23 am by Ramigrafx Reason: 1
Yes I know the downside of using delay and that is why I want to use millis.
Since you are all very good at using examples to prove your point. Look at this one.

At a sports event when a race starts they don't look at the clock and note that is say 10:15:35 and when the race ends they don't subtract the final time from the start time. No they start a stopwatch from 0 at the beginning of the race, and note the time at the end. At the end of the race they all don't start over again. There is a rest period, then they start another race from zero time again.

If I wrote a chapter of a book in English would you expect me to make a perfect gramatically correct translation into Chinese after learning the language for a two days. Of course not.

Anyone can find one to justify their argument

You all know a lot about programming. You need to look at your explanations from the point of view of someone who does not know much , but is trying to learn, and then they would not have to keep asking so many similar questions that obviously annoy some ofyou.

I understanrd the flow path of the events that I want.I am just trying to translate this into a foreign language.

If PaulS looked at my sample sketch at reply#4 that I have been using with delay in it he would understand what I was trying to do.

Thanks to those trying to help

dxw00d

Quote
At a sports event when a race starts they don't look at the clock and note that is say 10:15:35 and when the race ends they don't subtract the final time from the start time. No they start a stopwatch from 0 at the beginning of the race, and note the time at the end.

That's quite true, because they have a hardware timer that can do that. The Arduino doesn't, and so a different technique is required.

Krodal


Thanks to those trying to help


So ? Did you try my working sketch ?

PaulS

Quote
If PaulS looked at my sample sketch at reply#4 that I have been using with delay in it he would understand what I was trying to do.

I did look at it. If you'd read #3, you'd know that.

Quote
Thanks to those trying to help

What part have you contributed? What have you come up with? Are you expecting us to write the code for you?

Nick Gammon


You all know a lot about programming.


Well? Listen to what we are saying rather than trying to prove we are idiots.
Please post technical questions on the forum, not by personal message. Thanks!

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

GoForSmoke


Quote
At a sports event when a race starts they don't look at the clock and note that is say 10:15:35 and when the race ends they don't subtract the final time from the start time. No they start a stopwatch from 0 at the beginning of the race, and note the time at the end.

That's quite true, because they have a hardware timer that can do that. The Arduino doesn't, and so a different technique is required.


Not true. He could go to the extra trouble to set up a timer and interrupt and have his stopwatch. Hell, it's possible to reset the millis() counter with precautions on how you do it.

We just tried to take him through the -easy- way but what the heck do WE know?
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Ramigrafx



Thanks to those trying to help


So ? Did you try my working sketch ?


Thanks Krodal. I have printed out your sketch and am currently going through it, trying to understand it.
I am writting my sketch at the moment so it is helping me, together with many other pieces of information I have gathered.

Ramigrafx


Quote
If PaulS looked at my sample sketch at reply#4 that I have been using with delay in it he would understand what I was trying to do.

I did look at it. If you'd read #3, you'd know that.

Quote
Thanks to those trying to help

What part have you contributed? What have you come up with? Are you expecting us to write the code for you?


I am trying to write the code myself, when I understand the procedure. I don't want anyone to do it for me.
If you are going to get so bad tempered I suggest that you chill out for a while and give this job a rest. You put people off.

PaulS

Quote
If you are going to get so bad tempered I suggest that you chill out for a while and give this job a rest.

Fine. Good luck.

GoForSmoke

Look, Rami,

The chip has counter-timer circuits inside. Every cycle they add 1 and you know by your cycle time how many ticks makes a millisecond and that adds 1 to another memory register. That already happens. That's what's behind millis().

You can -make- your own count-down timer. You can put a time value in a volatile global variable and run an interrupt off a timer so when it rolls over the IRQ decrements the time value. Then your regular code has until the next interrupt to recognize when the value hits zero -or- it can know the time passed zero -if- it keeps the last time value stored and not be time-critical. If your time value increments are 1 ms or more then tight code will never miss when it zeroes.

You can make one without interrupt, IRQ and volatile variables just by using code that uses... millis(), and it will be simpler and work cleaner.

It's up to you.......
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Go Up