Stabilize sensor output in between 2 numbers jitter
Hi there,
Does anybody know what the logic should be for this? Like how do I solve this problem?
if a sensor output switches fast between one value and the next and back again, than what? :)
Please read below:
I recently posted here (https://cycling74.com/forums/filtering-out-a-flow-of-numbers) asking for your help. And I did receive all the help I needed at that time.
Unfortunately I realized my problems were a little different.
I have an Ultrasonic Sensor. Which outputs numbers representing duration (or if I divide that to 29 and than to 2, I get the distance in centimeters). The thing is I need precision! And of course, the ultrasonic sensor working with sound obviously is not that precise. It can calculate centimeters but don't try to check millimeters because it goes back and forth like hell.
So, like I said it does send proper distance in centimeters. But whenever it is trying to calculate in between 2 values it keeps switching between the 2. For example if I put a plane in front of the sensor in between 13cm and 14 cm, whenever the plane is at about 13.80cm to 14cm the value goes to 13 and than 14 and than 13 again and so on, very fast (as fast as I made it output from the arduino, of course).
I managed to make something. It uses [peak] and [trough] so that it outputs only greater than previous numbers while going up and less than previous numbers while going down. It resets whenever it reaches the extremes that I set (e.g. 3 and 20).
Do you know how I can make this thing reset itself even if I decide to switch direction in the middle? Let's say, when going up, while being at about 15cm, I decide to go down. In this configuration I can not!
I was thinking of resetting when it goes down 2 cm (not 1 cm as that is the problem I am trying to avoid!) while going up. And the other way around. I am still having difficulties creating this part.
Any suggestions?
Thank you!
ygreq
PS: There is a plane in front of the sensor that is supposed to be moved either back or forth! This is why I need to solve this.
What about averaging together the curent reading and the previous 2 readings?
I don't think that the type of sensors used here makes your issue 'special'; any form of interpolation or averaging is going to downgrade your precision - it's a trade off. The minimum and maximum values, or range of the sensors will fall into the 0-1023 range of Arduino's 10-bit byte, and you are performing division to get a centimetre representation of this range. 13.8 to 14cm sounds about a precise as your gonna get; have another look at my averaging function. Or buy a Kinect :¬p
Good luck
Brendan
Hey guys,
Thank you for your input!!
@damblk. Averaging is out of the question, unfortunately because I need realtime readings.
Whenever I move the plane in front of the sensor, a projected image moves with it. So real time si a must!
@n00b_meister. The is read through digital pins so the limitations you talk about don't imply in this case, or do they? I am still a n00b at arduino, but from what I know the limitations you talk about are related to analog pins.
While dividing the numer to get the distance out of duration (calculations related to speed of sound), I am the one limiting the sensor's precision. But in this way I make the values it outputs fluctuate less than if left unprocessed.
So now I am stuck with a sensor that can give me "accurate" distance in centimeters. And the only problem would be the fact that whenever it is close to the next value it starts to fluctuate:
e.g.
- while being at around 13.7cm, it reads 13cm
- at around 13.8cm to 13.9cm, the reading fluctuates between 13cm and 14cm
- at 14cm, it reads 14cm
- and so on
I managed to make something out of what I posted earlier. The only problem would be that if you change direction midway the patch will skip one reading.
How are you getting a varying voltage on the digital pins?
....AFAIK, digital pins can fake analog OUTPUT (via PWM), but you can't do analogRead on a digital pin; all you get is HIGH or LOW when you read a digital pin. Unless I'm missing something. Which is very likely!
Brendan
As Brendan says,
Digital pins on/off
Analogue - varying
It would be helpful also to know which Ultrasonic sensor you are talking about
I have trouble believing that the jitter you are getting cannot be tamed by some modification of one of the methods in the comparison file that was linked to in the first thread. In particular, I've used my flatline example with noisy sensors with good result.
@Brendan and Simon: I am using a sensor similar to Ping ))) that you can find here: http://www.hwkitchen.com/products/ultra-sonic-range-measurement-module/
and this is the thread I started in the Arduino forum:
http://arduino.cc/forum/index.php/topic,65751.msg482083.html#msg482083
Arduino-wise it works exactly like Ping ))) and that means that in order to measure the distance the sensor sends a ping (ultrasonic sound) and listens for the echo. Based on that (and the speed of sound: Speed = Distance / Time) we get the distance in centimeters. And you can send either the (total) time it takes the ping to echo back from the object in front or you can calculate the distance in Arduino and send that.
The problem is that by using sound, air and so forth instead of something more "tangible", the time it takes the ping to echo back is always a little different. And thus I get jitter. Like I said before I solved a part of the problem by using the distance instead of the duration (even though duration was more precise). And so I get jitter whenever I switch to the next value in centimeters.
@Chris: Thank you, Chris! I tried! Your solution is awesome and I saved it for later :). Unfortunately it doesn't help in my case. The details are written here.
Quite often, sensor jitter is 'tameable' up to a point, beyond which the interpolation introduces latency. Then one simply has to reevaluate the sensor(s) used. I have recently had a similar experience using a cheap resistive touchpanel.
As you say yourself, there are a number of variables over which you have no control (air pressure, moving plane etc), and cite these as the cause of the jitter:
"The problem is that by using sound, air and so forth instead of something more "tangible", the time it takes the ping to echo back is always a little different. And thus I get jitter. Like I said before I solved a part of the problem by using the distance instead of the duration (even though duration was more precise). And so I get jitter whenever I switch to the next value in centimeters".
Despite a number of threads (and replies, esp Chris' eminent solutions), you may well have to consider other options because it doesn't sound like you're going to get the solution you want.
ps: digital pins? are you sure?
Brendan
Could you perhaps capture some of the data so that we could see exactly what you're dealing with? At the end of the day you are getting a series of measurements that are more or less evenly spaced in time other than timing variations in your Arduino loop. (and it might be better to use a timer interrupt to make your readings regularly sampled)
Also, Arduino Max serial works reliably at 38400, in my experience, so you may want to speed that up.
Brendan, it looks like it's digital because the sensor sends a blip then sets a bit when the blip's reflection returns, and the time between those is calculated.
I will post here the Arduino sketch (the simplest version) for one sensor. Brendan, yes it is a digital pin and as Chris also explained, Arduino sends calculations/interpretations it made and not some voltage change.
Chris, I tried using Serial.begin 38400 but it doesn't help at all as everything is limited by the fact that arduino has to wait for the sensor to receive the reflection before it can send anything. I don't really understand what a timer interrupt is at this moment (heard about it, even used it with a water sensor :) ). But anyway I think I solved the problem with the sensor being to lazy (check last post in the arduino forum).
I even found a solution for the problems I was facing in relation to why I started this thread (check second patch I copied). But still I didn't have the chance to test it in the installation. So I have a lil bit of cold sweat :-SS
So yeap, Brendan, you are right! At this point I would have to reevaluate the sensors, but in my case, I am stuck with them as there is no more time for other experiments.
/* Ping))) Sensor
This sketch reads a PING))) ultrasonic rangefinder and returns the
distance to the closest object in range. To do this, it sends a pulse
to the sensor to initiate a reading, then listens for a pulse
to return. The length of the returning pulse is proportional to
the distance of the object from the sensor.
The circuit:
* +V connection of the PING))) attached to +5V
* GND connection of the PING))) attached to ground
* SIG connection of the PING))) attached to digital pin 7
created 3 Nov 2008
by David A. Mellis
modified 30 Jun 2009
by Tom Igoe
This example code is in the public domain.
*/
// this constant won't change. It's the pin number
// of the sensor's output:
const int pingPin = 7;
void setup() {
// initialize serial communication:
Serial.begin(9600);
}
void loop()
{
// establish variables for duration of the ping,
// and the distance result in inches and centimeters:
long duration, cm;
// The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
// Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
// The same pin is used to read the signal from the PING))): a HIGH
// pulse whose duration is the time (in microseconds) from the sending
// of the ping to the reception of its echo off of an object.
pinMode(pingPin, INPUT);
duration = pulseIn(pingPin, HIGH);
Serial.print ("A ");
Serial.println(duration);
delay(10);
}
This sketch outputs total duration which you would have to divide by 29 to get the total distance which you would have to divide by 2 to get the distance from the sensor to the object. All the calculations are done in max in this case.
Hi
I'm glad I'm involved in this - I wasn't aware of the pulseIn function in Arduino; very handy!
Anyhoo, as Chris points out, perhaps increasing the baud rate might help to get more accurate readings; this occasionaly adds ( or 'realises') more jitter tho (remember to change the baud rate in Max too). Unfortunately, the averaging function I suggested won't work in Arduino (or Max, Chris?) because your reading is temporal in nature; ie you only get a distance value once the ping has returned. Hmm, wait though. How fast is the sensor sending out pings? (Sorry, I was thinking of Sonar-type pings); maybe you could use an averaging function. Try this (save it under a different name so your original is safe!):
int pingPin = 7;
int samples = 5;
void setup(){
Serial.begin (38400);
}
void loop(){
long duration, cm;
pinMode(pingPin, OUTPUT);
digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);
pinMode(pingPin, INPUT);
for (int i=0; i
duration += pulseIn(pingPin, HIGH);
}
duration/=samples;
//do some more maths here if needed
Serial.print("A");
Serial.println(duration);
delay(10);
}
Brendan
Hey Brendan!
I don't know what you did but it's sooo slow :)
Did you hack this code, into some code of your own; I would expect some lag if the "int samples" value was around 100, but it's at 5.
Does the baud rate in Arduino match the baud rate argument in your Max [serial] object?
As I've said, unfortunately I'm not familiar with the pulseIN function, and I am a bit n00bish with Arduino.
Brendan
Yeap. It does. Still nothing.
I didn't understand what your sketch is suppose to do.
While were at it do you maybe know that is the problem with this patch?
Or anyone willing to help? I haven't got a clue why it acts differently
:((
I made a simpler patch here: https://cycling74.com/forums/jit-matrix-outputs-2-lines-instead-of-16-when-banged-w-metro
Actually, I think that any of the smoothing ideas would work (with their own benefits and drawbacks,) because at the end of the day, there is a number rolling out of the timing code that represents a distance. These numbers are numbers. :-)