Control 2 servo motors with 2 buttons Arduino - arduino

I'm working on another school project where I'm trying to make an obstacle course (model size). For this project I'm using 2 servo motors, which I want to control with 2 different buttons. So 1 button is connected to 1 servo motor and the other one is connected to the other servo. I'm actually struggling to get both buttons to work with the servo motors.
When I attach 1 button and 1 servo motor everything works exactly the way I want. I press the button, the servo motor moves 90 degrees and after 5 seconds it moves back.
The code:
#include <Servo.h>
Servo myservo;
const int servoPin = D8; // Servo pin
const int buttonPin = D7; // Pushbutton pin
void setup() {
myservo.attach(servoPin);
pinMode(buttonPin, INPUT);
}//setup
void loop() {
if (digitalRead(buttonPin) == HIGH) {
myservo.write(180);
delay(50); // waits 50ms to reach the position
delay(15000);//15 seconden wachten
myservo.write(0);
delay(50); // waits 50ms to reach the position
}
}//loop
However I read on a forum that when you want to use more then one servo motor, you have to write the code differently. You have to include servo motors like this:
#include <Servo.h>
Servo myservoa, myservob;
When I changed the code everything stopped working and I don't really understand what I'm doing wrong here. I want the servo motors to work AT THE SAME TIME, with 2 different buttons.
The new code:
#include <Servo.h>
Servo myservoa, myservob;
const int servoPin1 = D8; // Servo pin
const int servoPin2 = D6; // Servo pin
const int buttonPin1 = D7; // Pushbutton pin
const int buttonPin2 = D5; // Pushbutton pin
void setup() {
myservoa.attach(servoPin1);
myservob.attach(servoPin2);
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
}//setup
void loop() {
if (digitalRead(buttonPin1) == HIGH) {
myservoa.write(90);
delay(50); // waits 50ms to reach the position
delay(5000);// 5 seconden wachten
myservoa.write(0);
delay(50); // waits 50ms to reach the position
}
if (digitalRead(buttonPin2) == HIGH) {
myservob.write(90);
delay(50); // waits 50ms to reach the position
delay(5000);// 5 seconden wachten
myservob.write(0);
delay(50); // waits 50ms to reach the position
}
}//loop
I hope somebody can help me out!
EDIT:
So i found out that 2 servo motors actually was to much for my NodeMCU. The code in the comments worked fine tho! Now I'm trying to combine the servo motor with a small vibration motor. The 2 sensors work well together but I can't get the vibration motor to work properly.
I want the vibration motor to vibrate for 5 seconds after I pressed the button. After 5 seconds it has to stop automatically. With the code the vibration motor only vibrates when I press the button. When the button isn't pressed, the vibration motor stops directly.
Code:
#include <Servo.h>
Servo myservo;
const int servoPin = D8; // Servo pin
const int vibratiePin = D3; // Servo pin
const int buttonPin1 = D6; // Pushbutton pin
const int buttonPin2 = D5; // Pushbutton Pin
unsigned long stopA = 0;
unsigned long stopB = 0;
bool controlA = false;
bool controlB = false;
void setup() {
pinMode(buttonPin1, INPUT);
pinMode(buttonPin2, INPUT);
myservo.attach(servoPin);
pinMode(vibratiePin, OUTPUT);
}//setup
void loop() {
unsigned long now = millis();
if(controlA && stopA < now) {
myservo.write(0);
controlA = false;
} else if (!controlA && digitalRead(buttonPin1) == HIGH) {
controlA = true;
myservo.write(90);
stopA = millis() + 5000;
}
if(controlB && stopB < now) {
digitalWrite(vibratiePin, LOW);
controlB = false;
stopB = millis() + 5000;
} else if (!controlB && digitalRead(buttonPin2) == HIGH) {
controlB = true;
digitalWrite(vibratiePin, HIGH);
}
stopB = now;
}
I hope somebody can see the problem here because I don't understand what I'm doing wrong.

