Turning a motor into a servo

Hi,

I described my problem on Pololu's forum (http://forum.pololu.com/viewtopic.php?f=15&t=3592) but a short summary:

I have 2 brushed DC motors, a dual motor driver (with PWM control), a arduino UNO and 4 linear continuous rotation pots. I thought of making my own servo's cause I wanted a 1-on-1 angular positioning control (for tele-operation). I mean that each motor has a pot on its axis and I control its position with another but identical pot. I thought it would have been easy and just write a simple code where the two pot readouts must reach the same value but the motors where loud and unprecise. Pololu told me to use a PID feedback code for a good result (it would offer me Jrk-like performance - http://www.pololu.com/catalog/product/1392). I know what it is briefly (saw it in class) but they told me the code would be complicated.

I looked around and found some stuff about PID but I can't find my way in it. Does anyone know a code that would give servo-like perfomance with the hardware I have?? It would be very nice and efficient cause I don't want two buy 2 Jrk's if I can get the same with my motor driver and Arduino.

Thanks a lot.

I would expect that the noise you are experiencing is PWM hum, the only way to solve this is to make your PWM switch at much higher frequency which i i have NFI how to do on an Arduino. As far as the continuous pots, PID seems to be the way to go here, it will require some complex maths but it should work. A short intro here if u don't quite get it. Basically your motor driver would be told "move motor forward a bit" and would send PWM signal to motor to turn forwards. The controller then looks at the value that the pot changed and compares it to the change in PWM signal it sent. it does some maths here and thinks, if i want to turn it x amount, i change the PWM signal by x*4 (for example) and it does this constantly, adapting for changes in torque etc. this enables much higher amounts of accuracy. As to how to code this, it'd be fun, but quite challenging.

If you are on a beer budget, you may want to take a diffrent approach for your tele-operation (I assume a cam pan/tilt). You can make a cam pan/tilt platform using large standard hobby servos. If you can live with only +-45 deg. of movement (you might find or make one for a larger range), you can use an inexpensive servo tester like below to control each servo. Bottom are some more expensive cam mounts.

http://www.hobbycity.com/hobbycity/store/uh_viewItem.asp?idProduct=8296
http://www.hobbycity.com/hobbycity/store/uh_viewItem.asp?idProduct=14774

http://www.servocity.com/html/pan_tilt_roll___accessories.html
http://www.servocity.com/html/pt-2100_pan__tilt_system.html

@ fliggygeek,
I forgot about the switching frequency of the PWM signal. I have to look it up thanks. But I don't think it is the only reason for the bad servo attitude but I'll have to try it again with a higher frequency. I used the code you can see below and like you can see it is pretty simple. I use the difference of both pot positions for poistioning. The bigger the difference the higher speed I give the motor. But like you say, PID would be much better and it would be a challenge to write. Thanks for explaining the basics. I'll have to think about a clever feedback code. But aren't any standard PID algorithms in circulation?

