Arduino's multitasking - Part One

Bigger and better projects

If you've mastered basic flashing LEDs, simple sensors andservos , you're ready to start the adventure with bigger and better projects. This usually involves combining parts of simpler sketches and trying to work together. The first thing you'll discover is that some of these sketches, which separately work perfectly, don't fit together with others.

Arduino is a very simple module without an operating system that can only run one program. Unlike your personal computer or Raspberry Pi, Arduino is not able to load and run multiple programs.

This doesn't mean that we can't do many tasks in Arduino.We just have to use another method. We don't have an operating system to help, so we have to take matters into our own hands.

Wielozadaniowość Arduino

Get rid of the delay()

The first thing you learned while playing with Arduino is probably the use of the above function (delay(). The delay() function is not complicated, but it causes problems when you add additional functions. The trouble is that this function is "active waiting". (with busy wait), which dominates the processor.

When calling this function, you cannot react to inputs, you cannot process any data and you cannot change any output. It blocks the whole processor. So, if some part of your code uses this function, for that time, everything else is stopped.

Remember Blink?

  1. /*
  2. Blink
  3. Turns on an LED on for one second, then off for one second, repeatedly.
  4. This example code is in the public domain.
  5. */
  6. // Pin 13 has an LED connected on most Arduino boards.
  7. // give it a name:
  8. int led = 13;
  9. // the setup routine runs once when you press reset:

  10. void setup() {

  11. // initialize the digital pin as an output.

  12. pinMode(led, OUTPUT);

  13. }

  14.  
  15. // the loop routine runs over and over again forever:

  16. void loop() {

  17. digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)

  18. delay(1000); // wait for a second

  19. digitalWrite(led, LOW); // turn the LED off by making the voltage LOW

  20. delay(1000); // wait for a second

  21. }

  22.  
  23.  

A simple Blink sketch is almost all the time in the delay() function. So at this time, the processor can do nothing else.

You haven't forgotten your sweep?

