
Controlling a Stepper Motor with a Remote Control and Arduino
|
|
Time to read min
|
|
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.
For this example, I used:
an Arduino Nano,
JST connectors for the stepper motor,
and a custom printed printed circuit board that I soldered female and male header pins to.
I used a free PCB layout tool and had these printed.
This board simply connects the Arduino Nano to two sets of motor drivers, stepper motors, RC receiver channels, and a power source.
I used this to clean up the wiring, but a breadboard and jumper wires will also work for this demonstration.
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.
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.
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