I'm new to the Arduino and to C for the most part. I grabbed the sample code from Debounce and Servo Sweep and kind of melded them together to get what I was looking for. The paths are below:
file/examples/digital/debounce
file/examples/analog/sweep
So for my project I have a servo in a box with a lid. When I push the button I want the lid to open on press and close on press again. When the box is open or the button has been pressed once a light will go on signaling the box is open and the light will go off when the box closes.
So everything is working good almost. The light goes on when clicked and off on second click but the servo won't open all the way unless I keep my finger on the button and then it will retract when I take my finger off the button.
Can someone help me out and show me how to get the motor to open to full 160 on a single click and back on another click? I would really appreciate the help!
/*
Debounce
Each time the input pin goes from LOW to HIGH (e.g. because of a push-button
press), the output pin is toggled from LOW to HIGH or HIGH to LOW. There's
a minimum delay between toggles to debounce the circuit (i.e. to ignore
noise).
The circuit for LED:
* LED attached from pin 13 to ground
* pushbutton attached from pin 2 to +5V
* 10K resistor attached from pin 2 to ground
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// a maximum of eight servo objects can be created
int pos = 160; // variable to store the servo position
// constants won't change. They're used here to
// set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin
// Variables will change:
int ledState = HIGH; // the current state of the output pin
int buttonState; // the current reading from the input pin
int lastButtonState = LOW; // the previous reading from the input pin
// the following variables are long's because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long lastDebounceTime = 0; // the last time the output pin was toggled
long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
myservo.attach(9); // attaches the servo on pin 9 to the servo object
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
myservo.write(50);
// set initial LED state
digitalWrite(ledPin, ledState);
}
void loop() {
// read the state of the switch into a local variable:
int reading = digitalRead(buttonPin);
// check to see if you just pressed the button
// (i.e. the input went from LOW to HIGH), and you've waited
// long enough since the last press to ignore any noise:
// If the switch changed, due to noise or pressing:
if (reading != lastButtonState) {
// reset the debouncing timer
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > debounceDelay) {
// whatever the reading is at, it's been there for longer
// than the debounce delay, so take it as the actual current state:
// if the button state has changed:
if (reading != buttonState) {
myservo.write(50);
buttonState = reading;
// only toggle the LED if the new button state is HIGH
if (buttonState == HIGH) {
myservo.write(pos);
ledState = !ledState;
}
}
}
// set the LED:
digitalWrite(ledPin, ledState);
// save the reading. Next time through the loop,
// it'll be the lastButtonState:
lastButtonState = reading;
}
I like that you added comments and tried to separate things, but as for the code I did see something that concerns me.
if (reading != buttonState) {
myservo.write(50); // Your setting the servo to start at a certain place, fine, but why is it also set there in setup() ?
buttonState = reading;
// only toggle the LED if the new button state is HIGH
if (buttonState == HIGH) { // Now I see that if the button is held HIGH, you want the servo to move, but by how?
myservo.write(pos); // when does pos ever get updated to change the position of the servo?
ledState = !ledState;
}
See if you can added to this code to get your servo to work. Now keep in mind the button pin and LED pin.
const byte LED = 6;
const byte Button = 2;
byte ButtonState;
byte last = LOW;
int count = 0;
void setup() {
Serial.begin(9600);
pinMode(LED, OUTPUT);
pinMode(Button, INPUT);
}
void loop() {
ButtonState = digitalRead(Button);
if(ButtonState && ButtonState != last) { // update LED brightness if button is PRESSED, and not HELD
analogWrite(LED, count += 5);
Serial.println(count);
}
if(count > 255){ // this could be changed to 180 for your servo. What this line does is if the code see count get above 255, it will set it back to zero to start over.
digitalWrite(LED, LOW);
count = 0;
}
last = ButtonState;
}
Hey So the reason I added myservo.write(50); in setup is because I'm using a recycled servo and for some reason when it initiates it would twitch and open the door on my box about 10 degrees. I found that if I set it there it would close on startup the way I wanted it to.
As far as updating the position that's the part where I am coming up short. I don't know how to write the code in a way that will tell the motor to go to 50 or 160 degrees and stop.
Thanks for posting this code. I'll take a look and see what I can learn
vdub,
Can you test the following bit of code just to make sure your servo will move to the positions you need it to.
Behind the scenes the servo library is taking control of one of the timers in the Arduino CPU. It is using this timer to create a pulse train to the servo to control its position. So when you send a .write(int) command to the servo it will drive to that position and then stay there because while you are executing other code the timer is still sending the pulse train to the servo on its attached pin.
That means all you have to do is give the servo a .write(int) command and it will go there and stay there until you give it a new command.
So this sketch should test out moving the servo to open and close your box every three seconds. If this works then the next step is to control it with the button.
//Servo control example for moving between two positions.
#include <Servo.h>
const int duration = 3000; //milliseconds
const int closed = 50; //degrees
const int opened = 160; //degrees
Servo servo;
void setup() {
servo.attach(9);
}
void loop() {
servo.write(opened);
delay(duration);
servo.write(closed);
delay(duration);
}
When I push the button I want the lid to open on press and close on press again.
This indicates latch logic. In which you press the button once, the code saves the inverse of that value and sends it out. You press the button again and again it inverse the inversed value.
Simple button latch.
byte buttonPin = 2;
byte LED = 13;
byte buttonState;
byte latch;
byte lastState;
void setup(){
Serial.begin(9600);
pinMode(buttonPin, INPUT);
pinMode(LED, OUTPUT);
}
void loop() {
buttonState = digitalRead(buttonPin); // read the state of the button
if(buttonState && buttonState != lastState){ //See if the button state is HIGH, and does not equal the last state
latch = !latch; // flip the state of the LED
/* if(latch == true)
{
digitalWrite(LED, HIGH);
}
else
{
digitalWrite(LED, LOW);
}
*/
digitalWrite(LED, latch ? HIGH : LOW); // state of LED according to latch state, COMPACT IF / ELSE STATEMENT
Serial.println(latch); // visual of latch state
}
lastState = buttonState; // update last state
}
I need to ask, are you powering the servo off the 5+ on the Arduino or separate power supply? Those tiny micro servos can run off the Arduino, but a regular size servo can not. Which do you have?