Introduction: A DIY Multi-turn Servo Motor Pulley
As part of developing Candela, I needed a way to accurately position a number of pulleys. While I ended up using stepper motors for the final product, I investigated building my own servo motors first.
So, why servo motors? Servos are great for applications where you want absolute positioning capabilities. For example, if you want to turn a robot arm to exactly 74 degrees past center reliably and repeatedly, a servo motor is a great choice. If you want to spin a drive wheel, though, you might want to choose another type of motor, like stepper or brushless DC.
Servo motors are usually purchased as complete packages, entirely self-contained. But on the inside, they're mostly just a feedback circuit, a gear motor, and a potentiometer. While commercial servo motors are great for many applications, they come mostly in two configurations: single turn (that is, with a 180 or 360 degree sweep) or continuous rotation (so they can turn forever, but without that absolute positioning we mentioned above).
For my purposes, I wanted a cheap servo motor that could turn a large number of times. These are sometimes sold as "sail winch" servos, but can be expensive and usually turn 3 times or fewer. How could we build a really cheap, many-turn servo to use as a pulley?
Step 1: Materials
- A microcontroller
- If you have an Arduino laying around, those work great.
- If you want a smaller package, I'm using an ATTiny85 ($3 or less, available from Mouser). These can be programmed using something like a TinyAVR Programmer, or directly with an Arduino.
- A small gear motor
- The 3d printed parts are fit to an N20 motor, which I ordered from Aliexpress but are available from Pololu and elsewhere. We'll want a motor that can be driven at about 5v for the tutorial.
- An H-Bridge IC
- For example, this L293D replacement from Sparkfun.
- See this Instructable for more detail on how to use this chip.
- A power supply for the motor and microcontroller
- If you're using an Arduino, the on-board power supply cannot supply enough power to drive the motor safely!
- Something like Sparkfun's breadboard power supply might be useful in your setup, but you can use any regulated 5v power supply to power the Arduino and the motor.
- A multi-turn potentiometer
- I'm using a Bourne 3590S which has 10 turns, which was also ordered from Aliexpress but available from Mouser and elsewhere.
- A breadboard and some hookup wire to connect the parts
- Some 3d printed parts to connect the motor to the potentiometer
- STL files are attached, as well as available from Thingiverse.
- Fishing line and a load to actually raise and lower from the pulley
Phew! That's only about 6 electronic parts, some of which you might have laying around from other projects.
Step 2: The Circuit
The circuit is relatively simple: the ATTiny85 controls the L293D to power the motor left and right. It receives analog feedback from the potentiometer, and a control signal from an external voltage source (for instance, an Arduino using PWM). Two capacitors are used to protect the L293D.
The input, therefore, mimics the way commercial servo motors work: power, ground, and an analog signal to control position.
The whole circuit is available on circuits.io: https://circuits.io/circuits/3901445-diy-servo-mot..., you can even run the circuit and drag the potentiometer and input voltages around to test that it works!
Step 3: Software
If you use different pins, change the values of the constants at the top.
#define SIGNAL_PIN A3 #define POT_PIN A1 #define MOTOR_LEFT_PIN 1 #define MOTOR_RIGHT_PIN 4 // This is the range of values near target that are "close enough". static const int kTargetResolution = 2; void setup() { pinMode(SIGNAL_PIN, INPUT); pinMode(POT_PIN, INPUT); pinMode(MOTOR_LEFT_PIN, OUTPUT); pinMode(MOTOR_RIGHT_PIN, OUTPUT); } void loop() { // Input from the external world int target = analogRead(SIGNAL_PIN); // Feedback from the potentiometer int potVal = analogRead(POT_PIN); if (potVal < target - kTargetResolution) { // Motor is short of target, move right. digitalWrite(MOTOR_LEFT_PIN, LOW); digitalWrite(MOTOR_RIGHT_PIN, HIGH); } else if (potVal > target + kTargetResolution) { // Motor is too far of target, move left. digitalWrite(MOTOR_LEFT_PIN, HIGH); digitalWrite(MOTOR_RIGHT_PIN, LOW); } else { // Motor is close enough! Stop here. digitalWrite(MOTOR_LEFT_PIN, LOW); digitalWrite(MOTOR_RIGHT_PIN, LOW); } }
Step 4: Assembly + Testing
- Solder wires onto the potentiometer and motor leads.
- Place the potentiometer through one side of the base while attaching the pulley to it.
- Attach the motor to the pulley
- Bolt the motor down onto the base.
- Assemble the circuit, and connect to the potentiometer and motor.
- Program the ATTiny and place into the circuit board.
- Hook up the circuit to another microcontroller's PWM output.
- Fire it up!
I appreciate the work that goes into a compact, reliable commercial servo motor a lot more now!
Step 5: Bonus - Torque and Speed Calculations
Torque is given in units of mass * distance. For instance the motor I used in this project is spec'd at 40 oz-in or 2.9 kg-cm at stall (the maximum load the motor can move).
So to figure out how much weight our stepper motor pulley can raise, we divide that number by the radius of the pulley, which let's say is 2 centimeters.
Weight = Torque / Distance = 2.9 kg*cm / 2 cm = 1.45 kg (3.20 lbs)
So this contraption can lift a maximum of 1.45kg at up to 200rpm. How fast does that translate to vertically?
Linear speed = Rotation Speed * Circumference = 200rpm * (2cm * pi * 2) = 2,513 cm / minute = 4.18 cm / sec (1.65 in / sec)