Sweep uses the delay() function to control its speed. If you try to combine the basic blink sketch with an example of the servo of sweep, you will notice that alternately the LED flashes and the servo moves. However, this will not happen simultaneously.

  1. #include
  2. // Pin 13 has an LED connected on most Arduino boards.
  3. // give it a name:
  4. int led = 13;
  5. Servo myservo; // create servo object to control a servo
  6. // twelve servo objects can be created on most boards
  7. int pos = 0; // variable to store the servo position
  8. void setup()
  9. {
  10. // initialize the digital pin as an output.
  11. pinMode(led, OUTPUT);
  12. myservo.attach(9); // attachches the servo on pin 9 to the servo object
  13. }
  14. void loop()
  15. {
  16. digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
  17. delay(1000); // wait for a second
  18. digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
  19. delay(1000); // wait for a second
  20. for (pos = 0; pos <= 180; pos += 1) // goes from 0 degrees to 180 degrees
  21. { // in steps of 1 degree
  22. myservo.write(pos); // tell servo to go to position in variable 'pos'
  23. delay(15); // waits 15ms for the servo to reach the position
  24. }
  25. for (pos = 180; pos >= 0; pos -= 1) // go from 180 degrees to 0 degrees
  26. {
  27. myservo.write(pos); // tell servo to go to position in variable 'pos'
  28. delay(15); // waits 15ms for the servo

So how do we control the delay without using the delay function?

Using the millis() function in delay

A simple technique to implement a delay is to make a plan and watch the watch. Instead of focusing on the delay function, you simply systematically check the time to know when to act. In the meantime, other tasks can use the processor. A very simple example of this is the BlinkyWithoutDelay sketchwiththe development environment.

The connection diagram for the above code is shown below:

Wielozadaniowość Arduino - schemat podłączenia

Flickering without delay

Here is a sample code for BlinkWithoutDelay:

  1. /* Blink without Delay
  2. Turns on and off a light emitting diode(LED) connected to a digital
  3. pin, without using the delay() function. This means that other code
  4. can run at the same time without being interrupted by the LED code.
  5. The circuit:
  6. * LED attached from pin 13 to ground.
  7. * Note: on most Arduinos, there is already an LED on the board
  8. that's attached to pin 13, so no hardware is needed for this example.
  9. created 2005
  10. by David A. Mellis
  11. modified 8 Feb 2010
  12. by Paul Stoffregen
  13. This example code is in the public domain.
  14. http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay

  15. */

  16.  
  17. // constants won't change. Used here to

  18. // set pin numbers:

  19. const int ledPin = 13; // the number of the LED pin

  20.  
  21. // Variables will change:

  22. int ledState = LOW; // ledState used to set the LED

  23. long previousMillis = 0; // will store last time LED was updated

  24.  
  25. // the follow variables is a long because the time, measured in miliseconds,

  26. // will quickly become a bigger number than can be stored in an int.

  27. long interval = 1000; // interval at which to blink (milliseconds)

  28.  
  29. void setup() {

  30. // set the digital pin as output:

  31. pinMode(ledPin, OUTPUT);

  32. }

  33.  
  34. void loop()

  35. {

  36. // here is where you'd put code that needs to be running all the time.

  37.  
  38. // check to see if it's time to blink the LED; that is, if the

  39. // difference between the current time and last time you blinked

  40. // the LED is bigger than the interval at which you want to

  41. // blink the LED.

  42. unsigned long currentMillis = millis();

  43. if(currentMillis - previousMillis > interval) {

  44. // save the last time you blinked the LED

  45. previousMillis = currentMillis;

  46.  
  47. // if the LED is off turn it on and vice-versa:

  48. if (ledState == LOW)

  49. ledState = HIGH;

  50. else

  51. ledState = LOW;

  52.  
  53. // set the LED with the ledState of the variable:

  54. digitalWrite(ledPin, ledState);

  55. }

  56. }

  57.  
  58.  

Does that make any sense?

At first sight, BlinkWithoutDelay doesn't seem very interesting. It looks like a more complicated way to turn on the LEDs. However, BlinkWithoutDelay presents a very important concept known as StateMachine.

You no longer have to rely on the delay() function to create a flashing diode program. BlinkWithoutDelay remembers the current LED status and the last time it changed. After each loop, it checks the millis clock() to know if it should change the status of the LEDs again.

Welcome to the machine

Let's note the slightly more interesting blink variant, which has different on and off times. We called it "FlashWithoutDelay"

  1. // These variables store the flash pattern
  2. and the current state of the LED
  3. int ledPin = 13; // the number of the LED pin

  4. int ledState = LOW; // ledState used to set the LED

  5. unsigned long previousMillis = 0; // will store last time LED was updated

  6. long OnTime = 250; // milliseconds of on-time

  7. long OffTime = 750; // milliseconds of off-time

  8.  
  9. void setup()

  10. {

  11. // set the digital pin as output:

  12. pinMode(ledPin, OUTPUT);

  13. }

  14.  
  15. void loop()

  16. {

  17. // check to see if it's time to change the state of the LED

  18. unsigned long currentMillis = millis();

  19. if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))

  20. {

  21. ledState = LOW; // Turn it off

  22. previousMillis = currentMillis; // Remember the time

  23. digitalWrite(ledPin, ledState); // Update the actual LED

  24. }

  25. else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))

  26. {

  27. ledState = HIGH; // turn it on

  28. previousMillis = currentMillis; // Remember the time

  29. digitalWrite(ledPin, ledState); // Update the actual LED

  30. }

  31. }

  32.  
  33.  

Status + Mashine = State Machine

Note that we have variables that track whether the LED is on or off. There are also some that are watching the recent change. This is the part of the automat calledStatus.

We also have a code that watches over the status and decides when and how to change it. This is the part called the Machine. After each loop, we "start the machine" and it updates the status.

Then, we'll check how you connect the machines by starting them simultaneously.

Target - two at a time

Time for multitasking! First connect another LED, as shown in the diagram below:

Wielozadaniowość Arduino - schemat podłączenia diod LED

