Force Sensitive Resistor + Arduino

Sunday, November 25 th , 2012

The Force Sensitive Resistor, or FSR is one of those parts that fills bins in interaction design labs across the world. It’s a simple guy, a finicky guy, but it has its place in the maker toolbox.

A FSR is just what it sounds like – a resistor that changes its resistance with force. So if you press, sit, or punch it, its resistance changes. The finicky part tends to be when people want it to measure force with any sort of precision. It’s really not good for that, so if you need something sense even approximate weight or quantitative force, this is not your guy. But if you need something that will let you know if someone is sitting in a chair, or hugging a stuffed animal, this is it!

FSRs come in a wide variety of sizes, the larges ones can get a bit expensive, but you can probably find one to fit your project.

Hooking it up, and why

The FSR changes its resistance with force. It ranges from near infinite when not being touched, to under 300ohms when pressed really hard. So we can measure that change using one of the Arduino’s analog inputs. 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 FSR and the resistor.

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

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

But if the FSR is pressed on pretty hard, reading only 1K of resistance, the 10K resistor is going to soak up 10 times as much of that 5V. So the FSR would only get .45V. (analog reading of 92)

And if something is barely pressing on it, the FSR may be 40K of resistance, so the FSR will soak up 4 times as much of that 5V as the 10K resistor. So the FSR would get 4V. (analog reading of 819)

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.

//From the article: http://bildr.org/2012/11/force-sensitive-resistor-arduino

int FSR_Pin = A0; //analog pin 0

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

void loop(){
  int FSRReading = analogRead(FSR_Pin); 

  Serial.println(FSRReading);
  delay(250); //just here to slow down the output for easier reading
}
Unless otherwise stated, this code is released under the MIT License – Please use, change and share it.

Proximity Sensing with the VCNL4000 + Arduino

Friday, November 23 rd , 2012

I’m not really sure why, but proximity sensors are some of my favorite things in the sensor world. Maybe because there are so many of them? Who knows. Whatever the reason, the VCNL4000 is another proximity sensor that caught my eye, so I picked one up from Sparkfun on this handy breakout board.

The VCNL4000 looks like it is a single piece of silicon, but it really just is an infrared transmitter and receiver in a package that looks like a chip. Unfortunately, but much like many other proximity sensors the VCNL4000 can not easily be used for measuring exact distance. The way it works is that it shines a beam of IR light from an LED, and measures the intensity of light that is bounced pack. But that reading is not linear, so you can’t say 5cm is X so 10cm is 2X, it may only be 1.2X. Also note that because it is looking at reflected light, the surface of the object the light is reflecting off of will have an impact on the reading. So a reflective surface will read as a higher value than a dark matte surface even at the same distance.

But what makes this part special is that it also incorporates a pretty sensitive ambient light sensor. Also, unlike many other proximity sensors, the VCNL4000 does not have a simple analog output, but instead outputs a 16bit digital reading. So it is much more sensitive (32x) than what the Arduino’s native analog pins could do.

Proximity Sensing

The VCNL4000 data sheet claims a proximity sensing range of 20cm. In reality, I was only seeing a reasonable change inside 10cm, with major change happening within 8cm. Also, 16bits over 20cm is probably hugely overkill, and I doubt you will be able to tell a sub-milimenter difference as the numbers would have you believe. At least not until you get about 3cm away as the sensitivity seems to be exponential. But if you need that kind of result, you probably should get yourself a laser.

Ambient Light Sensing

The ambient light sensor on this thing is really, really good. It’s very stable and in lower light it was able to pickup very small changes in light. Shadows that I could barely notice myself triggered a noticeable change in the reading.

So if you only need short range proximity sensing, save your self a load of cash and just pick up a QRD1114. However, if you need both short-range proximity sensing, and ambient light sensing, this is a really great chip.

Hooking it up

The VCNL4000 is an I2C device. I2C is a 2-wire serial connection, so you just need to connect the SDA (Data) and SCL (Clock) lines to your Arduino for communication. On most arduinos SDA is on analog pin 4, and SCL is on analog pin 5. On an arduino mega, SDA is digital 20, and SCL is digital 21. The Leonardo’s have their own special connections.

The board needs 3.3v to run, but it also needs 5V for the IR led that it uses to check the proximity.

Code

Because the board operates on I2C, the code is kinda crazy. Please don’t ask how it works. I don’t know that I even know, and there are some bitwise operators on there to complicate it too. But if you just want it to work, here is the code.

Note: that the ambient light readings take about 100ms to execute

#include <Wire.h>

#define VCNL4000_ADDRESS 0x13  //I2C Address of the board