Your problem is that you are sleeping the code at each on if statement:
if (digitalRead(buttonPin1) == HIGH) {
...
delay(5000);// the code is blocked for 5 seconds here
...
}
So if the buttonPin1 is HIGH the code after that block will run just after 5100 milliseconds after (at least).
Indeed you shouldn't use longs delays like that inside the loop. The reason is what you see: while the code is stopped the motors are still running and it is a real dangerous scenario for real applications.
The solution is: don't sleep! There are several ways to do it. One of them is use a program variable to control the state of each of motors and another one to set the time limit to run the motor:
unsigned long stopA = 0;
unsigned long stopB = 0;
bool controlA = false;
bool controlB = false;
void loop() {
unsigned long now = mills();
if(controlA && stopA < now) {
myservoa.write(0);
controlA = false;
} else if (!controlA && digitalRead(buttonPin1) == HIGH) {
controlA = true;
myservoa.write(90);
stopA = mills() + 5050;
}
//similar to motor b
//...
}
This way the code never be blocked into a sleeping command and loop can perform other actions while each motor is running.

Related

Incorporating button into Servo Loop

I am extremely new so please bare with me. I am attempting to control a servo by both the internal timer and by button. Essentially the servo will open a door for 6 seconds every 24 hours or so OR if you press the button enter image description here
The loop for the timer works but the button doesn't. However if i just upload the button code it works fine. Help please! Even better if the servo could go to 180 when the button is held down and return to 0 when released would be ideal.
Here is my code. Tell me where I messed up please!
#include <Servo.h>
Servo myservo;
const int BUTTON_PIN = 8;
const int SERVO_PIN = 9;
int angle = 0; // the current angle of servo motor
int lastButtonState; // the previous state of button
int currentButtonState; // the current state of button
void setup(){
myservo.attach(SERVO_PIN);
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
myservo.write(angle);
currentButtonState = digitalRead(BUTTON_PIN);
}
void loop(){
myservo.write(0);// move servos to center position -> 90°
delay(18000);
myservo.write(180);// move servos to center position -> 120°
delay (6000);
lastButtonState = currentButtonState; // save the last state
currentButtonState = digitalRead(BUTTON_PIN); // read new state
if(lastButtonState == HIGH && currentButtonState == LOW) {
Serial.println("The button is pressed");
// change angle of servo motor
if(angle == 180)
angle = 0;
else
if(angle == 0)
angle = 180;
// control servo motor arccoding to the angle
myservo.write(angle);
}
}
Based on your picture your pins should be 7 and 9. Basically, the only issue with your code is that you can not use delay if you also want to be monitoring something (your button). So instead you use what is called a watchdog timer, where you basically make something happen ever so often based on the system clock, but then also remain available to do other things when that is not happening.
Comparing the blink and blink without delay examples in the arduino example sketch folder may help explain this concept further.
#include <Servo.h>
Servo myservo;
const int BUTTON_PIN = 7;
const int SERVO_PIN = 9;
unsigned long dayTimer_ms = 0;
unsigned long autoOpenDelay_ms = 86400000;
int angle = 0;
void setup(){
myservo.attach(SERVO_PIN);
Serial.begin(9600);
pinMode(BUTTON_PIN, INPUT_PULLUP);
myservo.write(0);
}
void loop() {
if(millis() - dayTimer_ms > autoOpenDelay_ms )
{
dayTimer_ms = millis();
myservo.write(180); //(open?)
delay(6000);
myservo.write(0);
}
if(millis()<dayTimer_ms)//overflow handling (in case this runs for more than 50 days straight)
{
dayTimer_ms = millis();
}
if (!digitalRead(BUTTON_PIN) && angle != 180)
{
angle = 180;
myservo.write(angle);
}
if (digitalRead(BUTTON_PIN) && angle != 0)
{
angle = 0;
myservo.write(angle);
}
}

Arduino LED control sleep

