Apparently using delay() commands locks the Arduino during the delay period and there are better ways to control a servo that free the Arduino to do other things at the same time as running the servo.
At this point my code consists of a servo going forwards and backwards like this:
void setup()
{
pinMode(1, OUTPUT); // makes pin 1 an output
}
void loop()
{
for(int i = 0; i<31; ++i) { //keeps in this position for about 400ms
digitalWrite(1, HIGH); //turns the servo pin to HIGH
delayMicroseconds(1000); //sets the servo to move clockwise
digitalWrite(1, LOW); //turns the servo pin to LOW
delay(19);
}
for(int i = 0; i<31; ++i) { // keeps in this position for about 400ms
digitalWrite(1, HIGH); // turns the servo pin to HIGH
delayMicroseconds(2000); //sets the servo to move anti-clockwise
digitalWrite(1, LOW); //turns the servo pin to LOW
delay(19);
}}
Where and how will I add some code that will allow the arduino to carry out another task for example blinking an led light during the approximately 20ms between servo pulses.
NOTE: The arduino is using the ATtiny 85 Processor.
3 Answers 3
Before and after the delay of 19 ms?
In setup add:
pinMode(2, OUTPUT); // LED pin output
Than changen in both cases:
delay(19);
into
digitalWrite(2, HIGH); // LED on
delay(19);
digitalWrite(2, LOW); // LED off
-
1When you say digitalWrite(2, HIGH); // LED on, you use pin 2 but when you say digitalWrite(1, LOW); // LED off, you use pin one. Is this a typo or what?Utsav– Utsav2017年09月19日 13:15:35 +00:00Commented Sep 19, 2017 at 13:15
-
1@Utsav ... it was a type and I updated it, thanks for the notificationMichel Keijzers– Michel Keijzers2017年09月19日 13:39:29 +00:00Commented Sep 19, 2017 at 13:39
Short answer: don't use delay()
if you want to do anything other than waiting, so rewrite your code without that call.
Long answer follows.
Instead of asking the Arduino to go to sleep (1) until a certain amount of time has passed, you should write your code to run continuously and do certain things whenever enough time has passed since the last time they have been executed. If the previous statement makes sense to you, then the following piece of code translates to C language what I just stated in English:
unsigned long time; // stores the time when the last motor movement happened, in ms
boolean clockwise; // stores the wanted direction: true CW, false CCW
unsigned byte counter; // stores how many time the wanted movement has occurred so far
unsigned long ledTimer; // stores the last time we changed the LED state
boolean ledIsOn; // stores the current LED state
void setup() {
pinMode(1, OUTPUT); // makes pin 1 an output
pinMode(13, OUTPUT); // makes pin 13 (onboard LED pin) an output
}
void loop() {
if (time - millis() >= 19) { // has enough time passed since the last time we executed a step motor movement?
time = millis(); // reset the timer for next pass
if (counter < 31) { // have we moved in the same direction enough?
if (clockwise) {
moveCW();
} else {
moveCCW();
}
counter++;
} else { // we moved enough times in the same direction: reset the counter and switch direction
counter = 0;
clockwise = !clockwise;
}
}
// do anything else, but don't use delay()!!!
// the following does the same as above, but on the LED
// blinking at 1Hz (500 ms on, 500ms off)
if (millis() - ledTimer >= 500) {
if (ledIsOn) {
digitalWrite(13, LOW);
} else {
digitalWrite(13, HIGH);
}
ledIsOn = !ledIsOn;
ledTimer = millis();
}
// need to do something more? go ahead and try
// but remember not to use delay() and not to waste too much time
// in complex calcs or the loop will take too long to wrap
}
void moveCW() {
digitalWrite(1, HIGH); //turns the servo pin to HIGH
delayMicroseconds(1000); //sets the servo to move clockwise
digitalWrite(1, LOW); //turns the servo pin to LOW
}
void moveCCW() {
digitalWrite(1, HIGH); // turns the servo pin to HIGH
delayMicroseconds(2000); //sets the servo to move anti-clockwise
digitalWrite(1, LOW); //turns the servo pin to LOW
}
There is a beautiful library called elapsedMillis
(reference) which can reduce a bit the boilerplate code regarding subtracting millis()
and all that stuff, but the code above is practically the same and, probably, more straightforward to begin with.
(1) The term sleep it's incorrect as it implies some sort of power reduction. Instead sleep()
is just wasting time at full power.
I'm not sure exactly what you mean with "between servo pulses" but I am assuming it means you want to blink the led while the servo is turning.
Use the Arduino Timer library: https://playground.arduino.cc/Code/Timer
Add this at top of the sketch:
#include "Timer.h"
Timer t;
#define BLINK_TIME 20
in setup, add:
t.oscillate(LED_PIN, BLINK_TIME, HIGH);
inside the two for-loops, add:
t.update();
This will make the led on LED_PIN turn on and off every 20 milliseconds.