[Beginner] Using a Flex Sensor

Hello everybody ! :slight_smile:

I have a big but (I think) easy problem to solve !

I'm trying very hard to use a Flex Sensor (the "FS7954", Click here to see the datasheet) but I can't figure out where the problem is and I don't even know if it's my circuit or my code that is wrong (or both maybe).

This is my circuit that I've done on Fritzing (I'm using a 10 000 Ohms Resistor) :

And this is 2 photos of my circuit in real life :


It's the same than my Frizting circuit, so the white wire goes to the A0 pin, the Resistor is a 10 kOhms Resistor and I've connected the GND to the "- line" and the 5V to the "+ line" (I'm sorry I don't know the correct terms).

This is the code that I have on my computer (which almost completely comes from SparkFun) :

const int FLEX_PIN = A0; 
const float VCC = 5; 
const float R_DIV = 10000.0; 

const float STRAIGHT_RESISTANCE = 25000; 
const float BEND_RESISTANCE = 125000; 

void setup() 
{
  Serial.begin(9600);
  
  pinMode(FLEX_PIN, INPUT);
  
}

void loop() 
{
  int flexADC = analogRead(FLEX_PIN);
  float flexV = flexADC * VCC / 1023.0;
  float flexR = R_DIV * (VCC / flexV - 1.0);
  Serial.println("Resistance: " + String(flexR) + " ohms");

  float angle = map(flexR, STRAIGHT_RESISTANCE, BEND_RESISTANCE, 0, 90.0);                   
  Serial.println("Bend: " + String(angle) + " degrees");
  Serial.println();

   delay(1000);
}

I have to admit that I don't fully understand the following lines of the code :

float flexV = flexADC * VCC / 1023.0;
float flexR = R_DIV * (VCC / flexV - 1.0);

Here is what the monitor displays when I don't touch my Flex Sensor (so when it is straight) and as you can see I don't have "0 degrees" :

And here is what the monitor displays when I bend the Flex Sensor a lot (between 45 and 90 degrees in my opinion) :

As you can see, it makes no sense !

In my code, I put :

const float STRAIGHT_RESISTANCE = 25000; 
const float BEND_RESISTANCE = 125000;

because on the DataSheet it says that :

By the way, I used the map function because it says on the DataSheet that the Flex Sensor is "linear" so in my opinion a map function is enough (I think that I don't have to find an actual function like an polynomial function that goes through a majority of the points).

So if someone understand what is wrong with my code and/or my circuit, I would love to hear some explanations !

Thanks ! :slight_smile:

map() doesn't take floats (decimal places).

10k fixed resistor is too low for this sensor.
You will have a higher resolution if the fixed resistor is about the same value as the flex sensor's average resistance.
Try 47k.

Why convert to voltage and then to degrees.
Why not convert directly from A/D value to degrees.

Write a simple sketch that just gets/prints A/D values.
Then map that range to 0-90.
Leo..

Hello Wawa and thanks for your answer :slight_smile:

Wawa:
map() doesn't take floats (decimal places).

So I must only use "int" values in the map() ? I guess it won't be a problem !
Should I use constrain() to make sure I don't have out-of-range values ?

Wawa:
10k fixed resistor is too low for this sensor.
You will have a higher resolution if the fixed resistor is about the same value as the flex sensor's average resistance.
Try 47k.

The problem is that I don't have such Resistors, I have only 10.000 Ohms Resistors (I should maybe buy some by the way...).

Wawa:
Why convert to voltage and then to degrees.
Why not convert directly from A/D value to degrees.

Write a simple sketch that just gets/prints A/D values.
Then map that range to 0-90.

You're right it was a dumb idea.
OK so something like that for example ?

const int FLEX_PIN = A0; 
const float VCC = 5; 
const float R_DIV = 10000.0; 

const float STRAIGHT_RESISTANCE = 25000; 
const float BEND_RESISTANCE = 125000; 

void setup() 
{
  Serial.begin(9600);
  
  pinMode(FLEX_PIN, INPUT);  
}

void loop() 
{
  int flexADC = analogRead(FLEX_PIN);
  int angle = map(flexADC, STRAIGHT_RESISTANCE, BEND_RESISTANCE, 0, 90);  
  angle = constrain(angle, 0, 90);                  
  Serial.println("Bend: " + String(angle) + " degrees");
  Serial.println();

   delay(1000);
}

It's too late (I'm from France so it's 1 am right now) for me to test it, but does it seem correct to you ? If yes, I'll try tomorrow morning !

Thanks again ! :slight_smile:

PaulJardin:
Should I use constrain() to make sure I don't have out-of-range values ?

Up to you. I would like to see angles more than 90 or less than 0.

As said, write a simple sketch that shows the A/D values.
See what you're getting, and write them down.

const byte flexPin = A0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  Serial.println(analogRead(flexPin));
  delay(250);
}

