Arduino: Why doesn't my stepper move in reverse direction? - arduino

I have verified that its not a wiring problem by using some non library example code, so it seems the problem is not with the circuit.
I'm expecting the following code to run the motor in one direction 200 steps then run 200 steps in the opposite direction. It seems to run the initial 200 steps but then stops, why?
In the setup function:
stepper.setCurrentPosition(0);
// Set the maximum speed in steps per second:
stepper.setMaxSpeed(1000);
In the loop function:
while(stepper.currentPosition() < 300){
stepper.moveTo(200);
stepper.setSpeed(200);
stepper.run();
if (stepper.distanceToGo() == 0) {
stepper.moveTo(-stepper.currentPosition());
stepper.setSpeed(200);
stepper.run();
}
}
Here's my entire code. The if/else at the bottom is where I want to run the motor. I've put in some non working example code in this block as an example:
#include <deprecated.h>
#include <MFRC522.h>
#include <MFRC522Extended.h>
#include <require_cpp11.h>
// Include the AccelStepper library:
#include <AccelStepper.h>
// constants won't change. They're used here to set pin numbers:
const int BUTTON_PIN = 2; // the number of the pushbutton pin
#define BLUE 7
#define GREEN 6
#define RED 3
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 53 // Configurable, see typical pin layout above
#define dirPin 10
#define stepPin 11
#define motorInterfaceType 1
// Variables will change:
String authKeyFob = "123456789";
String card_ID="";
int ledState = 0; // remember current led state
int buttonState = 0;
int oldButtonState = 0;
bool toggle = false;
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
AccelStepper stepper = AccelStepper(motorInterfaceType, stepPin, dirPin);
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
// initialize the pushbutton pin as an pull-up input
// the pull-up input pin will be HIGH when the switch is open and LOW when the switch is closed.
pinMode(BUTTON_PIN, INPUT);
pinMode(GREEN, OUTPUT);
pinMode(RED, OUTPUT);
pinMode(BLUE, OUTPUT);
stepper.setCurrentPosition(0);
stepper.setMaxSpeed(1000);
stepper.setAcceleration(50);
// stepper.setSpeed(200);
// stepper.moveTo(200);
}
void loop() {
/*
// Change direction once the motor reaches target position
if (stepper.distanceToGo() == 0) {
stepper.moveTo(-stepper.currentPosition());
}
// Move the motor one step
stepper.run();
*/
buttonState = digitalRead(BUTTON_PIN);
// read the state of the switch/button:
oldButtonState = LOW; // NEED TO ADD A DECLARATION FOR THIS BEFORE SETUP
buttonState = digitalRead(BUTTON_PIN);
// Look for new cards, and select one if present
if (!mfrc522.PICC_IsNewCardPresent() ) {
}
if(mfrc522.PICC_ReadCardSerial() ){
card_ID="";
for (byte i = 0; i < mfrc522.uid.size; i++) {
card_ID += mfrc522.uid.uidByte[i];
}
if(card_ID == authKeyFob){
toggle = !toggle;
delay(200);
}
}
// if the button just became pressed...
if(buttonState == HIGH && oldButtonState==LOW){
toggle = !toggle; // same thing, toggle our variable.
delay(200);
}
if (toggle) {
digitalWrite(GREEN, HIGH);
digitalWrite(RED, LOW);
stepper.moveTo(200);
stepper.setSpeed(200);
stepper.run();
} else {
digitalWrite(GREEN, LOW);
digitalWrite(RED, HIGH);
stepper.moveTo(200);
stepper.setSpeed(200);
stepper.run();
}
oldButtonState = buttonState; // save the button state for next time
}

