DIY Servo With Arduino, DC Motor, And Potentiometer « Drone Colony

Embed Size (px)

Citation preview

  • 7/26/2019 DIY Servo With Arduino, DC Motor, And Potentiometer Drone Colony

    1/9

    DIY Servo With Arduino, DC Motor, And

    PotentiometerBy Church on July 24th, 2008 Posted in Projects | Robots

    15

    Not being happy with the ability to only move a minimum of 1 degree and only at a single speed for my time-lapse automaton project, decided to

    hack up my pan servo and get a little more control over it via the arduino directly.

    The basic idea is to remove the controller from a servo entirely, modify the gears for continuous movement by removing any stop pins, and attachthe potentiometer directly to the arduino. If we then attach the motor to a motor controller (in my case, an L298 Compact Motor Controller) we

    can now control direction and speed. By using analogRead() with the wiper of the potentiometer, well have 1024 discreet positions we can read in asingle rotation. Or, about 0.35 degrees as a minimum movement.

    Its possible to use this same code and wiring to turn any old DC motor and a potentiometer into a servo by attaching the nal drive-gear of your

    motor or project to the shaft of the potentiometer in such a way that it rotates perfectly with the nal drive gear.

    This code uses a basic method to avoid the jitter youll get with the analog potentiometer of averaging and canceling out repetition. A number ofreadings are averaged, and if the same average occurs in either of the previous two readings, then the difference in position is not recorded.

    Otherwise, we use the average reading to determine our current position, and the difference to determine how far we have moved since our lastvalid reading.

    For mine, I modied an HS-645MG motor that came with the SPG645S kit. I used the potentiometer with the kit, as it mounts in the shaft with a slip-

    collar to prevent damaging the pot if you attempt to go past its stop. If you were to use a continuous-rotation pot, you could, perceivably, rotateinnitely. For my purposes, one rotation is enough, and the point is to be able to rotate very slowly while still being aware of our position. I nd that

    I am able to move exactly one reading value (1024 steps) between each delay in movement, and delay up to nine hours. Your mileage may varybased on your hardware and other code running.

    The code and a wiring diagram are behind the cut:

    Heres a diagram of how everything is wired for this sketch.Youll need to click on it to see the entire image.

    Edit: 7/25/08 It seems that WordPress had completely eaten my source code when posted. After some searching, I found a new way of doing it.

    While it isnt perfect, code portions are no longer eaten up. For best results click on view plain below.

    Addendum: there were two bugs preventing full READ_AVG resolution, one was in the division of the total ( tot / READ_AVG shouldve been tot /READ_AVG + 1), and the other was when re-setting step counter upon reaching READ_AVG, it had to be re-set to -1 to account for the post-

    increment operation at the end of read_pot().

    12345

    /*

    DIYServo 1.0

    Controller Motor Speed and Movement with Absolute Positioning

    Search...

    About Me Photography Projects

    http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/http://dronecolony.com/category/projects/http://dronecolony.com/category/photography/http://dronecolony.com/about-2/http://dronecolony.com/feedhttp://twitter.com/#!/droneonehttp://facebook.com/roamingdronehttp://dronecolony.com/http://dronecolony.com/category/projects/robots/http://dronecolony.com/category/projects/http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/
  • 7/26/2019 DIY Servo With Arduino, DC Motor, And Potentiometer Drone Colony

    2/9

    6789

    1011121314151617181920

    21222324252627282930313233343536

    37383940414243444546474849505152

    53545556575859606162636465666768

    69707172737475767778798081828384

    8586878889909192939495

    A sketch for turning a standard DC gear motor into a servo

    using a potentiometer. Can also be used to add finergrained control over existing servos.

    Control over motor : Speed (PWM) Direction Number of degrees to move (up to 1024) per move How to long to wait between moves

    To get finer control (1024 degrees, instead of 360) of an existing servo, remove the controller and any stoppins, disconnect the potentiometer wires. Connect power lines from servo motor to a DC motor controller, potentiometer wiper to an input pin on the arduino,

    and the ouside potentiometer pins to 5v/GND.Serial monitor:

    use 'l' to tell the servo to move left

    use 'r' to tell the servo to move right use 's' to stop the servo use 'g' to go (run the servo)

    (c) 2008 C. A. Church www.dronecolony.com

    7/24/08 initial version*/

    // USING_CONTROLLER says whether we have to bring an // enable pin high (such as for the Compact L298 controller) // before sending PWM down the LT/RT pins // set this to 0 if you don't need an enable pin

    #define USING_CONTROLLER 1

    // enable pin#define MOTOR_EN_PIN 8 // right direction pin#define MOTOR_RT_PIN 6 // left direction pin#define MOTOR_LT_PIN 9

    // READ_AVG is how many readings to average

    // set it to one less than the actual # // e.g.: 10 readings = set to 9 // // the more you average, the more accurate your reading is likely to // be too many though, and you'll start missing changes if the motor // is moving quickly#define READ_AVG 9

    // motor speed is from 0255, test with low values // as not all will move consistently for you

    intmotor_speed = 75;

    // how many ms to pause between allowed movementsintmotor_pause_tm = 1000;

    // how many 'degrees' (absolute differences between // potentiometer readings) to move before pausingintmotor_move_deg = 5;

    // a counter for how many degrees we have movedintmove_deg_cnt = 0;

    // setting to a default valueint motor_cur_pin = MOTOR_RT_PIN;

    // control indicatorsboolmotor_started = false;boolmotor_paused = false;boolfirst_run = true;boolmotor_run = false;longpaused_tm;

  • 7/26/2019 DIY Servo With Arduino, DC Motor, And Potentiometer Drone Colony

    3/9

    96979899

    100101102103104105106107108109110

    111112113114115116117118119120121122123124125126

    127128129130131132133134135136137138139140141142

    143144145146147148149150151152153154155156157158

    159160161162163164165166167168169170171172173174

    175176177178179180181182183184185

    // our current and previous potentiometer readingsintcur_reading = 0;intpre_reading = 0;intsteps = 0;

    // our current readings array, and our previous average readings arrayintvals[READ_AVG + 1];intprev_posts[2] = { 0, 0 };

    voidsetup() {

    Serial.begin(19200); Serial.println("Ready");memset( (char*)vals, 0, sizeof(int) * (READ_AVG + 1) );

    // set motor control pins

    if( USING_CONTROLLER )

    digitalWrite(MOTOR_EN_PIN, HIGH);

    digitalWrite(MOTOR_LT_PIN, LOW); digitalWrite(MOTOR_RT_PIN, LOW);

    }voidloop() {

    // see if any input has come in the serial port

    check_input();

    // figure out how many degrees we've moved (if at all)

    move_deg_cnt = move_deg_cnt + read_pot();

    if( motor_run == true) { // if the motor is supposed to be running

    // the following check is to prevent attempting to rotate all the

    // way around on a potentiometer that has a stop. If yours doesn't // have a stop in it, ou can remove this check

    if( (motor_cur_pin == MOTOR_RT_PIN && prev_posts[1] >= 1020 ) || ( motor_cur_pin == MOTOR_LT_PIN && prev_posts[1]

  • 7/26/2019 DIY Servo With Arduino, DC Motor, And Potentiometer Drone Colony

    4/9

    186187188189190191192193194195196197198199200

    201202203204205206207208209210211212213214215216

    217218219220221222223224225226227228229230231232

    233234235236237238239240241242243244245246247248

    249250251252253254255256257258259260261262263264

    265266267268269270271272273274275

    motor_paused = true;

    // record when we started our pause (so we know when to stop)

    paused_tm = millis(); } elseif( motor_paused == true&& (millis() paused_tm) > motor_pause_tm ) {

    // if enough time has passed to stop pausing

    Serial.println("Unpausing"); motor_paused = false; paused_tm = millis();

    // set move_deg_cnt to zero when restarting to avoid any

    // jitter while pausedmove_deg_cnt = 0;

    // generate PWM

    analogWrite(motor_cur_pin, motor_speed);

    } }}intread_pot() {//read the voltage on the potentiometer: cur_reading = analogRead(0);

    intdiff = 0;

    // we're going to average the last READ_AVG reads // put in a value for our current step

    vals[steps] = cur_reading;

    // if we've saved enough values to go ahead and perform an average...if( steps == READ_AVG ) {

    // reset our read counter

    steps = 1;

    // determine the average value read // this is mostly to deal with big jitter

    inttot = 0; intavg = 0;

    // sum up totals

    for(inti = 0; i prev_posts[1] ? avg prev_posts[1] : prev_posts[1] avg;

    // if there's a difference between the averages

    if( diff > 0 ) {

    // print our new readingSerial.println(avg, DEC);

    // move our last reading back, and put our current reading in

    // our array to track the last two positions

    prev_posts[0] = prev_posts[1]; prev_posts[1] = avg;

    // update this so the pause check knows that we have changed a position

  • 7/26/2019 DIY Servo With Arduino, DC Motor, And Potentiometer Drone Colony

    5/9

    276277278279280281282283284285286287288289290

    291292293294295296297298299300301302303304305306

    307308309310311312313314315316317318319320321322

    323

    // (otherwise, starting in a position oher than 0 will mess up our // pause check)

    first_run = false; }

    }

    // increment our saved value # for the next loop

    steps++;

    // return the difference recordedreturn(diff);

    }

    voidcheck_input() { if( Serial.available()) { charch = Serial.read();

    switch(ch) {case'g':

    Serial.println("Go Running Motor"); motor_run = true; digitalWrite(13, HIGH); break; case's':

    Serial.println("Stopping Motor"); motor_run = false; motor_started = false; analogWrite(motor_cur_pin, 0); digitalWrite(13, LOW); break; case'l': motor_cur_pin = MOTOR_LT_PIN; Serial.println("Direction = LEFT"); break; case'r': motor_cur_pin = MOTOR_RT_PIN; Serial.println("Direction = RIGHT"); break; } }

    }

    Marcel - July 28, 2008

    What happens to the pot when you go round the clock?

    [m]

    Reply

    Marcel - July 28, 2008

    Im kinda hoping that my project will also allow time lapse workwith 8 microsteps, I get .8 resolution on the

    stepper which is then geared to my drive wheel (not sure of ratio).

    Im thinking of also doing multipass video shots and mixing them. We have a massive 10m tidal range (low to

    high water). Id really like to shoot a moco shot of the tide coming in and out.

    Reply

    c.a. church - July 28, 2008

    Marcel A couple of points that may help you a good deal (Ill be posting this info up in much more detail later this

    week, with photos and instructions when my new gears come in the mail.)

    If you hook up your potentiometer to your nal drive gear, youll divide your measurable motion points by1024 so, at 360 degrees / 1024 == 0.35 deg minimum movement. However, I can tell you with quite a bit of

    authority (ran the test this weekend) @ 17mm F/L 0.35 deg is WAY too big of a movement to be smooth. In fact,its quite jumpy.

    However, if you gear down (slow down) the nal output gear relative to the motors shaft or input gear, you can

    http://shutterdrone.wordpress.com/http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=112#respondhttp://thebeardedwonder.blogspot.com/http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=111#respondhttp://thebeardedwonder.blogspot.com/
  • 7/26/2019 DIY Servo With Arduino, DC Motor, And Potentiometer Drone Colony

    6/9

    increase your resolution by measuring from the source instead.

    Say, for example, using my SPG645S kit from ServoCity, its geared at 5:1 so, if I can measure the rotation of

    the servos output, instead of the nal drive gear, I get: 360 / 1024 / 5 == 0.07 degrees, a lot ner-grained. Ill betesting later this week as to how functional that is, but I have plans to move to 15:1 gearing, giving me 0.02

    degrees measurable. The reason that works is that in 5:1 gearing, it would take ve rotations of the source toequal 1 rotation on the output. So, every individual measurement of the source rotation is 1/5th the distance (or

    degrees) moved on the nal drive.

    You need to know the nal gear ratio, otherwise you wont have anywhere near accurate measurement ofdistance, just count the teeth on all gears to determine gear ratio. (Or, if you know theyre the same pitch, you

    can get close by measuring the diameter of each. 48P == 48 teeth for each inch of diameter.)

    Its important, for the highest resolution, to measure movement off the point in the drive with the highest

    number of rotations. If Im running 5:1, I read off the source, if its 1:5, I read off the nal drive gear.As to the pot going round the clock, if your pot has a stop, you dont want to do that, no sir =) Youll likely

    damage the pot. Thats why in the code above it has a hard stop on each end of movement (see around line136). Obviously, this is a problem if were measuring off the source gear wed reduce our nal movement to

    1/5th of a rotation in 5:1 (we increased resolution, but decreased movement). Youll need to replace the pot w/a continuous rotation version, or cut the stop tab out. Ill be posting an example of doing that with the

    HS645MG and its built-in pot in a few days. Presuming I dont destroy the pot in the process! No worries if I do

    though, Ill just run one external using a horn in addition to the gear.

    If you have a continuous rotation pot, you can just count the times youve gone around to determine total

    distance. E.g. :

    Does that help? I think my thoughts were a little rambling there, but it starts to make a lot of sense after a while.By measuring the rotation with potentiometers, you get out of the realm of continuous motion, and into a

    specied amount of motion between shots.

    !c

    12

    3456

    if( cur_value < last_value ) { // calculate the absolute difference in values read

    diff = (1024 last_value) + cur_value; // update count of total rotations rotations++;}

    Reply

    Marcel - July 30, 2008

    Does the round-the-clock count work out accurate (precise) enough? Why not use a stepper or an encoder of

    some sort? Cost?

    Trying to get my buttons and LCD into a case of some description. Im using a VGA cable to communicate backto the Arduino on the dolly. That way i can unplug once its programmed if needed or use a longer VGA cable if

    needed. Ive been stripping a scanner to get some wires to hook up the LCD what fun!

    [m]

    Reply

    c.a. church - July 30, 2008

    Marcel, yes, it was all about cost and utilizing the equipment I had on-hand. Unfortunately, the tiny pots theyuse inside servos cannot effectively be modied (without serious effort, at least!) due to the wire-arms they

    use as wipers they end up shorting the +5v to GND when one goes all the way around.

    There would denitely be some lack of accuracy in the 10-20 degrees between the left and right contacts, in abest case scenario youd have a oating input leading to random reads, which could easily be compensated for

    in software, if need be. (You would simply know Im in this region, heading for 0 or 1024 depending on

    direction. )

    Its funny that you should mention steppers, I found some attached to some cool pumps I picked up recently at

    the electronics store, and I might use them for pan/tilt. Picked up a more powerful one as well for $9 used.

    Went ahead and ordered that stepper controller you mentioned. Essentially, Ill be replacing all of the servosand DC motors w/ steppers, as the rest of this stuff is too much work, and my September deadline is

    approaching =) So, w/ 1.8 deg stepper, 8 microstepping and 3-1 gearing (what Ill have available for this setup),that gets me 1.8 / 8 / 3 = 0.075 degrees/movement. Which should be acceptable. With a few more bucks and a

    little more fabricating, I can go to 9:1 gearing, giving 0.025 deg/move.

    The VGA cable is a good idea I have a second arduino coming in, therell be one driving the motors / camera,and one driving the UI. Im having the UI part in a separate hand-held case, and was considering using a USB

    cable to connect the two. I dont need many wires between, as I intend to use i2c to communicate between the

    http://shutterdrone.wordpress.com/http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=114#respondhttp://thebeardedwonder.blogspot.com/http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=113#respond
  • 7/26/2019 DIY Servo With Arduino, DC Motor, And Potentiometer Drone Colony

    7/9

    arduinos. But the UI needs to be connected as stop/start is handled by it, and status (position of each motor)

    will be displayed on the UI.

    The motor controllers, all power distribution, etc. will be housed inside of the case holding the truck motor onone end of the track.

    Its funny you mention cables, as I spent some time making a few last night for the LCD, keypad, and power on

    the UI board. I used the straight, friction-lock male PCB ends like these :http://www.jameco.com/webapp/wcs/stores/servlet/ProductDisplay?

    langId=-1&storeId=10001&catalogId=10001&productId=687885Just soldered the wires onto the PCB end, and then used some shrink-wrap to tidy them up. They look very

    good and only cost me a few cents a piece. The connectors stay in pretty tight as well, as the friction-lock

    plates press on the arduinos female headers. For the arduino side, I just got 1 six pins, 2 8 pins, and 2 2 pins (forvin/gnd and 5v/gnd).

    !c

    Reply

    Marcel - July 31, 2008

    Im glad things are moving forward for you c. (is that Chris, Cecil, Cuthbert??)

    I spent a while yesterday rewiring my LCD. I had it all sorted originally but when I came to think about casing

    my display and controls I found I was about an inch short. Damn! It took me ages to unsolder and re-solder itall. Im not very fast. Next job is to put the pair in a case of some sort. Its going to be rough!

    You may nd that with the steppers you will be able to run them fast during your setup so you can preview

    your start and end points which could be handy, then ip it over to your super slow mode at runtime.

    This is the rst time Ive used steppers and Ive been blown away by them. The EasyDriver board (glad thatsbeen of use to you) makes it SO easy(!) to use them.

    I had a couple of old Lexmark Optra C laser printers a little while back. Printers are a great source of steppers! Ijust dont have a lot of options for swapping gears in and out the motor has a cog xed to the shaft.

    Ive not got much of a budget for this so like you Im trying to use whats to hand!

    All the best.

    May all your solder joints be good ones!

    [m]

    Reply

    Maria - February 24, 2010

    hi how can i attach the POT to the output shaft please?

    Reply

    c.a. church - March 4, 2010

    Maria, sorry for the slow response, your comment got locked up in my spam folder (dunno why thats arst!).

    Anyhow, you have numerous options, you could have a supported shaft, with one end going beyond the

    support, and then either couple your potentiometer to the shaft, or use a hollow shaft with an ID largerthan the OD of your POT shaft and use a small amount of rubber material to create a tight t.

    Alternatively, you can use a shaft with one end drilled and tapped, and then match it to a POT with athreaded shaft, using a little low-strength thread-sealer to prevent it from working loose.

    Of course, theres yet another option of the shaft being the actual POT shaft, if it can handle the load.

    !c

    Reply

    c_gel - May 16, 2011

    hello,

    does your self made servo motor have brake function? I mean when certain angle is achieved, the shaft stops

    and freezes at that particular angle in rm way; which cannot be affected if someone tries to push using nger?

    http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=119#respondhttp://shutterdrone.wordpress.com/http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=118#respondhttp://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=116#respondhttp://thebeardedwonder.blogspot.com/http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=115#respondhttp://www.jameco.com/webapp/wcs/stores/servlet/ProductDisplay?langId=-1&storeId=10001&catalogId=10001&productId=687885
  • 7/26/2019 DIY Servo With Arduino, DC Motor, And Potentiometer Drone Colony

    8/9

    sorry for my english.. tq

    Reply

    Jesse Guardiani - June 18, 2013

    Hey, check out my Open Source DIY Servo project: http://www.diyservo.comWe use Arduino for the brain, Pololu 30A for the motor controller, a Magnetic Rotary Encoder (MRE) from the

    Mad Scientist Hut, and 3d Printed plastics! We plan to make kits so everyone can use DIYServo with a motor oftheir choice, or one of our pre selected motors. Come join the fun!

    Reply

    Nooman Mufti - September 1, 2013

    Hi guys,

    My apologies, I know this is an old post. I am working on a project in which I turn small mirrors to face the sunusing sensors. I was using servos, but I needed more than the usual voltage to drive them to move the heavy

    mirrors, so I burnt out the internal control chip.I used an L298N chip to drive the motor + gear box directly and then use the external solar sensors to tell the

    motor to go clockwise/anti-clockwise, stop, etc. What I cant make it do is resist a change in the desired

    position of the motor shaft once the position has been attained (like a normal Servo does if you try to force it byhand to change position once an angle is set). This is important for me, since the mirrors try to fall down

    because of their own weight and I need the modied Servo to stay and resist this change unless I give it acommand to change position.

    Thanks so much,

    Kind regards,Nooman

    Reply

    Church - September 2, 2013

    Nooman,

    Are you using the braking mode of the L298N when stopped? If not, try enabling it nearly all H-Bridge

    drivers, AFAIK, have a braking mode. If your payload is still too heavy to prevent movement when braking,you can always do like a normal servo controller, and constantly check the position of the motor via a PID

    loop (its possible to not use a PID loop, but you may end up with jitter and lots of back-and-forth

    movement). There is a PID library for Arduino here: Arduino PID Library

    Reply

    Nooman Mufti - September 2, 2013

    Dear Church,

    Thanks so much for your super prompt advise. I really appreciate it. The brake function is what Iinitially thought would work,essentially I set the Enable pin as high and both inputs to the motor as

    High, but it doesnt freeze the motor, which essentially just freely moves. I see some other people onthe net have had issues with L293D as well, so it may be a similar problem. Some people suggest

    using L6202 (MOSFET based) which denitely does a brake to address this issue

    (http://www.avrfreaks.net/index.php?name=PNphpBB2&le=printview&t=22646&start=0)I was thinking I could just get away with the motor doing an innite oscillation (clock, anticlockwise

    motion) once it reaches the desired position (using the solar angle sensors I have). But I think at theentire setups tipping point, the thing would fall then come back and so forthlots of big jitters, unless

    of course, I can do a full brake somehow.maybe I can keep a very low tolerance (super small error)in my solar angle sensors, so that it can do these innite clockwise/anticlocks at the desired

    position/angle (sounds terrible, I know)..maybe I need to try another motor controller chip ?

    I will try your other suggestion about the PID as well. I have also ordered another continuous rotation

    servo, but from past experience, I need more torque than they can provide at 7 V, so I would need toovervolt them, thereby burning the control chip againso an external motor control chip with a heatsink is perhaps the only way to go.

    Thanks so much again,

    Kind regards,Nooman

    http://www.avrfreaks.net/index.php?name=PNphpBB2&file=printview&t=22646&start=0http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=12587#respondhttps://github.com/br3ttb/Arduino-PID-Libraryhttp://droneone.wpengine.com/http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=12578#respondhttp://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=9339#respondhttp://www.diyservo.com/http://www.diyservo.com/http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=120#respond
  • 7/26/2019 DIY Servo With Arduino, DC Motor, And Potentiometer Drone Colony

    9/9

    Reply

    Leave A Reply

    Name (required)

    Mail (will not be published) (required)

    Website

    http://dronecolony.com/2008/07/24/diy-servo-with-arduino-dc-motor-and-potentiometer/?replytocom=12596#respond