Then simply fill in the numbers on xxx and xxx of this sketch.
Try to avoid 'Strings' in the small memory of an Arduino (assuming Uno).
Leo..

const byte flexPin = A0;
int angle;

void setup() {
  Serial.begin(9600);
}

void loop() {
  angle = map(analogRead(flexPin), xxx, xxx, 0, 90);
  //angle = constrain(angle, 0, 90); // optional
  Serial.print("Bend: ");
  Serial.print(angle);
  Serial.println(" degrees");
  delay(1000);
}

or, faster, and without the constant SerialPrints

const byte flexPin = A0;
int newAngle, previousAngle;

void setup() {
  Serial.begin(9600);
}

void loop() {
  newAngle = map(analogRead(flexPin), xxx, xxx, 0, 90);
  newAngle = constrain(newAngle, 0, 90); // optional
  if (newAngle != previousAngle) {
    Serial.print("Bend: ");
    Serial.print(newAngle);
    Serial.println(" degrees");
    previousAngle = newAngle;
  }
}

Thanks Wawa ! :slight_smile:

Wawa:
As said, write a simple sketch that shows the A/D values.
See what you're getting, and write them down.

So I tested your code on a breadboard without anything else and it told me that the values were between 745 (when straight) and 830 (when bent at 90°) ! So that was perfect. I then tested your second code, and it worked perfectly (again, on a breadboard with nothing else on it), the monitor was telling me the right angles every times !

