Using a ultrasonic (newping) library or not?

Hi, I'm a little unsure what the benefits of using an add-on library are, if a sensor works without it. In particular I have a ultrasonic sensor that appears to be supported by this newping library.

I don't know if I need to use it or not.

My only current problem with th sensors is that they don't seem to check often enough. I have a moving robot and the sensor is used to stop collisions. When the reading drops below 50 (cm?) it stops. But I rarely see a reading just above 50, it is more like 80, then under 50. Now speed is a factor here of course, and my robot could be covering 30 cm in a second, but I'd like it to be getting the distance checked much more often. so I can see smaller distance changes.

Now, would the newping library provide enhancements for an issue like this? Or should I focus on my code and forcing the distance check more often (which gets messy I've found). Any feedback on how to get a sensor to check constantly while it is busy doing other stuff would be appreciated. The "loop" is not sufficient IMO, and I'd like to have it just checking constantly, without needing to call it. Is that possible?

Now, would the newping library provide enhancements for an issue like this?

That depends on what you code currently does.

Or should I focus on my code and forcing the distance check more often (which gets messy I've found).

Why does checking more often get messy?

Any feedback on how to get a sensor to check constantly while it is busy doing other stuff would be appreciated.

How is the sensor busy doing something else?

The "loop" is not sufficient IMO, and I'd like to have it just checking constantly, without needing to call it.

What "loop"? What the hell is "it"?

Is that possible?

Anything's possible. But, probably not what you want.

if you've already got your robot measuring distances without the library, i'm guessing you don't need the NewPing addition.
that said, i haven't really explored the full features of it myself but just for simple ranging, i've found that a simple
* *trigger then read echo* *
is sufficient.

basically you read the value, what counts is then how & when you enact upon it.

if you have difficulties, i'm guessing it's to do with your program flow - which is why you should just paste it in here if you want someone to take a look at it.

The "loop" is not sufficient IMO, and I'd like to have it just checking constantly, without needing to call it.

I assume from what you say that it is checking the distance once per iteration of the loop() function. With the right coding you should be able to get several readings a second but until you post your code we don't know what else it is doing and how.

Seems like posting large code chunks here is cool? As opposed to using another service?

Oh, I'm a noob if my post count didn't make that clear. So please go easy on me. Just trying to learn.

Different movement tasks are broken up into their own functions. THis is one of the bajillion hacks of the SainSmart robot code that is out there. If you've seen it, you will notice the similarity.

As far as the "messy" part. Notice the distance checks in the turning functions (body_rturn/body_lturn), as well as nodanger/backup functions.

In general I haven't figured out how best to perform movement AND check distance while it is moving. I started creating ClearanceDecision functions, but haven't found them to be too helpful in checking more often.

FYI - I have a ultrasonic sensor on the front and back of the robot now. Just added, code may need adjustment for that.

Thanks!

#include <Servo.h> 

const int EchoPin = 2; // Ultrasonic 1 signal input
const int TrigPin = 3; // Ultrasonic 1 signal output

const int RearEchoPin = 13; // Ultrasonic rear signal input
const int RearTrigPin = 12; // Ultrasonic rear signal output

const int leftmotorpin1 = 9; //signal output of DC geared motor
const int leftmotorpin2 = 10;
const int rightmotorpin1 = 5;
const int rightmotorpin2 = 6;


int currDist = 49;  // distance
int currRearDist = 50; // reaer distance
int randomTurnTime = 0;  // Time to spend in the random turn


void setup() {
  Serial.begin(9600); // Serial begin texting
  pinMode(EchoPin, INPUT);
  pinMode(RearEchoPin, INPUT);
  //   for (int pinindex = 3; pinindex < 8; pinindex++) {
  for (int pinindex = 3; pinindex < 13; pinindex++) {
    pinMode(pinindex, OUTPUT); // set pins 3 to 13 as outputs
  }
  
}

void loop() {
  currDist = MeasuringDistance(); //measure front distance
  currRearDist = MeasuringRearDistance(); //measure rear distance
  
  if(currDist > 50) {
    nodanger();}
  else if(currDist <= 50){
    totalhalt();
    Serial.println("Look out!");
    backup();
    randTurn();
  }
  else {
    //whichway();
    randTurn();
  }
}

//measure distance, unit:cm
long MeasuringDistance() {
  long duration;
  Serial.println("MeasuringDistance");
  Serial.print("Current Distance: ");
  Serial.println(currDist);
  //pinMode(TrigPin, OUTPUT);
  digitalWrite(TrigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(TrigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(TrigPin, LOW);
  //pinMode(EchoPin, INPUT);
  duration = pulseIn(EchoPin, HIGH);
  return duration / 29 / 2;
}

//measure distance, unit:cm
long MeasuringRearDistance() {
  long durationrear;
  Serial.println("MeasuringRearDistance");
  Serial.print("Current Rear Distance: ");
  Serial.println(currRearDist);
  //pinMode(TrigPin, OUTPUT);
  digitalWrite(RearTrigPin, LOW);
  delayMicroseconds(2);
  digitalWrite(RearTrigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(RearTrigPin, LOW);
  //pinMode(EchoPin, INPUT);
  durationrear = pulseIn(RearEchoPin, HIGH);
  return durationrear / 29 / 2;
}

// forward
void nodanger() {
  Serial.println("Rolling...");
//  digitalWrite(leftmotorpin1, LOW);
//  digitalWrite(leftmotorpin2, HIGH);
//  digitalWrite(rightmotorpin1, LOW);
//  digitalWrite(rightmotorpin2, HIGH);

  analogWrite(leftmotorpin1, 0);
  analogWrite(leftmotorpin2, 180);
  analogWrite(rightmotorpin1, 0);
  analogWrite(rightmotorpin2, 180);
  delay(100);
}

//backward
void backup() {
  boolean allclear = false;
  Serial.println("backup");
  currRearDist = MeasuringRearDistance(); //measure rear distance
  if(currDist <= 50){
    totalhalt();
    Serial.println("Look out!");
    allclear = false;
  }
   else {
      allclear = true;
  }
  if (allclear) {
    digitalWrite(leftmotorpin1, HIGH);
    digitalWrite(leftmotorpin2, LOW);
    digitalWrite(rightmotorpin1, HIGH);
    digitalWrite(rightmotorpin2, LOW);
    delay(700);
    digitalWrite(leftmotorpin1, HIGH);
    digitalWrite(leftmotorpin2, HIGH);
    digitalWrite(rightmotorpin1, HIGH);
    digitalWrite(rightmotorpin2, HIGH);
    delay(200);
  }
}

void totalhalt() {
  Serial.println("Total halt!");
  digitalWrite(leftmotorpin1, HIGH);
  digitalWrite(leftmotorpin2, HIGH);
  digitalWrite(rightmotorpin1, HIGH);
  digitalWrite(rightmotorpin2, HIGH);
  delay(200);
}

//turn left
void body_lturn() {
  int turntime;
  turntime = randomTurnTime;
  Serial.print("randomTurnTime: ");
  Serial.println(randomTurnTime);
  
  for (int looper = 0; looper < (turntime/1000); looper++) { 
    if (ClearanceBehindDecision()) {
      Serial.println("Turning left while going backward: ");
      analogWrite(leftmotorpin1, 200/3);
      analogWrite(leftmotorpin2, 0);
      analogWrite(rightmotorpin1, 200);
      analogWrite(rightmotorpin2, 0);
      //delay(turntime/3);
      delay(1500);
      
      totalhalt();
    }
    if (ClearanceAheadDecision()) {
      Serial.println("Turning left while going forward: ");
      analogWrite(leftmotorpin1, 0);
      analogWrite(leftmotorpin2, 200);
      analogWrite(rightmotorpin1, 0);
      analogWrite(rightmotorpin2, 200/3);
      //delay(turntime/3);
      delay(1500);
      
      totalhalt();
      delay(turntime/4);
    }
    if(currDist > 50) {
      looper = turntime;
    }
  }
}

//turn right
void body_rturn() {
  int turntime;
  Serial.print("randomTurnTime: ");
  Serial.println(randomTurnTime);
  turntime = randomTurnTime;
  
  for (int looper = 0; looper < (turntime/1000); looper++) {
    if (ClearanceBehindDecision()) {
      Serial.println("Turning right while going backward: ");
      analogWrite(leftmotorpin1, 200);
      analogWrite(leftmotorpin2, 0);
      analogWrite(rightmotorpin1, 200/3);
      analogWrite(rightmotorpin2, 0);
      //delay(turntime/3);
      delay(1500);
      
      totalhalt();
    }
    if (ClearanceAheadDecision()) {
      Serial.println("Turning right while going forward: ");
      analogWrite(leftmotorpin1, 0);
      analogWrite(leftmotorpin2, 200/3);
      analogWrite(rightmotorpin1, 0);
      analogWrite(rightmotorpin2, 200);
      //delay(turntime/3);
      delay(1500);
      
      totalhalt();
      delay(turntime/4);
    }
    if(currDist > 50) {
      looper = turntime;
    }
  }
}

void randTurn(){
  Serial.println("randTurn");
  long randNumber;
  randomSeed(analogRead(0));
  randNumber = random(2, 10);
  Serial.print("randNumber= ");
  Serial.println(randNumber);
  randomTurnTime = (int(randNumber/2)+1) * 1000;
  if(randNumber > 6) {
  body_rturn();
  }
  else
  {
  body_lturn();
  }
}

boolean ClearanceAheadDecision(){
  
  boolean booallclear = false;
  currDist = MeasuringDistance(); //measure front distance
  
  if(currDist > 50) {
    nodanger();
    booallclear = true;
  }
  else {
    totalhalt();
    booallclear = false;
    Serial.println("Look out ahead!");
  }
  return(booallclear);
}


boolean ClearanceBehindDecision(){

  boolean booallclear = false;
  currRearDist = MeasuringRearDistance(); //measure rear distance
  
  if(currRearDist > 40) {
    nodanger();
    booallclear = true;
  }
  else {
    totalhalt();
    booallclear = false;
    Serial.println("Look out behind you!");
  }
  return(booallclear);
}

In general I haven't figured out how best to perform movement AND check distance while it is moving

In general you don't have to do this because once the robot has started moving it keeps going until you stop it. So, you start the robot moving and then use the loop() function to do frequent distance checks.

When the distance gets too small you stop and turn or backoff. When turning on the spot you do not need distance measurements to avoid collisions. If you move backwards then return to loop() and check behind the robot instead of in front. If you move in an arc either forwards or backwards then return to loop() checking front or rear distances as appropriate.

If you need to monitor distances whilst turning on the spot to decide which way to move then a different strategy is used. Turn a little, check distance and repeat until the distance is enough to move or the required angle has been turned.

Thanks UKHeliBob! I'm not able to turn on the spot, due to the surface. So I need to turn in an arc. That is what is making this partularly challenging. While turning, it is common for it to run into an object. The turn radius is annoying large. I am trying to go back and forth multiple times to prevent a huge arc.

It is almost like a need sensors all around my robot! agggh! :slight_smile:

So I'm still pursuing this idea of my Clearance Detection routines I think. It essentially needs to have the distance check in the middle of the turning logic every 250ms. If anyone has any ideas how to do this better I'd appreciate it.

I rely heavily on "delay" here, is there no other way to accomplish this for turning a motor/servo?

It essentially needs to have the distance check in the middle of the turning logic every 250ms. If anyone has any ideas how to do this better I'd appreciate it.

Apart from the problem that the sensor can only point in one direction unless you attach it to a servo and do a sweep left/right I still don't see the problem. As I said in a previous post

once the robot has started moving it keeps going until you stop it. So, you start the robot moving and then use the loop() function to do frequent distance checks.

As to the use of delay(), you can avoid using it by adopting the approach used in the BlinkWithoutDelay example in the IDE, which is to start an action and then to check periodically if it is time to stop it. Using that approach the program does not stop whilst waiting as it does when you use delay().

UKHeliBob:
once the robot has started moving it keeps going until you stop it. So, you start the robot moving and then use the loop() function to do frequent distance checks.

I'll have to figure out how to move all of my distance checks into the loop. Thanks.

UKHeliBob:
As to the use of delay(), you can avoid using it by adopting the approach used in the BlinkWithoutDelay example in the IDE, which is to start an action and then to check periodically if it is time to stop it. Using that approach the program does not stop whilst waiting as it does when you use delay().

ok, millis is a timer. I'll have to consider that. I was wondering how to track time, such as for logging. THis will work well enough.

Thanks for all your help! You've given me ideas on how to proceed.