Controlling a Servo, a Stepper and an LED with a single switch

Hello Arduino experts,
I am trying to control a Stepper motor, 2 servo motors and LED's all with one button.
The objective is when the button is pushed pulsate the LEDs and turn the Servo motors until the servos reach a certain angle then start moving the stepper motor. if button is release return the Stepper to original position and then move the servos.

Here is a summary:

Button pushed:

  • pulsate LEDs
  • turn Servos to angle 0
  • once servos reach angle 0 turn stepper to position 100

Button released:

  • turn stepper to position 0
  • once stepper reaches 0 turn servos to angle 179

I put togther the following code and it works perfectly and as required, but I wanted how should I be powering the stepper motor from an external power source ?
How should I be connecting it ? what hardware to use and what would that change in the code ?

Here is the code and schematics:
NOTE: I am using wokwi simulator


#include <Servo.h>
#include <AccelStepper.h>

Servo myservo;  // create servo object to control a servo
#define servoPin1 3 //~
#define pushButtonPin 2

int led = 5;         // the PWM pin the LED is attached to
int brightness = 0;  // how bright the LED is
int fadeAmount = 5;  // how many points to fade the LED by

int angle = 179;    // initial angle  for servo (beteen 1 and 179)
int angleStep = 1;
const int minAngle = 0;
const int maxAngle = 180;
int pos = 0;
int stepperMotorPosition = 0;

bool raisePlatform = false; // declares a String named doorsOpen to check doors

const int numberOfPins = 4;  // change this to fit the number of steps per revolution
const int type = 2; //watch video for details. Link is at the top of this code (robojax)

// initialize the stepper library on pins 8 through 11:
//Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);
AccelStepper myStepper(numberOfPins, 8, 9, 10, 11);

void setup() {

  // set the speed at 60 rpm:
  //myStepper.setSpeed(60);
  myStepper.setMaxSpeed(30);       //set max speed the motor will turn (steps/second)
  myStepper.setAcceleration(10);  //set acceleration (steps/second^2)
  // initialize the serial port:

  // declare pin 5 to be an output:
  pinMode(led, OUTPUT);

  // Servo button demo by Robojax.com
  Serial.begin(9600);          //  setup serial
  myservo.attach(servoPin1);  // attaches the servo on pin 3 to the servo object
  pinMode(pushButtonPin, INPUT_PULLUP);
  //Serial.println("Robojax Servo Button ");
  //myservo.write(angle);//initial position

}

void loop() {

  if (digitalRead(pushButtonPin) == LOW) {

    //begin LED dimming code

    analogWrite(led, brightness);
    if (angle == 0) { //if door is fully open raise platform
      raisePlatform = true;
      myStepper.moveTo(100);
      myStepper.run();
      stepperMotorPosition = myStepper.currentPosition();
      //Serial.println(stepperMotorPosition);
    }

    // change the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // reverse the direction of the fading at the ends of the fade:
    if (brightness <= 0 || brightness >= 255) {
      fadeAmount = -fadeAmount;
    }
    // wait for 30 milliseconds to see the dimming effect
    delay(10);

    //end LED dimming


    if (angle > 0 && angle <= 180) {
      angle = angle - angleStep;
      if (angle < 0) {
        angle = 0;
      }

      else {
        myservo.write(angle); // move the servo to desired angle: open doors
        raisePlatform = false; //Do not raise platform until door is fully open
      }

    }

    delay(20); // waits for the servo to get there

  }


  if (digitalRead(pushButtonPin) == HIGH) {

    myStepper.moveTo(0);
    myStepper.run();
    stepperMotorPosition = myStepper.currentPosition();
    //Serial.println("Switch is OFF");
    //Serial.println(stepperMotorPosition);

    analogWrite(led, 0);

    // Servo button demo by Robojax.com

    if (stepperMotorPosition == 0) {
      if (angle >= 0 && angle <= 180) {
        angle = angle + angleStep;
        if (angle > 180) {
          angle = 179; //was set to 180 should be same as starting position
        }

        else {
          myservo.write(angle); // move the servo to desired angle
        }
      }
    }
    delay(20); // waits for the servo to get there
  }


}

