I had a problem with some servos which i bought for my arduino but i don't know why , they were making some strange noises and were drawing too much current. So i decided to make my own servos ! . First of all its important to know exactly how a servo works.
The servo is mainly a DC motor with a motor driver , a comparator and a "feedback potentiometer". The potentiometer (as its name suggests ) gives a feedback to the controller about the current position of the servo shaft. These servos are usually expensive and are fragile. To make our own servo we'll need :
1. A microcontroller ( preferably Arduino coz i have made a library specially for these DIY Servos -- I've attached the library below
2. a 10k ohm free moving potentiometer as shown
3. a piece of strong flexible wire ( for mount )
4. some super glue
5. a motor driver : build your own 30 AMP MOTOR DRIVER : https://www.instructables.com/id/MOTOR-DRIVER-30Amp/
Step 1: Start Building It !
1. First bend the pins of the potentiometer outward as shown and Solder three wires to it .
2. now apply some superglue on the tip of the motor-shaft and place the potentiometer's knob carefully on the motor shaft
NOTE : Do not apply too much superglue as the viscosity of superglue is very less and it can easily lock your shaft / gears or ruin the potentiometer
3. now bend a piece of strong and flexible wire in such a way that it will hold the pot firmly in it's place
4. glue the ends of the wire mount to the potentiometer's body ( not the knob ) and fix it on the motor
Now your servo is ready !
Step 2: Library and Basic Working
Extract the folder from the zip to Program files (x86) / Arduino / libraries / CustomServo
Now restart the Arduino IDE and paste the code in it and upload it.
The custom servo can be used in robots , etc but not for RC planes or copters.
The servo shaft's position is encoded by the feedback pot from 0 to 1023 ( zero to extreme ) to avoid excess turning due to momentum of the shaft , the actual turn area has been limited to 160 degree cutting off 10 degree offset from each side.
When we send a value to the microcontroller , it compares the value and the position of the servo shaft . If there is a difference between these values ,the arduino commands the motor driver to drive the servo CW or CCW and equalize the values. To have smooth motion and less momentum build-up , PWM values are required to calculate the phase difference and set the motor speed accordingly. It has been tested with minimum 2 degrees of noticeable displacement .
FURTHER SCOPE OF IMPROVEMENT :
It requires many PWM outputs , these can be multiplexed using a 8-bit multiplexer ( 4051 ) to reduce the pin count
Step 3: Hook It Up to Arduino
The pin connection has been shown in the picture. The wiper goes to analog 0 , one of the wires from the potentiometer to GND on arduino and the other to +Vcc on arduino. The motor is to be connected to a motor driver and the inputs of the motor driver are connected to arduino PWM pins only ***
Step 4: Upload the Code
Download the provided CustomServo libray
here is the code by which you can tell the servo to set it's position as commanded by the used using serial monitor
it can take values from 0 to 160 (in degree)
/* Program and library made by electro18 (Tanay P.)
This code is an example of the CustomServo library
The user can input any value from (0 to 160) in the serial monitor
and drive the custom servo
pin connection :
motor driver input 1 : pin 9
motor driver input 2 : pin 11
Servo feedback pin : analog 0
pot pins to +5 and gnd on arduino
#include<CustomServo.h> //include the custom servo library
int angle; // angle by which the servo will rotate
CServo servo1(9,11,0); // initialize the servo with CServo myservo( pin 1 , pin 2 , analog feedback pin )
Serial.begin(9600); // setup serial connection
while(Serial.available()) // check for availability of serial port
angle=Serial.parseInt(); // input an integer from 0 to 160 as the angle value and hit enter
servo1.drive(angle); // drive the servo using myservo.drive( angle ) where 0 <= angle <= 160
Serial.println(angle); // print the current angle
The CustomServo library description :
1. setting up a custom servo --- > CServo myservo( pwm pin 1 , pwm pin 2, analog pin )
eg : CServo myservo(9,11,0);
2. Commanding it -----> myservo.drive( angle )
where angle lies b/w 0 and 160
eg : myservo.drive(120); // the servo will rotate 120 degrees