Sensing A Bend With A Flex Sensor + Arduino

Friday, November 23 rd , 2012

We spend so much time talking about sensing things less mechanical, that is is easy to forget the accelerometer isnt the only part in town. The flex sensor is one of those parts often overlooked by the advanced user. But what if you need to check if something bent? Like a finger, or a doll arm. (A lot of toy prototypes seem to have this need).

Anytime you need to detect a flex, or bend, a flex sensor is probably the part for you. They come in a few different sizes ( small, large).

The flex sensor is basically a variable resistor that reacts to bends. Unbent it measures about 22KΩ, to 40KΩ when bend 180º. Note that the bend is only detected in one direction and the reading can be a bit shaky, so you will have best results detecting changes of at least 10º.

Also, make sure you don’t bend the sensor at the base as it wont register as a change, and could break the leads. I always tape some thick board to the base of it to make it wont bend there.

Hooking it up, and why

The flex sensor changes its resistance when flexed so we can measure that change using one of the Arduino’s analog pins. But to do that we need a fixed resistor (not changing) that we can use for that comparison (We are using a 22K resistor). This is called a voltage divider and divides the 5v between the flex sensor and the resistor.

The analog read on your arduino is basically a voltage meter. at 5V (its max) it would read 1023, and at 0v it read 0. So we can measure how much voltage is on the flex sensor using the analogRead and we have our reading.

The amount of that 5V that each part gets is proportional to its resistance. So if the the flex sensor and the resistor have the same resistance, the 5V is split evenly (2.5V) to each part. (analog reading of 512)

Just pretend that the the sensor was reading only 1.1K of resistance, the 22K resistor is going to soak up 20 times as much of that 5V. So the flex sensor would only get .23V. (analog reading of 46)

And if we roll the flex sensor around a tibe, the flex sensor may be 40K or resistance, so the flex sensor will soak up 1.8 times as much of that 5V as the 22K resistor. So the flex sensor would get 3V. (analog reading of 614)

Code

The arduino code for this just could not be easier. We are adding some serial prints and delays to it just so you can easily see the readings, but they dont need to be there if you dont need them.

In my tests I was getting a reading on the arduino between 512, and 614. So the range isnt the best. But using the map() function, you can convert that to a larger range.

int flexSensorPin = A0; //analog pin 0

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

void loop(){
int flexSensorReading = analogRead(flexSensorPin);

Serial.println(flexSensorReading);

//In my tests I was getting a reading on the arduino between 512, and 614.
//Using map(), you can convert that to a larger range like 0-100.
int flex0to100 = map(flexSensorReading, 512, 614, 0, 100);
Serial.println(flex0to100);

delay(250); //just here to slow down the output for easier reading
}

Simple Light Reading With LDR + Arduino

Friday, November 23 rd , 2012

The LDR (light dependent resistor) also know as the Photo-resistor (and many other things) is supposed to be day 1 of electronics. But I guess I missed the note because I never used one with my arduino maybe until now. So I guess I’m weird. But the LDR is super cheap, probably one of the easiest parts to find / use, and certainly has to have the simplest code. You can find these at any electronics store ever I imagine, or do what I did and add a few to your next sparkfun order.

If you need precise light measurement check out the TEMT6000 or the TSL230R

The LDR / Photo-resistor is basically a very simple light sensor that changes its resistance with light, lowering with more light. You can find these used in everything from the furby to automatic night lights and things like that. The LDR isn’t very precise, so you cant get a quantitative LUX reading or anything like that. But it is good enough to tell the difference between light and shadow, or know if the light in your room is on/off. So if you just need to know if the light in the room has changed, or someone walked by (casting a shadow) this is your part.

Hooking it up, and why

The LDR changes its resistance with light so we can measure that change using one of the Arduino’s analog pins. But to do that we need a fixed resistor (not changing) that we can use for that comparison (We are using a 10K resistor). This is called a voltage divider and divides the 5v between the LDR and the resistor. Then we measure how much voltage is on the LDR using the analog read on your arduino, and we have our reading. The amount of that 5V that each part gets is proportional to its resistance.

With the arduino analogRead, at 5V (its max) it would read 1023, and at 0v it read 0.

So if the the LDR and the resistor have the same resistance, the 5V is split evenly (2.5V), to each part. (analogRead of 512)

But if the LDR is hit with a ton of light and is reading only 1K of resistance, the 10K resistor is going to soak up 10 times as much of that 5V. So the LDR would only get .45V (analogRead of 92).

And if it is in a dark room, the LDR may be 40K or resistance, so the LDR will soak up 4 times as much of that 5V as the 10K resistor. So the LDR would get 4V (analogRead of 818).

Code

The arduino code for this just could not be easier. We are adding some serial prints and delays to it just so you can easily see the readings, but they dont need to be there if you dont need them.

int LDR_Pin = A0; //analog pin 0

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

void loop(){
int LDRReading = analogRead(LDR_Pin);

Serial.println(LDRReading);
delay(250); //just here to slow down the output for easier reading
}

Rotary Encoder + Arduino

Thursday, August 2 nd , 2012

One of the first things anyone does when they start working with the Arduino is to connect it to a potentiometer and control the brightness of and LED or move a servo. Well, a rotary encoder may look like a potentiometer, but other than also having a knob, it is basically the complete opposite.

A rotary encoder is a device that you can rotate infinitely. Simple ones like this one I got from sparkfun have no real state like a pot does, so when you start up, you won’t be able to simply read from the encoder where it is turned to. But because you can keep turning it it has no beginning, middle or end anyways. However, if you keep track of that rotation in code, you can use it as a knob input you can turn up or down as much as you would like.

