Sensing servo feedback

PWM vs PPM

Hello Aniss1001,

Duty cycle, in a repeating signal, the duty cycle is the percentage of the period which the signal is a high (on, a 1 what ever). Sof 50% (50/50) the signal is a high for half the time.

Modulation, refers to the method of encoding the signal on the carry, for example Amplitude Modulation (AM) Radio encodes the signal by increasting and decreasting the ampliture of the carrier. So PWM is just stating that the signal (servo position) is encoded by the width of the pulse (1 to 2ms).

I think the above explanation is splitting hairs and is not quite right.

The statement that PWM varies the duty cycle is true, sort of but this depends on keeping the pulse interval constant, it is not necessary to keep the pulse interval constant. PWM VARIES THE WIDTH OF THE PULSE. I think the author is thinking of PWM control of motors.

Servos are very tollerant of the pulse interval, my servos only start to play up if I get much faster than 10ms and slower than 70ms, I have a servo tester built with a 555, I can vary the pulse interval and duration, if the pulse interval stays at >10 <70 only the pulse duration (width) changes the postion.

So If I can vary the interval between pulse, then the pulse position has little to do with the servo output position. So I would not call it pulse position modulation.

If I vary the width of the pulse the output position changes, so I would personally call it PWM.

An the Signetics Databook (real paper!) calls it PWM.

Anyway it is a bit of a simantic argument, if you keep the pulse interval to >10 & < 70ms and the pulse duration between 1 and 2ms, your servos will be happy.

all the best CW

The OpenServo modification
The OpenServo modification he made might rely on last position sent, but regular servos will only seek a position that is being updated every 20 ms or so. Stopping update pulses will cause the servo to go slack, not seek a position.

Thanks

That’s what I thought…

And as promised I’m out of questions…for the time being :slight_smile:

 

Aniss1001… over and out

Hi again cwignell


Hi again cwignell (and anyone who wish to contribute),

I’ve been looking at your solutions trying to understand them the best I can with my limited knowledge of electronics.

I tend to like the “low side” solution best because:

1) It’s simpler. Easier to understand and has less components/resistors.

2) It seems easier to combine with an analog multiplexer (to measure the current draw of several servos from 1 analog input).

3) It seems similar to my ORIGINAL idea I mentioned as option 1 in the topic description.

Here is a diagram of that idea:

img005.jpg

However this option has now been dumped because I was told it would cause servo noise. But the "low side" solution is basically the same just with a smaller resistor (I was told 0.1 Ohm would be appropriate) and the op amp. So I made a new drawing including the multiplexer, based on your "low side" solution (as well as others I've seen). Here it is:


img006.jpg



I added 3 servos in the drawing but in reality I’ll be using 12, so I’ll probably use a 16 channel analog multiplexer like this one.


Questions:

Does this seem possible? What kind/size of resistors will I have to use as R1 and R2 given that the servos use 5V, the Arduino analog in can measure from 0V to 5V and the peak current draw of the servos I’m gonna use is ~750mA? Would it be easier/better to use a (hall effect) current sensor IC like this one (still using a multiplexer)?


And then you lost me when you said: “Now the trap, the servo motors are reversable, so in one direction the shunt is on the low side and the other way the high side”. Are you sure you’re not refferring to DC motors? I don’t think servos are reversable?!


Best wishes

Aniss

PS: Please note that the diagrams are incomplete as I left of the digital outs (from Arduino) that control the servos as well as the multiplexer…

Well…

Well the discussion is still ongoing on the Arduino forum. However I decided just to call it servo signals/pulses from now on and leave it at that :slight_smile:

But the author is DEFINATELY refferring to standard SERVOS. And perhaps he has a point (however nitpicky it may be)…

Quote from wikipedia: “PWM of a signal or power source involves the modulation of its duty cycle”.

Quote from the author of the previous statement: “Are you aware that a servo can be operated correctly over its full range without altering the duty cycle of the control signal? If servo control can be achieved without modulating the duty cycle then PWM would seem a poor choice for describing its encoding”.

Low Side Servo Feedback

Hi (again ;-),

Measuring across the entire servo means you don’t have to worry about the motor reversing, the current will alway flow neg to positive. I was refering to DC motors, the tecnique is normally used across DC motors. But I suppose we can treat the enire servo as a DC motor.

Yes 6ohm is too high, if you feed the servos with 5V, 6ohm would result in ~3V which would cause a couple of problems.

First the servo need a little more than 3Volts across for the onboard regulator to work,

Second, we push the servo’s ground up, it is the reference for the signal and I think you might run in to problems here; also the 0 signal level will be below the servo ground, a lot of digital gates do not like the level to be pulled below ground.

For these reasons I would be inclind to go high side measurement, this has the advantage that the ground never changes so 2 is not a problem. But with a 0.1Omh shunt it probably wont be a problem.

So 0.1 Ohm is a good choice, with an Opamp you can adust the gain to get a nice full range (0-5V) signal although you may need to much around to match the gain to the servo performance.

You are going to have to do a bit of testing, running the servo and looking at the results so you can understand the Load vs Current, Starting currents etc, this may require you to expect a high start current and then a decreasing current until you hit something. You might even see little current pulses conenciding with the signal pulses; I am not sure how apparent these will be.

best regards

CW

Thanks

Thanks for all you advice…it’s all being taken under consideration.

However the pole shifting is going on INSIDE the servo. It’s all being taken care of by the servo’s motor controller. So I don’t have to worry about that. And I very much doubt you can treat it like a DC motor. In fact I think it’ll destroy the servo if one tried.

But you were on to something. Just read on the Arduino forum that a guy using a similar setup reported erratic readings (high current draw peaks) whenever a servo changes direction.

 

Regards

Aniss

Hmmm…

Hmm…the more I look at the original circuit…

lowside.jpg

...vs. my multiplexed one...

img006.jpg

...the more I think it's all wrong. The thing is..in the original the low side of a single sense resistor is being fed to the op amp's negative input. While in my version the low side of ALL the sense resistors are being fed to ditto.

I'm no wiz (as ya'll should know by now) but I can't help thinking this will mess up the readings? Perhaps I'm wrong. I hope so, but I did come up with a new circuit using 2 multiplexers. It also includes two 0.1uf capacitors that I was adviced to add for less noisy readings...

