Servo positioning accuracy - suggestions needed

I'm creating a servo-driven laser pointer (left-right,up-down) and I wish to be able to improve the accuracy of motion.

Basically I want to move the servo from once end of it's motion range to the other quickly (which I can already do with the arduino) but repeated runs of this code exhibit slight inconsistencies in the positioning and accuracy of the motion from one run to the next.

I know the servos are not intended for fine-motion but I was wondering if they could at least be physically hacked somehow to get extra position data.

Could interrupts be used somehow to accurately synchronise the motion of the servo to the code running on the arduino?

I've never used interrupts before so I'm not sure if this will help or not. I was thinking of opening up each servo and adding some small home-made sensors to detect when the servo has moved 1 degree.

Any thoughts?

Have you any idea, on the scale of a servo, how tiny one degree is?
Look at your wristwatch.
The gap between 12 o'clock and one minute past is six degrees.
Where do the interrupts come in?
Maybe try limit switches.

Yes it's a small angle certainly.

I shall describe my problem differently...

When the servo is running at full speed in one "smooth" movement from one end to the other, the motion will be fairly consistent. Meanwhile the Arduino is still running it's program - one degree takes about 5 milliseconds according to my calculations. I reckon a usable amount of processing can be done within 5ms.

I figured that a switch cunningly added to the servo somehow - could poke an interrupt so my code on the arduino would be aware of the left-right progress that has been made by the servo.

Am I barking up the wrong tree?

I don't see a problem using your 5ms, why do you?

Any thoughts?

Well, for starters you need to post the servo code you have tested that does/does not work as you like. From my testing hobby servos only have physical resolution of ~425 points in 190 deg of rotation at best. There is also mechanical slop in most hobby servos and usually in the mounting of the gizmo being moved. Servos are also physically limited as to how fast they can move. If you are using incremental moves like in the servo sweep example you always have access to the last incremented position that was sent to the servo.

Richard Crowley said: "Your servo can really move 180 degrees in 9/10 of a second?"

Yes, it's nothing special - just a £13 Futaba one from a 2ch radio kit.

Anyway, to clarify further there are only two positions that I am instructing the servo to go to - zero degrees and 180 degrees. I am not attempting to stop the servo at any other angle whatsoever. 0-->180-->0-->180-->0-->180-->0-->180-->.....

I want certain bits of logic to fire WHILE the servo is constantly moving, those things must only happen when the servo is passing through a given angle.

It so happens that the command to make the servo move returns instantly, allowing my code to do stuff while the servo is rotating.

The problem is that currently I am having to estimate the time that things should happen. This amount of time changes randomly because of things out of my control.

I just need to trigger an interrupt when the servo moves through 1 degree (or smaller if possible).

What about making your own servos with continuous rotation servos and some kind of gear or belt reduction system? Put easy to turn pots or shaft encoders on the axle shaft of each axis so you know the position of the axis. Then just let the Arudino compare the current position of the axis pot with the position you want it to be at and control the motor's speed and direction based on how far it is away from the desired position.

This would give you the positioning accuracy of the servo multiplied by the number of reductions in your gear/belt drive system. Your true accuracy would of course be limited to 1024 positions for each axle, due to the Arduino's ADC limits.

On the other hand, a dual-axis accelerometer placed right on the mount for the "device" (laser diode, mirror, etc.) could give you some more accuracy and save you the hassle of adding pots or shaft encoders to the rig. This would also give you the added benefit of that it could stay on target even if the structural base was moved, say you're holding this whole thing in your hand or it's mounted on a vehicle and you want that dot to stay on target.

I just need to trigger an interrupt when the servo moves through 1 degree (or smaller if possible).

If that is the answer to your issue, then insert one. Have you actually tried/looked at the servo sweep example to see what is going on?

Do you need to stop at a given place or just know you are at that place?

If the former you're out of luck.

If the latter you can fix a shaft encoder to the servo to get the position, this however will not produce an interrupt by itself every degree, you either have to interrupt for every pulse and do the maths in an ISR, or precondition the pulses with another chip.


Rob

Lots of things that "can't be done" happen every day. He's just looking for a solution to one of those problems. Saying it won't work over and over doesn't help.

How about tapping into the wires on the potentiometer in the servo and reading the value to figure out where it's at? I don't know if it would have enough resolution, but it seems like a start. Another idea, although this could be really tricky to fit inside a servo, would be to put a photo-interrupter straddling the teeth on one of the gears inside the servo. This way you would get a pulse out each time it moved one tooth over. By counting the pulses, you could figure out how far it has moved so far.

I was thinking of opening up each servo and adding some small home-made sensors to detect when the servo has moved 1 degree.

Even if you know the position to an infinitesimal fraction of one degree, you do not have the resolution to CONTROL the position to that accuracy.

Seems like a disconnect here between "1 deg." and "infinitesimal fraction of one degree". One might be able to come close to ~1 deg repeatability. I think the simple pots in hobby servos are probably the weak link in repeatable accuracy. The origional poster never posted the code he was using or the hardware mounting the laser. The mechanical setups with the laser may induce slop into the aiming. Anyhow, below are some of the tinkering I've done in the past to see just what a standard hobby servo could do resolution wise.

The best servo resolution that a specific servo can obtain would be by using the myservo.writeMicroseconds(1500); statement. All servos will respond in a range of 1000 to 2000 microseconds, but most have some additional range avalible above and below those standard 'end points'. Not all servos have the same degrees of total travel, 180 degrees is common, so is 120 degrees and some only do 90 degrees. Now if a specific servo will respond to a 1 microsecond change command depends on the quality of the specific servo you are using. Things like gear backlash and quality of feedback pot effect that and quality costs more money in most cases.

Anyway try playing with the myservo.writeMicroseconds(1500); statement and see how repeatable a move can be and how small a moment you can measure. Any limit you find will most likely be with the servo and better servos can be obtained, some called digital servos have much better resolution capablities.

Lefty

Richard, while I'm grateful for your effusive replies, I'd invite you to go back and read reply #8.

Thanks to everyone else also. Most helpful. I have now found a solution to my problem, if it performs satisfactorily in testing then I shall detail the fix in this thread.

looks for another arduino forum

Even if it doesn't work 'satisfactorily', it would be useful to post anyway, for comments on possible improvements.

For what it's worth, I've been looking at a similar problem recently, trying to get smooth motion control for a servo-operated delta robot.

I ended up writing code to manage the servo speed and acceleration myself. I kept track of where I would like the servo to be at any given moment, and every time I went round loop() I would update the servo position using writeMicroseconds().

As long as the motion-control code never requests a speed or acceleration that's outside the servo's physical limits, that gives reasonably smooth motion with a position that is known at all times.

The code is here, if it helps:
http://jarkman.co.uk/catalog/robots/sketchy.htm