Then we will create another automaton for the second LED, which flashes at completely different speeds. Using two separate automats will make these two LEDs flash without being dependent on each other.

  1. // These variables store the flash pattern
  2. // and the current state of the LED
  3. int ledPin1 = 12; // the number of the LED pin

  4. int ledState1 = LOW; // ledState used to set the LED

  5. unsigned long previousMillis1 = 0; // will store last time LED was updated

  6. long OnTime1 = 250; // milliseconds of on-time

  7. long OffTime1 = 750; // milliseconds of off-time

  8.  
  9. int ledPin2 = 13; // the number of the LED pin

  10. int ledState2 = LOW; // ledState used to set the LED

  11. unsigned long previousMillis2 = 0; // will store last time LED was updated

  12. long OnTime2 = 330; // milliseconds of on-time

  13. long OffTime2 = 400; // milliseconds of off-time

  14.  
  15. void setup()

  16. {

  17. // set the digital pin as output:

  18. pinMode(ledPin1, OUTPUT);

  19. pinMode(ledPin2, OUTPUT);

  20. }

  21.  
  22. void loop()

  23. {

  24. // check to see if it's time to change the state of the LED

  25. unsigned long currentMillis = millis();

  26. if((ledState1 == HIGH) && (currentMillis - previousMillis1 >= OnTime1))

  27. {

  28. ledState1 = LOW; // Turn it off

  29. previousMillis1 = currentMillis; // Remember the time

  30. digitalWrite(ledPin1, ledState1); // Update the actual LED

  31. }

  32. else if ((ledState1 == LOW) && (currentMillis - previousMillis1 >= OffTime1))

  33. {

  34. ledState1 = HIGH; // turn it on

  35. previousMillis1 = currentMillis; // Remember the time

  36. digitalWrite(ledPin1, ledState1); // Update the actual LED

  37. }

  38. if((ledState2 == HIGH) && (currentMillis - previousMillis2 >= OnTime2))

  39. {

  40. ledState2 = LOW; // Turn it off

  41. previousMillis2 = currentMillis; // Remember the time

  42. digitalWrite(ledPin2, ledState2); // Update the actual LED

  43. }

  44. else if ((ledState2 == LOW) && (currentMillis - previousMillis2 >= OffTime2))

  45. {

  46. ledState2 = HIGH; // turn it on

  47. previousMillis2 = currentMillis; // Remember the time

  48. digitalWrite(ledPin2, ledState2); // Update the actual LED

  49. }

  50. }

  51.  
  52.  

Thank you very much! Can I get another one?

You can add more slot machines as long as you have enough memory or GPIO pins. Each slot machine has its own flicker rate. As a task, edit the code above to be able to add a third slot machine.

  • First, copy all the status variables and the code of one of the slots.
  • Then, rename each variable again to avoid conflicting with the first machine.

This is not difficult to do. But rewriting the code all the time seems to be rather time consuming. There must be some other way to do it!

There are better ways to deal with it. These are programming techniques that are simpler and more effective.

Classes

Let's take another look at our last sketch. As you can see, it is very monotonous. The same code is copied almost word for word for every flickering LED. The only thing that changes (to a small extent) is the name of the variables.

This code is the best candidate forObject Oriented Programming(OOP)

OOP in a loop

Arduino language is a variation of C++ language, which supports object-oriented programming. Using OOP language we can collect all status variables and functions of flashing LED in C++ class.

This is not difficult to do, because we already have all the code written. We just have to repack it as a class.

Define the class:

We start by declaring the class "Flasher":

Then we add all variables from FlashWithoutDelay. They are part of the class, so we know them as member variables.

  1. class Flasher
  2. {
  3. // Class Member Variables
  4. // These are initialized at startup
  5. int ledPin; // the number of the LED pin
  6. long OnTime; // milliseconds of on-time
  7. long OffTime; // milliseconds of off-time
  8. // These maintain the current state

  9. int ledState; // ledState used to set the LED

  10. unsigned long previousMillis; // will store last time LED was updated

  11. };

  12.  
  13.  

Then we add aconstructor. It hasthe same name as the class and its task is to initiate all variables.

  1. class Flasher
  2. {
  3. // Class Member Variables
  4. // These are initialized at startup
  5. int ledPin; // the number of the LED pin
  6. long OnTime; // milliseconds of on-time
  7. long OffTime; // milliseconds of off-time
  8. // These maintain the current state

  9. int ledState; // ledState used to set the LED

  10. unsigned long previousMillis; // will store last time LED was updated

  11.  
  12. // Constructor - creates a Flasher

  13. // and initializes the member variables and state

  14. public:

  15. Flasher(int pin, long on, long off)

  16. {

  17. ledPin = pin;

  18. pinMode(ledPin, OUTPUT);

  19. OnTime = on;

  20. OffTime = off;

  21. ledState = LOW;

  22. previousMillis = 0;

  23. }

  24. };

  25.  
  26.  

