Lab 5: Motors

For our final lab in Object, we focused on using different types of motors, including servo motors, DC motors, and stepper motors.

Part 1: Servo Motor Control

First, we built a simple circuit using a servo motor. Servo motors are geared motors, which gives them high levels of torque but pretty low speed (compared to motors like DC motors). There are two main kinds of servos, and we implemented both during this part of the lab. The first kind can rotate up to 180 degrees, and can be programmed to specific angles and precise positions. In contrast, the second kind, a continuous servo, can spin all the way around, but the user can’t program it to go to a certain position, which means it isn’t very precise. Instead of writing a certain angle to turn to, you can control the speed and direction of a continuous servo.

To control the servo motors, we built a simple circuit with an analog sensor  (potentiometer) attached. A schematic and photo of the circuits can be seen below. One benefit of this setup was that we didn’t have to change anything about the circuit when we transitioned from the 180 degree servo to the continuous servo; we could just disconnect the 180 motor and replace it with the continuous one.

lab5-01
Schematic with a variable resistor (we used a potentiometer, so our setup didn’t require the pull-down fixed resistor) and the servo motor attached to an Arduino
IMG_4049
A photo of our simple circuit; the continuous servo is attached here

Once we had the circuit built, we had to write some basic Arduino code to actually control the servos. Essentially, you include the built-in servo library, create an instance of your servo object and attach it to a pin (I called my servo “mike”), then read from the analog sensor and remap the values to 0-180 so that you can write these values as an angle to the servo.


#include <Servo.h>
//make instance of servo object
Servo mike;
void setup() {
// put your setup code here, to run once:
//attach servo motor
//works with any digital pin
mike.attach(9);
}
void loop() {
int sensor = analogRead(A0);
//servo.Write() takes values between 0-180
int angle = map(sensor, 0, 1023, 0, 180);
// put your main code here, to run repeatedly:
mike.write(angle);
//to fix jitter, add a delay to write to servo less frequently
//delay(20);
//millis() counts milliseconds since program started
if(millis()%20<2)
{
//functionally the same as delay(20) but doesn't delay the rest of your code
mike.write(angle); //takes value between 0-180
}
}

view raw

servo.ino

hosted with ❤ by GitHub

Here’s a video of the 180 degree servo motor. As you can see, it turns with the potentiometer, because for 180 degree servos you are just writing specific angles for it to turn to. You have a lot of control over the position of the servo.

For attaching the continuous motor, we didn’t have to change up the main part of the circuit or the code, because you still write values of 0-180 to a continuous servo motor. However, instead of the value representing a specific angle to turn to, the value represents the speed and direction of the motor. 0 is full speed in one direction, 90 is stopped, and 180 is full speed in the other direction. Check it out in the below video:

Part 2: DC Motor Control

Next, we turned to DC motors. A DC motor’s strength is that it is often cheap, easy to work with, and can turn very quickly in either direction. However, it is not precise (similar to a continuous servo motor), and in order to be able to switch the direction of the motor without physically unhooking and switching its ground and power wires, you have to hook up a component called an H-bridge. The H-bridge is a motor driver and integrated circuit that can switch the polarity of the motor (which wire is receiving power and ground), allowing the user to switch the direction of the motor using code alone.

Hooking up the H-bridge was a little confusing at first, but we used a very helpful schematic that clearly laid out all of the required connections.

lab5-02
Schematic showing H-bridge and DC motor

At last, we had a circuit that looked like the one below, and we were ready to write some code for our motor.

IMG_0140.JPG
DC motor circuit using an H-bridge

Using the H-bridge, there are a few different pins to set up, for the switch input, each leg of the H-bridge (sending voltage to different legs switches the polarity, and direction, of the DC motor), and an enable pin. After setting the pin numbers and modes for these, you can activate the “enable” pin and then set a switch to send voltage to one leg or the other. The first time we activated the DC servo motor, we just used digitalWrite to send “HIGH” to each leg in turn, which allows the user to switch directions of the motor, both at the same speed. Since the servo spins so fast, it can be hard to see the actual spinning rotors in the video, but a brief glimpse of the rotor can be observed each time the motor switches direction.

Next, we took this process one step farther to vary the speed of the DC motor. Instead of using digitalWrite, we switched the pin of the second motor pin to be 5 (a PWM digital pin) so that we could use analogWrite to send varying voltages to the motor when it turned that direction. We left the other motor pin the same and continued to use digitalWrite for that one, meaning it stayed at the same speed from the last experiment. Again, it can be hard to tell on the video, but one of the directions of the motor is definitely much slower than the other.

 

