Pages: [1]   Go Down
Author Topic: Average of reading on IR sensor  (Read 1772 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 11
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hey people

I'm using a SHARP IR sensor for a school project. When im testing the sensor, it works but in between there are some irregular
readings when nothing is infront of the sensor (so i should read zero) but there are some very sort signal (of high value mostly).
I need to use it as a trigger and therefore need a way around this. Is it maybe poissble to gather lets say the last six or seven last
read values and create a average of this? Or is there some other way. I guess its because the sensor has some kind of loose connection?

Thanks!
Logged

Czech Republic
Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here is the code for the IR that could help you.
http://www.ladyada.net/learn/sensors/ir.html
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13742
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is it maybe poissble to gather lets say the last six or seven last
read values and create a average of this? Or is there some other way.

maybe these libs can be useful
- http://arduino.cc/playground/Main/RunningAverage -
- http://arduino.cc/playground/Main/RunningMedian -
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Dubuque, Iowa, USA
Offline Offline
Faraday Member
**
Karma: 47
Posts: 2521
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

To smooth an analog sensor I always do something like:

Code:
void loop() {
  x = analogRead(PIN);

  if (x > reading) {
    reading = reading + 1;
  } else if (x < reading) {
    reading = reading - 1;
  }
}


Logged

Peoples Republic of Cantabrigia
Offline Offline
God Member
*****
Karma: 6
Posts: 722
Arduino happiness
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Could be a noise issue. Have you checked your wiring and power supply to rule that out? I.e. there are no other relays, other things that are potentially interfering with the ADC?

You could also try putting a small capacitor across the output to smooth the response and resist spikes. Naturally, such a cap will slow the responsiveness of the sensor. You could also filter the results in software as suggested above. One technique I like using on (relatively speaking) slow moving signals is decimation. You end up with better accuracy and it filters noise too. See the Atmel AVR white paper for more info on this. Plus, you get to learn about bit shifting.

Last but not least, depending on the speed with which you are switching channels on the ADC, there can be problems also. If you left the ADC pre-scaler alone, this should not be an issue.
Logged

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13742
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@chagrin

I think your filter handles large changes and small noise the same way. I expect most people want the fine noise (last bit) to be suppressed.


I mostly use something like this
Code:
void loop()
{
  x = x - 0.15 * (x - analogRead(PIN) );  // 0.15 can be any value between 0.001 and 1.0
}

(it is a cleaner variation of x = 0.85*x + 0.15*analogRead(PIN); as it only has one tuneable param in the formula.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

New Hampshire
Offline Offline
God Member
*****
Karma: 17
Posts: 781
There are 10 kinds of people, those who know binary, and those who don't.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Actually, a small cap on the power in for the Sharp sensor is recommended and often needed (on the order of a few tens of microfarads, ie 20-30uf).  The sensor does not have a constant power draw, but a very spikey power draw (it pulses an IR LED, which are fairly high current LEDs), and a cap on the power line can help stabilize the entire sensor and provide a more stable output.
Logged


Peoples Republic of Cantabrigia
Offline Offline
God Member
*****
Karma: 6
Posts: 722
Arduino happiness
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Actually, a small cap on the power in for the Sharp sensor is recommended and often needed (on the order of a few tens of microfarads, ie 20-30uf).  The sensor does not have a constant power draw, but a very spikey power draw (it pulses an IR LED, which are fairly high current LEDs), and a cap on the power line can help stabilize the entire sensor and provide a more stable output.
Well, there you go.  smiley A stable power supply is always on the path to happiness. But putting a cap on the analog input on the arduino can also help alleviate spurious fluctuations.
Logged

Germany
Offline Offline
Jr. Member
**
Karma: 3
Posts: 83
I'm a newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

...
I mostly use something like this
Code:
void loop()
{
  x = x - 0.15 * (x - analogRead(PIN) );  // 0.15 can be any value between 0.001 and 1.0
}
...

I like that smiley

Is there a way of changing the formula so it calculates in int instead of float?
Logged

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de


Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13742
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
Is there a way of changing the formula so it calculates in int instead of float?
Of course there is

Code:
unsigned int x
void loop()
{
  x = (64 *x -10 * (x - analogRead(PIN) ))/64;   
}
// 64 gives a quick bitshift for division and 0.15 * 64 = 9.6 => 10

the max value is 1023 so 64 *1023 does not overflow!

the 10 can be replaced by (0..64) giving different weights to the oldvalue and the new value.

Test the difference in memory (sketch size) and speed (e.g. 10000 calls). 



Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Germany
Offline Offline
Jr. Member
**
Karma: 3
Posts: 83
I'm a newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you very much Rob.

The speed is what I'm after smiley
Logged

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de


Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13742
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Code:

// http://arduino.cc/forum/index.php/topic,56396.0.html
// and
// http://arduino.cc/forum/index.php/topic,74895.0.html

/*
  Sketch to demonstrate how to decrease time of analog read.
 it shortens the delay by manipulating registers and reducing the prescale
 timer value from 128 to 16;
 
 Note Serial Speed! Change to suit yourself!
 
 Sample Sketch From Arduino Cookbook by Margolis (O'Reilly Press)
 Modified by Willr March24, 2011
 
 Tested on Mega2560 Arduino board with an MA7361 Z output hooked to
 Sensor 5
 */

// CHANGE Sensor Pin to suit yourself...
const int sensorPin = 5;

// Change  number of entries to a value divisible by 100 only
const int numberOfEntries = 100;

unsigned long microseconds;
unsigned long duration1;
unsigned long duration2;

int results[numberOfEntries];

void setup()
{
  Serial.begin(9600); ///CHANGED
  Serial.flush();


  // standard analog read performance -- prescale == 128
  microseconds = micros();
  for (int i=0; i < numberOfEntries; i++)
  {
    results[i] = analogRead(sensorPin);
  }

  duration1 = micros() - microseconds;

  Serial.print(numberOfEntries);
  Serial.print("   readings took ");
  Serial.println(duration1);

  // This double loop just prints a neat table..
  for( int j=0; j < numberOfEntries; j=j+20)
  {
    for (int i=0; i < 20; i++)
    {
      Serial.print(results[j+i]);
      Serial.print(",  ");
    } //end loop i
    Serial.println();
  } //end loop j

  Serial.println();

  // prescale clock to 16
  bitClear(ADCSRA,ADPS0);
  bitClear(ADCSRA,ADPS1);
  bitSet(ADCSRA,ADPS2);

  // Performance with Changeed Prescale...
  microseconds = micros();
  for (int i=0; i < numberOfEntries; i++)
  {
    results[i] = analogRead(sensorPin);
  }

  duration2 = micros() - microseconds;
  Serial.print(numberOfEntries);
  Serial.print("   readings took ");
  Serial.println(duration2);

  for( int j=0; j < numberOfEntries; j=j+20)
  {
    for (int i=0; i < 20; i++)
    {
      Serial.print(results[j+i]);
      Serial.print(",  ");
    } //end loop i
    Serial.println();
  } //end loop j

  Serial.println();

  Serial.print("Ratio of read times is : ");
  Serial.println((float)duration1/duration2);
  Serial.println("********************");
}

void loop()
{
  // empty main loop is deliberate...
}

There are also optimizations known if the pin number is hard coded at compile time - could not find and example though -



Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Germany
Offline Offline
Jr. Member
**
Karma: 3
Posts: 83
I'm a newbie
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Rob, but I'm going to test the simple formula with my MS5611-01BA01 pressure sensor.
Logged

Leo

Project "ALTDuino" - A homemade altimeter for model rockets.
http://www.altduino.de


Pages: [1]   Go Up
Jump to: