Let's Make Robots!

Sensing servo feedback

Hi,

I'm new to this forum, robotics, electronics and microcontrollers, however I have been programming a long time and I'm currently studying computer science.

I recently bought an Arduino board with the purpose of making robots for experimenting with my special interest: AI.

I wish to build a walking robot and experiment with varios ways of giving it a nervous system. So I will need to find a way to get feedback directly from the servos, thereby being able to read the amount of stress (load) they experience at a given time.

So far I thought of 3 ways to do this:

1) The simplest way is connecting the servo output (=the servos ground wire) to an analog in port on the Arduino. My classmate who's into electronics said this was possible if I attached a small resisitor to the Arduino ground. The thing is he said that the Arduino would have a large resistor build in (so to speak) on the analog in. So if I just connected the servo output to the analog in without the resistor I would get no reading cause the electricity would flow into the Arduino ground where there is no resistance. Makes sense. He also calculated that I need a 6 ohm resistor based on the peak current draw of the servos I intend to use (HXT900 = 750mA). I'll try this out soon.

2) I could also use a current sensor (thermistor I believe they're called) to do the same thing, connecting it either to the servos 5V input or the output (not sure how?), and again reading the value from an analog in port. I'll also try this solution.

3) This is the really cool but difficult solution. A servo has build in a potentiometer. There are ways to modify servos so that you can read the position from this potentiomenter. Then one can actually move the servos position MANUALLY and later read it's position. And it can also provide a way of reading the stress of the servo.

Here is a manual on this conversion:

forums.trossenrobotics.com/tutorials/how-to-diy-128/get-position-feedback-from-a-standard-hobby-servo-3279/



So basically I need all the advice/input I can get. Does this sound plausible? Is there a 4th or 5th solution I haven't considered? Anyone has tried something similar? Any ideas would be appreciated...


Aniss1001 :)

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

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 :)

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 your final 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.

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

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

 

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 :)

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..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 :)

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.

To whom it may concern (perhaps FingerTech and Robotologist):

Our little discussion about whether a servo is controlled by PPM or PWM kinda bugged me, so I created a topic on the Arduino forum hoping to get a comment from the guy who wrote the comment I posted earlier. And I did. Here it is:

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1253149521/6#6

 

Aniss