Welcome to the Parallax Discussion Forums, sign-up to participate.

# Anybody knows how to find a route for my ABOT based on moving PING))) feed back?

Posts: 29
edited March 2017
I have built an Activity bot with a PING))) mounted on the front servo to turn 180 degrees. I have learned the Propeller tutorial on the fixed PING))) roaming. However I am stuck on how to find a route for my Activity Bot based on the distance fed back by the moving PING))) at front. My idea was as follows:

1. get PING))) distance from constant reading (0-180 deg) while ABOT is running forward
2. if ABOT spots any PING))) distance shorter than 15 cm than ABOT stops
3. ABOT sort out the max distance corresponding to that Front Servo's angle array and turn so that the ABOT is facing straight to the direction with max distance
4. repeat the loop

Does this make sense? I felt trouble to update constant PING))) readings then find out a route to go and turn, while ABOT is running forward, how can I achieve that in SimpleIDE?

• Posts: 632
It is a good approach. The problem will be to scan from 0 to 180 while the ABOT is moving. Since it takes some time for the servo to move the ping and then take a reading, the ABOT would have to be moving slowly. One alternative is to measure distance with a fairly wide spacing, maybe every 15 or 20 degrees. Another, would be to travel some distance, stop, scan, calculate where to go, turn and travel and repeat. The distance traveled each step could be based on some percentage of the distance measured in the preceding step.

One thing to be aware of is the angle the ultrasound is going to bounce off. If the plane of the object is far off 90 degrees to the ping axis, the sound will not bounce directly back to ping and may give an erroneously large distance (either due to bouncing off multiple objects before returning or never returning.)

Tom
• Posts: 29
Thanks! I will try to work it out.
• Posts: 29
edited March 2017
Hi Tom, I wrote the first parts of the code and it works fine "to some extent" and prints surrounding distance and corresponding turret angles. My code acts as followings:

1. move forward for 1m.
2. stop and scan area in front by turning turret (0-180 deg)
3. sort out the maximum distance and corresponding turret's angle
4. turn the car to the maximum distance direction (still working on)
5. repeat the loop

I finished step 1 to 3, however I am stuck at some strange issues as followings:
First issue is that after it prints distance and turret angles, the turret is stuck at 180 deg and it won't turn back to 90 deg as it is supposed so.
Second issue is I heard my turret servo buzzing noisily at the end of the program and it felt super hot when I touched it.
And then, somehow after I compiled other programs and unplug and plug it back and power cycled it, these issue are amazingly gone! But they will come back some time after I tried to debug some new codes! I am just confused...

• Posts: 632
Try commanding the servo to go less than 180 degrees at its maximum. The servo might be hitting an internal stop a rotation slightly less than 180. If that's the case, it will keep trying to get there and may jam, and not be able to return to a lower angle, all the while being energized, buzzing, and heating up.

On some of my servos, I limit rotation from 5 deg to 175 deg.

In the program you attached, you only have 1 cycle of move, measure, turn. Is that correct? Since the last step in the program tries to rotate the servo back to 90 degs, it seems that it may be stuck at 180.

Also when you have the servo move back to 90 deg, you should add a pause to give it time to finish moving before going to the next step in the program. In this case, the servo has a command to move to 90 and should do that even though the program ends immediately after sending the command (unless the servo ramp function is only sending incremental rotation commands. In that case even if not stuck, the servo would only move the amount specified in the servo angle function based on the ramp function).
• Posts: 10,002
Besides the issue Tom mentioned, you should keep in mind the angles used in the code will most likely not correspond directly to the angle moved by the servo.

Different models of servos move different amounts with the same change in pulse length. You really need to experiment a bit to find the range of motion of your servo and IMO, you're better off using your own pulse to angle conversion factor.

I added an ultrasound sensor to my S2. Whenever the S2 detected an obstacle, it would look around for the largest distance. It would then drive in the direction of this longest distance until it reached another obstacle. This algorithm turned out to produce rather boring behavior from the robot. It pretty much just drove back and forth across the room.

Here's a link to the project.

The S2 had IR obstacle detectors besides the ultrasound sensor. It turns out these two sensors working together are pretty good at detecting obstacles. Ultrasound alone will not detect objects with padding like couches. Ultrasound also doesn't detect hard flat surfaces from shallow angles of approach. Ultrasound is better than IR when it comes to detecting things like chair legs.