I want to implement a simple LED controller with an Arduino Uno, that goes to sleep and has different buttons.
Functions of buttons are:
Digital 2: Button for ON OFF
Digital 3: Button for Wake up
Everything works ok, but when it goes to sleep, the LEDs also turn off. I want that after 30 seconds, when Arduino goes to sleep, lights stays on.
Here is my code:
#include <avr/sleep.h>
#define REDPIN 10
#define GREENPIN 11
#define BLUEPIN 9
#define delayTime 20 //za fading cas
unsigned long interval= 30000;
unsigned long previousMillis = 0;
const int ledPin = 12; // the pin that the LED is attached to
const int buttonPin1 = 2; //on off
bool vklop = false;
int bela = 10;
int barva;
int prejsnja_barva = 0;
int buttonPushCounter1 = 0; // counter for the number of button presses
int buttonState1 = 0; // current state of the button
int lastButtonState1 = 0; // previous state of the button
/////////////////////////////////////*SETUP*/////////////////////////////////////////
void setup()
{
pinMode(buttonPin1, INPUT);
pinMode(ledPin, OUTPUT);
Serial.begin(9600);
pinMode(3,INPUT); //because of interrupts PIN digital 3
digitalWrite(3,HIGH);
}
/////////////////////////////////////*LOOP*/////////////////////////////////////////
void loop()
{
unsigned long currentMillis = millis();
if ((currentMillis-previousMillis) > interval) //15s timer
{
previousMillis = currentMillis;
Serial.println("SLEEP!"); // kaj delaj po preteku 5s
delay(50);
sleepSetup(); //sleep mode
}
else
{
buttonState1 = digitalRead(buttonPin1);
/////////////////////////////////////ON/OFF/////////////////////////////////////////
/////////////////////////////////////ON/OFF/////////////////////////////////////////
if (buttonState1 != lastButtonState1) // compare the buttonState to its previous state
{
if (buttonState1 == HIGH) // if the state has changed, increment the counter
{
buttonPushCounter1++; // if the current state is HIGH then the button went from off to on:
Serial.println("on");
Serial.print("number of BUTTON1 pushes: ");
Serial.println(buttonPushCounter1);
digitalWrite(ledPin, HIGH);
if(buttonPushCounter1 % 2 == 0)
{
setColor(bela, bela, bela);
vklop = true;
barva = 13;
}
else
{
setColor(0, 0, 0);
vklop = false;
}
}
else // if the current state is LOW then the button went from on to off:
{
Serial.println("off");
digitalWrite(ledPin, LOW);
}
delay(50); // Delay a little bit to avoid bouncing
}
lastButtonState1 = buttonState1; // save the current state as the last state, for next time through the loop
}
}
/////////////////////////////////functions/////////////////////////////////////////////
/////////////////////////////////functions/////////////////////////////////////////////
/////////////////////////////////functions/////////////////////////////////////////////
void setColor(int red, int green, int blue)
{
analogWrite(REDPIN, red);
analogWrite(GREENPIN, green);
analogWrite(BLUEPIN, blue);
}
void sleepSetup(void)
{
sleep_enable(); // Set sleep enable (SE) bit:
attachInterrupt(1, pinInterrupt, LOW); // Set pin 2 as interrupt and attach handler:
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // define our preferred sleep mode:
digitalWrite(13,LOW);
sleep_cpu();
Serial.println("Just woke up!"); //OD TU SE NADALJUJE PO PRITISKU TIPKE
digitalWrite(13,HIGH);
}
void pinInterrupt() //ISR
{
sleep_disable();
detachInterrupt(0);
}
You're using AVR's Power Down sleep mode. In this mode all timers are turned off to save power.
No timers -> no PWM -> no analogue output -> no PWM driven LEDs
To keep the LED on use another sleep mode.
See
http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf for details.
But to be honest I am not quite sure if this makes any sense. If you're driving an LED through 3 outputs the power you can save by putting the MCU into sleep is maybe a few percent.
And as sleep stops the CPU and hence your program you won't be able to have the LEDs turn off after 30s.
Why not just wait 30s befor going to sleep? The alternative would be some external timing circuitry that would also consume power. So I guess having a few milliamps more for 30 seconds is still a better alternative.

Arduino Button with LED

