Offline
Newbie
Karma: 0
Posts: 10
|
 |
« on: May 03, 2012, 06:31:20 am » |
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
|
|
|
|
|
|
|
|
|
Dubuque, Iowa, USA
Offline
Edison Member
Karma: 12
Posts: 1520
|
 |
« Reply #3 on: May 03, 2012, 10:44:25 am » |
To smooth an analog sensor I always do something like: void loop() { x = analogRead(PIN);
if (x > reading) { reading = reading + 1; } else if (x < reading) { reading = reading - 1; } }
|
|
|
|
|
Logged
|
|
|
|
|
Peoples Republic of Cantabrigia
Offline
God Member
Karma: 6
Posts: 634
Arduino happiness
|
 |
« Reply #4 on: May 03, 2012, 11:07:25 am » |
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
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 86
Posts: 9360
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #5 on: May 03, 2012, 02:23:32 pm » |
@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 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
|
|
|
|
|
New Hampshire
Offline
God Member
Karma: 13
Posts: 776
There are 10 kinds of people, those who know binary, and those who don't.
|
 |
« Reply #6 on: May 03, 2012, 02:32:36 pm » |
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
God Member
Karma: 6
Posts: 634
Arduino happiness
|
 |
« Reply #7 on: May 03, 2012, 06:25:09 pm » |
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.  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
Newbie
Karma: 0
Posts: 49
I'm a newbie
|
 |
« Reply #8 on: May 04, 2012, 07:46:54 am » |
... I mostly use something like this void loop() { x = x - 0.15 * (x - analogRead(PIN) ); // 0.15 can be any value between 0.001 and 1.0 } ... I like that  Is there a way of changing the formula so it calculates in int instead of float?
|
|
|
|
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 86
Posts: 9360
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #9 on: May 04, 2012, 07:56:45 am » |
Is there a way of changing the formula so it calculates in int instead of float? Of course there is 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
|
|
|
|
|
Germany
Offline
Newbie
Karma: 0
Posts: 49
I'm a newbie
|
 |
« Reply #10 on: May 04, 2012, 08:01:24 am » |
Thank you very much Rob. The speed is what I'm after 
|
|
|
|
|
Logged
|
|
|
|
|
Netherlands
Offline
Tesla Member
Karma: 86
Posts: 9360
In theory there is no difference between theory and practice, however in practice there are many...
|
 |
« Reply #11 on: May 04, 2012, 08:12:24 am » |
// 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
|
|
|
|
|
Germany
Offline
Newbie
Karma: 0
Posts: 49
I'm a newbie
|
 |
« Reply #12 on: May 04, 2012, 08:16:59 am » |
Thanks Rob, but I'm going to test the simple formula with my MS5611-01BA01 pressure sensor.
|
|
|
|
|
Logged
|
|
|
|
|
|