The code I used with the S2 is attached to the above linked post. The ultrasound on the S2 wasn't on a servo. I had the whole robot turn to point the sensor.
• Posts: 29
Thanks for the replies!

I have reduced the turret servo range to 5 - 175 deg and added pause for it turn back to 90 deg, it all worked!

However, I have a new problem :( that now I won't be able to convert a float 'ticks' to an integer! I have tried trunc, round, int(ticks), all didn't work. trunc() and round() won't even compile properly and SimpleIDE returns errors like in the picture...

So how can I convert a float into an integer?

Much thanks for any light!

```/*
ABOT roaming with PING)))
*/

#include "abdrive.h"
#include "simpletools.h"                        // Include simpletools header
#include "servo.h"                              // Include servo header
#include "ping.h"                               // Include ping header

int adist[35];                                 // 36 distance elements by PING)))

int main()                                      // Main function
{

int count = 0;
int location = 0;
float left = 0;
float right = 0;
float circum;
float ticks;

//drive_ramp(64, 64);                           // Ramp forward 64ticks/s
//pause(4800);                                  // Ramp forward for 4.8s for 1m
//drive_ramp(0, 0);                             // Stop

servo_setramp(16, 40);                        // Ramp up the PING))) servo to 40 deg per update, faster moving servo to 0 deg
servo_angle(16, 0);                           // Starts PING))) servo to 0 degree
pause(1000);                                  // Allow 1 second to get there
servo_setramp(16, 10);                        // Set back PING))) servo to ramp down to 10 deg per update

for(int deg = 50; deg <= 1750;  deg += 50)     // use for instead of while for PING))) servo degree update
{
servo_angle(16, deg);                       // Ramps PING))) servo from 0 to 180 deg
pause(150);                                 // Stay still for 0.15 sec after each time PING))) servo moves for ABOT to update PING)))

adist[count] = ping_cm(0);                  // Get cm distance from Ping)))

print("distance is = %d\n", adist[count]);  // Display distance
pause(100);                                 // Wait 0.1 second

count += 1;

}

//pause(500);

for (count = 1; count < 35; count++)
{

{

location = count;

}

}

print("maximum distance is %d and angle is %d\n", max, adeg[location]);

servo_setramp(16, 40);                        // Reset PING))) servo to 40 deg per update
servo_angle(16, 900);                         // Reset PING))) servo to 90 degree
pause(1000);

{

circum = ((90 - adeg[location]) * PI / 180) * 105.8;

ticks = trunc(circum / 3.25);

//int t = ticks;

left = ticks/2;
right = ticks/2;

//drive_goto(left, -right);

print("cirumference is: %f\ntotal ticks to turn is: %d\nleft ticks is: %d and right ticks is: %d", circum, ticks, left, right);

}

drive_close();

/*

{
rad = turndeg * PI / 180;
ticks = circum / pertick;
left = ticks/2;
right = ticks/2;

drive_goto(-left, right);

}

{
drive_ramp(0, 0);                            // Stop

}

*/

}
```
• Posts: 632
Try
```int t = (int) (ticks);    // this will truncate the value of ticks, not sure ( ) around ticks is needed
int t = (int) (ticks + 0.5);    // this will round
```
• Posts: 29
Thanks Tom! After I used (int)(ticks + 0.5) the ABOT is up and self-roaming now :)

However it still has some issues: the most noticeable is that the ABOT will not work on shallow angles with my current design and it will hit against the wall! How can I solve it with my only mounted turret PING)))? (or should I add couple of IRs to compensate dead angles?)
• Posts: 10,002
hans90 wrote: »
However it still has some issues: the most noticeable is that the ABOT will not work on shallow angles with my current design and it will hit against the wall! How can I solve it with my only mounted turret PING)))? (or should I add couple of IRs to compensate dead angles?)

This is one of the big weaknesses when using ultrasound for obstacle detection. Combining ultrasound with IR should greatly improve the bot's ability to detect obstacles.

• Posts: 632
Duane is right. The ultrasound beam reflects like light or a rolled ball. With shallow angles it never comes back to the receiver. Adding ir is probably the best.

You could try shortening the distance travel between ping scans, and then determine if the distance to objects (walls) on the right or left is getting closer. Then calculate how the distance to the object on the near side changes with the traveling distance. Then calculate how much further forward you can travel before hitting the wall.

It is a bit more math and some more complex programing, but it would be an interesting exercise; you could try it before adding the ir.

Tom
• Posts: 29
It is really good to know! I will try it.

Thanks Tom Thanks Duane!