We need links to their datasheets to provide useful and reliable replies.
Your Fritzing toy pictures looks like a nightmare. Drivers are needed for steppers.

The servos will need an external supply. An Arduino cannot, reliably, supply sufficient current for one servo, let alone two.

image

The stepper will need a driver and an external power supply. Like the servo the Arduino cannot supply enough current for a stepper motor. What is the part number of the stepper? Can you supply a data sheet?

Here are the components:

If you post a data sheet for the stepper we can help to recommend a proper driver. Please do not be tempted by the cheap L29x drivers. They are ancient technology DC motor drives and are not at all appropriate drivers for modern bipolar steppers. Those motors need current controlled drivers like the A4988 or DRV8825 (to name a couple) . Pololu has a good line of modern stepper drivers.

Hello groundFungus,
It's a NEMA 17 Stepper motor; here is the info about the Stepper I will be using :

I would use a DRV8825 stepper driver. The rated voltage of the stepper is not relevant.
The driver will control the current. You will need a power supply capable of providing 4A minimum at a mini.um of 8.5V. Higher voltage supply will yield more stepper speed and toque up to the maximum allowed by the driver.

It is imperative that the driver coil current be adjusted carefully before using the stepper. The Pololu page for the DRV8825 has instructions for setting the coil current. I would use a heat sink on the DRV8825 if the coil current is set to over 1.5A.

You do not have to set the coil current to the rated current. Set coil current to a lower value where the motor still performs reliably without missing steps. Setting the coil current to less than maximum will allow the stepper and driver to run cooler which will extend their lives.

But how do I connect and wire all of this ?
Sorry I am new to Arduino; I made all this on a simulator I still need to purchase the hardware. But need to know what to get.

I won’t need a lot of torque.

Can I use the A4988? And how do I do the wiring and the connections ? And do I need to change anything in the script ?

Yes, but for 1.7A you will need to use a heatsink and a fan for cooling the stepper driver. The A4988 is only good for 1A without heat sink and cooling. Also you must know the values of the shunt resistors (they are not the same, board to board) on the driver board to be able to set the coil current limit properly. So because the DRV8825 can handle more current without heat sink and active cooling and the current setting is a bit simpler I recommend the DRV8825.

The Pololu page for the DRV8825 (link already posted) or the A4988 show the wiring of those modules.

image

Yes, you will need to change the Accelstepper constructor to reflect that you are using an step/dir type of driver that uses only 2 pins. Other functions are the same (not motor type dependent).

AccelStepper stepper(AccelStepper::DRIVER, stepPin, dirPin);

Ok so the concern is the amount of amps. I found a stepper motor that uses less Amps only 0.7 A.
Would it make things simpler if I use this?
Which hardware should I use? And also I don’t see the connection to the Arduino in the pic above.

Not really. Still need a proper driver. Power supply needs to be around 2A.

The box labeled microcontroller.

image

@ waterslip Wouldn't it make it easier to split your code into functions and call each one as you need them.

For example void buttonOne() { while (pushButtonPin == 0){"Your other functions"}}?

I definitely prefer functions and code reusability, but I am not frequently calling these functions many times in the code. Feel free to make adjustments or propose enhancements.

@groundFungus ok now I understand what you mean. I managed to get it working with an A4988, there is no power supply in the pic because the simulator doesn't offer that component.
So here is the new diagram and code. I had the following questions :

  1. Since the change the stepper motor start position is now at -2 not 0, even if I try setting to setCurrentPosition to 0. Any reason why ?
  2. In your pic the logic power supply is powering both the Arduino and A4988 at 3-5.5 V, at the same time the A4988 is getting power from the motor power supply at 8-35V is this normal, getting 2 sources of power ?
  3. Shouldn't the Arduino be getting power of 7 - 12 Volt ? if I do change the logic power supply to 12 Volt would that effect the A4988 ? Thanks

#include <Servo.h>
#include <AccelStepper.h>

#define dirPin 12
#define stepPin 13
#define motorInterfaceType 1

Servo myservo;  // create servo object to control a servo
#define servoPin1 3 //~
#define pushButtonPin 2

int led = 5;         // the PWM pin the LED is attached to
int brightness = 0;  // how bright the LED is
int fadeAmount = 10;  // how many points to fade the LED by

int angle = 179;    // initial angle  for servo (beteen 1 and 179)
int angleStep = 1;
const int minAngle = 0;
const int maxAngle = 180;
int pos = 0;
int stepperMotorPosition = 0;

bool raisePlatform = false; // declares a String named doorsOpen to check doors

const int numberOfPins = 4;  // change this to fit the number of steps per revolution
const int type = 2; //watch video for details. Link is at the top of this code (robojax)

// initialize the stepper library on pins 8 through 11:
//Stepper myStepper(stepsPerRevolution, 8, 9, 10, 11);
//AccelStepper myStepper(numberOfPins, 8, 9, 10, 11);
AccelStepper myStepper = AccelStepper(motorInterfaceType, stepPin, dirPin);

void setup() {
//myStepper.setCurrentPosition(0);
  // set the speed at 60 rpm:
  //myStepper.setSpeed(60);
  myStepper.setMaxSpeed(30);       //set max speed the motor will turn (steps/second)
  myStepper.setAcceleration(10);  //set acceleration (steps/second^2)
  // initialize the serial port:

  // declare pin 5 to be an output:
  pinMode(led, OUTPUT);

  // Servo button demo by Robojax.com
  Serial.begin(9600);          //  setup serial
  myservo.attach(servoPin1);  // attaches the servo on pin 3 to the servo object
  pinMode(pushButtonPin, INPUT_PULLUP);
  //Serial.println("Robojax Servo Button ");
  //myservo.write(angle);//initial position

}

void loop() {

  if (digitalRead(pushButtonPin) == LOW) {

    //begin LED dimming code

    analogWrite(led, brightness);
    if (angle == 0) { //if door is fully open raise platform
      raisePlatform = true;
      myStepper.moveTo(100);
      myStepper.run();
      stepperMotorPosition = myStepper.currentPosition();
      //Serial.println(stepperMotorPosition);
    }

    // change the brightness for next time through the loop:
    brightness = brightness + fadeAmount;

    // reverse the direction of the fading at the ends of the fade:
    if (brightness <= 0 || brightness >= 255) {
      fadeAmount = -fadeAmount;
    }
    // wait for 30 milliseconds to see the dimming effect
    delay(10);

    //end LED dimming


    if (angle > 0 && angle <= 180) {
      angle = angle - angleStep;
      if (angle < 0) {
        angle = 0;
      }

      else {
        myservo.write(angle); // move the servo to desired angle: open doors
        raisePlatform = false; //Do not raise platform until door is fully open
      }

    }

    delay(20); // waits for the servo to get there

  }


  if (digitalRead(pushButtonPin) == HIGH) {

    myStepper.moveTo(0);
    myStepper.run();
    stepperMotorPosition = myStepper.currentPosition();
    //Serial.println("Switch is OFF");
    //Serial.println(stepperMotorPosition);

    analogWrite(led, 0);

    // Servo button demo by Robojax.com

    if (stepperMotorPosition == 0) {
      if (angle >= 0 && angle <= 180) {
        angle = angle + angleStep;
        if (angle > 180) {
          angle = 179; //was set to 180 should be same as starting position
        }

        else {
          myservo.write(angle); // move the servo to desired angle
        }
      }
    }
    delay(20); // waits for the servo to get there
  }


}

IN the following I am assuming that the Arduino is an Uno.

  1. The only place that you set the current position to 0 is commented out. A lot of your comments do not match the line of code that they go with. Bad comments are worse than no comments.
