Pretty new to all this. I'm trying to use a servo connected to a push button. And I'd like it so that, if the push button is pressed, it rotates to 180, then stops, if it is pressed again, it rotates back to 0, another press would rotate back to 180, so on and so forth.
#include <Servo.h>
Servo myservo; // create servo object to control a servo
const int ServoPin = 9;
const int ButtonPin = 8;
void setup()
{
pinMode(ButtonPin, INPUT_PULLUP);
myservo.attach(ServoPin); // attaches the servo on pin 9 to the servo object
}
void loop()
{
if (digitalRead(ButtonPin) == LOW) {
for(int 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
}
}
if (digitalRead(ButtonPin) == HIGH) {
for(int pos = 0; pos <180; pos += 0) // 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
}
}
}
Pretty sure, the problem is the code in the loop, but not sure what the correct doe would be. Thanks for any help
The program should, if the button is pressed (even momentarily) complete one arc, of 180 degrees (from whichever side it is one to the other). And then stop. The next press should move it the 180 back the other way.
Taking finger off the button mid-sweep, the servo should complete the arc, then stop. (and this is probably the primary way this would be used)
What should happen if the button is released and pressed again during the time when the servo is moving as it was commanded from A to B?
Don't say that won't happen! Yes it will, and the program will do (or not do) something… now is your opportunity to make this be what you want instead of what you get.
If the button is released, and then pressed a 2nd time whilst still moving, it should just complete the originally commanded arc and stop. Only once it's come to a stop should it register a button press for another movement.
Oh I presumed it would happen - I was one of those kids that did exactly that with toys I owned!
#include <Servo.h>
Servo myservo; // create servo object to control a servo
const int ServoPin = 9;
const int ButtonPin = 8;
byte flag = 0;
void setup()
{
pinMode(ButtonPin, INPUT_PULLUP);
myservo.attach(ServoPin); // attaches the servo on pin 9 to the servo object
}
void loop()
{
if (digitalRead(ButtonPin) == LOW)
{
delay(30);
if (digitalRead(ButtonPin) == LOW)
{
flag++;
}
}
while (flag == 1)
{
for (int pos = 0; pos < 180; pos ++) // 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
}
}
while (flag == 2)
{
for (int pos = 180; pos > 0; pos--) // 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
}
flag = 0;
}
}
#include <Servo.h>
Servo myservo; // create servo object to control a servo
const int ServoPin = 9;
const int ButtonPin = 8;
void setup()
{
pinMode(ButtonPin, INPUT_PULLUP);
myservo.attach(ServoPin); // attaches the servo on pin 9 to the servo object
Serial.begin(9600);
Serial.println("Setup");
}
void loop()
{
if (digitalRead(ButtonPin) == LOW) {
for(int 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
Serial.println("Loop1");
}
}
if (digitalRead(ButtonPin) == HIGH) {
for(int pos = 0; pos <180; pos += 0) // 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
Serial.println("Loop2");
}
}
}
And the monitor outputs:
Setup
Loop2
Loop2
Loop2
Loop2
etc. etc.
The first time I pressed the button a few uploads ago, it moved once to its current position, and since then has not responded. I'm inclined to think the code is telling it, if it is in one position AND the button is pressed, then move to the other position then STOP, but not the opposite, so once it's in the current position the code has no provision for moving it, but I'm not sure what that change would look like
No luck unfortunately. The servo resets to the centre position immediately. When the button is oressed the servo starts turning one way, reaches the limits, then immediately turns back the full arc, and start turning again. The servo doesn't stop after 1 arc. Pressing the button again doesn't yield anything, and the servo continues to turn
It should go nowhere - its simply a mistake. If you don' change your for loop variable, your for loop will never end and will do the same thing with every loop. See your printings.
pos +=1 leads to it continuously sweeping out an arc and resetting after the first button press. The serial monitor shows the same as before (Setup, Loop2, Loop2 etc.). (Also it seems to sweep slightly less than 180, but thats not a huge issue)
pos -=1 leads to the servo just lieing stationary, pressing the button does nothing and the serial monitor shows the same.
Hi @epideme
there really was my mistake.
Try this one fixed.
RV mineirin
#include <Servo.h>
Servo myservo; // create servo object to control a servo
const int ServoPin = 9;
const int ButtonPin = 8;
byte flag = 0;
void setup()
{
pinMode(ButtonPin, INPUT_PULLUP);
myservo.attach(ServoPin); // attaches the servo on pin 9 to the servo object
}
void loop()
{
if (digitalRead(ButtonPin) == LOW)
{
delay(30);
if (digitalRead(ButtonPin) == LOW)
{
flag++;
}
}
while (flag == 1)
{
for (int pos = 0; pos < 180; pos ++) // 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
}
flag = 2;
}
while (flag == 3)
{
for (int pos = 180; pos > 0; pos--) // 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
}
flag = 0;
}
}
Hello
Try this sketch and check it out for your project.
#include <Servo.h>
Servo myservo; // create servo object to control a servo
const int ServoPin = 9;
const int ButtonPin = 8;
void setup() {
pinMode(ButtonPin, INPUT_PULLUP);
myservo.attach(ServoPin); // attaches the servo on pin 9 to the servo object
}
void loop() {
static bool stateNew = false;
static bool turn = false;
static byte control_ = 0;
bool stateRecent = !digitalRead(ButtonPin);
if (stateNew != stateRecent) {
delay(20);
stateNew = stateRecent;
if (stateNew) control_++, turn = true;
}
if ((control_ & 1) && turn) {
for (int pos = 0; pos < 180; pos++) // 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
}
}
if (!(control_ & 1) && turn) {
for (int pos = 180; pos > 0; pos--) // goes from 180 degrees to 0 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
}
}
turn = false;
}
I must withhold the Gold Cigar Award for the nice fish @ruilviana gave you in #15.
The delay is tots unnecessary. The if statement can just be
if (digitalRead(ButtonPin) == LOW) flag++;
any bouncing or whatever the delay was in there for is more than taken care of because your while statements block. For some good time. 30 milliseconds is minor, but it does delay the onset of motion. In some cases any delay is bad - it makes sense to begin trying to avoid using it, no matter it makes little difference in this case.
But wait! There's more. Hold your finger down on the button and you get continuous sweeping back and forth.
If that's what you want, fine. If that just happened out of the code, not so fine.
Replace the if statement with a real edge detector and that'll fix you up.
Test code back from the wokwi simulator.
#include <Servo.h>
Servo myservo; // create servo object to control a servo
const int ServoPin = 9;
const int ButtonPin = 8;
byte flag = 0;
void setup()
{
pinMode(ButtonPin, INPUT_PULLUP);
myservo.attach(ServoPin); // attaches the servo on pin 9 to the servo object
}
void loop()
{
static unsigned long lastTime = 0;
static unsigned char lastButton = HIGH;
if (millis() - lastTime > 30) {
unsigned char theButton = digitalRead(ButtonPin);
if (theButton != lastButton) {
lastButton = theButton;
if (!theButton) flag++;
lastTime = millis();
}
}
while (flag == 1)
{
for (int pos = 0; pos < 180; pos ++) // 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
}
flag = 2;
}
while (flag == 3)
{
for (int pos = 180; pos > 0; pos--) // 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
}
flag = 0;
}
}
Try it yourself. Also you have noticed by now that you might want to send the servo somewhere in your setup code.
@paulpaulson has an edge detector, but makes the usual mistake of delaying, hindering rapid response to the button. 20 milliseconds, no large deal. Until it is.