top of page

Autonomous Robot Car

Project Log

Day 4

Goal

  • Implement encoders and speed sensors for more accurate path following and distance driving

  • Drive straight for one meter without veer on any surface

  • Drive in an accurate square

Goal

  • Make a Robot object

  • Drive a simple path

I want to make a robot object in case I use a different motor controller in the future or different sensors for that matter when I implement sensors. This will be much easier and cleaner to do with a Robot object rather than changing the hardware names throughout my whole code. I also want to set my speeds from a number from 0 to 100 instead of 0 to 255. I will write a simple method named convert_speed() for this. The setSpeed() function is only applicable for the specific motor controller I have. I'm going to make a general set speed function (both right and left) for all controllers. I also want to pass in negative values into speeds to indicate going backward. Here is the code in my robot.py file. 

from Raspi_MotorHAT import Raspi_MotorHAT

import atexit
class Robot(object):
     def __init__(self, motorhat_addr=0x6f):
          # Create the motor controller with correct address

          self._m_controller = Raspi_MotorHAT(addr=motorhat_addr)


          # create objects for each motor

          self.left_m = self._m_controller.getMotor(1)

          self.right_m = self._m_controller..getMotor(2)


          # motors stop when exiting code/file

          atexit.register(self.stop_motors)

     

     def convert_speed(self, speed):

          #Set default motor setting to stopped

          m_setting = Raspi_MotorHAT.RELEASE

          if speed > 0:

               m_setting = Raspi_MotorHAT.FORWARD

          if speed > 0:

               m_setting = Raspi_MotorHAT.BACKWARD

         #Make speed from -100 to 100

          output_speed = (abs(speed) * 255) / 100

          return m_setting, int(output_speed)

     def set_left(self, speed):

          m_setting, output_speed = convert_speed(speed)

          self.left_m.setSpeed(output_speed)

          self.left_m.run(m_setting)

    def set_right(self, speed):

          m_setting, output_speed = convert_speed(speed)

          self.right_m.setSpeed(output_speed)

          self.right_m.run(m_setting)

     def deactivate_motors(self):

          self.left_m.run(Raspi_MotorHAT.RELEASE)     

          self.right_m..run(Raspi_MotorHAT.RELEASE)

Now I'm going to use this robot object in my command files. I will create a new command called drive_path.py which will contain code to drive a simple path. I'll make some simple functions for going straight, right, left, and spin in place by simply changing the speeds in each function.


import robot
import time

def drive_straight(kRobot, sec):

     kRobot.set_left(75)

     kRobot.set_right(70)

def turn_right(kRobot, sec):

     kRobot.set_left(75)

     kRobot.set_right(20)

def turn_left(kRobot, sec):

     kRobot.set_left(20)

     kRobot.set_right(75)

def spin(kRobot, sec):

     kRobot.set_left(-75)

     kRobot.set_right(75)


kRobot = robot.Robot()

#path

straight(kRobot, 1)

turn_left(kRobot, 0.7)

straight(kRobot, 2)

turn_right(kRobot, 0.7)

straight(kRobot, 4)

spin(kRobot, 2)

sleep(1)

I had to tweak the seconds and speed values to get accurate 90 degree turns in driving straight properly. You might've noticed that in my drive_straight function, my left speed is actually set higher than my right to get my robot to drive straight. This is because I get some veer to the left if both speeds are set equal due to many factors: uneven weight on each side of the bot, bumpy floor, small variations in measurement of wheel diameters, one motor may just function better or the gearbox ratio could be slightly off from both sides.

I'm going to have to use encoders and a PID controller to account for these disruptions. Today taught me how important sensors are to get a more accurate running and smart robot.

Day 3

Goal

  • Connect Motors to Pi

  • Run motors with simple code

  • Understanding how the robot will turn/steer

  • Use object-oriented programming to make the robot object and make coding motors/sensors more efficient

I first installed the library to code/work with my motor controller. I do this by using Git since the library is on GitHub. I also need the I2C tool enabled because the Pi uses I2C buses to connect to the motor controller. I can do this in the raspi interface accessed through PuTTy. I can check if the Pi sees the motor controller with the command in PuTTy and it shows a device found at 6f and 70 (hexadecimal notation), which is my motor controller.

Here's the simple code to test run the motors in a file I named run_motors.py:

#Raspi_MotorHAT is library to interact with motors through the motor controller

from Raspi_MotorHAT import Raspi_MotorHAT

#Time library is used to have a quick second delay between starting/stopping motors

#atexit is used so I'm allowed to exit the file and still run the file in PuTTy 

import time
import atexit

#Create the motor controller object, I2C address passed in as addr, and the left and right motors

m_controller = Raspi_MotorHAT(addr=0x6f)

left_m = m_controller.getMotor(1)

right_m = m_controller.getMotor(2)

#function to make the motors stopped, utilized by Rasp_MotorHAT.RELEASE 

def deactivate_motors():

 

     left_m.run(Raspi_MotorHAT.RELEASE)         

     right_m.run(Raspi_MotorHAT.RELEASE)

atexit.register(turn_off_motors)

 

#Set speed (0 to 255) of motors
left_m.setSpeed(150)

rm.setSpeed(150)

 

#Run motors forward
left_m.run(Raspi_MotorHAT.FORWARD)

right_m.run(Raspi_MotorHAT.FORWARD)

#Code waits one second

time.sleep(1)

 

Now when I send this file to the Pi via FileZilla, I can now run it through the command in PuTTy,

 

python run_motors.py

 

For steering the robot I can simply change either the left motor or right motor's run command to Raspi_MotorHAT.BACKWARD so one side goes forward and the other goes backward for steering motion. 

 

Another approach for a less harsh turn makes both motors run forward but set one of the motor's speed to a small number. For example, if I set the left motor to a speed of 35 and the right motor speed of 150, then the robot will turn left. The same goes for the other way around. 
 

Day 2

Goal

  • Select/Build a not-bulky, rigid, but has a good amount of space robot chassis using a preordered kit

  • Attach Rasberry Pi with Motor Controller, Battery, and Breadboard to Robot in an efficient way

Requirements

  • The correctly setup SD Card/Rasberry Pi 

  • Motor Controller

  • Robot Chasis

  • Two DC Motors

  • Breadboard

  • Solder Kit 

  • Jumper wires (male to female)

  • USB power supply (portable charger) of 2.1 amps (3.6 x 2.3 x 0.9 in)

  • USB to Micro-USB cable

  • Velcro or double-sided tape

  • Screwdrivers and Wrench for M2.5 and M3 nuts and bolts

I've opted to go for a chassis with two wheels for sake of simplicity when it comes to wiring as I will have lots of sensors and more wiring in the future. It's also less expensive than say a four or six-wheel drive. Before I assemble the chassis, I notice that the wires attach to the motors as quite short and won't reach my motor controller hat. For this reason, I've decided to strip the end of the wires already on the motor and solder another set of wires onto them to increase length. Now I simply build the chassis following the instructions (not too complicated). 

Here's the final chassis built

I screw the Pi with the motor controller attached to it to the chassis. I taped the portable battery to power the pi on the back of the robot. I taped the breadboard on top of this battery to maximize space for other objects. I also taped another battery holder with 4 AA batteries to power the motor controller and motors. The reason I'm powering the motors separately and not simultaneously with the rest of the robot s because motors utilize a lot more power than the sensors, pi, etc (digital components). The motors can also interfere with other parts by pulling to much power to the point where there are brownouts and other parts lose power and don't function properly/consistently. I also read they can cause the digital components to not work properly since they can create electrical noise in the same power line. 

Here's the robot with the batteries (power the robot), PI (brain of the robot), and breadboard(wire the robot) attached. 

on

 

Day 1

Goal

  • Prepare SD Card with Raspbian for wireless control of robot

Requirements

  • MicroSD card with minimum 16GB

  • Raspberry Pi 3B+

  • Computer connected to the internet

  • PuTTY software 

Flashed the Raspbian software onto the microSD card using Etcher software

(can't just drag and drop the Raspbian zip file onto the card because it needs to be stored in a certain way on the card)

I'm going to control the raspberry pi wirelessly from my computer via network since I want the robot to drive without always being plugged into my computer, also known as a headless setup. 

I set up the Wi-Fi first by making two files that contain information about my Wi-Fi network and an empty file with no extension and putting them on the sd card and then inserting the card into the Pi.

 

I will be using a secure shell or an SSH system, which allows me to use a command line to send my py files, programs, commands to the Pi as well as interact with the Pi wirelessly with PuTTy Commands. The PuTTy allows me to access the SSH, so I downloaded PuTTy.

I now get my PuTTy tool connected to my Pi by configuring it with the hostname raspberrypi.local with port 22. A terminal-like window opens up and to configure the pi, I first login with the default username and password, pi and raspberry

I open the rasp-config interface by using a sudo command (sudo is used to make sure the command is run as a root user) in the PuTTy window/terminal. Now I can rename the Pi and set a new password for more security.

I now make a folder on my computer that will hold my code for the robot. I will use the application, FileZilla, as my SFTP (Secure File Transfer Protocol) tool to transfer my code files to the Pi via a network connection/sd card explained before. The hostname is what I renamed the Pi's host in the rasp-config interface, the username is still pi, and the password is the new password I set in the rasp-config interface. I can now quick-connect to see the files in the sd card in the Rasberry Pi and drag and drop my own files into it.

bottom of page