On most rotary encoders, when you rotate them, you will feel a bump. These are known as steps, and most rotary encoders like this guy have about 12 of these per rotation. But some have 200 or more. Basically this step is the minimum amount you can rotate the encoder to register any change.

Most simple encoders like this only make use of 3 pins, and one of those is ground. Those other two pins change state and are always either high or low, so they can only have a total of 4 combinations. 00, 01, 10, and 11. This is known as 2 bit gray code. So when you turn it, the arduino can say… Well you were at 01, and now you are at 00 so you move this way. Or you were at 01, but now you are at 10 so you must have moved the other way. You can see that this encoder has 5 pins, the other 2 are just a simple switch that is engaged when you press down. (see the second illustration on the right)

It sounds super simple, and it kinda is, but what we can do is every time a value changes we can check what direction it moved. Then if we increment a value every time it turned one way, and deincrement it when we move one step the other, we can keep track of how much it has moved since we started. So if you want a knob that can turn up to 11, this is your guy. (there is a double pun in there I promise)

So, the really funky thing about a rotary encoder is for it to work, we need to know every time those values change. This can be hard because if the arduino is in the middle of doing something, like delay(1000) or what have you, we will miss the change. So we need a way to say to the arduino “I don’t care what you are doing, or when you are doing it, if you see any of these two pins change state, you drop everything and attend to them”. To do this we need something called interrupts.

Hookup for just the encoder without the integrated pushbutton

Hookup for encoder and the integrated pushbutton

Interrupts Are Magic

Interrupt pins are special pins that can stop your arduino and force it to do something else before it moves on. Because they are special pins you only get a few of them on your arduino, but these pins can watch for any CHANGE (high to low / low to high), FALLING (high to low) or RISING (low to high). You can attach interrupt functions to these pins, so if a change happens, it will drop everything and run that function. It gets funky as it breaks the basic linear nature of the arduino loop, but can become the most powerful thing when you get the hang of it.

Any global variables that are used inside these functions have a special name. They are called volatile variables, and for good reason. Their values can change at any time. So if you use a volatile twice in your loop, it may not be the same value the second time if it was change during an interrupt function.

Code

To keep track of the rotary encoder we are going to do something that will look really weird, so bear with me. The encoder has 2 digital pins that are either HIGH (1) or LOW (0) right? If we treat the pins as binary, we read them as 00, 01, 10, or 11. The sequence the encoder outputs while spinning clockwise is 00, 01, 11, 10 repeat. So if you have a reading of 01, the next reading can either be 00 or 11 depending on the direction the knob is turned. So by adding the previous encoded value to the beginning of the current encoded value we get 1 of 8 possible numbers (0001, 0010, 0100, 0111, 1000, 1011, 1110 & 1101) 1101, 0100, 0010 & 1011 all mean cockwise movement. 1110, 0111, 0001 & 1000 are all counter-clockwise.

So now we can say this: (sum is last reading + current reading)

if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; //clockwise movement
if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; //counter-clockwise movement

If we wanted to treat the binary as decimal numbers we could even shorten that to this:

if(sum == 13 || sum == 4 || sum == 2 || sum == 11) encoderValue ++;
if(sum == 14 || sum == 7 || sum == 1 || sum == 8 ) encoderValue --;

Without pushbutton code


//From bildr article: http://bildr.org/2012/08/rotary-encoder-arduino/

//these pins can not be changed 2/3 are special pins
int encoderPin1 = 2;
int encoderPin2 = 3;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

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

pinMode(encoderPin1, INPUT);
pinMode(encoderPin2, INPUT);

digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

//call updateEncoder() when any high/low changed seen
//on interrupt 0 (pin 2), or interrupt 1 (pin 3)
attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);

}

void loop(){
//Do stuff here

Serial.println(encoderValue);
delay(1000); //just here to slow down the output, and show it will work even during a delay
}

void updateEncoder(){
int MSB = digitalRead(encoderPin1); //MSB = most significant bit
int LSB = digitalRead(encoderPin2); //LSB = least significant bit

int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; lastEncoded = encoded; //store this value for next time }

With pushbutton code


//From bildr article: http://bildr.org/2012/08/rotary-encoder-arduino/

//these pins can not be changed 2/3 are special pins
int encoderPin1 = 2;
int encoderPin2 = 3;
int encoderSwitchPin = 4; //push button switch

volatile int lastEncoded = 0;
volatile long encoderValue = 0;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

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

pinMode(encoderPin1, INPUT);
pinMode(encoderPin2, INPUT);

pinMode(encoderSwitchPin, INPUT);

digitalWrite(encoderPin1, HIGH); //turn pullup resistor on
digitalWrite(encoderPin2, HIGH); //turn pullup resistor on

digitalWrite(encoderSwitchPin, HIGH); //turn pullup resistor on

//call updateEncoder() when any high/low changed seen
//on interrupt 0 (pin 2), or interrupt 1 (pin 3)
attachInterrupt(0, updateEncoder, CHANGE);
attachInterrupt(1, updateEncoder, CHANGE);

}

void loop(){
//Do stuff here
if(digitalRead(encoderSwitchPin2)){
//button is not being pushed
}else{
//button is being pushed
}
 
Serial.println(encoderValue);
delay(1000); //just here to slow down the output, and show it will work even during a delay
}

void updateEncoder(){
int MSB = digitalRead(encoderPin1); //MSB = most significant bit
int LSB = digitalRead(encoderPin2); //LSB = least significant bit

int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number int sum = (lastEncoded << 2) | encoded; //adding it to the previous encoded value if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++; if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --; lastEncoded = encoded; //store this value for next time }

« Older Entries
Newer Entries »