#include <Servo.h>
Servo myservo1; // create servo object to control servo 1 ,
Servo myservo2; // create servo object to control servo 2 ,
int myservo1_pin = 11; // pin that controls the servo
int myservo2_pin = 12; // pin that controls the servo
int myservo1_speed = 5; // how fast the servo moves, 1 = very fast, 10 = very slow
int myservo2_speed = 5; // how fast the servo moves, 1 = very fast, 10 = very slow
long myservo1_movetime = 0; // next time in millis servo next moves
long myservo2_movetime = 0; // next time in millis servo next moves
int myservo1_gPos = 0; // target position to move towards
int myservo2_gPos = 0; // target position to move forward
int myservo1_cPos = 0; // current position of servo
int myservo2_cPos = 0; // current position of servo
int pos = 0; // variable to store the servo position
int cPos; // current position
int gPos; // goal position
int tDelay = 5; // delay between moves, gives appearance of smooth motion
const int ledPin = LED_BUILTIN ; // the number of led pin
int ledState = LOW; // ledState used to set led
unsigned long previousMillis = 0; // will store last time the led was updated
const long interval = 1000; // interval at which to blink ( in milliseconds)
void setup() {
Serial.begin(9600);
myservo1.attach(11); // attaches the servo on pin 11 to the servo object
myservo2.attach(12); // attaches the servo on pin 12 to the servo object
pinMode(ledPin, OUTPUT); // set the digital pin as output
Serial.println("setup complete : smooth servo movment without delay v2");
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >=interval){ // saves the time you last blinked the led
previousMillis=currentMillis; // if the led is off turn it on or vice-versa:
if (ledState == LOW){
ledState = HIGH;
} else {
ledState = LOW;
}
digitalWrite(ledPin, ledState);
}
cPos = myservo1.read();
cPos = myservo2.read();
if (cPos == 0) gPos = 180;
if (cPos == 180) gPos = 0;
if (cPos != gPos && millis() >= myservo1_movetime) {
moveServo();
if (cPos != gPos && millis() >= myservo2_movetime)
moveServo();
}
if (Serial.available() > 0) { GetCommand(); }
}
void moveServo() {
if (cPos < gPos) myservo2.write(cPos=1);
if (cPos > gPos) myservo2.write(cPos-1);
if (cPos < gPos) myservo1.write(cPos+1);
if (cPos > gPos) myservo1.write(cPos-1);
//if (cPos == gPos) // nothing
myservo1_movetime = millis() + tDelay;
myservo2_movetime = millis() + tDelay;
}
void GetCommand() {
int command = Serial.read() - '0';
int mVal = command;
if (mVal == 'x') {
tDelay = tDelay * 10;
} else {
tDelay = mVal;
}
Serial.print("Pauses changed to : "); Serial.print(tDelay); Serial.println(" mSeconds");
Serial.flush();
}
It took me a month ( with a lot of help from hear) to get to sweep one servo. Took me 2 days to sweep
2 servos. But when I tried to add " blink without delay " it loaded just fine but the built in led flashes just fine but now my servos don't move. I have looked but can't seam to find just what I'm doing wrong. Can some one have a look and see what I did wrong.
chickenhawk:
I have looked but can't seam to find just what I'm doing wrong. Can some one have a look and see what I did wrong.
Lots of people struggle with trying to get a servo to sweep and do other things simultaneously, so don't fret.
I find that the easiest way to accomplish it is also a difficult concept to grasp, particularly if you are not savvy in the way of Object Oriented programming.
Here is an example that basically adds a few functions to the Servo class (update(), moveTo() and moveAllTo()). Even if you don't understand the class definition, it should get you a long way towards your goal of un-blocking loop().
#include <Servo.h>
/******************* BEGIN CLASS DEFINITION *******************/
#define MOTION_SPEED_INTERVAL 10 // milliseconds
#define MAX_SERVO_INSTANCES 5
class Sweep : public Servo {
public:
Sweep(void(*_startCallback)(int), void(*_endCallback)(int));
Sweep();
void begin(int servo);
void moveTo(int newPosition);
static void moveAllTo(int newPosition);
static void update();
static void update(uint32_t now);
static int getServoCount();
int getPosition (void) const;
private:
enum {
ARM_STANDBY,
ARM_MOVING,
} motionState = ARM_MOVING;
void(*startCallback)(int);
void(*endCallback)(int);
static Sweep* instanceAddress;
static int instanceCount;
int servoPin;
uint32_t lastMotionMillis = 0;
int currentPosition;
int targetPosition;
uint32_t sensedChangedMillis;
static void setTargetPosition(Sweep* instance, int position);
};
int Sweep::instanceCount = 0;
Sweep* instances[MAX_SERVO_INSTANCES] = {nullptr};
Sweep::Sweep() {
instances[instanceCount++] = this;
}
Sweep::Sweep(void(*_startCallback)(int), void(*_endCallback)(int)) {
instances[instanceCount++] = this;
startCallback = _startCallback;
endCallback = _endCallback;
}
int Sweep::getServoCount() {
return instanceCount;
}
void Sweep::begin(int servo) {
servoPin = servo;
pinMode(servoPin, OUTPUT);
attach(servoPin);
moveTo(0);
delay(1000);
detach();
}
void Sweep::setTargetPosition(Sweep* instance, int position) {
instance->targetPosition = position;
}
void Sweep::moveTo(int newPosition) {
if (newPosition > 180) {
newPosition = 180;
} else if (newPosition < 0) {
newPosition = 0;
}
setTargetPosition(this, newPosition);
}
void Sweep::moveAllTo(int newPosition) {
if (newPosition > 180) {
newPosition = 180;
} else if (newPosition < 0) {
newPosition = 0;
}
for (auto i : instances)
{
setTargetPosition(i, newPosition);
}
}
void Sweep::update() {
update(millis());
}
void Sweep::update(uint32_t now) {
for (auto srv : instances) {
switch (srv->motionState) {
case ARM_MOVING:
if (now - srv->lastMotionMillis > MOTION_SPEED_INTERVAL) {
if (srv->targetPosition == srv->currentPosition) {
if (srv->attached()) {
srv->detach();
srv->motionState = ARM_STANDBY;
if (srv->endCallback) {
srv->endCallback(srv->getPosition());
}
}
} else {
if (!srv->attached()) {
srv->attach(srv->servoPin);
}
if (srv->targetPosition > srv->currentPosition) {
srv->currentPosition++;
srv->write(srv->currentPosition);
} else {
srv->currentPosition--;
srv->write(srv->currentPosition);
}
}
srv->lastMotionMillis = now;
}
break;
case ARM_STANDBY:
if (srv->targetPosition != srv->currentPosition) {
srv->motionState = ARM_MOVING;
if (srv->startCallback) {
srv->startCallback(srv->getPosition());
}
}
break;
}
}
}
int Sweep::getPosition(void) const {
return currentPosition;
}
/******************** END CLASS DEFINITION ********************/
void startMoving(int value);
void stoppedMoving(int value);
Sweep servo1(startMoving, stoppedMoving); //callback functions to execute when the servo starts or stops moving.
//Sweep servo2; // callback functions not required
void setup() {
Serial.begin(9600);
servo1.begin(4);
pinMode(13, OUTPUT);
Serial.print("Total Attached Servos:\t");
Serial.println(Sweep::getServoCount());
}
void loop() {
Sweep::update(); // this is necessary
if (Serial.available()) {
int destination = Serial.parseInt();
Serial.print(F("servo1 asked to move to: "));
Serial.print(destination);
Serial.print(F(" degrees\n"));
servo1.moveTo(destination);
}
}
void startMoving(int value) {
Serial.print(F("servo1 motion started at: "));
Serial.print(value);
Serial.print(F(" degrees\n"));
digitalWrite(13, HIGH);
}
void stoppedMoving(int value) {
Serial.print(F("servo1 motion completed at: "));
Serial.print(value);
Serial.print(F(" degrees\n"));
digitalWrite(13, LOW);
}
The demo Several Things at a Time is an extended example of BWoD. It blinks some LEDs and sweeps a servo. It may help with understanding the technique.
Note how each function runs very briefly and returns to loop() so the next one can be called. Long running processes are achieved a tiny piece at a time. And there may be dozens of calls to some functions before it is actually time for anything to happen.
So my " blink without delay" is blocking my sketch from running the servo sweep part? I will re read " Several Things at a time" again. And see If I can figure it out. I would like to leave the servo sweep part alone as I would like to add more servos and it took me a fair bit of time and studying to get to where I understood what I was doing.
But after re reading Several Things at the same time, I have a dumb question. I'm powering the 2 servos and the on board led from my " Red Board" is there any way that my board does not have the power output to run all three things at once?
O crap #######
if (cPos < gPos) myservo2.write(cPos=1);
if (cPos < gPos) myservo2.write(cPos+1);
You must hold the shift key down when going from = to +
Well guess what, I fixed what Delta_G spotted that I could not see and everything works great. Pardon me while I remove my head from my ###. I will rig up a different power supply for the servos.