I need a robot (see bottom animation) front ultrasonic range sensor (US-100 because of Arduino Due 3.3V) measurements to stop the robot quickly when an obstacle comes near.
I read about NewPing library, and especially this from initial comment of NewPingEventTimer.ino on NewPing's ping_timer method:
... The advantage of using this method over the standard ping method is that it permits a more event-driven sketch which allows you to appear to do two things at once. An example would be to ping an ultrasonic sensor for a possible collision while at the same time navigating. This allows a properly developed sketch to multitask. ...
I had to learn that unfortunately NewPing library does not work for the Due.
I had code to measure distance with US-100 with pulseIn(), but that does active waiting.
"Re: Is it OK to (mis?)use pins for playing role of GND and VCC?"
https://forum.arduino.cc/index.php?topic=458557.msg3191753#msg3191753
So I tried to use attachInterrupt() and do the pulse width measurement myself via a "CHANGE" ISR (Interrupt Service Routine). It works pretty good, but the durations (in μs) between pulseIn() and interrupt method differed. I calculated the quotient and to my surprise for different distances the factor was always 1.5, which I don't have an explanation for:
304 mm (1792) 0 mm (1196) 1.50
297 mm (1751) 0 mm (1168) 1.50
347 mm (2047) 0 mm (1368) 1.50
390 mm (2297) 0 mm (1533) 1.50
390 mm (2297) 0 mm (1528) 1.50
423 mm (2493) 0 mm (1665) 1.50
What is the explanation for this factor? Or am I doing something just wrong?
Here is the sketch (in robot application, instead writing output, motor speed would be set to 0 if obstacle/wall is near):
#define VCC0 8
#define trigPin0 9
#define echoPin0 10
#define GND0a 11
#define GND0b 12
void setup() {
Serial.begin (57600);
pinMode(VCC0, OUTPUT); digitalWrite(VCC0, HIGH);
pinMode(trigPin0, OUTPUT);
pinMode(echoPin0, INPUT);
pinMode(GND0a, OUTPUT); digitalWrite(GND0a, LOW);
pinMode(GND0b, OUTPUT); digitalWrite(GND0b, LOW);
}
volatile unsigned long duration=0;
unsigned long duration0, distance, dur0, dur1;
void loop() {
detachInterrupt(echoPin0);
distance = distdur(trigPin0, echoPin0, duration0);
out(distance, duration0);
attachInterrupt(echoPin0, change, CHANGE);
duration=dur0=0;
digitalWrite(trigPin0, LOW);
delayMicroseconds(2);
digitalWrite(trigPin0, HIGH);
delayMicroseconds(50);
digitalWrite(trigPin0, LOW);
delay(200);
}
void change() {
dur1 = micros();
if (digitalRead(echoPin0)==HIGH) {
dur0 = dur1;
} else if (dur0) {
duration = dur1 - dur0;
out(0L, duration);
Serial.println((1.0*duration0)/duration);
duration=dur0=0;
}
}
void out(long distance, long duration) {
Serial.print(distance);
Serial.print(" mm (");
Serial.print(duration);
Serial.print(") ");
}
long distdur(int trigPin, int echoPin, volatile unsigned long &duration) {
long distance;
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(50);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = duration * 34 / 100 / 2;
return (distance>4000) ? 4000 : distance;
}
Hermann.