bool raisePlatform = false; // declares a String named doorsOpen
const int numberOfPins = 4;  // change this to fit the number of steps per revolution

  1. Yes, there must be 2 sources of power to the A4988. There is nothing on the A4988 board to drop the motor power to the voltage required by the logic so the logic power must come form off the A4988. Your schematic does not show the 5V logic power from the Arduino to the A4988. It is required for the A4988 to work.

  2. If you apply 12V to the logic power input of the A4988 you will destroy it.

The Pololu illustration is for a generalized microcontroller. For an Uno, specifically, I would say:
The Arduino needs 5V to work. That can come from the USB, from the on board 5V regulator that is fed from the power jack or Vin (7V-12V) or from an external well regulated 5V supply. USB can supply limited current. 500mA or so. If I need more 5V current or USB is not available I will use a well regulated external 5V power supply connected to the 5V pin. I do not use the onboard 5V regulator unless the current demands on the 5V supply is very low. Use a buck converter to 5V that is supplied by your stepper power supply.

The servos must not be powered by the Arduino on board 5V regulator. One servo may work as long as it is not loaded. No Arduino is a power supply. The Arduino cannot supply enough current for one servo, let alone two. Each small servo will need about 1A. For larger servos, consult their data sheets to see what the stall current is and make sure that the servo power supply can provide that current.

In the actual end use, how is the Uno itself powered? Will it be connected to USB?

Your wiring diagram is hard to follow. There are wires on top of wires and some that just get lost.

The commented part of the code for setting the stepper to 0 I commented it out after noticing that it didn’t work.

Yes it is an Arduino Uno which I will be powering from an external power source of 12 V (not USB). As shown in the pic
So if I understand correctly, the servos will get their own power source, the stepper powered from the A4988. I put this diagram to show how I will be supplying power.
So there will 3 power sources:

  • 5 Volt to power the servos
  • 12 Volt with a capacitor to the A4988 on the VMOT pin
  • 12 Volt to power the Arduino Uno (no USB)

Does this seem right ?

As long as you are only powering a couple of LEDs with the on board 5V, the way that you have it is fine. If you add anything to the Uno 5V, consider powering the Uno with the 5V from the servo supply. Connect the servo 5V to the Uno 5V pin.

The amount of current that the on board 5V regulator, if powered at 12V, can comfortably supply is less than 100mA before the regulator starts getting too hot and shutting down and resetting the Uno.

I never use the power jack or Vin.

Hi, @waterslip

It looks fine, just the two LEDS and some signal current should be fine with 12v power through the DC-Jack to supply those 5V loads.

As @groundFungus has suggested, using the 5V servo supplyand connect its +5v to the 5V pin on the UNO would be more efficient.

What sort of 5V supply are you thinking of using?
If you use a DC-DC converter, you can power all your project off the 12V supply.

Tom.. :smiley: :+1: :coffee: :australia:

I always thought that the 5V pin provides 5 volt output, it is not an input, can you provide some guidance ?
5V arduino

If you add anything to the Uno 5V, consider powering the Uno with the 5V from the servo supply.

By this do you mean just running a wire from the 5V power supply to the 5V pin on the Arduino Uno ?
And lastly if we are connecting the A4988 to 12 Volt on the VMOT pin, why are we connecting the VDD to 5 Volt; why 2 power sources ?

The 5V pin is the output of the onboard 5V regulator. The 5V pin them goes on to supply the Vcc and AVcc to the atmega328 chip, the USB to serial converter chip and etc. (consult the Uno schematic).

Yes. The will bypass the weak onboard regulator and provide more current.

Caution: do not power the Uno through the USB and the 5V pin at the same time. The 2 supplies can conflict and cause trouble.

Because the A4988 chip requires 2 different voltages. I can't really tell why, but that is the way that it is. As to the reason that the user must supply the logic power, my guess is that, in order to provide the logic voltage from the motor power supply would require a voltage regulator and the voltage regulator would have to be adjustable (3.3V or 5V). That would add considerable complexity and expense to the driver module.