The run method doesn't block. It just takes one step if it is time. So let's step through your code. First we enter the while loop and tell it to step to 200 and set the speed and call run. We keep repeating that over and over. If we get to a point where we have 0 to go then you say moveTo the negative position, set the speed, call run once and then the while loop exits and repeats. On that repeat we say move to 200 and start calling run on that. So you're only calling run once with the moveTo set to the negative number.
You need to rethink the logic on this. I don't know what else is in your loop, so it's hard to say what exactly you want. If you really insist on it being blocking in the while loop then:
stepper.moveTo(200);
stepper.setSpeed(200);
while(stepper.distanceToGo() != 0){
stepper.run();
}
stepper.moveTo(-200);
while(stepper.distanceToGo != 0){
stepper.run();
}

This code moves the stepper in each direction.
if (toggle) {
digitalWrite(GREEN, HIGH);
digitalWrite(RED, LOW);
while(stepper.currentPosition() <= 200){
stepper.moveTo(200);
stepper.setSpeed(200);
stepper.runSpeedToPosition();
if(stepper.currentPosition()==200){
break;
}
}
} else {
digitalWrite(GREEN, LOW);
digitalWrite(RED, HIGH);
while(stepper.currentPosition() >= -200){
stepper.moveTo(-200);
stepper.setSpeed(200);
stepper.runSpeedToPosition();
if(stepper.currentPosition()==-200){
break;
}
}
}

Related

Problem with blinking a led with bluetooth in arduino