Our code can be seen below. Note that this code is the version that uses PWM and analog write to send a value of 90 (out of 255) to the motor for the second motor pin. For values under 90, we couldn’t get the motor to actually spin because it didn’t have enough power.


const int switchPin = 2; // switch input
const int motor1Pin = 3; // H-bridge leg 1 (pin 2, 1A)
const int motor2Pin = 5; // H-bridge leg 2 (pin 7, 2A)
const int enablePin = 9; // H-bridge enable pin
void setup() {
// set the switch as an input:
pinMode(switchPin, INPUT);
// set all the other pins you're using as outputs:
pinMode(motor1Pin, OUTPUT);
pinMode(motor2Pin, OUTPUT);
pinMode(enablePin, OUTPUT);
// set enablePin high so that motor can turn on:
digitalWrite(enablePin, HIGH);
Serial.begin(9600);
}
void loop() {
//check if switch works
//Serial.println(digitalRead(switchPin));
// if the switch is high, motor will turn on one direction
// set leg 1 of the H-bridge low
// set leg 2 of the H-bridge high
if(digitalRead(switchPin)==HIGH)
{
digitalWrite(motor1Pin, HIGH);
analogWrite(motor2Pin, 0);
}
// else (which means the switch is low), motor will turn in the other direction
// set leg 1 of the H-bridge high
// set leg 2 of the H-bridge low
else{
digitalWrite(motor1Pin, LOW);
analogWrite(motor2Pin, 90);
}
}

view raw

DCmotor.ino

hosted with ❤ by GitHub

Part 3: Stepper Motor Control

Last, it was time to implement a stepper motor. Stepper motors are continuous rotation motors that offer really precise control to move in either direction, using coils and small magnets to “step” around the motor’s revolution. Because they are more complex, these motors are more expensive than the other two types of motors, and they are the most complicated to work with. Luckily, we had a type of motor driver called an EasyDriver to use with our stepper motor. Using schematics and diagrams, we were able to connect the motor to the EasyDriver and the Arduino, and also hooked up a potentiometer and a switch with a 10 kilo-ohm pull-down resistor. We used an external power supply as well — a 9V wall wart. A schematic that we created with Fritzing of our final circuit can be viewed below.

Screenshot 2018-11-13 14.31.09
Schematic of the stepper motor – definitely more complicated!
IMG_0325
Picture of our stepper motor circuit

The code for this motor was a bit more complicated as well. First, we made sure we could get the stepper motor to spin with some example code, and then once that was working, we integrated our potentiometer. Our button turned on the motor, and using different values of the potentiometer input, we were able to change the stepper’s speed. After defining various pin functions, this code uses a loop that moves the stepper 1000 “steps” forward. We mapped the potentiometer input values to a range of 1-50, and then we assigned this value to be the delay between each step. In this way, a delay of 1ms would cause the stepper to rotate much faster than a delay of 50ms between each step. A video of the variable stepper speed and our code can be viewed below! At the end of the video, the stepper continues for a short while before stopping, because it has to complete its loop of 1000 steps.


//Declare pin functions on Redboard
#define stp 2
#define dir 3
#define MS1 4
#define MS2 5
#define EN 6
//Declare variables for functions
char user_input;
int x;
int y;
int state;
int buttonState = LOW;
int pot = 0;
void setup() {
pinMode(stp, OUTPUT);
pinMode(dir, OUTPUT);
pinMode(MS1, OUTPUT);
pinMode(MS2, OUTPUT);
pinMode(EN, OUTPUT);
pinMode(8, INPUT);
pinMode(A0, INPUT);
resetEDPins(); //Set step, direction, microstep and enable pins to default states
Serial.begin(9600); //Open Serial connection for debugging
}
void loop() {
// put your main code here, to run repeatedly:
buttonState = digitalRead(8);
//Serial.println(pot);
if(buttonState==HIGH) //if button is on
{
digitalWrite(dir, LOW); //Pull direction pin low to move "forward"
for(x= 1; x<1000; x++) //Loop the forward stepping enough times for motion to be visible
{
pot = analogRead(A0);
int mappedPot = map(pot, 0, 1023, 1, 50);
int delayTime = mappedPot;
digitalWrite(stp,HIGH); //Trigger one step forward
delay(delayTime);
digitalWrite(stp,LOW); //Pull step pin low so it can be triggered again
delay(delayTime);
}
}
else{
resetEDPins();
}
}
//Reset Easy Driver pins to default states
void resetEDPins()
{
digitalWrite(stp, LOW);
digitalWrite(dir, LOW);
digitalWrite(MS1, LOW);
digitalWrite(MS2, LOW);
digitalWrite(EN, HIGH);
}

view raw

stepper.ino

hosted with ❤ by GitHub

Leave a comment