So I am playing around with the ultrasonic and have placed it on top of a servo so that every 1/2 second it rotates 5 degrees and takes 4 readings. What I am finding is that the reading are very inconsistent. I have put in delays thinking I needed time for the servo to get into position, delays between pings, long delays, short delays and just seem to get an almost random reading. Is ths how accurate ultrasonics are in general? Here is a sample of the results and at no time am i up against the wall as the measurements might indicate.
#include <Stepper.h>
#include <NewPing.h>
#include <Servo.h>
// change this to the number of steps on your motor
#define STEPS 200
// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to
Stepper stepper1(STEPS, 10, 11, 12, 13);
Stepper stepper2(STEPS, 4, 5, 6, 7);
// Ultrasonic settings
#define TRIGGER_PIN 2
#define ECHO_PIN 3
#define MAX_DISTANCE 500
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
//Servo
Servo myServo;
int angle = 0; //Starting position for servo
int looking = 1;//Starts looking right
// Body
#define WHEEL 3.81 //wheel diameter in cm
//Radar
int iSpy [37][2];
//Light detection
int val = 50;
int previous = 1000;
int delta = 0;
int steps = 0;
const int leftSensorPin = A1;
const int rightSensorPin = A2;
int leftSensorValue = 0;
int rightSensorValue = 0;
void setup() {
Serial.begin(9600); //Open serial communication
stepper1.setSpeed(200); // set the speed of the motor to 200 RPMs
stepper2.setSpeed(200); // set the speed of the motor to 200 RPMs
myServo.attach(9);
myServo.write(0);
for (int x=0; x < 37; x++){
iSpy [x][0] = x * 5;
myServo.write(map(iSpy [x][0],0,180,10,150));
// delay(500); //1000ms = 1s
unsigned int uS = sonar.ping();
iSpy [x][1] = uS / US_ROUNDTRIP_CM;
Serial.print(iSpy [x][0]);
Serial.print(" - ");
Serial.print(iSpy [x][1]);
uS = sonar.ping();
iSpy [x][1] = uS / US_ROUNDTRIP_CM;
Serial.print(" ");
Serial.print(iSpy [x][1]);
uS = sonar.ping();
iSpy [x][1] = uS / US_ROUNDTRIP_CM;
Serial.print(" ");
Serial.print(iSpy [x][1]);
uS = sonar.ping();
iSpy [x][1] = uS / US_ROUNDTRIP_CM;
Serial.print(" ");
Serial.println(iSpy [x][1]);
delay(500); //1000ms = 1s
}
}
void loop() {
}
You haven't mentioned which ultrasonic sensor you're using. A HC-SR04 needs a delay between individual readings. The datasheet says 60mS, and Tim Eckel, (NewPing), says either 30mS or 50mS, (can't remember which).
Other ultrasonic modules would be similar, I imagine.
Currently, the only real delay between your readings at each position is the time taken for the serial prints.
OldSteve:
A HC-SR04 needs a delay between individual readings. The datasheet says 60mS, and Tim Eckel, (NewPing), says either 30mS or 50mS, (can't remember which).
Isn't it a little strange that the library doesn't manage that requirement?
aarg:
Isn't it a little strange that the library doesn't manage that requirement?
There's a 'ping_timer()' method, that does it for you, using a timer, but the basic 'ping()' ( edit: and ping_cm() ) methods don't.
Here's the 'loop()' from the basic "NewPing.ino" example:-
void loop() {
delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the shortest delay between pings.
Serial.print("Ping: ");
Serial.print(sonar.ping_cm()); // Send ping, get distance in cm and print result (0 = outside set distance range)
Serial.println("cm");
}
Thanks OldSteve, that did help. The unit that I am using is the HC-SR04. I added in a 60us delay which helped with the consistency of the numbers. Still have some odd numbers in there which might be related to my servo as it appear to have a nervous tick that causes to jump around. I am as some points in the reading also finding that I am pinging up against fabric that does not give reliable readings but at least it is consistently unreliable now.
#include <Stepper.h>
#include <NewPing.h>
#include <Servo.h>
// change this to the number of steps on your motor
#define STEPS 200
// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to
Stepper stepper1(STEPS, 10, 11, 12, 13);
Stepper stepper2(STEPS, 4, 5, 6, 7);
// Ultrasonic settings
#define TRIGGER_PIN 2
#define ECHO_PIN 3
#define MAX_DISTANCE 500
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
//Servo
Servo myServo;
int angle = 0; //Starting position for servo
int looking = 1;//Starts looking right
// Body
#define WHEEL 3.81 //wheel diameter in cm
//Radar
int iSpy [37][2];
//Light detection
int val = 50;
int previous = 1000;
int delta = 0;
int steps = 0;
const int leftSensorPin = A1;
const int rightSensorPin = A2;
int leftSensorValue = 0;
int rightSensorValue = 0;
void setup() {
Serial.begin(9600); //Open serial communication
stepper1.setSpeed(200); // set the speed of the motor to 200 RPMs
stepper2.setSpeed(200); // set the speed of the motor to 200 RPMs
myServo.attach(9);
myServo.write(0);
delay(500); //1000ms = 1s
for (int x=0; x < 37; x++){
iSpy [x][0] = x * 5;
myServo.write(map(iSpy [x][0],0,180,10,150));
//delay(500); //1000ms = 1s
Serial.print(iSpy [x][0]);
Serial.print(" - ");
for (int y=1; y < 10; y++){
unsigned int uS = sonar.ping();
iSpy [x][1] = uS / US_ROUNDTRIP_CM;
delay(60); //1000ms = 1s
Serial.print(iSpy [x][1]);
Serial.print(" ");
}
Serial.println();
delay(60); //1000ms = 1s
}
}
void loop() {
}
You could be getting weird readings because the objects you are sensing are not flat. I suggest you keep the ultrasonic sensor at one angle and don't move it just to see if your setup is working. Then, you may want to consider making the times between rotating the sensor longer.
dgkindy:
Still have some odd numbers in there which might be related to my servo as it appear to have a nervous tick that causes to jump around.
As Paul asked, how are you powering the servo? It needs a separate power supply and can't be powered directly from the Arduino.
I am as some points in the reading also finding that I am pinging up against fabric that does not give reliable readings but at least it is consistently unreliable now.
Yep, fabric can cause inconsistent and out-of-range readings. Also note what goodinventor said. A ping sensor works best when the target is directly across the line of sensing, at 90 degrees.
When set up properly, this system should work well. I do exactly the same thing with my robot car - the ping sensor is attached to the body of an inverted servo and takes measurements at 5 positions during a sweep from one side to the other. I only stop the servo for a few milliseconds at each of the 5 positions, (to the naked eye it can't really be seen to stop), and it works well.
I am powering the servo from the Arduino. This is the way is shows to do it in the Arduino Starter Kit. Based on the other comments sounds like this is bad.
goodinventor, i did as you suggested and got a good consistent set of reading. I inserted a 5 second delay between movement and first ping. Much betters numbers until it is pointed at a couch/wall and then it gives me the primarily the zero readings until it is pointed at me down at the 135 range.
I noted on the data sheet that it has a measuring angle of 15 degrees. I imagine this is a cone coming out from the unit so at 2.5 meters away, the cone would be getting quite large and could be bouncing off anything but does not explain why I am getting all the zeroes.
#include <Stepper.h>
#include <NewPing.h>
#include <Servo.h>
// change this to the number of steps on your motor
#define STEPS 200
// create an instance of the stepper class, specifying
// the number of steps of the motor and the pins it's
// attached to
Stepper stepper1(STEPS, 10, 11, 12, 13);
Stepper stepper2(STEPS, 4, 5, 6, 7);
// Ultrasonic settings
#define TRIGGER_PIN 2
#define ECHO_PIN 3
#define MAX_DISTANCE 400
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
//Servo
Servo myServo;
int angle = 0; //Starting position for servo
int looking = 1;//Starts looking right
// Body
#define WHEEL 3.81 //wheel diameter in cm
//Radar
int iSpy [37][2];
//Light detection
int val = 50;
int previous = 1000;
int delta = 0;
int steps = 0;
const int leftSensorPin = A1;
const int rightSensorPin = A2;
int leftSensorValue = 0;
int rightSensorValue = 0;
void setup() {
Serial.begin(9600); //Open serial communication
stepper1.setSpeed(200); // set the speed of the motor to 200 RPMs
stepper2.setSpeed(200); // set the speed of the motor to 200 RPMs
myServo.attach(9);
myServo.write(80);
delay(500); //1000ms = 1s
for (int x=0; x < 37; x++){
iSpy [x][0] = x * 5;
myServo.write(map(iSpy [x][0],0,180,10,150));
delay(5000); //1000ms = 1s
Serial.print(iSpy [x][0]);
Serial.print(" - ");
for (int y=1; y < 10; y++){
unsigned int uS = sonar.ping();
iSpy [x][1] = uS / US_ROUNDTRIP_CM;
delay(60); //1000ms = 1s
Serial.print(iSpy [x][1]);
Serial.print(" ");
}
Serial.println();
// delay(60); //1000ms = 1s
}
}
void loop() {
}