i am trying to make a program that turns on ,off and blinks an led with the help from bluetooth
On and of were pretty easy to replicate,but i can't make the blink to work.There are to options either blinks once,either if i ad a while it never stops from looping.i tried with both if and case.Can somebody help me.I am using an esp32.
The code with if:
#include "BluetoothSerial.h"
#include <Arduino.h>
#include <analogWrite.h>
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
int received;// received value will be stored in this variable
char receivedChar;// received value will be stored as CHAR in this variable
const char turnON ='a';
const char turnOFF ='b';
const char turnBLINK= 'c';
//const char turnFADE='d';
const int LEDpin = 12;
//int brightStep = 1;
//int brightness = 0;
void setup() {
Serial.begin(115200);
SerialBT.begin("Mono"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
Serial.println("To turn ON send: a");//print on serial monitor
Serial.println("To turn OFF send: b"); //print on serial monitor
pinMode(LEDpin, OUTPUT);
// analogWriteResolution(LEDpin, 12);
}
void loop() {
receivedChar =(char)SerialBT.read();
if (Serial.available()) {
SerialBT.write(Serial.read());
}
if (SerialBT.available()) {
// while(SerialBT.available()){
// receivedChar =(char)SerialBT.read();
// }
SerialBT.print("Received:");// write on BT app
SerialBT.println(receivedChar);// write on BT app
Serial.print ("Received:");//print on serial monitor
Serial.println(receivedChar);//print on serial monitor
//SerialBT.println(receivedChar);//print on the app
//SerialBT.write(receivedChar); //print on serial monitor
if(receivedChar == turnON)
{
SerialBT.println("LED ON:");// write on BT app
Serial.println("LED ON:");//write on serial monitor
digitalWrite(LEDpin, HIGH);// turn the LED ON
}
if(receivedChar == turnOFF)
{
SerialBT.println("LED OFF:");// write on BT app
Serial.println("LED OFF:");//write on serial monitor
digitalWrite(LEDpin, LOW);// turn the LED off
}
if(receivedChar == turnBLINK)
{
SerialBT.println("LED blink:");// write on BT app
Serial.println("LED blink:");//write on serial monitor
while (receivedChar == turnBLINK){
//receivedChar =(char)SerialBT.read();
//if(receivedChar != turnBLINK){
// break;
// } else {
digitalWrite(LEDpin, HIGH);// turn the LED off
delay(1000);
digitalWrite(LEDpin,LOW);
delay(1000);
if(receivedChar != turnBLINK){
break; }
}
}
}
delay(20);
}
and with case:
#include "BluetoothSerial.h"
#include <Arduino.h>
#include <analogWrite.h>
#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif
BluetoothSerial SerialBT;
int received;// received value will be stored in this variable
char receivedChar;// received value will be stored as CHAR in this variable
char data;
int option;
int blink=0;
const int LEDpin = 12;
void setup() {
Serial.begin(115200);
SerialBT.begin("Mono"); //Bluetooth device name
Serial.println("The device started, now you can pair it with bluetooth!");
Serial.println("To turn ON send: 1");//print on serial monitor
Serial.println("To turn OFF send: 0"); //print on serial monitor
pinMode(12, OUTPUT);
}
void loop(){
receivedChar =(char)SerialBT.read();
// if (Serial.available()) {
// SerialBT.write(Serial.read());
// }
if (SerialBT.available()) {
// while(SerialBT.available()){
// receivedChar =(char)SerialBT.read();
// }
SerialBT.print("Received:");// write on BT app
SerialBT.println(receivedChar);// write on BT app
Serial.print ("Received:");//print on serial monitor
Serial.println(receivedChar);//print on serial monitor
//SerialBT.println(receivedChar);//print on the app
//SerialBT.write(receivedChar); //print on serial monitor
data=receivedChar;
if(data == '0')
{
option = 0;
blink=0;
}else if(data == '1')
{
option = 1;
blink=0;
}else if(data == '2')
{
option = 2;
blink=1;
}
switch (option)
{
case 0: // LED OFF
digitalWrite(LEDpin, LOW);
break;
case 1: //LED ON
digitalWrite(LEDpin, HIGH);
break;
case 2:
while(blink=1){// LED BLINK
digitalWrite(LEDpin , HIGH);
delay(200);
digitalWrite(LEDpin, LOW);
delay(200);
}
break;
}
}
}
First of all, you should clean your code to a minimum reproducible example. Remove all unnecessary comments and pieces of code that do not represent the main problem you are facing.
After a quick skim over your code, I immediately noticed this:
while(blink=1){// LED BLINK
digitalWrite(LEDpin , HIGH);
delay(200);
digitalWrite(LEDpin, LOW);
delay(200);
}
where it should be while(blink==1){ } --> very common mistake. This should be a comparison, NOT an assignment.
Now, you mention that it never stops running. Even after correcting the error I just pointed at, what part inside of your while loop breaks the logic of blink from being equal to 1? Otherwise, the while-loop will never stop
Finally, do not read the serial data inside the main loop(). Use SerialEvent, rather.
Again, it is quite tricky to follow the flow of your code. I suggest you divide your code into functions in order to make it more readable.

Arduino Mega: How do I switch an LED's colour using the same authenticated RFID tag and using a button too?

I'm having some issues getting my code to do what I want on my Arduino Mega. What I'm aiming to do is to have the same RFID tag change an LED colour from red to green and when presented again from green to red. I also want to do this with a button. This is for a door lock so that the door can been locked and unlocked from both sides of the door.
The code below will allow an RFID tag to change the colour from red to green and vice versa but as soon as I try to test for an authenticated card it fails miserably. Also when I try to add the button to it my code ends up getting very messy and unusable. I've tried various things but I think my major problem is because the code sites inside the loop function. I've tried while(1) when trying to set the LED to a particular colour but it just doesn't work properly.
This I thought would be fairly trivial to do, maybe it is, I'm just not familiar enough with this.
Can anyone help point me in the right direction which will help me move further forward with this?
#include <SPI.h>
#include <MFRC522.h>
// constants won't change. They're used here to set pin numbers:
const int BUTTON_PIN = 2; // the number of the pushbutton pin
#define BLUE 7
#define GREEN 6
#define RED 3
#define RST_PIN 9 // Configurable, see typical pin layout above
#define SS_PIN 53 // Configurable, see typical pin layout above
// Variables will change:
String authKeyFob = "54321098765";
String card_ID="";
//int lastState = HIGH; // the previous state from the input pin
//int currentState = LOW; // the current reading from the input pin
int buttonState = 0; // current state of the button
int lastButtonState = 0; // previous state of the button
int ledState = 0; // remember current led state
int rfidState = 0;
int lastRfidState = 0;
bool toggle = false;
bool cardValid = false;
MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance
void setup() {
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
while (!Serial); // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
SPI.begin(); // Init SPI bus
mfrc522.PCD_Init(); // Init MFRC522 card
// initialize the pushbutton pin as an pull-up input
// the pull-up input pin will be HIGH when the switch is open and LOW when the switch is closed.
pinMode(BUTTON_PIN, INPUT);
pinMode(GREEN, OUTPUT);
pinMode(RED, OUTPUT);
pinMode(BLUE, OUTPUT);
}
void loop() {
// read the state of the switch/button:
buttonState = digitalRead(BUTTON_PIN);
// Look for new cards, and select one if present
if (mfrc522.PICC_IsNewCardPresent() || mfrc522.PICC_ReadCardSerial() ) {
if(toggle == false){
toggle = true;
} else {
toggle = false;
}
delay(200);
}
if(toggle == 1){
digitalWrite(GREEN, HIGH);
digitalWrite(RED, LOW);
} else if (toggle == 0) {
digitalWrite(GREEN, LOW);
digitalWrite(RED, HIGH);
}
}
All you need to do is to have another if statement that reads your button and toggles your toggle variable just like you do for the card. See if you understand what's going on here:
void loop() {
// read the state of the switch/button:
oldButtonState = LOW; // NEED TO ADD A DECLARATION FOR THIS BEFORE SETUP
buttonState = digitalRead(BUTTON_PIN);
// Look for new cards, and select one if present
if (mfrc522.PICC_IsNewCardPresent() || mfrc522.PICC_ReadCardSerial() ) {
toggle = !toggle; // A way easier way to write the if statements you had.
}
// if the button just became pressed...
if(buttonState == HIGH && oldButtonState==LOW){
toggle = !toggle; // same thing, toggle our variable.
}
oldButtonState = buttonState; // save the button state for next time
if (toggle) {
digitalWrite(GREEN, HIGH);
digitalWrite(RED, LOW);
} else {
digitalWrite(GREEN, LOW);
digitalWrite(RED, HIGH);
}
}
See the State Change Example to see why I store the old state of the button. I also changed that set of if statements to just set toggle to not toggle, that's an easier way to reverse a boolean value. I also made that last else if just an else since a boolean can only have two values. If it isn't true then it must be false.
This is my updated version with the RFID tag working consistently with the button and LED.
void loop() {
// read the state of the switch/button:
oldButtonState = LOW; // NEED TO ADD A DECLARATION FOR THIS BEFORE SETUP
buttonState = digitalRead(BUTTON_PIN);
// Look for new cards, and select one if present
if (!mfrc522.PICC_IsNewCardPresent() ) {
}
if(mfrc522.PICC_ReadCardSerial() ){
toggle = !toggle;
delay(200);
}
// if the button just became pressed...
if(buttonState == HIGH && oldButtonState==LOW){
toggle = !toggle; // same thing, toggle our variable.
delay(200);
}
oldButtonState = buttonState; // save the button state for next time
if (toggle) {
digitalWrite(GREEN, HIGH);
digitalWrite(RED, LOW);
} else {
digitalWrite(GREEN, LOW);
digitalWrite(RED, HIGH);
}
}

I am not able to rerun the loop

I am using HC-05 with arduino and controlling a motor.
I want a motor to run till a specific value (k) every time I send a character (Eg. 'R') from my app to Bluetooth. I am able to it once, but when I send 'R' again, It doesnot work.
I want that the motor should run whenever I send the character 'R'.
Arduino code
#define stpwm 13
#define stdir 12
int j=0;
int k=20;
char inChar;
void setup() {
Serial.begin(9600);
pinMode(stpwm, OUTPUT);
pinMode(stdir, OUTPUT);
}
void loop() {
if (Serial.available() > 0 ) { // Checks whether data is comming from the serial port
inChar = (Serial.read()); // Reads the data from the serial port
}
if (inChar == 'R')
{
if (j<=k)
{
analogWrite(AN2, 100);
analogWrite(AN1, 50);
analogWrite(stpwm, 50);
digitalWrite(stdir, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(100);
Serial.println(j);
j++;
}
analogWrite(stpwm,0);
}
Try
if (inChar == 'R')
{
while (j<=k)
{
analogWrite(AN2, 100);
analogWrite(AN1, 50);
analogWrite(stpwm, 50);
digitalWrite(stdir, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(100);
Serial.println(j);
j++;
}
j=0;
analogWrite(stpwm,0);
}
There is one main issue with your code:
the variable you use to control the if statement never resets, so it comes a time (when j >= k) that it can never be true unless you restart the system;
Although Pradeep's answer has potential to work, it would lock your system in a loop, while j is less then k.
Therefore, if you want to implement future control code in your system, this could become an issue. For instance, if you need to have an emergency stop set as another letter, this would only be read if you're not stuck within the while loop.
I'd recommend making use of a very simple structure: else; as per below:
#define stpwm 13
#define stdir 12
#define k 20
uint8_t j=0;
char inChar[1];
void setup() {
Serial.begin(9600);
pinMode(stpwm, OUTPUT);
pinMode(stdir, OUTPUT);
}
void loop() {
if (Serial.available() > 0 ) { // Checks whether data is comming from the serial port
inChar = (Serial.read()); // Reads the data from the serial port
}
if (inChar == 'R')
{
if (j<=k)
{
analogWrite(AN2, 100);
analogWrite(AN1, 50);
analogWrite(stpwm, 50);
digitalWrite(stdir, HIGH);
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(100);
Serial.println(j);
j++;
}
}
else{
// resets both j and inChar, so that the iteration does not restart
j = 0;
inChar = "";
// turn off signal only when this criteria is met: j > k
analogWrite(stpwm, 0);
}
}
I also made some minor changes to your code:
Defined k as a constant, as you won't be changing it on your program
declared j as an 8-bit integer, which holds values that range from 0 to 255; this saves memory
modified the position where you were turning off stpwm. The way it was set, your signal always turned off at the end of each iteration, which could damage your motor (you were, in a way implementing another pulse modulation)
Hope this helps.

arduino interrupts with servo motor

currently am working on project to open a door with access code using arduino UNO and a servo motor. Normal operation requires entering access code using keypad which is working fine. Another option requires pressing a button that causes an interrupt to rotate the servo motor. My problem is my interrupt only works once and never works again. Plus how do i put the for-loop to rotate the servo motor inside the interrupt function with a delay. I know that is not possible but am calling another function that has the delayMicroseconds but all this is not working. Below is my implementation please help
#include <Keypad.h>
#include <LiquidCrystal.h>
#include <Servo.h>
Servo servo;
const int openButtonPin = 2;
void setup() {
// put your setup code here, to run once:
servo.attach(5);
pinMode(openButtonPin, INPUT); //Pin 2 is input
attachInterrupt(0, enforceOpenAccess, HIGH); // PIN 2
}
void(* resetFunc)(void) = 0;
void loop()
{
//My other keypad implementations go here
}
void myDelay(int x) // function to cause delay in the interrupt
{
for(int i = 0; i<x; i++)
{
delayMicroseconds(1000);
}
}
void enforceOpenAccess() // ISR
{
for(int k =0; k<=180; k+=2)
{
servo.write(k); //rotate the servo
myDelay(30); //delay the rotation of the servo
}
}
The code above is run on arduino UNO being simulated in proteus and the interrupt button is a push button. Please if there is other ways of implementing that but with the same behaviour as I have described above help out. Thanks a lot
There are a couple of problems in the slice of code you posted. Just for completeness, you should post the loop function, since we can't guess what you wrote inside.
Just one comment: did you put a pullup? Otherwise use INPUT_PULLUP instead of INPUT for the button pinmode.
The main one is that you attached the interrupt for the HIGH mode, which will trigger the interrupt any time the pin is up, not on the rising edge. And please use the macro digitalPinToInterrupt to map to the correct pin:
attachInterrupt(digitalPinToInterrupt(openButtonPin), enforceOpenAccess, RISING);
Then.. Let's improve the code. You really should use the interrupts only when strictly necessary when you have to respond IMMEDIATELY (= less than a couple of milliseconds) to an input. Here you don't have to, so it's MUCH better to check for the button in the loop (more on turning the motor following)
uint8_t lastState;
void setup()
{
...
lastState = LOW;
}
void loop()
{
uint8_t currentState = digitalRead(openButtonPin);
if ((currentState != lastState) && (currentState == HIGH))
{
// Start turning the motor
}
lastState = currentState;
...
}
This will enable you to properly debounce the button too:
#include <Bounce2.h>
Bounce debouncer = Bounce();
void setup()
{
...
pinMode(openButtonPin, INPUT); //Pin 2 is input
debouncer.attach(openButtonPin);
debouncer.interval(5); // interval in ms
}
void loop()
{
debouncer.update();
if (debouncer.rose())
{
// Start turning the motor
}
...
}
If, on the other way, you REALLY want to use the interrupts (because waiting for a couple of milliseconds is too much for you), you should do something like this:
#include <Bounce2.h>
Bounce debouncer = Bounce();
void setup()
{
...
pinMode(openButtonPin, INPUT);
attachInterrupt(digitalPinToInterrupt(openButtonPin), enforceOpenAccess, RISING);
}
void loop()
{
...
}
void enforceOpenAccess() // ISR
{
// Start turning the motor
}
It looks like your code? No, because now we'll speak about turning the motor
You should NOT use delays to make steps, because otherwise you will wait for 30ms * 180 steps = 5.4s before being able to do anything else.
You can, however, make a sort of reduced state machine. You want your servo to move from 0 to 180 in steps of 1. So let's code the "don't move" state with any value greater than 180, and consequently we can do something like this in the loop:
unsigned long lastServoTime;
uint8_t servoPosition = 255;
const int timeBetweenSteps_in_ms = 30;
void loop()
{
...
if (servoPosition <= 180)
{ // servo should move
if ((millis() - lastServoTime) >= timeBetweenSteps_in_ms)
{
lastServoTime += timeBetweenSteps_in_ms;
servoPosition++;
if (servoPosition <= 180)
servo.write(servoPosition);
}
}
}
Then, using any of the previous examples, instead of // Start turning the motor write
lastServoTime = millis();
servoPosition = 0;
servo.write(servoPosition);
This way you won't block the main loop even when the button is pressed
This is what is in my loop()
char key = keypad.getKey();
if(key)
{
if(j < 10)
{
studentNumber[j] = key;
//holdMaskedNumber[j] = '*';
lcd.setCursor(0,2);
lcd.print(String(studentNumber));
if(j == 9)
{
studentNumber[9] = '\0';
//holdMaskedNumber[9] = 0;
lcd.clear();
//String number = String(studentNumber);
//lcd.print(number);
//delay(1000);
//lcd.clear();
lcd.print("Access Code");
}
j++;
}
else
{
if(i < 5)
{
accessCode[i] = key;
holdMaskedCode[i] = '*';
lcd.setCursor(1,2);
lcd.print(String(holdMaskedCode));
if(i == 4)
{
holdMaskedCode[5] = '\0';
accessCode[5] = '\0';
//lcd.clear();
//lcd.setCursor(0,0);
//accessCodeString = String(accessCode);
//lcd.print(accessCodeString);
//delay(1000);
lcd.clear();
for(int i =0; i<6; i++)
{
lcd.print("Please wait.");
delay(500);
lcd.clear();
lcd.print("Please wait..");
delay(500);
lcd.clear();
lcd.print("Please wait...");
delay(500);
lcd.clear();
}
digitalWrite(4, HIGH);
lcd.print("Access Granted");
for(int k =0; k<=180; k+=2)
{
servo.write(k);
delay(30);
}
resetFunc();
}
i++;
}
}
}

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

Resources