Flex sensor with Arduino-Help plz!!!

Hey yall

i have a seniors project which im currently working on

Im making a robotic hand which mimics the hand of its user

I’m using 5 flex sensors which control five servos via an arduino uno microcontroller

5V----------

|

Pin 0----- 100K ------ One end of flex sensor---------

| |

| Flex Sensor

| |

Ground-------------------other end of flex sensor-----

this is how i’ve connected the flex sensors to the arduino, now ive got five of theses in different analog pins,

and the servos connected to the digital

my problem is that, when i go to bend the flex sensor the servo rotates the full 180 degrees, but if i want to

stop it at a sertain point in that rotation, say half way, the servo kinda stutters and jolts around and dosnt stay in the place i want it to.

heres the code:

#include <Servo.h>

Servo myservo; // create servo object to control a servo

Servo myservo2;

Servo myservo3;

Servo myservo4;

Servo myservo5;

int potpin = 0; // analog pin used to connect the potentiometer

int potpin2 = 1;

int potpin3 = 2;

int potpin4 = 3;

int potpin5 = 4;

int val; // variable to read the value from the analog pin

void setup()

{

myservo.attach(8); // attaches the servo on pin 9 to the servo object

myservo2.attach(9);

myservo3.attach(10);

myservo4.attach(11);

myservo5.attach(12);

}

void loop()

{

val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)

val= analogRead(potpin2);

val= analogRead(potpin3);

val= analogRead(potpin4);

val= analogRead(potpin5);

val = map(val, 150, 179, 90, 179); // scale it to use it with the servo (value between 0 and 180)

myservo.write(val); // sets the servo position according to the scaled value

myservo2.write(val);

myservo3.write(val);

myservo4.write(val);

myservo5.write(val);

delay(5); // waits for the servo to get there

}

i’ve cut and pasted from codes i’ve found o n the net, and made my own, also the code line val=map( val, 150,179,90,179), i tried to use the smae values as the ones on the example in the arduino libary, val = map(val, 0, 1023, 0, 179)and nothing happened so i messed around with the values and this combo seems to work

can some one please help me,

have i wrote the code wrong?

are my servos or sensors stuffed?

please help

thz

p.s be nice this is my first try at this stuff =D

I can’t quite figure out your schematic… The resistor should connect between +5 and the analog input. The flex sensor between the analog input and ground. You are making a voltage divider here.

As for the code, there are some issues - you are overwriting the values that you read from the ADC, and write the last one to all servos. You will need 5 variables and 5 map() calls (or code it as read_ADC/map/write_servo repeated 5 times).

I would try to split the problem in half to make it easier to debug.

Start by reading the sensor and printing the value to your PC. That will tell you if the wiring and ADC code works.

Then, try driving the servos with fixed values (or a sweep of values using a for() loop) to see

what their ranges are and to make sure you have them wired correctly and your power supply is sufficient to move all at once.

Finally, you can figure out the scaling needed to go from ADC readings to servo positions.

/mike

sorry

for some reason the drwaing of how the flex sensor is connected6 didnt come out

too well, its just one end of the flex sensor connected to ground, and the other connectd to an anaglog

pin and.5v

if u still dont under stand i got it from here

C:\Users\Surath\Desktop\Add a flex sensor.mht

what i still dont get is what u mean by this:

“you are overwriting the values that you read from the ADC, and write the last one to all servos. You will need 5 variables and 5 map() calls (or code it as read_ADC/map/write_servo repeated 5 times).”

what do u mean by ADC?

can u please explain

i’m new to this

cheers

ADC = Analog Digital Converter.

It is the magic piece of hardware that allows AnalogRead to work.

Suggest this:

val1 = analogRead(potpin1);
val1 = map(val1, 150, 179, 90, 179);
val2= analogRead(potpin2);
val2 = map(val2, 150, 179, 90, 179);
val3= analogRead(potpin3);
val3 = map(val3, 150, 179, 90, 179);
val4= analogRead(potpin4);
val4 = map(val4, 150, 179, 90, 179);
val5= analogRead(potpin5);
val5 = map(val5, 150, 179, 90, 179);
myservo1.write(val1);
myservo2.write(val2);
myservo3.write(val3);
myservo4.write(val4);
myservo5.write(val5);

Also suggest powering a large number of servos from a beefier power supply.

Connect the 100k fixed resistor between +5 and the analog input. Also, connect the flex sensor between the same analog input and ground. That will make a voltage divider.

if u still dont under stand i got it from here

C:\Users\Surath\Desktop\Add a flex sensor.mht

No, that's a file on your computer. Nobody else can see it. You would need to either attach the file to the post, or host it on a web server and link to it.

ADC = analog to digital converter (the part of the processor that reads analog values and converts them to digital values)

val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023) 
val= analogRead(potpin2);
val= analogRead(potpin3);
val= analogRead(potpin4);
val= analogRead(potpin5);

This will read potpin, and store the reading in val. Then, it will read potpin2, and overwrite the value in val with the new reading. It will then to the same with potpin3-5. So val will have the reading of potpin5 at the end, which you send to all the servos.

There are two better ways to do this.

val1 = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023) 
val2= analogRead(potpin2);
val3= analogRead(potpin3);
val4= analogRead(potpin4);
val5= analogRead(potpin5);

followed by the appropriate five map() and servo.write() calls

or

val = analogRead(potpin); 
val = map(val, 150, 179, 90, 179); // scale it to use it with the servo (value between 0 and 180) 
myservo.write(val);

repeated for each pot/servo.

/mike

thx to all who replied

but my problems arent over unfortunatley :frowning:

this is my code curently

#include <Servo.h>

Servo myservo; // create servo object to control a servo

Servo myservo2;

Servo myservo3;

Servo myservo4;

Servo myservo5;

int potpin = 0; // analog pin used to connect the potentiometer

int potpin2 = 1;

int potpin3 = 2;

int potpin4 = 3;

int potpin5 = 4;

int val; // variable to read the value from the analog pin

int val2;

int val3;

int val4 ;

int val5;

void setup()

{

myservo.attach(8); // attaches the servo on pin 9 to the servo object

myservo2.attach(9);

myservo3.attach(10);

myservo4.attach(11);

myservo5.attach(12);

}

void loop()

{

val = analogRead(potpin); // reads the value of the potentiometer (value between 0 and 1023)

val = map(val,150,179,90,179);

val2= analogRead(potpin2);

val2 = map(val,150,179,90,179);

val3= analogRead(potpin3);

val3 = map(val,150,179,90,179);

val4= analogRead(potpin4);

val4 = map(val,150,179,90,179);

val5= analogRead(potpin5);

val5 = map(val, 150, 179, 90, 179); // scale it to use it with the servo (value between 0 and 180)

myservo.write(val); // sets the servo position according to the scaled value

myservo2.write(val);

myservo3.write(val);

myservo4.write(val);

myservo5.write(val);

delay(5); // waits for the servo to get there

}

Is this wat u ment or is t still wrong?

the servo works with this code but stilkl stutters at positions within that 180 arc

is the servo stuffed?

what i’ve also noticed is when it stutteres when i try to stop it is a certain position

the on ligh of the arduino flicker constantly, do i need a seperate power source for the servo

remember with this code, i only hooked up one servo to try ount not all 5

cheers

p.s sorry about the message errors, i thought i pasted the page url…woops :wink:

and is there anyway i can upload a video to this site?, then i can realy get my message across

Closer…

Try this (I just modified your code; I don’t have an Arduino to try this out on…)

#include <Servo.h> 

Servo myservo1; // create servo object to control a servo 
Servo myservo2; 
Servo myservo3;
Servo myservo4;
Servo myservo5;

int potpin1 = 0; // analog pin used to connect the potentiometer
int potpin2 = 1;
int potpin3 = 2;
int potpin4 = 3;
int potpin5 = 4;
int val1; // variable to read the value from the analog pin 
int val2; 
int val3;
int val4 ; 
int val5;

void setup() 
{ 
    myservo1.attach(8); // attaches the servo on pin 9 to the servo object 
    myservo2.attach(9);
    myservo3.attach(10);
    myservo4.attach(11);
    myservo5.attach(12);
}

void loop() 
{ 
    val1 = analogRead(potpin1); // reads the value of the potentiometer (value between 0 and 1023) 
    val1 = map(val1,150,179,90,179);
    val2 = analogRead(potpin2);
    val2 = map(val2,150,179,90,179);
    val3 = analogRead(potpin3);
    val3 = map(val3,150,179,90,179);
    val4 = analogRead(potpin4);
    val4 = map(val4,150,179,90,179);
    val5 = analogRead(potpin5); 
    val5 = map(val5, 150, 179, 90, 179); // scale it to use it with the servo (value between 0 and 180) 
    myservo1.write(val1); // sets the servo position according to the scaled value 
    myservo2.write(val2); 
    myservo3.write(val3);
    myservo4.write(val4);
    myservo5.write(val5);
    delay(5); // waits for the servo to get there 
}

The stuttering and blinking power light tells me that your power supply can’t supply enough current. Are you trying to power the servos from the 5V regulator on the Arduino? I doubt that will be able to supply enough current. You will need a separate supply for the servos (4 D-cells in series will work for testing if you don’t have a bench supply handy). Connect the ground or negative of the new supply to the ground of the Arduino, and the positive of the supply to the servo power pins.