Finally, we change the loop into a component function called"Update()".

  1. class Flasher
  2. {
  3. // Class Member Variables
  4. // These are initialized at startup
  5. int ledPin; // the number of the LED pin
  6. long OnTime; // milliseconds of on-time
  7. long OffTime; // milliseconds of off-time
  8. // These maintain the current state

  9. int ledState; // ledState used to set the LED

  10. unsigned long previousMillis; // will store last time LED was updated

  11.  
  12. // Constructor - creates a Flasher

  13. // and initializes the member variables and state

  14. public:

  15. Flasher(int pin, long on, long off)

  16. {

  17. ledPin = pin;

  18. pinMode(ledPin, OUTPUT);

  19. OnTime = on;

  20. OffTime = off;

  21. ledState = LOW;

  22. previousMillis = 0;

  23. }

  24.  
  25. void Update()

  26. {

  27. // check to see if it's time to change the state of the LED

  28. unsigned long currentMillis = millis();

  29. if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))

  30. {

  31. ledState = LOW; // Turn it off

  32. previousMillis = currentMillis; // Remember the time

  33. digitalWrite(ledPin, ledState); // Update the actual LED

  34. }

  35. else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))

  36. {

  37. ledState = HIGH; // turn it on

  38. previousMillis = currentMillis;

    // Remember the time
  39. digitalWrite(ledPin, ledState); // Update the actual LED
  40. }
  41. }
  42. };
  43.  

By changing our code into a Flasher class, we have narrowed down all variables(status) and functions(machine) of the flashing LED.

Now let's use this:

For each LED we want to light up, we create an example ofthe Flasher class, invoking the constructor. Every timewe go throughthe loop, we have to invoke Update() for each example of the Flasher.

You no longer need to repeat the whole code of the machine. All we have to do is ask for more Flasher examples!

  1. class Flasher
  2. {
  3. // Class Member Variables
  4. // These are initialized at startup
  5. int ledPin; // the number of the LED pin
  6. long OnTime; // milliseconds of on-time
  7. long OffTime; // milliseconds of off-time
  8. // These maintain the current state

  9. int ledState; // ledState used to set the LED

  10. unsigned long previousMillis; // will store last time LED was updated

  11.  
  12. // Constructor - creates a Flasher

  13. // and initializes the member variables and state

  14. public:

  15. Flasher(int pin, long on, long off)

  16. {

  17. ledPin = pin;

  18. pinMode(ledPin, OUTPUT);

  19. OnTime = on;

  20. OffTime = off;

  21. ledState = LOW;

  22. previousMillis = 0;

  23. }

  24.  
  25. void Update()

  26. {

  27. // check to see if it's time to change the state of the LED

  28. unsigned long currentMillis = millis();

  29. if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))

  30. {

  31. ledState = LOW; // Turn it off

  32. previousMillis = currentMillis; // Remember the time

  33. digitalWrite(ledPin, ledState); // Update the actual LED

  34. }

  35. else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))

  36. {

  37. ledState = HIGH; // turn it on

  38.  
  39. previousMillis = currentMillis; // Remember the time

  40. digitalWrite(ledPin, ledState); // Update the actual LED

  41. }

  42. }

  43. };

  44.  
  45. Flasher led1(12, 100, 400);

  46. Flasher led2(13, 350, 350);

  47.  
  48. void setup()

  49. {

  50. }

  51.  
  52. void loop()

  53. {

  54. led1.Update();

  55. led2.Update();

  56. }

  57.  
  58.  

Less is more!

Finally -Each additional LED requires only two lines of code!

This code is shorter and easier to read. And since there is no duplicate code, there is lessto compile! Thisall saves memory for other projects!

What else can we do?

Let's apply the same rules to the servo codesand get started.

First, connect two servos to each other on the contact plate, as shown below. Then, connect the third LED as well .

Wielozadaniowość Arduino - schemat podłączenia serw i diod LED

Here's the standard code for your sweep servo. Note that it invokes the unwanted delay() function. We'll take some of this code to build the Sweeper.

  1. // Sweep
  2. // by BARRAGAN
  3. // This example code is in the public domain.
  4. #include

  5. Servo myservo; // create servo object to control a servo

  6. // a maximum of eight servo objects can be created

  7. int pos = 0; // variable to store the servo position

  8. void setup()

  9. {

  10. myservo.attach(9); // attaches the servo on pin 9 to the servo object

  11. }

  12. void loop()

  13. {

  14. for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees

  15. { // in steps of 1 degree

  16. myservo.write(pos); // tell servo to go to position in variable 'pos'

  17. delay(15); // waits 15ms for the servo to reach the position

  18. }

  19. for(pos = 180; pos>=1; pos-=1) // go from 180 degrees to 0 degrees

  20. {

  21. myservo.write(pos); // tell servo to go to position in variable 'pos'

  22. delay(15); // waits 15ms for the servo to reach the position

  23. }

  24. }

The following Sweeper class summarizes the sweep action, but uses the millis() function to set the delay.