I have put together an Arduino circuit that turns the led's off when the button is pressed. How do I code it so when I press it once it comes on and stays on and will only turn off once its pressed again? Any help would be appreciated
My Current code is:
int ledred = 12;
int ledgreen = 8;
int BUTTON = 4;
int speakerPin = 1;
void setup() {
// initialize the digital pin as an output.
Serial.begin(9600);
pinMode(ledgreen, OUTPUT);
pinMode(ledred, OUTPUT);
pinMode(BUTTON,INPUT);
}
void loop() {
if(digitalRead(BUTTON) == HIGH){
digitalWrite(ledred,HIGH);
digitalWrite(ledgreen,HIGH);
}else
{
digitalWrite(ledred,LOW);
digitalWrite(ledgreen,LOW);
}
}
If all you want is do this, you can use one of the interrupt pins and watch for the RISING (or FALLING) event.
Something similar to this example:
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING);
}
void loop() {
digitalWrite(ledPin, state);
}
void blink() {
state = !state;
}
Mind that you may still need some debouncing strategy.
Also, you don't need to use an interrupt for that, but then you'd need some edge-detection algorithm. These are quite well explained in the debouncing article above. I personally prefer these, since interrupt pins in the UNO board are precious enough not to be used with humble button pressings... :o)
/*
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:
- LED attached from pin 13 to ground
- pushbutton attached from pin 2 to +5V
- 10 kilohm resistor attached from pin 2 to ground
- Note: On most Arduino boards, there is already an LED on the board connected
to pin 13, so you don't need any extra components for this example.
created 21 Nov 2006
by David A. Mellis
modified 30 Aug 2011
by Limor Fried
modified 28 Dec 2012
by Mike Walters
modified 30 Aug 2016
by Arturo Guadalupi
This example code is in the public domain.
http://www.arduino.cc/en/Tutorial/Debounce
*/
// 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 unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime = 0; // the last time the output pin was toggled
unsigned long debounceDelay = 50; // the debounce time; increase if the output flickers
void setup() {
pinMode(buttonPin, INPUT);
pinMode(ledPin, OUTPUT);
// 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) {
buttonState = reading;
// only toggle the LED if the new button state is HIGH
if (buttonState == HIGH) {
ledState = !ledState;
}
}
}
// set the LED:
digitalWrite(ledPin, ledState);
// save the reading. Next time through the loop, it'll be the lastButtonState:
lastButtonState = reading;
}

continuous rotation servo (arduino) responding to button press

