What else can we do with it?
Let’s apply the same principles to some servo code and get some action going.
First hook up a couple of servos on your breadboard as shown below. As long as we are at it, let's hook up a third LED too.
Here is the standard Servo sweep code. Note that it calls the dreaded delay(). We'll take the parts we need from it to make a "Sweeper" state machine.
// Sweep // by BARRAGAN <http://barraganstudio.com> // This example code is in the public domain. #include <Servo.h> Servo myservo; // create servo object to control a servo // a maximum of eight servo objects can be created int pos = 0; // variable to store the servo position void setup() { myservo.attach(9); // attaches the servo on pin 9 to the servo object } void loop() { for(pos = 0; pos < 180; pos += 1) // goes from 0 degrees to 180 degrees { // in steps of 1 degree myservo.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15ms for the servo to reach the position } for(pos = 180; pos>=1; pos-=1) // goes from 180 degrees to 0 degrees { myservo.write(pos); // tell servo to go to position in variable 'pos' delay(15); // waits 15ms for the servo to reach the position } }
The Sweeper class below encapsulates the sweep action, but uses the millis() function for timing, much like the Flasher class does for the LEDs.
We also need to add Attach() and Detach() functions to associate the servo with a specific pin:
class Sweeper { Servo servo; // the servo int pos; // current servo position int increment; // increment to move for each interval int updateInterval; // interval between updates unsigned long lastUpdate; // last update of position public: Sweeper(int interval) { updateInterval = interval; increment = 1; } void Attach(int pin) { servo.attach(pin); } void Detach() { servo.detach(); } void Update() { if((millis() - lastUpdate) > updateInterval) // time to update { lastUpdate = millis(); pos += increment; servo.write(pos); Serial.println(pos); if ((pos >= 180) || (pos <= 0)) // end of sweep { // reverse direction increment = -increment; } } } };
How many would you like?
Now we can instantiate as many Flashers and Sweepers as we need.
Each instance of a Flasher requires 2 lines of code:
- One to declare the instance
- One to call update in the loop
Each instance of a Sweeper requires just 3 lines of code:
- One to declare the instance
- One to attach it to a pin in setup
- And one call to update in the loop
#include <Servo.h> class Flasher { // Class Member Variables // These are initialized at startup int ledPin; // the number of the LED pin long OnTime; // milliseconds of on-time long OffTime; // milliseconds of off-time // These maintain the current state int ledState; // ledState used to set the LED unsigned long previousMillis; // will store last time LED was updated // Constructor - creates a Flasher // and initializes the member variables and state public: Flasher(int pin, long on, long off) { ledPin = pin; pinMode(ledPin, OUTPUT); OnTime = on; OffTime = off; ledState = LOW; previousMillis = 0; } void Update() { // check to see if it's time to change the state of the LED unsigned long currentMillis = millis(); if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime)) { ledState = LOW; // Turn it off previousMillis = currentMillis; // Remember the time digitalWrite(ledPin, ledState); // Update the actual LED } else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime)) { ledState = HIGH; // turn it on previousMillis = currentMillis; // Remember the time digitalWrite(ledPin, ledState); // Update the actual LED } } }; class Sweeper { Servo servo; // the servo int pos; // current servo position int increment; // increment to move for each interval int updateInterval; // interval between updates unsigned long lastUpdate; // last update of position public: Sweeper(int interval) { updateInterval = interval; increment = 1; } void Attach(int pin) { servo.attach(pin); } void Detach() { servo.detach(); } void Update() { if((millis() - lastUpdate) > updateInterval) // time to update { lastUpdate = millis(); pos += increment; servo.write(pos); Serial.println(pos); if ((pos >= 180) || (pos <= 0)) // end of sweep { // reverse direction increment = -increment; } } } }; Flasher led1(11, 123, 400); Flasher led2(12, 350, 350); Flasher led3(13, 200, 222); Sweeper sweeper1(15); Sweeper sweeper2(25); void setup() { Serial.begin(9600); sweeper1.Attach(9); sweeper2.Attach(10); } void loop() { sweeper1.Update(); sweeper2.Update(); led1.Update(); led2.Update(); led3.Update(); }
Now we have 5 independent tasks running non-stop with no interference. And our loop() is only 5 lines of code! Next we'll add a button so we can interact with some of these tasks.
Text editor powered by tinymce.