@ zoomkat,
It is indeed a pan/tilt setup I would like to control with my head (with the help of a headset). Later on I would like to add the roll too but you got to start 'simple'. I don't know why I tried servo's first but I am not sure if servo's can make precise angle reproduction... it follows your pots' movement very well but can you make it move 59,5 degrees if your turn your pot 59,5 degrees?? Is it simpel to setup like the 'Knob' tutorial (http://arduino.cc/en/Tutorial/Knob)? I have to learn more about servo's I guess. I thought of using the hardware I have and it should work with the right software but I must check out the local RC stores for some quality/price ideas. I need more or less a 170° and a 120° movement. Those servo testers are simple useful things its seems. Those large pan/tilt setups use about the same motors that I have I think. Thanks for the links!

/*
Motor Position Control
Control a motor's position with two potentiometers.
*/
void setup()
{
Serial.begin(9600);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
}
void loop()
{
int sensorposition = analogRead(0);
int motorposition = analogRead(1);
int difference = sensorposition - motorposition;
Serial.println(difference, DEC);
if (difference > 0)
{
digitalWrite(8, HIGH);
digitalWrite(9, LOW);
if (difference > 255)
{ analogWrite(10, 255); }
else { analogWrite(10, difference); }
}
if (difference < 0)
{
digitalWrite(8, LOW);
digitalWrite(9, HIGH);
if (abs(difference) < 255)
{ analogWrite(10, abs(difference)); }
else { analogWrite(10, 255); }
}
if (difference == 0)
{
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
analogWrite(10, 0);
}
}

It is indeed a pan/tilt setup I would like to control with my head (with the help of a headset).

This is the part that you will probably find not workable for what you want to do unless you accept some limitations.

@ zoomkat: Why would that be? It has to turn 90°left/right and about 60° down/up. It must be fast so it will have to be powered by larger motors. But for a start I can make some limitations!

I don't know why I tried servo's first but I am not sure if servo's can make precise angle reproduction... it follows your pots' movement very well but can you make it move 59,5 degrees if your turn your pot 59,5 degrees??

If you are looking for smooth .5 deg control resolution using your head, I doubt it will happen. I made a simple joystick control for my servo based webcam pan/tilt and learned a lot. You could get a pair of plastic safety glasses and attach a laser pointer to see how well you can make the laser dot stay on target. What do you do if you need to move your head without moving the cam? If you manage that, how do you get the cam and head controller back in sync? I'd do some simple proof of concept testing before starting to invest serious $$$.

If you are looking for fast .5 degree resolution control, servos arent what you need, you can find some good sized stepper motors that with a 2-1 gear ratio will give you incredibly fast speed and .5 degree or better resolution. these are what they use for CNC mills so you can be sure they're the best option.

zoomkat:
If you are looking for smooth .5 deg control resolution using your head, I doubt it will happen. I made a simple joystick control for my servo based webcam pan/tilt and learned a lot. You could get a pair of plastic safety glasses and attach a laser pointer to see how well you can make the laser dot stay on target. What do you do if you need to move your head without moving the cam? If you manage that, how do you get the cam and head controller back in sync? I'd do some simple proof of concept testing before starting to invest serious $$$.

I guess reaching 0.5° precision is hard if you got a tight budget and maybe it is too precise too but with stepper motors (like fliggygeek proposes) it must work. Thanks for letting me realize it. The problem if you want to turn your head without the camera's is not an issue with my project. It goes into a larger project where you are stuck into a suit that allows you to control a humanoid from far away :). The person in the suit has video glasses that show both camera's of the robot (giving you 3D sense). Moving your head will give you the feeling of being in the robot's position. I know it is too big for me to start but that is why I just will start with the head control part. And dreaming doesn't hurt!

fliggygeek:
If you are looking for fast .5 degree resolution control, servos arent what you need, you can find some good sized stepper motors that with a 2-1 gear ratio will give you incredibly fast speed and .5 degree or better resolution. these are what they use for CNC mills so you can be sure they're the best option.

I never stood still with the possibility of using stepper motors because I thought using DC motors was the way to walk. Got to check them out, thanks. But I hope I can use my DC motors for something else or for a proof of concept setup. But I need absolute position sensing so I must still use a pot or make some memory/preset function.

To interpret head movement why not use a 3-axis accelerometer chip. This will give you the required three degrees of rotation.
jack

@ jackrae:

I have a mechanical setup in mind that is quite compact and simple.
I have some problems with using accelerometers:

  • I need the orientation (and not the movement) of my head relative to my torso. If I move my whole body (running in all directions) the accelerometer will give values while I keep my head still relative to my torso.
  • The accuracy is not great, I would like to have about 1,5° of accuracy. I think it is not the case with acelerometers.
  • I need a sensor that detects the horizontal plane and measures the difference with its plane relative to the horizontal. I don't know if accelerometers can do that. Which sensors can measure the deviation from the horizontal plane? I know that an Iphone can sense the horizontal.
  • I would like to try mechanical feedback (if you can't move your robot head it should give you the feeling you can't move your head).
  • I must convert the accelerometers data into angles. With my mechanical approach I must only copy-paste the absolute position of the encoder to the robot head. OK once you got the code this is not an issue.

Correct me if I'am wrong, judging with falls information is not a good judge.

UPDATE:

When I use PWM signals at 10kHz the motor makes a small noise but doesn't move. I guess 10kHz is too much for my DC motor?? If that is the case my motors are not good for precision positioning (http://www.pololu.com/catalog/product/1107) and I need other ones, perhaps with a larger gearing? Or what else can make precision positioning possible?? The motor driver can handle 20kHz PWM pulses so no problem with that.

http://www.sparkfun.com/products/9238 Stepper Motor
EasyDriver - Stepper Motor Driver - ROB-12779 - SparkFun Electronics Stepper Driver board (does two steppers)

http://translate.google.com/translate?js=n&prev=_t&hl=en&ie=UTF-8&layout=2&eotf=1&sl=auto&tl=en&u=http%3A%2F%2Flusorobotica.com%2Findex.php%2Ftopic%2C106.0.html Tutorial (Sorry its in translated Portuguese)

Whole setup should cost you no more than $60USD, will get you running in no time.
Use the analog inputs for your continuous rotation pots, the serial for the driver board, you'll be all set.

Great links fliggygeek!

I must make a tough decision now. I consider three choices:

  • continue with what I have and look for a good working PID code. Not sure if I ever can achieve good results but it is the cheapest choice.
  • Use a stepper motor setup (from sparkfun) like fliggygeek proposed. It fits in my budget and looks straightforward and relatively simple to set up and use.
  • Get a Jrk motor controller from Pololu. Here I'am sure about the results (seen a video and goes fast and accurate). The price for a single controller is not cheap but maybe I can use the motors I have.

For the first and third option I doubt that my 131:1 motors are good for it. At high PWM frequency it doesn't move at all (just makes noise). My motor driver looks pretty useless for positioning tasks as long as I don't have good code. Maybe I can sell them!

Thanks everybody for the input. My view on the subject has surely improved and I am reconsidering different aspects of my project (which is good cause I went a bit to fast for a beginner).

"Output loads can be pulse width modulated (PWM-ed) at frequencies up to 20 kHz." got that off your motor driver site, seems the driver IC works, I might suggest getting some cheap DC motors and chuck them on the driver to see if they work at the higher frequency. This will determine if it is an issue with your motors or the driver circuit.

Yes indeed. It can make up to 20kHz PWM signals. But the limitation is the Arduino's PWM frequency limits I think. I don't know how much it is but I use the code below to test the motor at variable pulse width and frequency. Should it work?? Cause I can only get the motor turning (sloooow) at freq= 900 with pusle=850 and freq=1000 with pulse=900 (all in microseconds). If this code is correct its clearly the motor reached its limits (1kHz is too much).

void setup()
{
Serial.begin(9600);
pinMode(13, OUTPUT); //motor B output
pinMode(12, OUTPUT); //motor A output
pinMode(11, OUTPUT); //PWM output
}

void loop()
{
int freq = analogRead(0); //change PWM frequency in microseconds (100 = 10kHz)
int pulse = analogRead(1); //change pulse width in microseconds (1000 = 1kHz)
freq = map(freq, 0, 1023, 50, 1000);
pulse = map(pulse, 0, 1023, 50, 1000);
Serial.print("pulse:"); // use this code so I can check both values during testing
Serial.print(pulse, DEC);
Serial.println();
Serial.print("freq:");
Serial.print(freq, DEC);
digitalWrite(13, LOW);
digitalWrite(12, HIGH);
digitalWrite(11, HIGH);
delayMicroseconds(pulse);
digitalWrite(11, LOW);
delayMicroseconds(freq-pulse);
}

http://www.arduino.cc/playground/Code/PIDLibrary

Just found this, might be of interest to you.

I saw it too, thanks. I didn't try it but know I did. The motor does some strange stuff but that could be due to the constants I used.
I asked my professor of Control Systems class and he too recommended to use stepper motors for my application. They are better for specific angle positioning. So I'll probably get a setup but don't know which one. Personnaly I've been a Pololu customer and they helped me out on the forum so I'll get it there... The A4983 stepper motor driver with the unipolar/bipolar 42x48mm stepper motor is less then 40 dollars and that wil probably the final decision. It is a bit more expensive than Sparkfun's mix. But the motor has a good holding torque which is nice and the driver can deliver more current. Its what they call 'learning money' :).
I'll use my 2 DC motors and dual motor driver for another project (or sell it to a friend)!

Yes indeed. It can make up to 20kHz PWM signals. But the limitation is the Arduino's PWM frequency limits I think.

You can produce 256 levels of PWM at upto 62.5kHz with the ATmega's timers if programmed with divide-by-1 prescale. By default they are set at divide-by-64.

A 'scope may be useful to determine what's going on.

Okay so my motor driver is the limit :). I used a simple method to change PWM frequency (bit-banging PWM - see http://arduino.cc/en/Tutorial/SecretsOfArduinoPWM). I posted the used code earlier. It is probably not efficient but it is all the arduino needs to do. I did not yet tried the timer method.

Thanks