Making an Autonomous Rover With Phidgets

by InformalAbsence in Circuits > Robots

534 Views, 2 Favorites, 0 Comments

Making an Autonomous Rover With Phidgets

20211208_110522.jpg

The Phidgets Rover was an awesome project that my Highschool incorporated into their computer programming curriculum and was my first real exposure to human-computer interactive programming. The best part about it is it wasn't limited to a small use case, and you could basically make it do whatever you wanted to provided you wrote the code. The starter projects worked well for getting familiar with it, but I wanted to take it one step further.


For me, the first thing that I wanted to do was to get rid of the joystick and let the rover decide where to go all on its own. So that's what I did! The following instructable is based on some of what I did while in my high school programming class and will show you how to make your Phidgets Rover autonomous.


Please note that although I will briefly go over how to build the rover it is not the main focus of this tutorial, so a much more detailed set of instructions on building the rover can be found here at the Phidgets Education website.

Supplies

Build the Rover

RoverCloseup.jpg
20211208_110710.jpg
20211208_110529.jpg

This step is optional, as you may have already built the rover previously, or want to go ahead and do it with no instructions. If you did that's great, but if you wish to build yours the same as mine here is a brief overview of how to do it.


  1. Start by unboxing everything and laying it out in front of you.
  2. Then grab the 2xDC Motor Phidget and attach it to the rover using the provided dual lock in between the wheel and the hole provided to run cables through.
  3. Pull through the red and black wire pairs from the bottom side of the rover to the top using the provided cable hole, trying to keep the pairs of red and black wires together.
  4. Attach the one pair of red and black wires to the +0 and 0- terminals, where the red wires go to the positive and the black wires go to the negative, repeating the process for the second pair as well.
  5. Using more of the provided dual lock, attach the Sonar Phidget to the front of the rover, and the HUB5000 over the rear of the rover on top of the battery. You will want to make sure that the ethernet port on the HUB5000 is facing the cable hole.
  6. Now connect the wiring harness to the battery, pull all the remaining wires through the cable management hole to the top of the rover. You will want to attach the red wire to VCC on the Motor Phidget and the black wire to GND. For now, leave the barrel jack unplugged.
  7. Then using two of the included VINT cables connect the Sonar and DC Motor Phidget to the HUB5000. In my case, the Sonar Phidget is connected to port 5 and the motor controller to port 3. Finally, use the provided cable management to tuck away the VINT cables


Now that everything is wired up go ahead and plug in the barrel jack to the HUB5000. You should see a red light appear at the back of it, but if not try charging your battery with the included USB charger.

Connect to the Rover

20211208_110739.jpg

Now that the rover is on we can try connecting to it. First you will need to make sure you already have the Phidgets libraries installed for later. In Python, you can do this by running


python3 -m pip install Phidget22Native


Next, you will need to use the included wifi adapter to connect to your rover. Start by plugging it into your PC, then look for the name of your rover in wifi. The name of your rovers wifi network will be in in the form


Phidgets_HUB5000_XXXXXX


Where the 6 x's are the last six digits of the ENET mac address, not including the ":" characters, as marked on the sticker located at the top of the HUB5000. Once it is found you can connect to it by using the provided password on the sticker. Once connected you will likely be prompted that there is no internet which is expected.

Move Your Rover

Now that the rover is online and connected we need to figure out which way the motors are wired up. The DC Motor controller will take a range from -1 to 1. Usually, 1 will be forward, and -1 backwards, but sometimes that's not the case.


To start we are going to write a small script that will test the rover's movement. I will provide one below written in Python3, but you are more than welcome to write your own. You can name the file whatever you want, but I chose to name mine "Rover.py". I will continue to build the rest of the project off of this file so I will be using global constants to track certain numbers.


# Import required Phidgets Libraries
from Phidget22.Devices.DCMotor import *
from Phidget22.Devices.DistanceSensor import *
from Phidget22.Net import *


# Import time for use in sleep statement
import time 


# Motor Speed, Change This Value 
MOTOR_SPEED = 1

# Motors Forward
MOTORS_FORWARD = MOTOR_SPEED

# Motor Stop, this will always be the same 
MOTOR_STOP = 0


# Connect to the wireless rover at ip 192.168.100.1 and port 5661
Net.addServer("", "192.168.100.1", 5661, "", 0)


# Initialize Motor Objects 
LeftMotors = DCMotor()
RightMotors = DCMotor()


# Address motor channels 
LeftMotors.setChannel(0)
RightMotors.setChannel(1)


# Open Objects with 5000ms delay
LeftMotors.openWaitForAttachment(5000)
RightMotors.openWaitForAttachment(5000)


LeftMotors.setTargetVelocity(MOTORS_FORWARD)
RightMotors.setTargetVelocity(MOTORS_FORWARD)


# Wait 1 second 
time.sleep(1)


# Stop Motors
LeftMotors.setTargetVelocity(MOTOR_STOP)
RightMotors.setTargetVelocity(MOTOR_STOP)


Wait! Before you run your program make sure you place your rover in a clear space. It won't move very much but you don't want it to fall off your desk or ride up onto your keyboard. Provided you are connected to your rover, and it is powered on, when you run your program it should move. Now we need to know how it moved.


  • Did it spin? If so swap the wire pairs on the 0 channel of the 2x DC Motor Phidget so that the black is at the +0 and the red is at the 0-
  • Did it move backwards? If so flip the signs on the MOTOR_SPEED constant (ex. 1 => -1)