We also need to add Attach() and Detach() functions to bind the servo to a specific pin:

  1. class Sweeper
  2. {
  3. Servo servo; // the servo
  4. int pos; // current servo position
  5. int increment; // increment to move for each interval
  6. int updateInterval; // interval between updates
  7. unsigned long lastUpdate; // last update of position
  8. public:

  9. Sweeper(int interval)

  10. {

  11. updateInterval = interval;

  12. increment = 1;

  13. }

  14. void Attach(int pin)

  15. {

  16. servo.attach(pin);

  17. }

  18. void Detach()

  19. {

  20. servo.detach();

  21. }

  22. void Update()

  23. {

  24. if((millis() - lastUpdate) > updateInterval) // time to update

  25. {

  26. lastUpdate = millis();

  27. pos += increment;

  28. servo.write(pos);

  29. Serial.println(pos);

  30. if ((pos >= 180) || (pos <= 0)) // end of sweep

  31. {

  32. // reverse direction

  33. increment = -increment;

  34. }

  35. }

  36. }

  37. };

  38.  

How much?

Now we can make as many copies of Flashersand Sweepersaswe want.

Each example of a Flashlight requires two lines of code:

  • one to declare an example
  • the second to call up an update in the loop

Each Sweeper example requires only 3 lines of code:

  • one to declare an example
  • the second to tie the servo to the pin
  • and a third to recall the update in the loop

  1. #include
  2. class Flasher

  3. {

  4. // Class Member Variables

  5. // These are initialized at startup

  6. int ledPin; // the number of the LED pin

  7. long OnTime; // milliseconds of on-time

  8. long OffTime; // milliseconds of off-time

  9. // These maintain the current state

  10. int ledState; // ledState used to set the LED

  11. unsigned long previousMillis; // will store last time LED was updated

  12. // Constructor - creates a Flasher

  13. // and initializes the member variables and state

  14. public:

  15. Flasher(int pin, long on, long off)

  16. {

  17. ledPin = pin;

  18. pinMode(ledPin, OUTPUT);

  19. OnTime = on;

  20. OffTime = off;

  21. ledState = LOW;

  22. previousMillis = 0;

  23. }

  24. void Update()

  25. {

  26. // check to see if it's time to change the state of the LED

  27. unsigned long currentMillis = millis();

  28. if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))

  29. {

  30. ledState = LOW; // Turn it off

  31. previousMillis = currentMillis; // Remember the time

  32. digitalWrite(ledPin, ledState); // Update the actual LED

  33. }

  34. else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))

  35. {

  36. ledState = HIGH; // turn it on

  37. previousMillis = currentMillis; // Remember the time

  38. digitalWrite(ledPin, ledState); // Update the actual LED

  39. }

  40. }

  41. };

  42. class Sweeper

  43. {

  44. Servo servo; // the servo

  45. int pos; // current servo position

  46. int increment; // increment to move for each interval

  47. int updateInterval; // interval between updates

  48. unsigned long lastUpdate; // last update of position

  49. public:

  50. Sweeper(int interval)

  51. {

  52. updateInterval = interval;

  53. increment = 1;

  54. }

  55. void Attach(int pin)

  56. {

  57. servo.attach(pin);

  58. }

  59. void Detach()

  60. {

  61. servo.detach();

  62. }

  63. void Update()

  64. {

  65. if((millis() - lastUpdate) > updateInterval) // time to update

  66. {

  67. lastUpdate = millis();

  68. pos += increment;

  69. servo.write(pos);

  70. Serial.println(pos);

  71. if ((pos >= 180) || (pos <= 0)) // end of sweep

  72. {

  73. // reverse direction

  74. increment = -increment;

  75. }

  76. }

  77. }

  78. };

  79. Flasher led1(11, 123, 400);

  80. Flasher led2(12, 350, 350);

  81. Flasher led3(13, 200, 222);

  82. Sweeper sweeper1(15);

  83. Sweeper sweeper2(25);

  84. void setup()

  85. {

  86. Serial.begin(9600);

  87. sweeper1.Attach(9);

  88. sweeper2.Attach(10);

  89. }

  90. void loop()

  91. {

  92. sweeper1.Update();

  93. sweeper2.Update();

  94. led1.Update();

  95. led2.Update();

  96. led3.Update();

  97. }

At the moment, we have 5 independent tasks running non-stop, without interruption. And our loop() function has only 5 lines of code!

All together!

We also want your entrance

