Software > Software

Force sensing with servo current

(1/2) > >>

happy_hippo:
Hello, I would like to add some basic sensing capability to my robot. In particular measuring the force on each leg of my robot, for example if there is a hill/obstacle. One option would be to buy some kind of force sensors and attach them to the legs, but I was wondering if there is any way to get a feel of the current running though the servos from Webbotlib? And software?
Thanks

P.S. I got AXON 2 and 18 servos on my hexapod robot

P.S.2 Other advice I got is to get 12 shunt resistors, put them in series to the servos and connect to ADC on the AXON to measure the voltage drop. Then I can get the current from I = V/R . This should be cheap.

mikevlz:
another option is to use IR-pairs that would work as length-meters/range-sensors on each leg. You will know, how far is each leg from the floor. It will be cheaper than force-sensors.
But all the options use ADC.
By the way, if servo breaks, it can stuck in a wrong position, so you'll think, that you are climbing the wall, but it's only broken servo.

waltr:
this could work with some additional circuits (op-amps, filters) and some algorithms that can determine when the servo's current draw is from an increased load verse when it is commanded to move (srevos do draw high currents when moving).
 
Search the forums her for current limiting circuits. There is a current thread that has been discussing the circuit required to sense a motor current. This is exactly what you will need plus a good bit of experimentation and coding.
In all this should be a fun project in which you will learn a lot.

jwatte:
Current sensors seem reasonable. You probably want very low resistance resistors (0.1 Ohm or less) to avoid too much voltage drop. That, in turn, means you probably want an instrumentation amp to actually buffer and amplify the difference. And, unless you want to create a ground reference problem for the PWM signal, you want the sense resistor to be at the top of the power rail, rather than on the return ground rail, so you have a voltage offset to deal with (instrument amps do this for you.)

Another option is the ACS based current sensors (or something like them) which are Hall effect based, and don't drop the voltage noticeably. Pololu has some nice carriers, such as this one: http://www.pololu.com/catalog/product/1185

happy_hippo:
Great news ! I was able to do it and it works reasonably well: it gives an indication of how much force is applied to a servo.
I put a 0.2 Ohm resistor (later changed to 0.1 Ohm, works too) in series with the servo GND lead (black). Then I connected the terminal of the resistor opposite from the ground to the ADC input (not GNR and not 5V).

I then sampled the reading in mV from the ADC every 1 microsecond "ADC conversion time step" (~60us) for 100 microseconds steps for 1) No Load 2) some load 3) higher load. These are shown on the attached graph.

I then wrote some code to find the pulse width. This looks like in the range from 0 to 50 microseconds samplings. So, I wrote some code to say that 0 is 0% load and 50 is 100% load.

Now, if I don't touch the servo it shows 0, if I slightly touch it I get 15-30% load, if I push it get 70-90% load. Probably the precision is about 10%, but it's difficult to distinguish. For my application I want to distinguish between say 20% and 90%, so this is all great.

Code is attached below, I hope it will be useful for someone as replacement of EXPENSIVE force sensors.


--- Code: ---if (tempbyte=='a')
{
int adc[100]; int cn1; int servo_load=0;

        //take the reading : 100 readings, 1 microsecond each, save in array adc
for (cn1=0; cn1<100; cn1=cn1+1)
{
adc[cn1]=a2dReadMv(ADC0);
delay_ms(0.001);

}


      //let's find the first pulse, i.e. non-zero area. And measure how long it is. For my setup, longest is about 50 us, so I make 50 us -> 100 % load
cn1=0;
if (adc[cn1]==0)
{
while (adc[cn1]==0)
{
cn1=cn1+1;
}

while (adc[cn1]>0)
{
servo_load=servo_load+1;
cn1=cn1+1;
}


}
else
{
while (adc[cn1]>0)
{
cn1=cn1+1;
}

while (adc[cn1]==0)
{
cn1=cn1+1;
}

while (adc[cn1]>0)
{
servo_load=servo_load+1;
cn1=cn1+1;
}

}

printf("Servo load is %d, \r", servo_load*2);
--- End code ---

Navigation

[0] Message Index

[#] Next page

Go to full version