But then, I tried on another Breadboard with more things (because I need for a project to also have a LCD Screen, a 3-Colors LED and some other components that I will add later) and it was complete nonsense. So I tried on this Breadboard to start from scratch in order to get the values between 0 and 1023 for this circuit, but it was strange... It was telling that values are 0 or 1023 (I have a 1 second delay and I wasn't touching my flex sensor, so he was straight the whole time) :

Here is a photo of my circuit (I will later add 3 other Flex Sensor at the right of the first one, I have a LCD Screen functioning perfectly with a Potentiometer, and a 3-Colors LED also functioning very well) :

I think that the part with the LCD Screen and the other stuff is not important, because it works fine, I haven't any problem with that :

This is the part the causes me trouble :

Once again, I don't understand why the code that you gave me to get the A/D Values works perfectly for a simple circuit with nothing else on it like that :

But doesn't work on my circuit and just tells me 0 for approximately ten seconds then 1023 and so on...

By the way, this is the code that I used and that gives me strange values:

const int FLEX_PINA0 = A0; 
int angleA0;
void setup() 
{
  Serial.begin(9600);
}

void loop() 
{
  Serial.println(analogRead(FLEX_PINA0));
  delay(1000);
}

There were other lines on the code (to print some things on the LCD Screen and to blink the LED) but it was all in comments (with "//" so it appears in a grey color in the Sketch) so it doesn't even "count' in my code and the problem doesn't come from that in my opinion.

Thanks ! :slight_smile:

If you want us to be able to read your Serial console output, copy/paste the output and post it between code tags, not as screenshot. Screenshots have their uses, this is not one of them.

That you get 0 and 1023 (i.e. max and min values) implies wiring issue, probably poor connections. A solderless breadboard gives ample opportunity for that to happen, it's one of their specialties.

PaulJardin:
So I tested your code on a breadboard without anything else and it told me that the values were between 745 (when straight) and 830 (when bent at 90°) ! So that was perfect. I then tested your second code, and it worked perfectly (again, on a breadboard with nothing else on it), the monitor was telling me the right angles

You can get a greater range if you take a resistor that's approximately the average value of your flex sensor.

Your flex sensor apparently goes from 27k to 43k; a 33k resistor would give you a range of 458 to 579, that's 121 ADC points instead of 85. Almost 50% better resolution that way.

Hello wvmarie and thanks for your answer !

wvmarle:
If you want us to be able to read your Serial console output, copy/paste the output and post it between code tags, not as screenshot. Screenshots have their uses, this is not one of them.

Ok I'm sorry I didn't know, I will copy and paste the output of my monitor from now on !

wvmarle:
That you get 0 and 1023 (i.e. max and min values) implies wiring issue, probably poor connections. A solderless breadboard gives ample opportunity for that to happen, it's one of their specialties.

Ok so I used new wires (except for the wires that are in the 5V Pin and in the GND Pin, because since my LCD Screen and LED were working, the problem isn't coming from these wires. But here is what my monitor displayed :

693
268
286
304
307
470
662
695
636
542
519
472
263
129
142
220
251
304
531
423
393
359
359
304
172
119
134
236
224
232
315
394
405
393
373

I wasn't touching my flex sensor (it was straight the whole time) so you were right, I had wiring issues, but it looks like I still have another issue !

wvmarle:
You can get a greater range if you take a resistor that's approximately the average value of your flex sensor.

Your flex sensor apparently goes from 27k to 43k; a 33k resistor would give you a range of 458 to 579, that's 121 ADC points instead of 85. Almost 50% better resolution that way.

Just a quick question : How do you know that my sensor goes from 27 kOhms to 43 kOhms ? Because on the DataSheets (I posted it on my first message) it says that it goes from 25 kOhms to 125 kOhms (with a 30% variation).

Thanks for your message !

PaulJardin:
Screen and LED were working, the problem isn't coming from these wires. But here is what my monitor displayed :

That looks like a floating pin. Did you select the correct pin? Code uses A0. Is it connected properly to that pin?

Do check the voltage at the pin with your multimeter.

Just a quick question : How do you know that my sensor goes from 27 kOhms to 43 kOhms ?

Simple calculation. You gave the value for the pull-up resistor and the analog readings, the value of the unknown resistor follows from that. It's even independent of the actual value of Vcc, as it's a ratio.

Thanks for your answer wvmarie :slight_smile:

wvmarle:
That looks like a floating pin. Did you select the correct pin? Code uses A0. Is it connected properly to that pin?

Yes, I'm connected to A0. I tried with the A1 pin (so I changed it in my code and in my circuit), and I had the same kind of numbers displayed in my monitor (again, when my flex sensor is straight) :

434
426
412
394
373
338
335
296
243
222
226
229
238
247
255
294
341
369
376
387
373
356
344
335
327
306
280
256
238
233
232
235

So I don't think that all of my Analog Pin are broken, it would be strange.

wvmarle:
Do check the voltage at the pin with your multimeter.

I don't have a multimeter unfortunately so I'll try to find an easy tutorial to do that on the Web and I'll post the answer as soon as I find the voltage at my A0 pin.

Ok thanks for your answer, I guess that maybe it says that it goes to 125 kOhms but it's when the flex sensor is bent to 180°, and I'm not interested to go that far, 90° is enough for what I want to do, so that's maybe why it "only" goes to 43 kOhms.

Thank you again :slight_smile:

Put a multimeter on your shopping list, without it you're working blind. It's one of the most essential tools for this hobby.

Connect the A0 to GND, and you will see as steady stream of 0. Connect it to 5V, and you see a steady stream of 1023. Connect it to 3.3V and you see a steady stream of about 670.

It seems there's no connection between your flex sensor and your pin. Another thing a multimeter can confirm quickly.

Ok so to get the voltage at my A0 pin here's the circuit I did :

The left wire (the red one) is connected to the "+ line", the right wire (the yellow one) is connected to the "- line" and the middle wire (the blue one) is connected directly to the A0 pin.

Then I wrote the following code :

void setup() {
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(A0);
  float voltage = sensorValue * (5.0 / 1023.0);
  Serial.println(voltage);
  delay(1000);
}

And here's what was displayed on my monitor (while I wasn't touching my potentiometer) :

2.77
2.68
2.73
2.33
2.22
1.52
0.87
1.08
1.32
1.54
2.60
2.59
2.29
2.15
1.38
0.82
1.03
1.26
1.41
2.22
2.01
1.98
1.86
1.76
1.41
1.26
1.23
1.30
1.36
1.61

Isn't it strange that the values goes from 0.82 V to 2.77 V if I wasn't touching anything ? Is it a problem with my A0 pin ?

Thanks :slight_smile:

You see how the red and blue lines along your power rail are interrupted?

No doubt the metal conductor in there does the same. You have to bridge that gap with jumper wires. Quite a common thing for breadboards - they don't all have it and I still haven't found a use for it. You don't have a power connection at the left-hand side of your breadboard, and thus your pin is floating.

Ahahah it's such a dumb mistake !

I didn't even realize that but now that you said that to me it seems obvious !

I'll try and I'll let you know !

Thanks a lot wvmarie (even though I feel stupid right now) :slight_smile:

Thank you wvmarie, that was the problem !

Now everything works, and I've added 3 more flex sensors and they work too !

Thanks for your help :slight_smile:

You're welcome.

And don't feel too stupid... it's a very common mistake, ran into the same problem myself when I just started playing with those breadboards. Luckily most of my breadboards don't have this split halfway.

Hello :slight_smile:

I'm already back for another question ! But this time it will be faster in my opinion. It is about a different sensor so I don't know if I should create another topic but for the moment I'll stay here.

I have to connect an accelerometer (it's the MMA8452Q, but I can't find any Datasheets, on every website when I click on "Datasheet" it shows me a Datasheet of an older model) to my Arduino Uno but I have two questions about the Hook-up.

I've done researches on multiple websites, and the best hook-up guide that I found was on SparkFun.

The MMA8452Q is a 3.3V device so I'll need to do some level-shifting between my Uno and the Accelerometer. They propose on their website two different hook-up.

The first one, which is simple :

And the second one, which is a little bit harder but not too complicated :

I do have the exact same Bi-Directional Logic Level Shifter that they use on the second photo, so that's not a problem for me. They say it's "a more reliable level-shifting setup" than the first one.

So I would like to hear your advices about which setup I should choose for my project !

Thanks again :slight_smile:

Depends on the accelerometer board: does it have level shifters and regulator on board already?

If not, use the second method.

Resistors are not level shifters.

Thanks wvmarie :slight_smile:

wvmarle:
Depends on the accelerometer board: does it have level shifters and regulator on board already?

No it doesn't. So yes I think that I'm going to use the second method (it seems way more reliable).

But I was wondering on this picture, why do the "bottom" wires have white lines on them ? Is this simply to indicate that they have a 3.3V and not 5V ? Or is it something more complicated ?

I guess whoever made this image ran out of colours, or wanted to make it clear they're related but different.

Using bands on a wire is a common way to have more colours available, and indeed they're often related - just look at the colour coding of a UTP cable, each pair is colour and colour/white.

Now you also see why we prefer proper schematics. So much easier to read than this spaghetti type image.

Thanks wvmarle !

I've just finished the hookup and everything works as planned ! :slight_smile:

wvmarle:
Now you also see why we prefer proper schematics. So much easier to read than this spaghetti type image.

Yes that's true, but for a beginner like me it's harder to read the schematics, I don't understand everything !

Thanks anyway !