Once it's moving in the right direction we can move on to the next step.

Making the Rover Drive by Itself

This will be the most code-intensive part, but also where you get to be the most creative. For your convenience, I have included both the starter sample for you to build off of and the fully written one that I have done attached in the project files.


There are lots of ways to write the self-driving code, but I think the easiest is to take what we have written above and add Sonar functionality. The Sonar measures distance in mm, so if we want to add collision avoidance we need to find a set distance that we want to trigger an obstacle warning.


I picked 60mm or 6 cm. I used this value because the Sonar can only measure things as close as 40mm, therefore it gives the rover just enough time to react while not causing it to trigger every time it passes near something like a wall without actually hitting it. One problem you may find is that your rover is moving too fast to react to the objects in front of it. If that's what's happening you will either need to increase the sensing distance to something like 200, or lower the velocity.


I chose to run the rover at one quarter (0.25) of the max velocity, as I found the rover moves way too fast at full speed and would end up going head-on into things. This is where having global constants in place really helps, as instead of having to change the values in every setTargetVelocity() statement, I can simply change the constant value to one quarter of what it was.


For the self-driving code I'm going to simply replace everything below the start of the forward movement statement with a "while" loop for our self-driving code to exist in. My loop ended up like this:

# Start self driving loop
while True:

    # Print out current distance              To convert mm to cm, just divide by 10
    print("Distance from nearest object is {}cm".format((Sonar.getDistance() / 10)))

    # If the rover is less than 10cm from an object, then we need to avoid it.
    if Sonar.getDistance() < TRIGGER_DISTANCE:

        # Set Motor velocity to zero 
        LeftMotors.setTargetVelocity(MOTOR_STOP)
        RightMotors.setTargetVelocity(MOTOR_STOP)

        # Print out that an object is too close
        print("Obstacle in the way, moving around it.")

        # Reverse Direction
        LeftMotors.setTargetVelocity(MOTORS_REVERSE)
        RightMotors.setTargetVelocity(MOTORS_REVERSE)

        # Wait 2s to give time for reverse 
        time.sleep(2)

        # Turn left until distance is greater than 15cm 
        while Sonar.getDistance() < SAFE_DISTANCE:    

            # Start left turn by putting left wheels in reverse and right wheels forward
            LeftMotors.setTargetVelocity(MOTORS_REVERSE)
            RightMotors.setTargetVelocity(MOTORS_FORWARD)

            # Wait .01s for turn
            time.sleep(.01)

        # Set Motor velocity to zero 
        LeftMotors.setTargetVelocity(MOTOR_STOP)
        RightMotors.setTargetVelocity(MOTOR_STOP)

    # Start forward movement
    LeftMotors.setTargetVelocity(MOTORS_FORWARD)
    RightMotors.setTargetVelocity(MOTORS_FORWARD)


Remember that you will need to initialize the Sonar ahead of time, just like we did with the motors. That code should look something like this:

# Initialize Sonar
Sonar = DistanceSensor()
# Open Objects
Sonar.openWaitForAttachment(5000)


Now running your program should yield a rover that drives itself around the room, hopefully not crashing into everything.

Limitations

PhidgetException.PNG

As I mentioned earlier the Sonar Phidget can only measure distances as close as 40mm, but it also can only go as far as 10m. The latter isn't likely a concern, as 10m is a long distance for this litter rover, but the former may become an issue.


If your rover gets too close to something before measuring the distance, it can throw a PhidgetException. Although usually this will stop your code, there are things that can be done to mitigate this. The first and most easy thing to do is to either lower your MOTOR_SPEED or increase your TRIGGER_DISTANCE and SAFE_DISTANCE for obstacle avoidance, but that's not your only option.


You could also add a try-except statement around your measurements. This way when the Sonar gets too close and throws a PhidgetException error, instead of your program breaking you can just start your avoidance code. That might look something like this:

while True:
  try:
    if Sonar.getDistance() < TRIGGER_DISTANCE:
      # Avoidance code
    # Move forward again
  except PhidgetException:
    #Object is too close to sense, start avoidance code


The only thing to watch out for is that the Distance Sensor isn't the only thing that can throw a PhidgetException, and blanketing the error may result in false positives, or weird program behaviour.


Of course, the code that I have written out in this tutorial isn't perfect and doesn't cover every edge case, but it can. There is a ton of fine-tuning that can be done to make this rover drive itself with no issues, and I encourage you to try.

Troubleshooting

Flowchart.png

I have provided a basic troubleshooting flowchart above. The most common issues occur when not connected to the rover's wifi, and when the distance sensor gets too close to something as mentioned in Step 5.


If this is your first time working with the Phidgets Rover Kit and you are completely stuck, I would recommend going over the setup and testing instructions thoroughly, provided here on the Phidgets Education website.

Wrapping Things Up

As you can see there is lots that can be done with the rover, and you can almost fall down a rabbit hole of trying to add as many features as possible. I personally had a great time in my class with the Rover Kit, and found it to be a great learning experience. It also put up with a surprising amount of abuse, as testing it for the first time didn't always yield the results I had expected.


Thank you for taking the time to read this Instructable, I hope you learned something!