I am trying to make a continous rotation servo move clockwise if button on pin2 is pressed, and counterclockwise if button on pin3 is pressed. I want the servo to keep moving in the direction set according to the button until the button is released. This is the code I have so far (I am new to arduino):
#include <Servo.h>
Servo myservo; // create servo object to control a servo
// CONSTANTS
// PINS
const int crServo = 12; // sets pin 12 as servo
const int buttonPinCW = 2; // sets pin 2 as button; CW => clockwise => FOCUS FAR
const int buttonPinCC = 3; // sets pin 3 as button; CC => counterclockwise => FOCUS NEAR
const int ledPin = 10; // sets pin 10 as LED
// SERVO PROPERTIES
const int crSpeedDefault = 1500; // 1500 is the stay still position, motor should not turn
const int crSpeedCW = 1300; // 1300 turns the motor full speed clockwise
const int crSpeedCC = 1700; // 1700 turns the motor full speed counter-clockwise
const int crStepDefault = 2;
// SET BUTTON STATES
int buttonStateCW = 0; //sets button 1 as off
int buttonStateCC = 0; // sets button 2 as off
void setup()
{
myservo.attach(crServo); // attaches the servo on pin 12 to the servo object
pinMode (buttonPinCW, INPUT); // sets button as input
pinMode (buttonPinCC, INPUT); // sets button as input
pinMode (ledPin, OUTPUT); // sets led as output
myservo.write(crSpeedDefault); // default servo to crSpeedDefault
}
int slowFocusPull(int x){
int result;
result = abs(x - crSpeedDefault) / crStepDefault;
return result;
}
void loop()
{
buttonStateCW = digitalRead(buttonPinCW);
buttonStateCC = digitalRead(buttonPinCC);
// clockwise rotation
if (buttonStateCW == HIGH) {
digitalWrite(ledPin, HIGH);
myservo.write(slowFocusPull(crSpeedCW));
// counterclockwise rotation
} else if (buttonStateCC == HIGH) {
digitalWrite(ledPin, HIGH);
myservo.write(slowFocusPull(crSpeedCC));
} else {
digitalWrite(ledPin, LOW);
}
}
The issue lies in the function slowFocusPull. Basically I just want to be able to adjust the speed with just modifying the constant. Without this function everything works fine.
UPDATE: final loop for reference
void loop()
{
buttonStateCW = digitalRead(buttonPinCW);
buttonStateCC = digitalRead(buttonPinCC);
// clockwise rotation
if (buttonStateCW == HIGH) {
digitalWrite(ledPinR, HIGH);
float speed = crSpeedCW;
Serial.print("CLOCKWISE-ROTATION \n");
for (int i = 0; i < t * 5; i++) {
speed += ((float)crSpeedDefault - speed)/ 10;
Serial.print(speed);
Serial.print("\n");
myservo.write((int)speed);
delay(100);
}
myservo.write(crSpeedCW);
}
else if (buttonStateCC == HIGH) {
digitalWrite(ledPinG, HIGH);
float speed = crSpeedCC;
Serial.print("COUNTER-CLOCKWISE-ROTATION \n");
for (int i = 0; i < t * 5; i++) {
speed += ((float)crSpeedDefault - speed) / 10;
Serial.print(speed);
Serial.print("\n");
myservo.write((int)speed);
delay(100);
}
myservo.write(crSpeedCC);
}
else {
myservo.write(crSpeedDefault);
digitalWrite(ledPinR, LOW);
digitalWrite(ledPinG, LOW); // turn the LED off by making the voltage LOW
}
}
Looks like your project would benefit from using Hardware Interrupts, which asynchronously call functions when events (like button presses) occur (these are perfect for controllers, and remove the overhead of polling).
Try wiring up the two pins and wiring up the buttons to pins 2 and 3 as is shown in this diagram:
Hardware interrupts literally interrupt the code, the uno has two such pins: digital pin 2 and digital pin 3 (this is really useful for robotics, also the mega has 6 such pins!)
here's a skeleton for how your code might want to look
void setup() {
attachInterrupt(0, goClockwise, RISING); //the "0" places arduino uno's interrupt pin 2 (for uno r3)
attachInterrupt(1, goCounterClockwise, RISING); //the "1" places interrupt for arduino uno's pin 3
}
void loop() {
delay(1000); dummy delay, code is handled in interrupt functions
}
void goClockwise () {
//runs when pin 2's button is pressed
//code for making servo go clockwise
}
void goCounterClockwise () {
//code triggered when pin 3's button is pressed
//code for ccw goes here
}
If you have any questions on I'd be happy to work through them with you.
Here's a link to the Arduino ref page for hardware interrupts:
click here to learn more about arduino hardware interrupts

Arduino IR door

i want to make an IR sensor door with DFRobot IRsensor (switch) and Servo. the problem is in the if statement because the digitalread is always changing when there's nothing in front of the IR sensor which is the way it suppouse to be... so it rapidly closing and opening. but i want the door to be open when there's something in front of the sensor and then some delay, then its gonna close if there's something (new) in front of the door.
mycode:
#include <Servo.h>
Servo myservo;// create servo object to control a servo
// a maximum of eight servo objects can be created
int IRsensor =8;
int pos = 180; // variable to store the servo position
int d;
boolean kondisi;
void setup()
{
myservo.attach(9); // attaches the servo on pin 9 to the servo object
pinMode (IRsensor,INPUT);
Serial.begin (9600);
}
void loop()
{
d = digitalRead (IRsensor);
bukatutup (d);
delay (15);
}
void bukatutup(int IR)
{
Serial.println (IR);
if (IR == 0 and (kondisi == false))
{
pos = 0;
Serial.println ("terbuka");
myservo.write (pos);
kondisi == true;
delay(1000);
}
else if ( IR == 0 and (kondisi == true))
{
pos = 180;
Serial.println ("tertutup");
kondisi == false;
myservo.write (pos);
delay (1000);
}
}
Thx,

Resources