2009-05-23

Autocalibrate and Analog Sensors

Most analog sensors like LDRs (Light Dependent Resistor) and FSRs (Force Sensitive Resistor) take a little fiddling to get useful input.

Your Arduino has a 10 bit ADC (Analog to Digital Converter) on its analog inputs (0-1023 steps) which accepts a voltage swing of 0 to +5Vdc. This has to translate to an 8 bit PWM (0-255 steps) signal on one of the PWM capable digital output pins.

You need to create a voltage divider using the variable resistor and a fixed resistor, that will get as close to the 5 volt swing as possible. LDRs and FSRs have a nominal value, and not much accuracy. Components in the same batch can vary in their at rest resistance and in their change in resistance to equal inputs.

The easiest method of calibration would probably be to just give up and put a potentiometer wired as a rheostat on each sensor, tweak and be done. Of course that adds to the expense of the circuit, so we probably want to use a fixed resistor. The formula to figure this is fairly simple for a two resistor circuit:
Vout = R2/(R1+R2)*Vin

Daycounter Inc. voltage divider calculator

For our purposes, we can view this voltage divider as being unloaded as it is feeding into a high impedance load (Arduino ADC pin). Once you get the fixed resistor close enough to give you a usable voltage swing, why not let the microcontroller do a little bit of fine tuning?

We can read the sensor value on an analog pin and use it to vary the output on a PWM pin easily enough, just take the input reading, divide by 4 (10 bit to 8 bit) and set the analogWrite() to use that value.

In the following sketch, we will add a variable to store a maximum reading, a variable to store a minumum reading and then use the map() function to convert the recorded input range into a useful output range (full 0 to 255).

Just in case we get something odd, we can also use the constrain() function to keep the output between 0 and 255 so we don't get odd results (256 wraps to 0).

Added to the mix is the idea of adding a threshold function which smooths out the response by ignoring changes below a chosen value.

Brightness Sensor Autocalibrate
/**********************************************************************
* Brightness Sensor Autocalibrate by capt.tagon
*
* Modification on Example 06B in "Getting Started with Arduino"
* by Massimo Banzi (co-founder of Arduino
*
* Set the brightness of the LED to a value determined by an
* analog sensor on specified sensor pin.
* State is recorded and compared to threshold value.
* Auto calibrate from sensor input to get full output swing (0-255)
***********************************************************************/

#define ledPin 11 // the pin for the LED
#define sensorPin 0 // the pin for the sensor input

int sensorVal = 0; // variable for reading sensor value
int mappedSensorVal = 0; // variable for holding remapped sensor value
int prevSensorVal = 0; // variable for holding previous sensor value
int sensorMin = 1023; // variable for holding maximum sensor value
int sensorMax = 0; // variable for holding minimum sensor value
int THRESHOLD = 2; // sensor change threshold

void setup() {
pinMode(ledPin, OUTPUT); // LED is as an OUTPUT
Serial.begin(9600); // Start serial output
}

void loop() {

sensorVal = analogRead(sensorPin); // read value from the sensor

if (sensorVal > sensorMax) { // record maximum sensor value read
sensorMax = sensorVal;
}

if (sensorVal < sensorMin) { // record minimum sensor value read
sensorMin = sensorVal;
}

/* map 10-bit ADC value, potentially 0-1023 to 8-bit pwm output 0-255
adjusted to actual minimum and maximum values read by ADC */
mappedSensorVal = map(sensorVal, sensorMin, sensorMax, 0, 255);

/* compare current reading with previous and only change if the
threshold value is exceeded */
if (abs(mappedSensorVal - prevSensorVal) >= THRESHOLD) {
Serial.print("Level: "); // serial debug output
Serial.println(mappedSensorVal);
mappedSensorVal = constrain(mappedSensorVal, 0, 255); // limit to 0-255
analogWrite(ledPin, mappedSensorVal); // use PWM to set LED brightness
prevSensorVal = mappedSensorVal; // save mapped sensor value to
} // compare to threshold
}

No comments:

Post a Comment