Controlling a Stepper Motor with a Remote Control and Arduino

Written by: Brandon Tsuge

|

|

Time to read min

In previous posts, I demonstrated how use an Arduino to read RC signals and how to move a stepper motor without using delay functions. In this post, I combine these two concepts and use an Arduino and remote control to control the speed and direction of a stepper motor.

Parts Used

For this example, I used:

I used a free PCB layout tool and had these printed.

PCB Layout Screen

This board simply connects the Arduino Nano to two sets of motor drivers, stepper motors, RC receiver channels, and a power source.

PCB Layout with Mounted Components

I used this to clean up the wiring, but a breadboard and jumper wires will also work for this demonstration.

Wiring

To wire this circuit:

  • connect the DIR pin on the A4988 motor driver to pin 4 on the Arduino.

  • Connect the STEP pin to pin 5.

  • Connect the SLEEP and RST pins to each other on the motor driver.

  • MS1 through MS3 will be connected to pins 6-8.

  • VDD and GND are connected to 5V and GND on the Arduino.

  • The four wires of the stepper motor connect to 1A, 1B, 2A, and 2B on the driver. (This is where I used the JST connectors)

  • VMotor and GND are connected to the positive and negative of the battery,

  • and a capacitor should be wired in parallel with this source.

  • The RC receiver should also receive 5V and GND from the Arduino,

  • and the signal is connected to pin on the Arduino.

Wiring Diagram

Arduino Code

A link to the full Arduino sketch can be found here. In the initialization section of the sketch, the variables and interrupt function is set up:

  • Start by defining the pins for RCPin, DIR, STEP, and the 3 MS pins.

  • Then create an unsigned long variable previousMotorTime and set it equal to the millis() function.

  • Create a long variable MotorInterval and volatile long variable StartTime and CurrentTime, which will both be initialized to 0. (These are variables related to the stepper motor movement).

  • Then create a volatile long variable called Pulses and set it to 0.

  • Create an integer PulseWidth and also set it to 0. (These are the two variables used to read the RC Signal).

//Define Pins
#define RCPin 2
#define DIR 4
#define STEP 5
#define MS3 6
#define MS2 7
#define MS1 8

//Set up time variables for Stepper motor
unsigned long previousMotorTime = millis();
long MotorInterval;
volatile long StartTime = 0;
volatile long CurrentTime = 0;

//Set up time variables for RC Read
volatile long Pulses = 0;
int PulseWidth = 0;

In the setup:

  • Set the baud rate to 9600.

  • Set the pin mode for the RCPin to INPUT_PULLUP.

  • Create an interrupt using attachInterrupt(digitalPinToInterrupt). Do this for RCPin and have it call a function called PulserTimer. (This will create an interrupted, every time a CHANGE is detected.

  • Next set pins 4-8 to OUTPUT.

  • Set all MS pins to LOW to enable full step mode.

void setup() {
  Serial.begin(9600);

  //RC Read Setup
  pinMode(RCPin, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(RCPin), PulseTimer, CHANGE); 

  // Set pins 4-8 to Outputs
  for (int i = 4; i <= 8; i++){
    pinMode(i, OUTPUT);
  }

  //Set MS1 to full step mode
  digitalWrite(MS1, LOW);
  digitalWrite(MS2, LOW);
  digitalWrite(MS3, LOW);
}

At the bottom of the sketch, set up the PulseTimer function that is called by the interrupt:

  • Start by setting CurrentTime to micros().

  • Create a condition that tests if CurrentTime is greater that StartTime.

  • If this condition is true, set the Pulse variable as the difference of the two time variables,

  • then set the StartTime variable equal to the CurrentTime variable.

//Function to measure the length of the pulses from the remote control
void PulseTimer(){
  CurrentTime = micros();
  if (CurrentTime > StartTime){
    Pulses = CurrentTime - StartTime;
    StartTime = CurrentTime;
  }

Finally, set up the code in the loop to bring it all together:

  • Start by setting the STEP variable to LOW using digitalWrite().

  • If the Pulses variable is less than 2000, then the PulseWidth variable will be set to Pulses.

  • Next, use a set of conditions to set the MotorInterval variable, which will ultimately determine the motor speed.

  • If PulseWidth is between 1400 and 1600, the stick is near the center, and I don't want the motor to move at this point. For this case, I will write the STEP variable to LOW so that the motor will not move.

  • If PulseWidth is less than 1400, I set DIR to LOW and map the PulseWidth variable from 1000 - 1400 to 1 - 25.

  • If this variable is greater than 1600, I set DIR to HIGH to move the motor in the other direction. The PulseWidth variable will also be mapped from 1600 - 1984 to 25 - 1.

  • For these two mapping functions, 1 represents a time between pulses of 1ms and 25 represents 25ms between pulses.

  • Lastly to move the motor, check if currentMotorTime - previousMotorTime > MotorInverval and write the STEP pin to HIGH.

  • Then set previousMotorTime to currentMotorTime.

void loop() {
  digitalWrite(STEP, LOW);

  //Only save HIGH pulse lengths
  if (Pulses < 2000){
    PulseWidth = Pulses;
  }

  //Stepper motor speed, bigger MotorInterval is a slower speed.
  if (PulseWidth >= 1400 && PulseWidth <= 1600){
    digitalWrite(STEP, LOW); //Motor doesn't move if the joystick is near the midpoint
  }
  else if (PulseWidth < 1400){
    digitalWrite(DIR, LOW);
    //map the RC signal to the motor speed in reverse when the joystick is pulled down
    MotorInterval = map(PulseWidth, 1000, 1400, 1, 25); 
  }
  else if (PulseWidth > 1600){
    digitalWrite(DIR, HIGH);
   //map the RC signal to the motor speed when the joystick is pushed forward.
    MotorInterval = map(PulseWidth, 1600, 1984, 25, 1); 
  }
  
  //check if the MotorInterval time has elapsed and step the motor.
  unsigned long currentMotorTime = millis(); 
  if (currentMotorTime - previousMotorTime > MotorInterval){
    digitalWrite(STEP, HIGH);
    previousMotorTime = currentMotorTime;
  }  
}

After uploading the code, the stepper motor should respond to the joystick movement on the remote control.

Stepper Motor Movement with Remote Control

The Bored Robot LLC is a participant in the Amazon Services LLC Associates Program, an affiliate advertising program designed to provide a means for sites to earn advertising fees by advertising and linking to Amazon.com