11. Output devices
A Beginner's Guide to Choosing & Using Motors, Servos and More
Group project
measure the power consumption of an output device
Sam showed us how he powers the brushless DC motors for his drone.
Henk used the lab's power supply to measure how much power output devices draw. The test that showed this the best was with a string of LEDs.
5V + 500A = the LED strip turned off after ~70% of the LEDs turned on.
5V + 800A = the LED made it through the red + green + blue + flashing displays, but when the multicolored routine started, the strip turned off.
5V + 1A = the LED was able to stay on throughout all of the display.
We also used an app on Sam's phone to test how much power our circuits from Input Devices week were drawing, but we weren't sure how reliable the results were.
Individual project
Motor types
For my project, I decided to try using stepper motors. Below are the pros and cons of the three most common motors in mechatronics.
Servo motor
- Pros: Simple to control, good for automated seats with slow and smooth movement
- Cons: Limited weight capacity, may struggle with very heavy seats, limited range
DC gear motor
- Pros: Stronger than a servo, smooth motion, can be used with limit switches for precise stopping
- Cons: Requires a motor driver circuit, powered and not spinning = stalling which will destroy the motor
Stepper motor
- Pros: Precise control, good for slow & controlled lifting
- Cons: Needs a driver (e.g., A4988), more complex than DC motors
Nema 17 stepper motor
17HS19-2004S1: A Nema 17 bipolar stepper motor with high torque. We have one available in the lab.
The NEMA 17 motor is rated at 2A per phase.
The DRV8825 driver can deliver up to 2.2A per phase.
Stepper drivers
Given that I'm going to try use the NEMA 17 stepper motor, here are some considerations for which stepper driver for this week's project.
Driver Selection: Choose a driver capable of supplying at least 2.0A per phase.
Power Supply: Calculate required voltage (with headroom) V = I * R + headroom. Here, minimum V = 2.0A * 1.4ohms + ~4V ≈ 6.8V.
Here are a selection of step sticks from Pololu. Ultimately, I ended up choosing the DRV8825, because I found it in Henk's drawer (I didn't know it was Henk's drawer).
DRV8825 Step stick
I begun by setting up the circuit up using a breadboard (given my failed PCB circuit design for Input Devices).
There are lots of tutorials online. However I struggled to get the motor to respond. Below are two that I attempted.
Stepper Motors and Arduino - The Ultimate Guide:
The issue was that I hadn't grounded the motor power supply
and logic power supply
correctly. The following schematic worked (kind of), I was getting a response from the NEMA 17, but it wasn't such a nice sound.
DRV8825 Stepper Motor Driver – Complete Guide (YouTube / website).
NB. DO NOT INCLUDE THE CABLE WITH the 'x' through it. That's how I fried my Arduino Uno.
A neat trick for figuring out which pins are connected on a stepper motor. Plug a cable into two of them and find the ones where the motor turns less freely.
Current limiter
Set the current limit to avoid exceeding your motor current limit (and a video from Pololu on it):
Current Limit = VREF × 2
NEMA 17: 2.0A per phase 2.0A = VREFx2 VREF = 1V
You can find the Vref wit just the Arduino Uno powered on.
Blown Arduino Uno
I ordered the parts I would need to make the circuit and they arrived on Tuesday evening. Unfortunately, blew up my Arduino Uno's voltage regulator by being frustrated and careless with my power supply settings.
15.7 V 1.8 A
Vera has similar troubles to me. Eventually, during her debugging process, she borrowed the driver of a colleague after replacing all of the circuit's components, and it worked.
It turns out her driver was buggered, and she had wrecked a few step sticks, thinking that there was an issue with the VREF. She had this to say:
And you can measure the VRef perfeclty when the part is broken so it’s very hard to tell if your step stick works or not. Make sure you have two drivers so you can change this, when the other driver is not working don’t play with the VRef the problem is somewhere else.
How do we not destroy step sticks?
By destroying a few of them and learning to be careful with them during the set up process.
Here's the code that Vera eventually used to get her stepper driver spinning.
/*
* Simple demo, should work with any driver board
*
* Connect STEP, DIR as indicated
*
* Copyright (C)2015-2017 Laurentiu Badea
*
* This file may be redistributed under the terms of the MIT license.
* A copy of this license has been included with this distribution in the file LICENSE.
*/
#include <Arduino.h>
#include "BasicStepperDriver.h"
// Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step
#define MOTOR_STEPS 200
#define RPM 120
// Since microstepping is set externally, make sure this matches the selected mode
// If it doesn't, the motor will move at a different RPM than chosen
// 1=full step, 2=half step etc.
#define MICROSTEPS 1
// All the wires needed for full functionality
#define DIR D9
#define STEP D10
//Uncomment line to use enable/disable functionality
//#define SLEEP 13
// 2-wire basic config, microstepping is hardwired on the driver
BasicStepperDriver stepper(MOTOR_STEPS, DIR, STEP);
//Uncomment line to use enable/disable functionality
//BasicStepperDriver stepper(MOTOR_STEPS, DIR, STEP, SLEEP);
void setup() {
stepper.begin(RPM, MICROSTEPS);
// if using enable/disable on ENABLE pin (active LOW) instead of SLEEP uncomment next line
// stepper.setEnableActiveState(LOW);
}
void loop() {
// energize coils - the motor will hold position
// stepper.enable();
/*
* Moving motor one full revolution using the degree notation
*/
stepper.rotate(360);
/*
* Moving motor to original position using steps
*/
stepper.move(-MOTOR_STEPS*MICROSTEPS);
// pause and allow the motor to be moved by hand
// stepper.disable();
delay(5000);
}
Or from Pololu:
/* Simple step test for Pololu stepper motor driver carriers
This code can be used with the A4988, DRV8825, DRV8824, and
DRV8834 Pololu stepper motor driver carriers. It sends a pulse
every 500 ms to the STEP pin of a stepper motor driver that is
connected to pin 2 and changes the direction of the stepper motor
every 50 steps by toggling pin 3. */
#define STEP_PIN 2
#define DIR_PIN 3
bool dirHigh;
void setup()
{
dirHigh = true;
digitalWrite(DIR_PIN, HIGH);
digitalWrite(STEP_PIN, LOW);
pinMode(DIR_PIN, OUTPUT);
pinMode(STEP_PIN, OUTPUT);
}
void loop()
{
// Toggle the DIR pin to change direction.
if(dirHigh)
{
dirHigh = false;
digitalWrite(DIR_PIN, LOW);
}
else
{
dirHigh = true;
digitalWrite(DIR_PIN, HIGH);
}
// Step the motor 50 times before changing direction again.
for(int i = 0; i < 50; i++)
{
// Trigger the motor to take one step.
digitalWrite(STEP_PIN, HIGH);
delay(250);
digitalWrite(STEP_PIN, LOW);
delay(250);
}
}
TB67H451AFNG,EL
Designing a circuit board that uses a stepper motor.
Henk suggested that I use the TB67H451
RS
= Motor Output Current sense
VM
= Motor Power Supply
VREF
= Motor Output Current Setting Pin
PAD
= Thermal Pad
Trace Widths: Use wide traces for motor power lines (VM, OUT1, OUT2) to handle high currents without significant voltage drops. Signal Isolation: Keep logic signal traces (e.g., IN1, IN2) away from high-current traces to reduce EMI. Component Placement: Place capacitors as close as possible to their respective pins (e.g., VM, VREF).
In the datasheet, from Toshiba, there is a schematic for how to use the part to control a stepper motor.
The stepper driver only has two output pins, which would get the motor to move in one direction. A stepper motor can move in two, therefore we need a second stepper driver.
"Furthermore, the TB67H451FNG has two inputs, IN1 and IN2, which are capable of selecting of the four operation modes; forward (clockwise), reverse (counter-clockwise), short brake, and stop modes."
These are the capacitor suggestions from Toshiba.
I followed the project Neil showed us in the global lecture when deciding on a few factors about the circuit's design. In this case, I used 0.1uF and 10uF capacitors.
I referenced a previous student when designing my schematic.
NB. From the datasheet of the stepper driver: "In order to disable the constant current function, RS pin should be connected to GND, and the voltage of 1 to 5V should be applied to VREF pin."
Kicad files
Milling
Notes to self:
- Beware of 45 degree angles
- Don't fill edgecuts on F.Cu gerber-2-PNG render
Arduino code
Since I added a button to my design (without a board mounted pull up resistor), I had to make sure the XIAO RP2040 internal pull up resistor was activated.
Here's an example code for how to do that:
#include <Arduino.h>
const int buttonPin = 2; // Example: GPIO pin 2
void setup() {
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP); // Enable internal pull-up resistor
}
void loop() {
int buttonState = digitalRead(buttonPin); // Read the button state
if (buttonState == LOW) { // Button is pressed (connected to GND)
Serial.println("Button Pressed");
} else {
Serial.println("Button Released");
}
delay(100);
}
The button worked!
Neil's code:
//
// hello.TB67H451.RP2040.ino
// XIAO RP2040 TB67H451 H-bridge hello-world
//
// Neil Gershenfeld 11/7/23
//
// This work may be reproduced, modified, distributed,
// performed, and displayed for any purpose, but must
// acknowledge this project. Copyright is retained and
// must be preserved. The work is provided as is; no
// warranty is provided, and users accept all liability.
//
uint32_t duty_min = int(0.65*65535);
uint32_t duty_max = int(0.75*65535);
uint32_t delay_ms = 500;
void setup() {
analogWriteFreq(100000);
analogWriteRange(65535);
}
void loop() {
analogWrite(0,0);
analogWrite(1,duty_min);
delay(delay_ms);
//
analogWrite(0,duty_min);
analogWrite(1,0);
delay(delay_ms);
//
analogWrite(0,0);
analogWrite(1,duty_max);
delay(delay_ms);
//
analogWrite(0,duty_max);
analogWrite(1,0);
delay(delay_ms);
}
Debugging
The input pins of the stepper driver were connected to digital pins, rather than analog ones. I changed that by rerouting them.
The H-bridge in the stepper motor isn't delivering current through the output pins:
I decided to go through the datasheets again, more slowly.
- VM: Power supply voltage for the motor drive circuitry.
- GND: Ground connection for the IC.
- IN1, IN2: Input pins for controlling the H-bridge, likely used to control the direction and speed of a motor.
- OUT1, OUT2: Output pins connected to the load (e.g., motor).
- VREF: Reference voltage input, often used for setting a voltage level for internal comparators or control circuits.
- RS: Current sense resistor connection. This is used to measure the current flowing through the H-bridge for current limiting or regulation.
Testing the circuit with a DC motor.
Testing with different components: motor, stick, cables, etc.
"Input range of control logic frequency fLOGIC ― ― 400 kHz IN1, IN2"
The digital control signals applied to the IN1 and IN2 pins should not exceed a frequency of 400 kHz for the control logic to function correctly.
Some code I'm trying:
#include <Arduino.h>
// Define the pins connected to the TB67H451FNG
#define IN1_PIN 3
#define IN2_PIN 2
const int buttonPin = 2; // Example: GPIO pin 2
void setup() {
Serial.read(9600);
// Set the control pins as outputs
pinMode(IN1_PIN, OUTPUT);
pinMode(IN2_PIN, OUTPUT);
digitalWrite(IN1_PIN, HIGH); // Set IN1 high
digitalWrite(IN2_PIN, LOW); // Set IN2 low
pinMode(buttonPin, INPUT_PULLUP);
}
void loop() {
// Example 1: Rotate the motor clockwise for 1 second
digitalWrite(IN1_PIN, HIGH); // Set IN1 high
digitalWrite(IN2_PIN, LOW); // Set IN2 low
delay(1000); // Wait for 1 second
// Example 2: Stop the motor for 0.5 seconds
digitalWrite(IN1_PIN, LOW); // Set IN1 low
digitalWrite(IN2_PIN, LOW); // Set IN2 low
delay(500); // Wait for 0.5 seconds
// Example 3: Rotate the motor counter-clockwise for 1 second
digitalWrite(IN1_PIN, LOW); // Set IN1 low
digitalWrite(IN2_PIN, HIGH); // Set IN2 high
delay(1000); // Wait for 1 second
// Example 4: Stop the motor for 0.5 seconds
digitalWrite(IN1_PIN, LOW); // Set IN1 low
digitalWrite(IN2_PIN, LOW); // Set IN2 low
delay(500); // Wait for 0.5 seconds
}
// void loop() {
// // Example 1: Rotate the motor clockwise at half speed
// analogWrite(IN1_PIN, 127); // PWM signal on IN1 (0-255)
// digitalWrite(IN2_PIN, LOW); // IN2 low
// delay(1000);
// // Example 2: Stop
// digitalWrite(IN1_PIN, LOW);
// digitalWrite(IN2_PIN, LOW);
// delay(500);
// // Example 3: Rotate counter-clockwise at full speed
// analogWrite(IN1_PIN, 255);
// digitalWrite(IN2_PIN, LOW);
// delay(1000);
// // Example 4: Stop
// digitalWrite(IN1_PIN, LOW);
// digitalWrite(IN2_PIN, LOW);
// delay(500);
// }