void setup(){
  Serial.begin(9600);  // Serial's used to debug and print data
  Wire.begin();  // initialize I2C stuff
  initVCNL4000(); //initilize and setup the board
}

void loop(){
  unsigned int ambientValue = readAmbient(); //can a tiny bit slow
  unsigned int proximityValue = readProximity();

  Serial.print(ambientValue);
  Serial.print(" | ");
  Serial.println(proximityValue);

  delay(100);  //Just here to slow down the printing
  //note that the readings take about 100ms to execute
}






void initVCNL4000(){
  byte temp = readVCNLByte(0x81);

  if (temp != 0x11){  // Product ID Should be 0x11
    Serial.print("initVCNL4000 failed to initialize");
    Serial.println(temp, HEX);
  }else{
    Serial.println("VNCL4000 Online...");
  } 

  /*VNCL400 init params
   Feel free to play with any of these values, but check the datasheet first!*/
  writeVCNLByte(0x84, 0x0F);  // Configures ambient light measures - Single conversion mode, 128 averages
  writeVCNLByte(0x83, 15);  // sets IR current in steps of 10mA 0-200mA --> 200mA
  writeVCNLByte(0x89, 2);  // Proximity IR test signal freq, 0-3 - 781.25 kHz
  writeVCNLByte(0x8A, 0x81);  // proximity modulator timing - 129, recommended by Vishay 
}


unsigned int readProximity(){
  // readProximity() returns a 16-bit value from the VCNL4000's proximity data registers
  byte temp = readVCNLByte(0x80);
  writeVCNLByte(0x80, temp | 0x08);  // command the sensor to perform a proximity measure

  while(!(readVCNLByte(0x80)&0x20));  // Wait for the proximity data ready bit to be set
  unsigned int data = readVCNLByte(0x87) << 8;
  data |= readVCNLByte(0x88);

  return data;
}


unsigned int readAmbient(){
  // readAmbient() returns a 16-bit value from the VCNL4000's ambient light data registers
  byte temp = readVCNLByte(0x80);
  writeVCNLByte(0x80, temp | 0x10);  // command the sensor to perform ambient measure

  while(!(readVCNLByte(0x80)&0x40));  // wait for the proximity data ready bit to be set
  unsigned int data = readVCNLByte(0x85) << 8;
  data |= readVCNLByte(0x86);

  return data;
}


void writeVCNLByte(byte address, byte data){
  // writeVCNLByte(address, data) writes a single byte of data to address
  Wire.beginTransmission(VCNL4000_ADDRESS);
  Wire.write(address);
  Wire.write(data);
  Wire.endTransmission();
}


byte readVCNLByte(byte address){
  // readByte(address) reads a single byte of data from address
  Wire.beginTransmission(VCNL4000_ADDRESS);
  Wire.write(address);
  Wire.endTransmission();
  Wire.requestFrom(VCNL4000_ADDRESS, 1);
  while(!Wire.available());
  byte data = Wire.read();

  return data;
}
Unless otherwise stated, this code is released under the MIT License – Please use, change and share it.

Simple Temperature With Thermistor + Arduino

Friday, November 23 rd , 2012

A Thermistor is a thermal-resistor. It’s just a simple device that changes it’s resistance based on temperature. If the LRD/Photoresistor is day of of arduino class. The thermistor should be day 1.01. (Can I do that?).

If you need precise temperature readings, this is not the part for you. Check out the DS18B20, TMP102, or MLX90614

Thermistors are not that precise or anything, so you wont be able to tell the temperature with it, but if you need to know when the temperature has changed, this will work for you. And on the plus side, they are crazy cheap considering the alternatives, incredibly simple to hookup, and have some of the easiest code ever. You can find these pretty easily at most hobby electronics shops, or just add some to your next sparkfun order.

Hooking it up, and why

The thermistor changes its resistance with temperature 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 thermistor 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 thermistor 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 thermistor and the resistor have the same resistance, the 5V is split evenly (2.5V) to each part. (analog reading of 512)

But if the thermistor is really hot and is reading only 1K of resistance, the 10K resistor is going to soak up 10 times as much of that 5V. So the thermistor would only get .45V. (analog reading of 92)

And if it is in the refrigerator, the thermistor may be 40K or resistance, so the thermistor will soak up 4 times as much of that 5V as the 10K resistor. So the thermistor would get 4V. (analog reading of 819)

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 thermistorPin = A0; //analog pin 0

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

void loop(){
  int thermistorReading = analogRead(thermistorPin); 

  Serial.println(thermistorReading);
  delay(250); //just here to slow down the output for easier reading
}
Unless otherwise stated, this code is released under the MIT License – Please use, change and share it.

« Older Entries
Newer Entries »