/mike

Anticipating the next problem… Once you solve the power supply issue and the power LEDs stop blinking, you will find that the servos will always likely be hunting. They may not move a lot, but they will always be buzzing even if your hand is still. The issue will be that the ADCs will be returning different values just from tiny changes as your hand moves even when ‘still’. The hunting over time will lower the life span of the servos. For the short term it will not be a problem unless you find the noise objectionable. One possible solution is to add some hysteresis or a simple time lag filter.

Wooooot

fil-freak, i realised that the servo will be hunting even with the hand at rest, but thats just some thing i’m gonna have to live with

i’m gonna try and solve the power issure now

n1ist

OMG i LOVE UUU!!!

thx for the mod code, works a treat

owe u one :wink:

just gotta sovle the power problem now

probs been a paint in the rear end, casue i’m such a noob at this

but thax to evey one who replied

cheers

T3rminator

I’ve thought of trying a similar project and thought of the same problem. What is happening is as mentioned in a previous post… the ADC will be returning the minute differences with each reading… this is from minute muscle twitch and electrical noise. My suggestion is creating a “Dead Band” how you would do this is in your code.

What this will do is compare the current position or value to a new one, by doing this the code can determine how much you’ve moved your finger… if its alot then it will move the servo, if its minute due to muscle twitch or electrical noise then it will stay at it’s last position without jitter. The outline below is for one servo, but all you need to do is get one servo working and then expand the code to do the same for all 5.

Step 1: Initialize and Read ADC value and then position servo accordingly.

Step 2: On all subsequent reads of the ADC compare the new value of the ADC to the old and use a if statement to decide if there is a significant change in position… a general block might look something like this:

Read ADC // Get ADC reading

ADC = newValue // save value

move_Servo(newValue); // Servo control function

oldValue = newValue // save current value into oldValue for comparison for next read

Read ADC // Get next ADC reading

if((newValue - oldValue) > deadBand) OR (newValue - oldValue) < deadBand)) // if newValue has a difference greater than or less than the dead band then move

{

move_Servo(newValue):

}

Remember this is a general outline… you’ll need to find the actual syntax commands to apply… such as the OR in the if statement… I believe it’s “^” but check to make sure… let me know how this works.

Correction…

Considerations:

  1. Deadband

  2. Drift

  3. Updating servo with new value

Thoughts:

  1. What we want to do is eliminate the electrical noise and minute muscle twitch. As the ADC will pick both of these up we must compensate in software. This is where our deadband comes in play. It allows us to dictate the amount of change that must be registered before reacting. In this way electrical noise and muscle twitching will be ignored.

  2. Drift will occur if our reads continually compare the new value to the old value. Think of it like this. Is it possible to move your fingures ever so slightly and slowly that the difference between each read of the ADC is less than our deadband, but still drifting slightly away from the current servo position, so that overtime our servo position no longer reflects our finger position?

Example…

Deadband = 20

newValue = 150

oldValue = 140

according to the if statement there is no signigicant change… however if we constantly update the oldValue based on the newValue you will then get this next time

oldValue = 150… and say the newValue now equals 160

newValue = 160

Still no significant change… again if we continue to update the oldValue based on the newValue we may again get the same situation

oldValue = 160

newValue = 170

Still no significant change… so our servo has not budged a single bit… however compare the current position to the new value and what do you get

170(newValue) - 140(value where we started and where the servo is holding)

that difference is 30… well above our deadband, but the value has been allowed to accumulate drift, so our servo is still in the initial position.

To get rid of this we need update the oldValue ONLY when the deadband range is exceeded. This way ALL new reads of the ADC are compared to the current position of the servo.

  1. Unless we exceed the deadBand range we update the servo control function(running in an isr called every 20ms, 16 bit timer would be ideal) with the last value each time through the program. When the range is exceeded we feed it the new value.

So perhaps a better outline would be:

const char DeadBand = 20; // Dead band range constant

int newValue = 0; // value of the most recent ADC read

int currentValue = 0; // Value of the current ADC value used to hold current servo position

void isr routine(void)

{

// insert code to give desired pulse width based on currentValue variable (timer0 would be ideal here)

}

void main()

{

//setup hardware

Read ADC // Get initial position of flex sensor

currentValue = ADC // save to currentValue variable

// Configure TMR1 to call interrupt isr every 20ms

while(1) // Do forever

{

Read ADC

newValue = ADC // save ADC read to new variable

if ( ((newValue - currentValue) > deadBand) ^ ((currentValue - newValue) > deadBand))

{

currentValue = newValue // update servo position value

}

}

}

Again this is a very rough outline, but I hope it gives you the general gist…