Another problem with timing based on the delay() function is that user input, such as pressing a button, is often ignored. This is because the processor cannot check the state of the button when it is in the delay() function. With a delay based on the millis() function, the processor can regularly check the status of buttons and other inputs. This allows us to build complex programs that can do many things at once and still react.

We will demonstrate this by adding a button to our circuit, as shown in the figure:

Wielozadaniowość Arduino - schemat podłączenia z przyciskiem

The code below will check the state of the button on each loop passage. Led1and sweeper2will not be updatedwhen the button is pressed.

  1. #include
  2. class Flasher

  3. {

  4. // Class Member Variables

  5. // These are initialized at startup

  6. int ledPin; // the number of the LED pin

  7. long OnTime; // milliseconds of on-time

  8. long OffTime; // milliseconds of off-time

  9. // These maintain the current state

  10. int ledState; // ledState used to set the LED

  11. unsigned long previousMillis; // will store last time LED was updated

  12. // Constructor - creates a Flasher

  13. // and initializes the member variables and state

  14. public:

  15. Flasher(int pin, long on, long off)

  16. {

  17. ledPin = pin;

  18. pinMode(ledPin, OUTPUT);

  19. OnTime = on;

  20. OffTime = off;

  21. ledState = LOW;

  22. previousMillis = 0;

  23. }

  24. void Update()

  25. {

  26. // check to see if it's time to change the state of the LED

  27. unsigned long currentMillis = millis();

  28. if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))

  29. {

  30. ledState = LOW; // Turn it off

  31. previousMillis = currentMillis; // Remember the time

  32. digitalWrite(ledPin, ledState); // Update the actual LED

  33. }

  34. else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))

  35. {

  36. ledState = HIGH; // turn it on

  37. previousMillis = currentMillis; // Remember the time

  38. digitalWrite(ledPin, ledState); // Update the actual LED

  39. }

  40. }

  41. };

  42. class Sweeper

  43. {

  44. Servo servo; // the servo

  45. int pos; // current servo position

  46. int increment; // increment to move for each interval

  47. int updateInterval; // interval between updates

  48. unsigned long lastUpdate; // last update of position

  49. public:

  50. Sweeper(int interval)

  51. {

  52. updateInterval = interval;

  53. increment = 1;

  54. }

  55. void Attach(int pin)

  56. {

  57. servo.attach(pin);

  58. }

  59. void Detach()

  60. {

  61. servo.detach();

  62. }

  63. void Update()

  64. {

  65. if((millis() - lastUpdate) > updateInterval) // time to update

  66. {

  67. lastUpdate = millis();

  68. pos += increment;

  69. servo.write(pos);

  70. Serial.println(pos);

  71. if ((pos >= 180) || (pos <= 0)) // end of sweep

  72. {

  73. // reverse direction

  74. increment = -increment;

  75. }

  76. }

  77. }

  78. };

  79. Flasher led1(11, 123, 400);

  80. Flasher led2(12, 350, 350);

  81. Flasher led3(13, 200, 222);

  82. Sweeper sweeper1(15);

  83. Sweeper sweeper2(25);

  84. void setup()

  85. {

  86. Serial.begin(9600);

  87. sweeper1.Attach(9);

  88. sweeper2.Attach(10);

  89. }

  90. void loop()

  91. {

  92. sweeper1.Update();

  93. if(digitalRead(2) == HIGH)

  94. {

  95. sweeper2.Update();

  96. led1.Update();

  97. }

  98. led2.Update();

  99. led3.Update();

  100. }

3 LEDs will blink at their own rate. 2 sweepers willalsowork at their own speed. But when the button is pressed, sweeper2and led1willstopuntil the button is released.

wielozadaniowość Arduino - działanie

We now have 5 user input tasks, working independently. There are no delays that will block the processor. And our powerful object-oriented programming code leaves plenty of room for expansion!

Conclusion:

In this guide we've shown that Arduino can perform many different tasks and still react to external events.

  • We learned how to measure time with millis() instead of delay(), which allowed the CPU to do other things.
  • We learned how to define tasks as automats that can work at the same time as other automats, but independently of them.
  • We discovered how to include these slots in C++ classes to keep the code simple and concise.

These techniques will not turn your Arduino into a supercomputer. However, they will help you get the best out of this small but amazingly powerful module.

In the second part, we'll build using these techniques. We'll also discover other ways to make Arduino react to external events while keeping many tasks running.

part two ->

Source: https://learn.adafruit.com/multi-tasking-the-arduino-part-1

Botland.store - shop for makers!