img008S.jpg

Any opinions on this?

 

Best wishes

Aniss

Hmmmm part 2

Hi Aniss1001,

You don’t need the bottom Mux (2), the connections to this mux will always be at ground, thus it wont matter which is selecte so get rid of it. The caps are ok they will by pass the hi-freq stuff. but other than that should be ok

 

COOL!

That’s good news (about mux 2). It was getting rather complicated. I just couldn’t help thinking it would be better to feed the op amp with a matching high+low side of one sense resistor at a time…

But I’m glad I don’t have to go there.

Thanks for a VERY quick answer :slight_smile:

Technically the original
Technically the original multiplexed circuit is already connected to both side of the sense resistors; the multiplexer connects the (+) OpAmp input to the high-side of the resistor, and the (-) OpAmp input is always connected to ground, which is the same point the low-side of the sense resistors are connected to.

Well…

Well…I have a similar topic running on the Arduino forum (I need all the input I can get). A guy who’s running a similar setup (though he used several op amps BEFORE the MUX) said:

The current signal is pretty noisy when the motor is switching directions though. That is coupling into other A/D signals at the moment.

In other words the outputs from the different servos are interferring with each other. I was trying to figure out a way to avoid this. Still don’t quite understand why the 2 MUX solution isn’t better in that sense. BUT I believe you guys when you say it :slight_smile:

The 2 MUX solution is

The 2 MUX solution is redundant because the 2nd MUX takes 3 identical inputs and spits them back out again. Having the OpAmps before the MUX is totally different because each OpAmp needs to be connected to ground.

If you want to cut back on noise you should consider dropping a few caps on the signal lines to cut out high-frequency interference, and maybe put a larger cap on the supply line to reduce voltage sag when the motors pull a large current (ie: when stalling or changing direction suddenly).
Additionally you can reduce inductive interference by keeping your wires as short as possible, especially your signal wires. If it is realistic to do so you should also keep the signal wires away from the high current motor wires.

If you note my first comment

If you note my first comment on this, I do acknowledge that the signal between the radio and the receiver can be PPM. However the signal(s) that come out of the receiver to drive the servos is PWM. The servos change position based on the width of the pulse from the receiver (or controlling electronics), not on when the pulse occurs. The radio transmitter sends out a series of pulses in a train over a specified frequency. The receiver can then decode from the position of the pulses which servo is being commanded to properly route the right pulse width it to the right servo. So with the radio control set-up, the PPM exists in the signal transmitted to the receiver and PWM exists from the receiver to each servo.

