809Views30Replies

# Need help for improving PING Ultrasonic sensor code to make it precise Answered

Hi guys,
I havebuilt a circuit to detect the swinging of an object using ultrasonic sensor and send signals to the Arduino Duemilanove board which in turn activates the solenoid. The circuit is working fine but I'm using a PING Ultrasonic sensor and I'm having hard time controlling it with the code. Do you have any idea about how to control and make the readings precise for the Sensor? If you want, I can post my code here... Any help is appreciated. Thanks in advance!

Tags:

## Discussions

Also I want to put a counter. So the solenoid should be high only when the counter number is prime.. Can you help me code that as well? Thanks in advance!

Tricky. What kind of time intervals are there between bat transitions, and between the transitions. I'd reckon you go, say, to and fro in 1/2 second, then there's a second or two before the next attempt ?

Hi Steve,
You're right! At first it was tricky for me, now its turned out to be a challenge! I think the time between bat intervals is about 1/2 a second... But the second transition keeps continuing! It doesn't stop.. So it means, there is 1/2 a second to one second gap for the next transition..!

You need to start a timer when you detect the bat the first time. You look at the count at the next bat transition If the count < bat time, you have a valid detection, other wise reset the timer.

Steve,
Instead of a timer, I have tried this method. First detection, let go and there is a delay(300); and then again a "if" loop for testing the detection. This is working fine if the swing speed is constant. Even if there is a slight change in the swing speed, it goes wrong!!!!!!

Good Idea! Can you help me with the program? I'm pretty bad with programming!!! Thanks!

Well, you COULD test for prime, but its probably easier to have a array with 30 or 40 primes in it.

Sounds good.. Can you help me in editing my code for the 30 prime numbers. My code is posted below in one of the comments! Thanks steve.. You're of great help man. Appreciate it!

Hi steve!
This is me, again. I'm almost done with my project. But I still have two major problems with the way my sensor is working! I need to swing the bat(oscillates) in front of the sensor.. The sensor has to detect only when the bat is swung for the second time. I mean, first it passes infront of the sensor, which is TO and then it comes back, FRO. It should stay idle for the first detection and detect the FRO! I tried various things with the code, its not working that way. Can you help me out with this.

Here is the code:

#include
#include
#include
int pingPin = 7;
int val = 0;
int output = 2;
int button = 8;
int check = 0;
int ctr = 0;
int p13 = 13;
void setup() {
Serial.begin(9600);
pinMode(output, OUTPUT);
pinMode(pingPin, INPUT);
pinMode(button, INPUT);
pinMode(p13, OUTPUT);
}
void loop(){
unsigned long duration;

if(check == HIGH){
pinMode(pingPin, OUTPUT);

digitalWrite(pingPin, LOW);
delayMicroseconds(2);
digitalWrite(pingPin, HIGH);
delayMicroseconds(5);
digitalWrite(pingPin, LOW);

pinMode(pingPin, INPUT);

duration = pulseIn(pingPin, HIGH, 20000);
duration = constrain(duration, 1000, 20000);
int val = map(duration, 1000, 20000, 0, 255);
duration = (duration/2) / 29.1;

if(duration < 1700 && duration > 1000) {
{ ctr++;
}

if (ctr == 2)
{
ctr = 0;
delay(150);
digitalWrite(output, HIGH);
digitalWrite(p13, HIGH);
}}

else
{
digitalWrite(output, LOW);
digitalWrite(p13, LOW);
}}

else
{
digitalWrite(output, LOW);

digitalWrite(p13, LOW);
}
}

I have the sensor working. I want the sensor pulses to be more faster than it is currently and it should detect any object swining within 10cm of its range and neglect the others.

The problem is, that viable pulses may still be reflected from targets and trip the sensor, so you need to seriously turn down the gain of the sensor - that's an electrical adjustment.

Steve

Can you let me know how to turn down the gain through electrical adjustment, so that the pulses do not travel that far? Thanks Steve!

Looking at the datasheet, its only got a range/time of 3m/10 mSec anyway, which should give you 100 pps. How fast do you realisitically expect it to go ?

I don't want the sensor pulses to travel farther than 10cm.. All I want from the sensor now is - when I swing my bat, it should detect the bat when the bat passes infront of the sensor and send a signal to the arduino and activate my solenoid.

You can't STOP them ! They're just sounds !

At 100 PPS, you should be able to catch it OK surely ?

So you mean to say I can't stop the speed at which it is emitted, so that it doesn't travel larger distance?

K now, can you help me with the code steve? I want to actually count the number of times the sensor detects a swining bat within the 10cm range and put a counter to count it and for every 3rd time, I want to activate the solenoid. The code which I have is:

#include
#include
int pingPin = 7; // Choose the input pin (for PING Sensor)
int val = 0; // variable for reading the sensor values
int output = 2; // Choose the pin for the Solenoid
int button = 8; // Choose the input pin (for a push button)
int check = 0; // A variable to read whether pushbutton is pressed or not

