Hi,
The sketch below just sweep CW, and doesn't return, why?
Thanks
Adam
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// BOTH FLSERVO and FRSERVO use same millis:
unsigned long SweepstartMillis; //some global variables available anywhere in the program
unsigned long SweepcurrentMillis;
const unsigned long Sweepperiod = 50; //the value is a number of milliseconds
unsigned long SweepstartMillisn; //some global variables available anywhere in the program
unsigned long SweepcurrentMillisn;
const unsigned long Sweepperiodn = 50; //the value is a number of milliseconds
unsigned long LedstartMillis; //some global variables available anywhere in the program
unsigned long LedcurrentMillis;
const unsigned long Ledperiod = 20; //the value is a number of milliseconds
int pos = 0; // variable to store the servo position
int posn = 180;
int led = 13;
int SweepStart = 0;
int ReturnStart = 0;
void setup() {
// put your setup code here, to run once:
pinMode(led, OUTPUT);
myservo.attach(47); // attaches the servo on pin 9 to the servo object
}
void loop() {
// put your main code here, to run repeatedly:
SERVO_sweep();
}
void SERVO_sweep()
{
while (!SweepStart == 0)
{
Serial.println("L55 wait for!");
}
// put your main code here, to run repeatedly:
SweepcurrentMillis = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (SweepcurrentMillis - SweepstartMillis >= Sweepperiod) //test whether the period has elapsed
{
// digitalWrite(ledPin, !digitalRead(ledPin)); //if so, change the state of the LED. Uses a neat trick to change the state
pos = pos + 2;
if (pos > 180) ///// WAS: 180, [int SERVO_range = 180;] SERVO scan the first 180 degree and then no readings but just turn ~175 degree?
{
SweepStart = 1;
ReturnStart = 1;
SERVO_return();
posn = 180;
pos = 180;
}
myservo.write(pos);
SweepstartMillis = SweepcurrentMillis; //IMPORTANT to save the start time of the current LED state.
}
}
void SERVO_return()
{
while (!ReturnStart == 1)
{
Serial.println("L87 wait for!");
}
Serial.println("SERVO_return start!");
SweepcurrentMillisn = millis(); //get the current "time" (actually the number of milliseconds since the program started)
if (SweepcurrentMillisn - SweepstartMillisn >= Sweepperiodn) //test whether the period has elapsed
{
// digitalWrite(ledPin, !digitalRead(ledPin)); //if so, change the state of the LED. Uses a neat trick to change the state
posn = posn - 2;
if (posn = 0) ///// WAS: 180, [int SERVO_range = 180;] SERVO scan the first 180 degree and then no readings but just turn ~175 degree?
{
// SERVO_return();
SweepStart = 0;
pos = 0;
posn = 0;
}
myservo.write(posn);
SweepstartMillisn = SweepcurrentMillisn; //IMPORTANT to save the start time of the current LED state.
}
}
You only call SERVO_return() once so its timing and servo movement have no chance of working. You need to call it repeatedly once the initial sweep has taken place
Using millis() is looking at the clock, and do what should be done at that moment.
When using millis(), the sketch will run smooth if there are no delay() and there is no waiting for something with a while-statement. Let the loop() run as fast and as many times per second as possible.
To control a servo motor with millis(), the current servo position is often updated every 10ms or every 20ms. That means that only a single millis-timer with a fixed delay of 10ms or 20ms is needed to control many servo motors at the same time.
You need math to calculate where the posistion of the servo motor should be at that moment. You might also need extra variables to tell if the servo motor is moving or not or going upward or downward and at what speed.
I have made a example in Wokwi simulation for that. Click the start button and turn the knobs and push the buttons. The explanation is in the sketch.
and the slowly sweeping is done "in the backround"
You can read status-information
myServo.moving();
myServo.read();
So the sweeping reduces to
set sweeping-speed
set target-angle
check if target-angle is reached
if target-ange is reached set new target-angle
repeat
#include <MobaTools.h>
/* Demo to move a servo slowly
In this example a servo sweeps slowly between two positions as long as
a button is pressed. If the button is released, it stops immediately and
starts again from that position if the button is pressed again.
The sketch does not block and can be extended to do other tasks.
*/
// The button must be connected between pin and Gnd
const int buttonPin1 = A2; //button1 Pin 2
const int servoPin = 3 ; // The servo is connected to this pin
// Position to sweep
const byte target1 = 30;
const byte target2 = 120;
bool buttonPressed;
byte targetPos = target1; // actual targetposition for the servo
MoToServo myServo;
void setup() {
pinMode(buttonPin1, INPUT_PULLUP);
myServo.attach(servoPin);
myServo.setSpeed( 5 ); // set speed of servo
}
void loop() {
buttonPressed = !digitalRead(buttonPin1); // 'ButtonPressed is 'true' if pin is LOW
if (buttonPressed && not myServo.moving() ) {
if ( myServo.read() == target1 ) targetPos = target2;
if ( myServo.read() == target2 ) targetPos = target1;
myServo.write(targetPos); //will move slowly
}
if ( !buttonPressed ) myServo.write( myServo.read() ); // stop immediately
}
You are setting ReturnStart to 1 just before calling SERVO_return().
At the beginning of SERVO_return() you wait for "not ReturnStart" (in other words, false or 0) to be equal to 1. That is never going to be true. Your function will be stuck in that loop sending "L87 wait for!" forever.