And yes, a servo can be operated over it’s entire range without changing duty cycle but by changing the frequency of the signal being sent. Servo electronics are somewhat forgiving in the range of frequencies they will accept a pulse width. However, to change the frequency of pulse delivery also changes the servo response (faster pulse repetition means quicker response, more torque) as well as the way a micro can be programmed. In some cases you have to change both the frequency and duty cycle in programming to get this to occur, as the electronics are such that the primary (frequency) being adjusted requires the secondary (duty cycle) to be adjusted before any signal is output. If you want your servo to go as quickly and powerfully to a wide pulse position as to a narrow pulse position, then chaning the width rather than the frequency is the best method.

Progress :slight_smile:

Finally got hold of some small resistors and had some time to set it up. I tried the original setup (no op amp) with respectively 0.26 and 0.51 Ohm resistors. It actually works pretty well :slight_smile:

Here is a reading using a 0.51 Ohm resistor (which doesn’t seem to affect the servos performance):

scope_100_blue_millis_small.jpg

Here is a reading where I'm inhibiting the servo's movement by force:

scope_100_blue_stress_small.jpg

As you can see it's fairly easy to see that SOMETHING is wrong in the 2nd. Not bad for a low tech solution using only A RESISTOR!!

The servo moves from 5 to 175 degrees (or reverse) every 2 secs. Im currently reading from the ADC as fast as possible, and everytime I have 100 values I calculate the average and send the result by serial to my PC. This seems to smoothen out noise as well as it limits the amount of data sent by serial. Even so the serial can't keep up allthough I'm running it at max speed: 114200 BAUD. I'll keep experimenting but so far I'm a happy man :) This was an important step towards creating a robotic nervous system.

Thanks again to everybody for contributing with info and in particular to clcheunghk and cwignel...

 

Aniss

PS: If anyone is interested I'll post the code used and/or provide more info.

Yes, please. Your code and
Yes, please. Your code and your final circuit.

Code and circuit

The setup I’m running now is my original idea BUT with a much smaller resistor. Here is the circuit:

img005s.jpg

The resistor I'm using now is 0.51 Ohm. A 6 Ohm resistor will not work since it will slow the servo down too much. Perhaps it wont even move. Otherwise it's the same. With the smaller resistor I don't get the full resolution, however enough to get useful readings.

Here is the Arduino test code:

#include <Servo.h>

#define SERVOPIN 6
#define ADCPIN 4
#define AVERAGE 100
#define FREQUENCY 2000

Servo myservo;
unsigned long mytime;
unsigned int val;
unsigned int i = 0;
unsigned int vals[AVERAGE];

void setup()
{
Serial.begin(115200);

myservo.attach(SERVOPIN);
delay(1000);
myservo.write(5);
delay(1000);
}

void loop()
{
mytime = millis();

if(myservo.read() == 5) myservo.write(175);
else myservo.write(5);

while(millis() < (mytime+FREQUENCY)) {
val=analogRead(ADCPIN);
vals[i] = val;
i++;

if(i == (AVERAGE-1)) {
val = 0;
for(i=0; i<AVERAGE; i++) val+= vals[i];
val = val/AVERAGE;
i = 0;

Serial.print(0xff, BYTE);
Serial.print((val >> 8) & 0xff, BYTE);
Serial.print(val & 0xff, BYTE);
}
}
}

The Processing code is a slightly modified version of the Arduino oscilloscope. It receives the data from the serial port and draws the waveforms. Here is that code:

import processing.serial.*;

Serial port;
int val;
int[] values;

void setup()
{
size(1024, 480);
port = new Serial(this, Serial.list()[1], 115200);
values = new int[width];
smooth();
}

int getY(int val) {
return (int)(val / 1023.0f * height) - 1;
}

void draw()
{
while (port.available() >= 3) {
if (port.read() == 0xff) {
val = (port.read() << 8) | (port.read());
println(val);
}
}
for (int i=0; i<width-1; i++) values[i] = values[i+1];
values[width-1] = val*10;
background(0);
stroke(255);
for (int x=1; x<width; x++) {
line(width-x, height-1-getY(values[x-1]),
width-1-x, height-1-getY(values[x]));
}
}

Please not that Processing is RIDICULOUSLY slow so even though the readings are made in realtime the waveforms are delayed, and sometimes it messes up completely. When I get time I'll find/write a similar solution using C# or C++ for better performance.