void setup() {
Serial.begin(9600);
pinMode(output, OUTPUT); // Declare Solenoid as output
pinMode(pingPin, INPUT); // Declare PING Sensor as input
pinMode(button, INPUT); // Declare Pushbutton as input
}

// Initialize duration and check for the pushbutton press and then perform sensor action

void loop(){
long duration;

int count;
// count = count + 1;
for(count=0; count<100; count++)
{
int prime = 1;
//int prime1 = 3;
//int prime2 = 5;
//int prime3 = 7;

if(check == HIGH){

// 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); // Read pulse length and store it in 'duration'
duration = constrain(duration, 1000, 20000); // Ignore values outside 1000 & 20000 //microseconds
int val = map(duration, 1000, 20000, 0, 255); // Map duration to the range 0 - 255 (consider data //type!)

//Check for the condition with the sensor values to activate the Solenoid
if(duration > 1000)
{
if(count == prime)
{
digitalWrite(output, HIGH);
}
else
{
digitalWrite(output, LOW);
}
}}
// This is for the pushbutton. If the button is not pressed, the machine will not start("LOW")
else
{
digitalWrite(output, LOW);
}
}}

So you mean to say I can't stop the speed at which it is emitted, so that it doesn't travel larger distance?

Of course. You have to wait for the maximum permissible return time before you can go again.

If I'd been you, I'd've used capacitance sensing of the bat, not ultrasound, but its too late now

K so is it possible to modify the code for the way I want it to work? Can you help me with that?

Where does the prime business come in ? You say you want to count 10cm approaches, and then every 3rd close the solenoid.

That's

If (duration <2000)
{ ctr++};

If (ctr >=3)
{ ctr==0;
digitalwrite(output,high)
}

Hi Steve!
I've added your portion of the code to my main code. I still have problems with precise detection. I'm placing the Ping sensor 3cm above the ground on a breadboard. The bat i'm swinging infront of the sensor is something like a golf putter stick. Its a metal bat! It swings a little faster, is this a problem for the sensor to detect it? The sensor has to detect when bat crosses the sensor and send a signal to the solenoid, making it HIGH to activate!!! Could you help me with this? Thanks!

Try adding a timeout argument to your pulsein command, since you're pointing at the sky presumably, try pulseIn(pingPin, HIGH,20000)

Great Steve! This is working!! But now I'm planning to take the Arduino board outside, that is provide Arduino with an external voltage source. I am planning to hook it up to a 9v battery. But the UltraSonic sensor just takes 5V as its input. I think i'll have to use a resistor to cut down the current and make only 5V flow to it, right:? Or do I have to use any other devices along with a resistor? Kindly reply me for this! Thanks in advance!

Great! Thanks for all your help. I'll get back to you if I have queries or to thank if everything is going great!

Lol ok!
Steve,
I've one more question regarding to the Arduino UNO board. I need to know how to reset the board using a software. I've asked this on the questions section. If you know the answer, kindly answer me. Thanks in advance!

Yes! The prime has to be integrated into the code after
"if (duration > 1000)"

Add a moving average filter to the raw distance information might help.

Thanks for your reply. I appreciate it! Can you help me with this code? I'm not a software background, so I'm not very good with coding.. This is the code I have now:

#include
#include
int pingPin = 7; // Choose the input pin (for PING Sensor)
int val = 0; // variable for reading the sensor values
int output = 2; // Choose the pin for the Solenoid
int button = 8; // Choose the input pin (for a push button)
int check = 0; // A variable to read whether pushbutton is pressed or not

void setup() {
Serial.begin(9600);
pinMode(output, OUTPUT); // Declare Solenoid as output
pinMode(pingPin, INPUT); // Declare PING Sensor as input
pinMode(button, INPUT); // Declare Pushbutton as input
}

// Initialize duration and check for the pushbutton press and then perform sensor action

void loop(){
long duration;

int count;
// count = count + 1;
for(count=0; count<100; count++)
{
int prime = 1;
//int prime1 = 3;
//int prime2 = 5;
//int prime3 = 7;

if(check == HIGH){

// 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); // Read pulse length and store it in 'duration'
duration = constrain(duration, 1000, 20000); // Ignore values outside 1000 & 20000 //microseconds
int val = map(duration, 1000, 20000, 0, 255); // Map duration to the range 0 - 255 (consider data //type!)

//Check for the condition with the sensor values to activate the Solenoid
if(duration > 1000)
{
if(count == prime)
{
digitalWrite(output, HIGH);
}
else
{
digitalWrite(output, LOW);
}
}}
// This is for the pushbutton. If the button is not pressed, the machine will not start("LOW")
else
{
digitalWrite(output, LOW);
}
}}